From 3c5c8d2a0b0ea88f8c4d67d202c48a0bd59b5ff8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:29:37 +0200 Subject: [PATCH 01/12] Remove the typed array check when calling `LoopbackPort` in `PDFWorker._setupFakeWorker` With version 2.0, native support for typed arrays is now a requirement for using the PDF.js library; see PR 9094 where the old polyfills were removed. Hence the `isTypedArraysPresent` check, when setting up fake workers, no longer serves any purpose here and can thus be removed. --- src/display/api.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index b121661f8..92b842eba 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1553,12 +1553,7 @@ var PDFWorker = (function PDFWorkerClosure() { this._readyCapability.reject(new Error('Worker was destroyed')); return; } - - // We cannot turn on proper fake port simulation (this includes - // structured cloning) when typed arrays are not supported. Relying - // on a chance that messages will be sent in proper order. - var isTypedArraysPresent = Uint8Array !== Float32Array; - var port = new LoopbackPort(isTypedArraysPresent); + let port = new LoopbackPort(); this._port = port; // All fake workers use the same port, making id unique. From 47a9d38280fc54d156c77ad89e7ac1b2b4bcc4ec Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:29:42 +0200 Subject: [PATCH 02/12] Add more validation in `PDFWorker.fromPort` The signature of the `PDFWorker.fromPort` method, in addition to the `PDFWorker` constructor, was changed in PR 9480. Hence it's probably a good idea to add a bit more validation to `PDFWorker.fromPort`, to ensure that it won't fail silently for an API consumer that updates to version 2.0 of the PDF.js library. --- src/display/api.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/display/api.js b/src/display/api.js index 92b842eba..cce2704b0 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1593,6 +1593,9 @@ var PDFWorker = (function PDFWorkerClosure() { * @param {PDFWorkerParameters} params - The worker initialization parameters. */ PDFWorker.fromPort = function(params) { + if (!params || !params.port) { + throw new Error('PDFWorker.fromPort - invalid method signature.'); + } if (pdfWorkerPorts.has(params.port)) { return pdfWorkerPorts.get(params.port); } From dc6e1b4176700e8796225afba524bebecab7dfa3 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:29:47 +0200 Subject: [PATCH 03/12] Use `Uint8ClampedArray` for the image data returned by `JpegDecode`, in src/display/api.js Since all the built-in PDF.js image decoders now return their data as `Uint8ClampedArray`, for consistency `JpegDecode` on the main-thread should be doing the same thing; follow-up to PR 8778. --- src/display/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/display/api.js b/src/display/api.js index cce2704b0..ce3713afa 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -2028,7 +2028,7 @@ var WorkerTransport = (function WorkerTransportClosure() { var height = img.height; var size = width * height; var rgbaLength = size * 4; - var buf = new Uint8Array(size * components); + var buf = new Uint8ClampedArray(size * components); var tmpCanvas = document.createElement('canvas'); tmpCanvas.width = width; tmpCanvas.height = height; From eef53347fef37838f6ed451c8b85a357dd32a263 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:29:52 +0200 Subject: [PATCH 04/12] Ensure that the correct data is sent, with the `test` message, from the worker if typed arrays aren't properly supported With native typed array support now being mandatory in PDF.js, since version 2.0, this probably isn't a huge problem even though the current code seems wrong (it was changed in PR 6571). Note how in the `!(data instanceof Uint8Array)` case we're currently attempting to send `handler.send('test', 'main', false);` to the main-thread, which doesn't really make any sense since the signature of the method reads `send(actionName, data, transfers) {`. Hence the data that's *actually* being sent here is `'main'`, with `false` as the transferList, which just seems weird. On the main-thread, this means that we're in this case checking `data && data.supportTypedArray`, where `data` contains the string `'main'` rather than being falsy. Since a string doesn't have a `supportTypedArray` property, that check still fails as expected but it doesn't seem great nonetheless. --- src/core/worker.js | 2 +- src/display/api.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/worker.js b/src/core/worker.js index 45c8e33cc..567343864 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -335,7 +335,7 @@ var WorkerMessageHandler = { // check if Uint8Array can be sent to worker if (!(data instanceof Uint8Array)) { - handler.send('test', 'main', false); + handler.send('test', false); return; } // making sure postMessage transfers are working diff --git a/src/display/api.js b/src/display/api.js index ce3713afa..3bd0a60ee 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1480,8 +1480,7 @@ var PDFWorker = (function PDFWorkerClosure() { terminateEarly(); return; // worker was destroyed } - var supportTypedArray = data && data.supportTypedArray; - if (supportTypedArray) { + if (data && data.supportTypedArray) { this._messageHandler = messageHandler; this._port = worker; this._webWorker = worker; From e89afa589929e31575de83f21f2d4810cdc94291 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:29:56 +0200 Subject: [PATCH 05/12] Stop sending the `PDFManagerReady` message from the Worker, since it's unused in the API After PR 8617 the `PDFManagerReady` message handler function, in `src/display/api.js`, is now a no-op. Hence it seems completely unnecessary to keep sending this message from `src/core/worker.js`. --- src/core/worker.js | 3 +-- src/display/api.js | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/worker.js b/src/core/worker.js index 567343864..106d31bcb 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -629,9 +629,8 @@ var WorkerMessageHandler = { newPdfManager.terminate(); throw new Error('Worker was terminated'); } - pdfManager = newPdfManager; - handler.send('PDFManagerReady', null); + pdfManager.onLoadedStream().then(function(stream) { handler.send('DataLoaded', { length: stream.bytes.byteLength, }); }); diff --git a/src/display/api.js b/src/display/api.js index 3bd0a60ee..a9415b071 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1834,9 +1834,6 @@ var WorkerTransport = (function WorkerTransportClosure() { this.downloadInfoCapability.resolve(data); }, this); - messageHandler.on('PDFManagerReady', function transportPage(data) { - }, this); - messageHandler.on('StartRenderPage', function transportRender(data) { if (this.destroyed) { return; // Ignore any pending requests if the worker was terminated. From 4f4b50e01eb95f470bf58ed67be7196b0fedf720 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:30:00 +0200 Subject: [PATCH 06/12] Rename `PDFDocumentProxy.pdfInfo` to `PDFDocumentProxy._pdfInfo` to indicate that the property should be considered "private" Since `PDFDocumentProxy` already provide getters for all the data returned by `GetDoc` (in the Worker), there isn't any compelling reason for accessing the `pdfInfo` directly on `PDFDocumentProxy`. --- src/display/api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index a9415b071..cfda93dd8 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -585,7 +585,7 @@ var PDFDataRangeTransport = (function pdfDataRangeTransportClosure() { */ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { function PDFDocumentProxy(pdfInfo, transport, loadingTask) { - this.pdfInfo = pdfInfo; + this._pdfInfo = pdfInfo; this.transport = transport; this.loadingTask = loadingTask; } @@ -594,14 +594,14 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { * @return {number} Total number of pages the PDF contains. */ get numPages() { - return this.pdfInfo.numPages; + return this._pdfInfo.numPages; }, /** * @return {string} A unique ID to identify a PDF. Not guaranteed to be * unique. */ get fingerprint() { - return this.pdfInfo.fingerprint; + return this._pdfInfo.fingerprint; }, /** * @param {number} pageNumber The page number to get. The first page is 1. From b263b702e8f9230484e835d88c206feda2ecb743 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:30:06 +0200 Subject: [PATCH 07/12] Rename `PDFPageProxy.pageInfo` to `PDFPageProxy._pageInfo` to indicate that the property should be considered "private" Since `PDFPageProxy` already provide getters for all the data returned by `GetPage` (in the Worker), there isn't any compelling reason for accessing the `pageInfo` directly on `PDFPageProxy`. The patch also changes the `GetPage` handler, in `src/core/worker.js`, to use modern JavaScript features. --- src/core/worker.js | 20 +++++++++----------- src/display/api.js | 10 +++++----- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/core/worker.js b/src/core/worker.js index 106d31bcb..5b5020dfd 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -639,19 +639,17 @@ var WorkerMessageHandler = { handler.on('GetPage', function wphSetupGetPage(data) { return pdfManager.getPage(data.pageIndex).then(function(page) { - var rotatePromise = pdfManager.ensure(page, 'rotate'); - var refPromise = pdfManager.ensure(page, 'ref'); - var userUnitPromise = pdfManager.ensure(page, 'userUnit'); - var viewPromise = pdfManager.ensure(page, 'view'); - return Promise.all([ - rotatePromise, refPromise, userUnitPromise, viewPromise - ]).then(function(results) { + pdfManager.ensure(page, 'rotate'), + pdfManager.ensure(page, 'ref'), + pdfManager.ensure(page, 'userUnit'), + pdfManager.ensure(page, 'view'), + ]).then(function([rotate, ref, userUnit, view]) { return { - rotate: results[0], - ref: results[1], - userUnit: results[2], - view: results[3], + rotate, + ref, + userUnit, + view, }; }); }); diff --git a/src/display/api.js b/src/display/api.js index cfda93dd8..b5fa9e8d2 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -831,7 +831,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() { var PDFPageProxy = (function PDFPageProxyClosure() { function PDFPageProxy(pageIndex, pageInfo, transport, pdfBug = false) { this.pageIndex = pageIndex; - this.pageInfo = pageInfo; + this._pageInfo = pageInfo; this.transport = transport; this._stats = (pdfBug ? new StatTimer() : DummyStatTimer); this._pdfBug = pdfBug; @@ -853,27 +853,27 @@ var PDFPageProxy = (function PDFPageProxyClosure() { * @return {number} The number of degrees the page is rotated clockwise. */ get rotate() { - return this.pageInfo.rotate; + return this._pageInfo.rotate; }, /** * @return {Object} The reference that points to this page. It has 'num' and * 'gen' properties. */ get ref() { - return this.pageInfo.ref; + return this._pageInfo.ref; }, /** * @return {number} The default size of units in 1/72nds of an inch. */ get userUnit() { - return this.pageInfo.userUnit; + return this._pageInfo.userUnit; }, /** * @return {Array} An array of the visible portion of the PDF page in the * user space units - [x1, y1, x2, y2]. */ get view() { - return this.pageInfo.view; + return this._pageInfo.view; }, /** From c8e2163bbca459b5050e3c772e21a5bbbdec6cf8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:30:11 +0200 Subject: [PATCH 08/12] Remove incorrect/unnecessary validation of the `verbosity` parameter in the `PDFWorker` constructor (PR 9480 follow-up) --- src/display/api.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index b5fa9e8d2..65ee503a1 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -16,7 +16,7 @@ import { assert, createPromiseCapability, getVerbosityLevel, info, InvalidPDFException, - isArrayBuffer, isNum, isSameOrigin, MissingPDFException, NativeImageDecoding, + isArrayBuffer, isSameOrigin, MissingPDFException, NativeImageDecoding, PasswordException, setVerbosityLevel, shadow, stringToBytes, UnexpectedResponseException, UnknownErrorException, unreachable, Util, warn } from '../shared/util'; @@ -1382,7 +1382,8 @@ var PDFWorker = (function PDFWorkerClosure() { * @param {PDFWorkerParameters} params - The worker initialization parameters. */ function PDFWorker({ name = null, port = null, - postMessageTransfers = true, verbosity = null, } = {}) { + postMessageTransfers = true, + verbosity = getVerbosityLevel(), } = {}) { if (port && pdfWorkerPorts.has(port)) { throw new Error('Cannot use more than one PDFWorker per port'); } @@ -1390,7 +1391,7 @@ var PDFWorker = (function PDFWorkerClosure() { this.name = name; this.destroyed = false; this.postMessageTransfers = postMessageTransfers !== false; - this.verbosity = (isNum(verbosity) ? verbosity : getVerbosityLevel()); + this.verbosity = verbosity; this._readyCapability = createPromiseCapability(); this._port = null; From 871bf5c68b1d6ad0365baac4e1056cb14faf635c Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:30:14 +0200 Subject: [PATCH 09/12] Remove the, now obsolete, handling of the `CMapReaderFactory` parameter in `getDocument` This special handling was added in PR 8567, but was made redundant in PR 8721 which stopped sending everything but the kitchen sink to the Worker side. --- src/display/api.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 65ee503a1..acd8fc746 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -231,7 +231,6 @@ function getDocument(src) { let params = Object.create(null); var rangeTransport = null; let worker = null; - let CMapReaderFactory = DOMCMapReaderFactory; for (var key in source) { if (key === 'url' && typeof window !== 'undefined') { @@ -260,14 +259,12 @@ function getDocument(src) { 'data property.'); } continue; - } else if (key === 'CMapReaderFactory') { - CMapReaderFactory = source[key]; - continue; } params[key] = source[key]; } params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE; + params.CMapReaderFactory = params.CMapReaderFactory || DOMCMapReaderFactory; params.ignoreErrors = params.stopAtErrors !== true; params.pdfBug = params.pdfBug === true; @@ -355,7 +352,7 @@ function getDocument(src) { var messageHandler = new MessageHandler(docId, workerId, worker.port); messageHandler.postMessageTransfers = worker.postMessageTransfers; var transport = new WorkerTransport(messageHandler, task, networkStream, - params, CMapReaderFactory); + params); task._transport = transport; messageHandler.send('Ready', null); }); @@ -387,7 +384,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { docId, apiVersion: (typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('BUNDLE_VERSION') : null), - source: { + source: { // Only send the required properties, and *not* the entire object. data: source.data, url: source.url, password: source.password, @@ -1614,14 +1611,13 @@ var PDFWorker = (function PDFWorkerClosure() { * @ignore */ var WorkerTransport = (function WorkerTransportClosure() { - function WorkerTransport(messageHandler, loadingTask, networkStream, - params, CMapReaderFactory) { + function WorkerTransport(messageHandler, loadingTask, networkStream, params) { this.messageHandler = messageHandler; this.loadingTask = loadingTask; this.commonObjs = new PDFObjects(); this.fontLoader = new FontLoader(loadingTask.docId); this._params = params; - this.CMapReaderFactory = new CMapReaderFactory({ + this.CMapReaderFactory = new params.CMapReaderFactory({ baseUrl: params.cMapUrl, isCompressed: params.cMapPacked, }); From 2fdaa3d54c7bcadbdfc9cec0f9c8282af40d5c04 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:30:23 +0200 Subject: [PATCH 10/12] Update the `postMessageTransfers` comment in `createDocumentHandler` in the `src/core/worker.js` file Since the old comment mentions a now unsupported browser, let's update it such that someone won't accidentally conclude that the code in question can be removed. --- src/core/worker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/worker.js b/src/core/worker.js index 5b5020dfd..6cfa09950 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -390,8 +390,8 @@ var WorkerMessageHandler = { var workerHandlerName = docParams.docId + '_worker'; var handler = new MessageHandler(workerHandlerName, docId, port); - // Ensure that postMessage transfers are correctly enabled/disabled, - // to prevent "DataCloneError" in older versions of IE (see issue 6957). + // Ensure that postMessage transfers are always correctly enabled/disabled, + // to prevent "DataCloneError" in browsers without transfers support. handler.postMessageTransfers = docParams.postMessageTransfers; function ensureNotTerminated() { From 547f119be628f58e12237addd528ea5239b80e6c Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Tue, 5 Jun 2018 20:30:26 +0200 Subject: [PATCH 11/12] Simplify the error handling slightly in the `src/display/node_stream.js` file The various classes have `this._errored` and `this._reason` properties, where the first one is a boolean indicating if an error was encountered and the second one contains the actual `Error` (or `null` initially). In practice this means that errors are basically tracked *twice*, rather than just once. This kind of double-bookkeeping is generally a bad idea, since it's quite easy for the properties to (accidentally) get into an inconsistent state whenever the relevant code is modified. Rather than using a separate boolean, we can just as well check the "error" property directly (since `null` is falsy). --- Somewhat unrelated to this patch, but `src/display/node_stream.js` is currently *not* handling errors in a consistent or even correct way; compared with `src/display/network.js` and `src/display/fetch_stream.js`. Obviously using the `createResponseStatusError` utility function, from `src/display/network_utils.js`, might not make much sense in a Node.js environment. However at the *very* least it seems that `MissingPDFException`, or `UnknownErrorException` when one cannot tell that the PDF file is "missing", should be manually thrown. As is, the API (i.e. `getDocument`) is not returning the *expected* errors when loading fails in Node.js environments (as evident from the `pending` API unit-test). --- src/display/node_stream.js | 37 +++++++++++++++---------------------- test/unit/api_spec.js | 4 +++- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/display/node_stream.js b/src/display/node_stream.js index 3332d46d9..84ab37a8b 100644 --- a/src/display/node_stream.js +++ b/src/display/node_stream.js @@ -90,8 +90,7 @@ class BaseFullReader { constructor(stream) { this._url = stream.url; this._done = false; - this._errored = false; - this._reason = null; + this._storedError = null; this.onProgress = null; let source = stream.source; this._contentLength = source.length; // optional @@ -137,8 +136,8 @@ class BaseFullReader { if (this._done) { return Promise.resolve({ value: undefined, done: true, }); } - if (this._errored) { - return Promise.reject(this._reason); + if (this._storedError) { + return Promise.reject(this._storedError); } let chunk = this._readableStream.read(); @@ -170,8 +169,7 @@ class BaseFullReader { } _error(reason) { - this._errored = true; - this._reason = reason; + this._storedError = reason; this._readCapability.resolve(); } @@ -199,8 +197,8 @@ class BaseFullReader { } // Destroy ReadableStream if already in errored state. - if (this._errored) { - this._readableStream.destroy(this._reason); + if (this._storedError) { + this._readableStream.destroy(this._storedError); } } } @@ -209,8 +207,7 @@ class BaseRangeReader { constructor(stream) { this._url = stream.url; this._done = false; - this._errored = false; - this._reason = null; + this._storedError = null; this.onProgress = null; this._loaded = 0; this._readableStream = null; @@ -228,8 +225,8 @@ class BaseRangeReader { if (this._done) { return Promise.resolve({ value: undefined, done: true, }); } - if (this._errored) { - return Promise.reject(this._reason); + if (this._storedError) { + return Promise.reject(this._storedError); } let chunk = this._readableStream.read(); @@ -258,8 +255,7 @@ class BaseRangeReader { } _error(reason) { - this._errored = true; - this._reason = reason; + this._storedError = reason; this._readCapability.resolve(); } @@ -281,8 +277,8 @@ class BaseRangeReader { }); // Destroy readableStream if already in errored state. - if (this._errored) { - this._readableStream.destroy(this._reason); + if (this._storedError) { + this._readableStream.destroy(this._storedError); } } } @@ -339,8 +335,7 @@ class PDFNodeStreamFullReader extends BaseFullReader { } this._request.on('error', (reason) => { - this._errored = true; - this._reason = reason; + this._storedError = reason; this._headersCapability.reject(reason); }); // Note: `request.end(data)` is used to write `data` to request body @@ -378,8 +373,7 @@ class PDFNodeStreamRangeReader extends BaseRangeReader { } this._request.on('error', (reason) => { - this._errored = true; - this._reason = reason; + this._storedError = reason; }); this._request.end(); } @@ -398,8 +392,7 @@ class PDFNodeStreamFsFullReader extends BaseFullReader { fs.lstat(path, (error, stat) => { if (error) { - this._errored = true; - this._reason = error; + this._storedError = error; this._headersCapability.reject(error); return; } diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 3b0cdf23f..1d3264649 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -164,7 +164,9 @@ describe('api', function() { }); it('creates pdf doc from non-existent URL', function(done) { if (isNodeJS()) { - pending('XMLHttpRequest is not supported in Node.js.'); + pending('Fix `src/display/node_stream.js` to actually throw ' + + 'a `MissingPDFException` in all cases where a PDF file ' + + 'cannot be found, such that this test-case can be enabled.'); } var loadingTask = getDocument( buildGetDocumentParams('non-existent.pdf')); From 07d610615c2832b9dc3ca1f5cdd976dc64510ea7 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Thu, 7 Jun 2018 13:52:40 +0200 Subject: [PATCH 12/12] Move, and modernize, `Util.loadScript` from `src/shared/util.js` to `src/display/dom_utils.js` Not only is the `Util.loadScript` helper function unused on the Worker side, even trying to use it there would throw an Error (since `document` isn't defined/available in Workers). Hence this helper function is moved, and its code modernized slightly by having it return a Promise rather than needing a callback function. Finally, to reduced code duplication, the "new" loadScript function is exported and used in the viewer. --- src/display/api.js | 6 ++--- src/display/dom_utils.js | 14 +++++++++++ src/pdf.js | 1 + src/shared/util.js | 15 ------------ web/app.js | 51 +++++++++++++--------------------------- 5 files changed, 34 insertions(+), 53 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index acd8fc746..c9c8d4164 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -21,8 +21,8 @@ import { UnexpectedResponseException, UnknownErrorException, unreachable, Util, warn } from '../shared/util'; import { - DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer, PageViewport, - RenderingCancelledException, StatTimer + DOMCanvasFactory, DOMCMapReaderFactory, DummyStatTimer, loadScript, + PageViewport, RenderingCancelledException, StatTimer } from './dom_utils'; import { FontFaceObject, FontLoader } from './font_loader'; import { apiCompatibilityParams } from './api_compatibility'; @@ -1356,7 +1356,7 @@ var PDFWorker = (function PDFWorkerClosure() { } } else { let loader = fakeWorkerFilesLoader || function(callback) { - Util.loadScript(getWorkerSrc(), function() { + loadScript(getWorkerSrc()).then(function() { callback(window.pdfjsWorker.WorkerMessageHandler); }); }; diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index 94e3b10f2..06f7a7b8e 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -428,6 +428,19 @@ class DummyStatTimer { } } +function loadScript(src) { + return new Promise((resolve, reject) => { + let script = document.createElement('script'); + script.src = src; + + script.onload = resolve; + script.onerror = function() { + reject(new Error(`Cannot load script at: ${script.src}`)); + }; + (document.head || document.documentElement).appendChild(script); + }); +} + export { PageViewport, RenderingCancelledException, @@ -440,4 +453,5 @@ export { DOMSVGFactory, StatTimer, DummyStatTimer, + loadScript, }; diff --git a/src/pdf.js b/src/pdf.js index 1de68d330..cc4c2c5e6 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -108,6 +108,7 @@ exports.RenderingCancelledException = exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl; exports.LinkTarget = pdfjsDisplayDOMUtils.LinkTarget; exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes; +exports.loadScript = pdfjsDisplayDOMUtils.loadScript; exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions; exports.apiCompatibilityParams = pdfjsDisplayAPICompatibility.apiCompatibilityParams; diff --git a/src/shared/util.js b/src/shared/util.js index 6ffbedf60..a52df0c42 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -908,21 +908,6 @@ var Util = (function UtilClosure() { } }; - Util.loadScript = function Util_loadScript(src, callback) { - var script = document.createElement('script'); - var loaded = false; - script.setAttribute('src', src); - if (callback) { - script.onload = function() { - if (!loaded) { - callback(); - } - loaded = true; - }; - } - document.getElementsByTagName('head')[0].appendChild(script); - }; - return Util; })(); diff --git a/web/app.js b/web/app.js index de4f8c8ec..b9f3f1d62 100644 --- a/web/app.js +++ b/web/app.js @@ -22,8 +22,8 @@ import { } from './ui_utils'; import { build, createBlob, getDocument, getFilenameFromUrl, GlobalWorkerOptions, - InvalidPDFException, LinkTarget, MissingPDFException, OPS, PDFWorker, shadow, - UnexpectedResponseException, UNSUPPORTED_FEATURES, version + InvalidPDFException, LinkTarget, loadScript, MissingPDFException, OPS, + PDFWorker, shadow, UnexpectedResponseException, UNSUPPORTED_FEATURES, version } from 'pdfjs-lib'; import { CursorTool, PDFCursorTools } from './pdf_cursor_tools'; import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue'; @@ -1551,11 +1551,11 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) { } function loadFakeWorker() { - return new Promise(function(resolve, reject) { - if (!GlobalWorkerOptions.workerSrc) { - GlobalWorkerOptions.workerSrc = AppOptions.get('workerSrc'); - } - if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) { + if (!GlobalWorkerOptions.workerSrc) { + GlobalWorkerOptions.workerSrc = AppOptions.get('workerSrc'); + } + if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) { + return new Promise(function(resolve, reject) { if (typeof SystemJS === 'object') { SystemJS.import('pdfjs/core/worker').then((worker) => { window.pdfjsWorker = worker; @@ -1568,37 +1568,18 @@ function loadFakeWorker() { reject(new Error( 'SystemJS or CommonJS must be used to load fake worker.')); } - } else { - let script = document.createElement('script'); - script.src = PDFWorker.getWorkerSrc(); - script.onload = function() { - resolve(); - }; - script.onerror = function() { - reject(new Error(`Cannot load fake worker at: ${script.src}`)); - }; - (document.head || document.documentElement).appendChild(script); - } - }); + }); + } + return loadScript(PDFWorker.getWorkerSrc()); } function loadAndEnablePDFBug(enabledTabs) { - return new Promise(function (resolve, reject) { - let appConfig = PDFViewerApplication.appConfig; - let script = document.createElement('script'); - script.src = appConfig.debuggerScriptPath; - script.onload = function () { - PDFBug.enable(enabledTabs); - PDFBug.init({ - OPS, - }, appConfig.mainContainer); - resolve(); - }; - script.onerror = function () { - reject(new Error('Cannot load debugger at ' + script.src)); - }; - (document.getElementsByTagName('head')[0] || document.body). - appendChild(script); + let appConfig = PDFViewerApplication.appConfig; + return loadScript(appConfig.debuggerScriptPath).then(function() { + PDFBug.enable(enabledTabs); + PDFBug.init({ + OPS, + }, appConfig.mainContainer); }); }