Add support for async/await using Babel

For proof-of-concept, this patch converts a couple of `Promise` returning methods to use `async` instead.
Please note that the `generic` build, based on this patch, has been successfully testing in IE11 (i.e. the viewer loads and nothing is obviously broken).

Being able to use modern JavaScript features like `async`/`await` is a huge plus, but there's one (obvious) side-effect: The size of the built files will increase slightly (unless `SKIP_BABEL == true`). That's unavoidable, but seems like a small price to pay in the grand scheme of things.

Finally, note that the `chromium` build target was changed to no longer skip Babel translation, since the Chrome extension still supports version `49` of the browser (where native `async` support isn't available).
This commit is contained in:
Jonas Jenwald 2018-07-30 13:58:09 +02:00
parent 4ea663aa8a
commit 099ed08852
13 changed files with 159 additions and 179 deletions

View File

@ -1,6 +1,6 @@
{ {
"parserOptions": { "parserOptions": {
"ecmaVersion": 6, "ecmaVersion": 8,
"sourceType": "module", "sourceType": "module",
}, },

View File

@ -288,6 +288,7 @@ function preprocessPDFJSCode(ctx, code) {
}, },
}; };
var parseOptions = { var parseOptions = {
ecmaVersion: 8,
locations: true, locations: true,
sourceFile: ctx.sourceFile, sourceFile: ctx.sourceFile,
sourceType: 'module', sourceType: 'module',

View File

@ -177,7 +177,14 @@ function createWebpackConfig(defines, output) {
exclude: /src[\\\/]core[\\\/](glyphlist|unicode)/, exclude: /src[\\\/]core[\\\/](glyphlist|unicode)/,
options: { options: {
presets: skipBabel ? undefined : ['env'], presets: skipBabel ? undefined : ['env'],
plugins: ['transform-es2015-modules-commonjs'], plugins: [
'transform-es2015-modules-commonjs',
['transform-runtime', {
'helpers': false,
'polyfill': false,
'regenerator': true,
}],
],
}, },
}, },
{ {
@ -808,7 +815,7 @@ gulp.task('mozcentral', ['mozcentral-pre']);
gulp.task('chromium-pre', ['buildnumber', 'locale'], function () { gulp.task('chromium-pre', ['buildnumber', 'locale'], function () {
console.log(); console.log();
console.log('### Building Chromium extension'); console.log('### Building Chromium extension');
var defines = builder.merge(DEFINES, { CHROME: true, SKIP_BABEL: true, }); var defines = builder.merge(DEFINES, { CHROME: true, });
var CHROME_BUILD_DIR = BUILD_DIR + '/chromium/', var CHROME_BUILD_DIR = BUILD_DIR + '/chromium/',
CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/'; CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/';
@ -897,6 +904,11 @@ gulp.task('lib', ['buildnumber'], function () {
presets: noPreset ? undefined : ['env'], presets: noPreset ? undefined : ['env'],
plugins: [ plugins: [
'transform-es2015-modules-commonjs', 'transform-es2015-modules-commonjs',
['transform-runtime', {
'helpers': false,
'polyfill': false,
'regenerator': true,
}],
babelPluginReplaceNonWebPackRequire, babelPluginReplaceNonWebPackRequire,
], ],
}).code; }).code;

37
package-lock.json generated
View File

@ -1210,6 +1210,15 @@
"regenerator-transform": "^0.10.0" "regenerator-transform": "^0.10.0"
} }
}, },
"babel-plugin-transform-runtime": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
"integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
}
},
"babel-plugin-transform-strict-mode": { "babel-plugin-transform-strict-mode": {
"version": "6.24.1", "version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
@ -3361,14 +3370,12 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -3383,20 +3390,17 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -3513,8 +3517,7 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -3526,7 +3529,6 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -3541,7 +3543,6 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -3549,14 +3550,12 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -3575,7 +3574,6 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -3656,8 +3654,7 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -3669,7 +3666,6 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -3791,7 +3787,6 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",

View File

@ -7,6 +7,7 @@
"babel-core": "^6.26.3", "babel-core": "^6.26.3",
"babel-loader": "^7.1.5", "babel-loader": "^7.1.5",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0", "babel-preset-env": "^1.7.0",
"core-js": "^2.5.7", "core-js": "^2.5.7",
"escodegen": "^1.11.0", "escodegen": "^1.11.0",

View File

@ -131,19 +131,17 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
this.options = options || DefaultPartialEvaluatorOptions; this.options = options || DefaultPartialEvaluatorOptions;
this.pdfFunctionFactory = pdfFunctionFactory; this.pdfFunctionFactory = pdfFunctionFactory;
this.fetchBuiltInCMap = (name) => { this.fetchBuiltInCMap = async (name) => {
if (this.builtInCMapCache.has(name)) { if (this.builtInCMapCache.has(name)) {
return Promise.resolve(this.builtInCMapCache.get(name)); return this.builtInCMapCache.get(name);
} }
return this.handler.sendWithPromise('FetchBuiltInCMap', { const data = await this.handler.sendWithPromise('FetchBuiltInCMap',
name, { name, });
}).then((data) => { if (data.compressionType !== CMapCompressionType.NONE) {
if (data.compressionType !== CMapCompressionType.NONE) { // Given the size of uncompressed CMaps, only cache compressed ones.
// Given the size of uncompressed CMaps, only cache compressed ones. this.builtInCMapCache.set(name, data);
this.builtInCMapCache.set(name, data); }
} return data;
return data;
});
}; };
} }

View File

@ -1497,29 +1497,23 @@ var XRef = (function XRefClosure() {
return xrefEntry; return xrefEntry;
}, },
fetchIfRefAsync: function XRef_fetchIfRefAsync(obj, suppressEncryption) { async fetchIfRefAsync(obj, suppressEncryption) {
if (!isRef(obj)) { if (!isRef(obj)) {
return Promise.resolve(obj); return obj;
} }
return this.fetchAsync(obj, suppressEncryption); return this.fetchAsync(obj, suppressEncryption);
}, },
fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { async fetchAsync(ref, suppressEncryption) {
var streamManager = this.stream.manager; try {
var xref = this; return this.fetch(ref, suppressEncryption);
return new Promise(function tryFetch(resolve, reject) { } catch (ex) {
try { if (!(ex instanceof MissingDataException)) {
resolve(xref.fetch(ref, suppressEncryption)); throw ex;
} catch (e) {
if (e instanceof MissingDataException) {
streamManager.requestRange(e.begin, e.end).then(function () {
tryFetch(resolve, reject);
}, reject);
return;
}
reject(e);
} }
}); await this.pdfManager.requestRange(ex.begin, ex.end);
return this.fetchAsync(ref, suppressEncryption);
}
}, },
getCatalogObj: function XRef_getCatalogObj() { getCatalogObj: function XRef_getCatalogObj() {

View File

@ -72,7 +72,7 @@ class BasePdfManager {
return this.pdfDocument.cleanup(); return this.pdfDocument.cleanup();
} }
ensure(obj, prop, args) { async ensure(obj, prop, args) {
unreachable('Abstract method `ensure` called'); unreachable('Abstract method `ensure` called');
} }
@ -111,15 +111,12 @@ class LocalPdfManager extends BasePdfManager {
this._loadedStreamPromise = Promise.resolve(stream); this._loadedStreamPromise = Promise.resolve(stream);
} }
ensure(obj, prop, args) { async ensure(obj, prop, args) {
return new Promise(function(resolve) { const value = obj[prop];
const value = obj[prop]; if (typeof value === 'function') {
if (typeof value === 'function') { return value.apply(obj, args);
resolve(value.apply(obj, args)); }
} else { return value;
resolve(value);
}
});
} }
requestRange(begin, end) { requestRange(begin, end) {
@ -155,30 +152,20 @@ class NetworkPdfManager extends BasePdfManager {
this.pdfDocument = new PDFDocument(this, this.streamManager.getStream()); this.pdfDocument = new PDFDocument(this, this.streamManager.getStream());
} }
ensure(obj, prop, args) { async ensure(obj, prop, args) {
return new Promise((resolve, reject) => { try {
let ensureHelper = () => { const value = obj[prop];
try { if (typeof value === 'function') {
const value = obj[prop]; return value.apply(obj, args);
let result; }
if (typeof value === 'function') { return value;
result = value.apply(obj, args); } catch (ex) {
} else { if (!(ex instanceof MissingDataException)) {
result = value; throw ex;
} }
resolve(result); await this.requestRange(ex.begin, ex.end);
} catch (ex) { return this.ensure(obj, prop, args);
if (!(ex instanceof MissingDataException)) { }
reject(ex);
return;
}
this.streamManager.requestRange(ex.begin, ex.end)
.then(ensureHelper, reject);
}
};
ensureHelper();
});
} }
requestRange(begin, end) { requestRange(begin, end) {

View File

@ -152,23 +152,21 @@ class PDFFetchStreamReader {
return this._isStreamingSupported; return this._isStreamingSupported;
} }
read() { async read() {
return this._headersCapability.promise.then(() => { await this._headersCapability.promise;
return this._reader.read().then(({ value, done, }) => { const { value, done, } = await this._reader.read();
if (done) { if (done) {
return Promise.resolve({ value, done, }); return { value, done, };
} }
this._loaded += value.byteLength; this._loaded += value.byteLength;
if (this.onProgress) { if (this.onProgress) {
this.onProgress({ this.onProgress({
loaded: this._loaded, loaded: this._loaded,
total: this._contentLength, total: this._contentLength,
});
}
let buffer = new Uint8Array(value).buffer;
return Promise.resolve({ value: buffer, done: false, });
}); });
}); }
let buffer = new Uint8Array(value).buffer;
return { value: buffer, done: false, };
} }
cancel(reason) { cancel(reason) {
@ -223,20 +221,18 @@ class PDFFetchStreamRangeReader {
return this._isStreamingSupported; return this._isStreamingSupported;
} }
read() { async read() {
return this._readCapability.promise.then(() => { await this._readCapability.promise;
return this._reader.read().then(({ value, done, }) => { const { value, done, } = await this._reader.read();
if (done) { if (done) {
return Promise.resolve({ value, done, }); return { value, done, };
} }
this._loaded += value.byteLength; this._loaded += value.byteLength;
if (this.onProgress) { if (this.onProgress) {
this.onProgress({ loaded: this._loaded, }); this.onProgress({ loaded: this._loaded, });
} }
let buffer = new Uint8Array(value).buffer; let buffer = new Uint8Array(value).buffer;
return Promise.resolve({ value: buffer, done: false, }); return { value: buffer, done: false, };
});
});
} }
cancel(reason) { cancel(reason) {

View File

@ -453,16 +453,16 @@ PDFNetworkStreamFullRequestReader.prototype = {
return this._headersReceivedCapability.promise; return this._headersReceivedCapability.promise;
}, },
read: function PDFNetworkStreamFullRequestReader_read() { async read() {
if (this._storedError) { if (this._storedError) {
return Promise.reject(this._storedError); throw this._storedError;
} }
if (this._cachedChunks.length > 0) { if (this._cachedChunks.length > 0) {
var chunk = this._cachedChunks.shift(); var chunk = this._cachedChunks.shift();
return Promise.resolve({ value: chunk, done: false, }); return { value: chunk, done: false, };
} }
if (this._done) { if (this._done) {
return Promise.resolve({ value: undefined, done: true, }); return { value: undefined, done: true, };
} }
var requestCapability = createPromiseCapability(); var requestCapability = createPromiseCapability();
this._requests.push(requestCapability); this._requests.push(requestCapability);
@ -534,14 +534,14 @@ PDFNetworkStreamRangeRequestReader.prototype = {
return false; // TODO allow progressive range bytes loading return false; // TODO allow progressive range bytes loading
}, },
read: function PDFNetworkStreamRangeRequestReader_read() { async read() {
if (this._queuedChunk !== null) { if (this._queuedChunk !== null) {
var chunk = this._queuedChunk; var chunk = this._queuedChunk;
this._queuedChunk = null; this._queuedChunk = null;
return Promise.resolve({ value: chunk, done: false, }); return { value: chunk, done: false, };
} }
if (this._done) { if (this._done) {
return Promise.resolve({ value: undefined, done: true, }); return { value: undefined, done: true, };
} }
var requestCapability = createPromiseCapability(); var requestCapability = createPromiseCapability();
this._requests.push(requestCapability); this._requests.push(requestCapability);

View File

@ -131,31 +131,30 @@ class BaseFullReader {
return this._isStreamingSupported; return this._isStreamingSupported;
} }
read() { async read() {
return this._readCapability.promise.then(() => { await this._readCapability.promise;
if (this._done) { if (this._done) {
return Promise.resolve({ value: undefined, done: true, }); return { value: undefined, done: true, };
} }
if (this._storedError) { if (this._storedError) {
return Promise.reject(this._storedError); throw this._storedError;
} }
let chunk = this._readableStream.read(); let chunk = this._readableStream.read();
if (chunk === null) { if (chunk === null) {
this._readCapability = createPromiseCapability(); this._readCapability = createPromiseCapability();
return this.read(); return this.read();
} }
this._loaded += chunk.length; this._loaded += chunk.length;
if (this.onProgress) { if (this.onProgress) {
this.onProgress({ this.onProgress({
loaded: this._loaded, loaded: this._loaded,
total: this._contentLength, total: this._contentLength,
}); });
} }
// Ensure that `read()` method returns ArrayBuffer. // Ensure that `read()` method returns ArrayBuffer.
let buffer = new Uint8Array(chunk).buffer; let buffer = new Uint8Array(chunk).buffer;
return Promise.resolve({ value: buffer, done: false, }); return { value: buffer, done: false, };
});
} }
cancel(reason) { cancel(reason) {
@ -220,28 +219,27 @@ class BaseRangeReader {
return this._isStreamingSupported; return this._isStreamingSupported;
} }
read() { async read() {
return this._readCapability.promise.then(() => { await this._readCapability.promise;
if (this._done) { if (this._done) {
return Promise.resolve({ value: undefined, done: true, }); return { value: undefined, done: true, };
} }
if (this._storedError) { if (this._storedError) {
return Promise.reject(this._storedError); throw this._storedError;
} }
let chunk = this._readableStream.read(); let chunk = this._readableStream.read();
if (chunk === null) { if (chunk === null) {
this._readCapability = createPromiseCapability(); this._readCapability = createPromiseCapability();
return this.read(); return this.read();
} }
this._loaded += chunk.length; this._loaded += chunk.length;
if (this.onProgress) { if (this.onProgress) {
this.onProgress({ loaded: this._loaded, }); this.onProgress({ loaded: this._loaded, });
} }
// Ensure that `read()` method returns ArrayBuffer. // Ensure that `read()` method returns ArrayBuffer.
let buffer = new Uint8Array(chunk).buffer; let buffer = new Uint8Array(chunk).buffer;
return Promise.resolve({ value: buffer, done: false, }); return { value: buffer, done: false, };
});
} }
cancel(reason) { cancel(reason) {

View File

@ -160,13 +160,13 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() {
return this._stream._contentLength; return this._stream._contentLength;
}, },
read: function PDFDataTransportStreamReader_read() { async read() {
if (this._queuedChunks.length > 0) { if (this._queuedChunks.length > 0) {
var chunk = this._queuedChunks.shift(); var chunk = this._queuedChunks.shift();
return Promise.resolve({ value: chunk, done: false, }); return { value: chunk, done: false, };
} }
if (this._done) { if (this._done) {
return Promise.resolve({ value: undefined, done: true, }); return { value: undefined, done: true, };
} }
var requestCapability = createPromiseCapability(); var requestCapability = createPromiseCapability();
this._requests.push(requestCapability); this._requests.push(requestCapability);
@ -216,14 +216,14 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() {
return false; return false;
}, },
read: function PDFDataTransportStreamRangeReader_read() { async read() {
if (this._queuedChunk) { if (this._queuedChunk) {
let chunk = this._queuedChunk; let chunk = this._queuedChunk;
this._queuedChunk = null; this._queuedChunk = null;
return Promise.resolve({ value: chunk, done: false, }); return { value: chunk, done: false, };
} }
if (this._done) { if (this._done) {
return Promise.resolve({ value: undefined, done: true, }); return { value: undefined, done: true, };
} }
var requestCapability = createPromiseCapability(); var requestCapability = createPromiseCapability();
this._requests.push(requestCapability); this._requests.push(requestCapability);

View File

@ -18,13 +18,11 @@ import {
ReadableStream, UnexpectedResponseException, UnknownErrorException ReadableStream, UnexpectedResponseException, UnknownErrorException
} from './util'; } from './util';
function resolveCall(fn, args, thisArg = null) { async function resolveCall(fn, args, thisArg = null) {
if (!fn) { if (!fn) {
return Promise.resolve(undefined); return;
} }
return new Promise((resolve, reject) => { return fn.apply(thisArg, args);
resolve(fn.apply(thisArg, args));
});
} }
function wrapReason(reason) { function wrapReason(reason) {