From d4d933538b9fba893a464362d0f37f6ec14b4099 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 19 May 2020 15:10:05 +0200 Subject: [PATCH 1/2] Re-factor `setPDFNetworkStreamFactory`, in src/display/api.js, to also accept an asynchronous function As part of trying to reduce the usage of SystemJS in the development viewer, this patch is a necessary step that will allow removal of some `require` statements. Currently this uses `SystemJS.import` in non-PRODUCTION mode, but it should be possible to replace those with standard *dynamic* `import` calls in the future. --- src/display/api.js | 63 ++++++++++++++++++++++--------------- src/display/fetch_stream.js | 6 ++++ src/display/node_stream.js | 16 +++++++--- src/pdf.js | 19 ++++++++++- 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 6e8abb6e9..d3d6b0b89 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -65,7 +65,8 @@ const RENDERING_CANCELLED_TIMEOUT = 100; // ms * @typedef {function} IPDFStreamFactory * @param {DocumentInitParameters} params - The document initialization * parameters. The "url" key is always present. - * @returns {IPDFStream} + * @returns {Promise} A promise, which is resolved with an instance of + * {IPDFStream}. * @ignore */ @@ -80,7 +81,7 @@ let createPDFNetworkStream; * data transport. * @param {IPDFStreamFactory} pdfNetworkStreamFactory - The factory function * that takes document initialization parameters (including a "url") and - * returns an instance of {IPDFStream}. + * returns a promise which is resolved with an instance of {IPDFStream}. * @ignore */ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { @@ -313,34 +314,44 @@ function getDocument(src) { if (task.destroyed) { throw new Error("Loading aborted"); } - return _fetchDocument(worker, params, rangeTransport, docId).then( - function (workerId) { - if (task.destroyed) { - throw new Error("Loading aborted"); - } - let networkStream; - if (rangeTransport) { - networkStream = new PDFDataTransportStream( - { - length: params.length, - initialData: params.initialData, - progressiveDone: params.progressiveDone, - disableRange: params.disableRange, - disableStream: params.disableStream, - }, - rangeTransport - ); - } else if (!params.data) { - networkStream = createPDFNetworkStream({ - url: params.url, + const workerIdPromise = _fetchDocument( + worker, + params, + rangeTransport, + docId + ); + const networkStreamPromise = new Promise(function (resolve) { + let networkStream; + if (rangeTransport) { + networkStream = new PDFDataTransportStream( + { length: params.length, - httpHeaders: params.httpHeaders, - withCredentials: params.withCredentials, - rangeChunkSize: params.rangeChunkSize, + initialData: params.initialData, + progressiveDone: params.progressiveDone, disableRange: params.disableRange, disableStream: params.disableStream, - }); + }, + rangeTransport + ); + } else if (!params.data) { + networkStream = createPDFNetworkStream({ + url: params.url, + length: params.length, + httpHeaders: params.httpHeaders, + withCredentials: params.withCredentials, + rangeChunkSize: params.rangeChunkSize, + disableRange: params.disableRange, + disableStream: params.disableStream, + }); + } + resolve(networkStream); + }); + + return Promise.all([workerIdPromise, networkStreamPromise]).then( + function ([workerId, networkStream]) { + if (task.destroyed) { + throw new Error("Loading aborted"); } const messageHandler = new MessageHandler( diff --git a/src/display/fetch_stream.js b/src/display/fetch_stream.js index c74483025..a1b9c9023 100644 --- a/src/display/fetch_stream.js +++ b/src/display/fetch_stream.js @@ -26,6 +26,12 @@ import { validateResponseStatus, } from "./network_utils.js"; +if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { + throw new Error( + 'Module "./fetch_stream.js" shall not be used with MOZCENTRAL builds.' + ); +} + function createFetchOptions(headers, withCredentials, abortController) { return { method: "GET", diff --git a/src/display/node_stream.js b/src/display/node_stream.js index 79125524a..bbfb5b844 100644 --- a/src/display/node_stream.js +++ b/src/display/node_stream.js @@ -14,11 +14,6 @@ */ /* globals __non_webpack_require__ */ -const fs = __non_webpack_require__("fs"); -const http = __non_webpack_require__("http"); -const https = __non_webpack_require__("https"); -const url = __non_webpack_require__("url"); - import { AbortException, assert, @@ -30,6 +25,17 @@ import { validateRangeRequestCapabilities, } from "./network_utils.js"; +if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { + throw new Error( + 'Module "./node_stream.js" shall not be used with MOZCENTRAL builds.' + ); +} + +const fs = __non_webpack_require__("fs"); +const http = __non_webpack_require__("http"); +const https = __non_webpack_require__("https"); +const url = __non_webpack_require__("url"); + const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//; function parseUrl(sourceUrl) { diff --git a/src/pdf.js b/src/pdf.js index 2233f3438..3e3c2d018 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -30,7 +30,24 @@ var pdfjsDisplaySVG = require("./display/svg.js"); const pdfjsDisplayWorkerOptions = require("./display/worker_options.js"); const pdfjsDisplayAPICompatibility = require("./display/api_compatibility.js"); -if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { +if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) { + const streamsPromise = Promise.all([ + SystemJS.import("pdfjs/display/network.js"), + SystemJS.import("pdfjs/display/fetch_stream.js"), + ]); + pdfjsDisplayAPI.setPDFNetworkStreamFactory(params => { + return streamsPromise.then(streams => { + const [{ PDFNetworkStream }, { PDFFetchStream }] = streams; + if ( + pdfjsDisplayDisplayUtils.isFetchSupported() && + pdfjsDisplayDisplayUtils.isValidFetchUrl(params.url) + ) { + return new PDFFetchStream(params); + } + return new PDFNetworkStream(params); + }); + }); +} else if (PDFJSDev.test("GENERIC")) { const { isNodeJS } = require("./shared/is_node.js"); if (isNodeJS) { const PDFNodeStream = require("./display/node_stream.js").PDFNodeStream; From e2c3312416d34f4756da9dbbb3b3d02a32e4d1e3 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 19 May 2020 15:13:43 +0200 Subject: [PATCH 2/2] Convert the `src/pdf.js` and `src/pdf.worker.js` files to use standard `import`/`export` statements As part of reducing our reliance on SystemJS in the development viewer, this patch replaces usage of `require` statements with modern standards `import`/`export` statements instead. If we want to try and move forward with reducing usage of SystemJS, we don't have much choice but to make these kind changes (despite what prior test-results showed, however I'm no longer able to reproduce the issues locally). --- src/pdf.js | 160 ++++++++++++++++++++++++++-------------------- src/pdf.worker.js | 9 ++- 2 files changed, 94 insertions(+), 75 deletions(-) diff --git a/src/pdf.js b/src/pdf.js index 3e3c2d018..a2b703e8b 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -12,36 +12,66 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* eslint-disable no-unused-vars */ -"use strict"; +import { + addLinkAttributes, + getFilenameFromUrl, + isFetchSupported, + isValidFetchUrl, + LinkTarget, + loadScript, + PDFDateString, + RenderingCancelledException, +} from "./display/display_utils.js"; +import { + build, + getDocument, + LoopbackPort, + PDFDataRangeTransport, + PDFWorker, + setPDFNetworkStreamFactory, + version, +} from "./display/api.js"; +import { + CMapCompressionType, + createObjectURL, + createPromiseCapability, + createValidAbsoluteUrl, + InvalidPDFException, + MissingPDFException, + NativeImageDecoding, + OPS, + PasswordResponses, + PermissionFlag, + removeNullCharacters, + shadow, + UnexpectedResponseException, + UNSUPPORTED_FEATURES, + Util, + VerbosityLevel, +} from "./shared/util.js"; +import { AnnotationLayer } from "./display/annotation_layer.js"; +import { apiCompatibilityParams } from "./display/api_compatibility.js"; +import { GlobalWorkerOptions } from "./display/worker_options.js"; +import { renderTextLayer } from "./display/text_layer.js"; +import { SVGGraphics } from "./display/svg.js"; -var pdfjsVersion = +/* eslint-disable-next-line no-unused-vars */ +const pdfjsVersion = typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_VERSION") : void 0; -var pdfjsBuild = +/* eslint-disable-next-line no-unused-vars */ +const pdfjsBuild = typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_BUILD") : void 0; -var pdfjsSharedUtil = require("./shared/util.js"); -var pdfjsDisplayAPI = require("./display/api.js"); -var pdfjsDisplayTextLayer = require("./display/text_layer.js"); -var pdfjsDisplayAnnotationLayer = require("./display/annotation_layer.js"); -var pdfjsDisplayDisplayUtils = require("./display/display_utils.js"); -var pdfjsDisplaySVG = require("./display/svg.js"); -const pdfjsDisplayWorkerOptions = require("./display/worker_options.js"); -const pdfjsDisplayAPICompatibility = require("./display/api_compatibility.js"); - if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) { const streamsPromise = Promise.all([ SystemJS.import("pdfjs/display/network.js"), SystemJS.import("pdfjs/display/fetch_stream.js"), ]); - pdfjsDisplayAPI.setPDFNetworkStreamFactory(params => { + setPDFNetworkStreamFactory(params => { return streamsPromise.then(streams => { const [{ PDFNetworkStream }, { PDFFetchStream }] = streams; - if ( - pdfjsDisplayDisplayUtils.isFetchSupported() && - pdfjsDisplayDisplayUtils.isValidFetchUrl(params.url) - ) { + if (isFetchSupported() && isValidFetchUrl(params.url)) { return new PDFFetchStream(params); } return new PDFNetworkStream(params); @@ -51,20 +81,17 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) { const { isNodeJS } = require("./shared/is_node.js"); if (isNodeJS) { const PDFNodeStream = require("./display/node_stream.js").PDFNodeStream; - pdfjsDisplayAPI.setPDFNetworkStreamFactory(params => { + setPDFNetworkStreamFactory(params => { return new PDFNodeStream(params); }); } else { const PDFNetworkStream = require("./display/network.js").PDFNetworkStream; let PDFFetchStream; - if (pdfjsDisplayDisplayUtils.isFetchSupported()) { + if (isFetchSupported()) { PDFFetchStream = require("./display/fetch_stream.js").PDFFetchStream; } - pdfjsDisplayAPI.setPDFNetworkStreamFactory(params => { - if ( - PDFFetchStream && - pdfjsDisplayDisplayUtils.isValidFetchUrl(params.url) - ) { + setPDFNetworkStreamFactory(params => { + if (PDFFetchStream && isValidFetchUrl(params.url)) { return new PDFFetchStream(params); } return new PDFNetworkStream(params); @@ -86,56 +113,49 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) { return true; } }; - if ( - pdfjsDisplayDisplayUtils.isFetchSupported() && - isChromeWithFetchCredentials() - ) { + if (isFetchSupported() && isChromeWithFetchCredentials()) { PDFFetchStream = require("./display/fetch_stream.js").PDFFetchStream; } - pdfjsDisplayAPI.setPDFNetworkStreamFactory(params => { - if ( - PDFFetchStream && - pdfjsDisplayDisplayUtils.isValidFetchUrl(params.url) - ) { + setPDFNetworkStreamFactory(params => { + if (PDFFetchStream && isValidFetchUrl(params.url)) { return new PDFFetchStream(params); } return new PDFNetworkStream(params); }); } -exports.build = pdfjsDisplayAPI.build; -exports.version = pdfjsDisplayAPI.version; -exports.getDocument = pdfjsDisplayAPI.getDocument; -exports.LoopbackPort = pdfjsDisplayAPI.LoopbackPort; -exports.PDFDataRangeTransport = pdfjsDisplayAPI.PDFDataRangeTransport; -exports.PDFWorker = pdfjsDisplayAPI.PDFWorker; -exports.renderTextLayer = pdfjsDisplayTextLayer.renderTextLayer; -exports.AnnotationLayer = pdfjsDisplayAnnotationLayer.AnnotationLayer; -exports.createPromiseCapability = pdfjsSharedUtil.createPromiseCapability; -exports.PasswordResponses = pdfjsSharedUtil.PasswordResponses; -exports.InvalidPDFException = pdfjsSharedUtil.InvalidPDFException; -exports.MissingPDFException = pdfjsSharedUtil.MissingPDFException; -exports.SVGGraphics = pdfjsDisplaySVG.SVGGraphics; -exports.NativeImageDecoding = pdfjsSharedUtil.NativeImageDecoding; -exports.CMapCompressionType = pdfjsSharedUtil.CMapCompressionType; -exports.PermissionFlag = pdfjsSharedUtil.PermissionFlag; -exports.UnexpectedResponseException = - pdfjsSharedUtil.UnexpectedResponseException; -exports.OPS = pdfjsSharedUtil.OPS; -exports.VerbosityLevel = pdfjsSharedUtil.VerbosityLevel; -exports.UNSUPPORTED_FEATURES = pdfjsSharedUtil.UNSUPPORTED_FEATURES; -exports.createValidAbsoluteUrl = pdfjsSharedUtil.createValidAbsoluteUrl; -exports.createObjectURL = pdfjsSharedUtil.createObjectURL; -exports.removeNullCharacters = pdfjsSharedUtil.removeNullCharacters; -exports.shadow = pdfjsSharedUtil.shadow; -exports.Util = pdfjsSharedUtil.Util; -exports.RenderingCancelledException = - pdfjsDisplayDisplayUtils.RenderingCancelledException; -exports.getFilenameFromUrl = pdfjsDisplayDisplayUtils.getFilenameFromUrl; -exports.LinkTarget = pdfjsDisplayDisplayUtils.LinkTarget; -exports.addLinkAttributes = pdfjsDisplayDisplayUtils.addLinkAttributes; -exports.loadScript = pdfjsDisplayDisplayUtils.loadScript; -exports.PDFDateString = pdfjsDisplayDisplayUtils.PDFDateString; -exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions; -exports.apiCompatibilityParams = - pdfjsDisplayAPICompatibility.apiCompatibilityParams; +export { + addLinkAttributes, + getFilenameFromUrl, + LinkTarget, + loadScript, + PDFDateString, + RenderingCancelledException, + build, + getDocument, + LoopbackPort, + PDFDataRangeTransport, + PDFWorker, + version, + CMapCompressionType, + createObjectURL, + createPromiseCapability, + createValidAbsoluteUrl, + InvalidPDFException, + MissingPDFException, + NativeImageDecoding, + OPS, + PasswordResponses, + PermissionFlag, + removeNullCharacters, + shadow, + UnexpectedResponseException, + UNSUPPORTED_FEATURES, + Util, + VerbosityLevel, + AnnotationLayer, + apiCompatibilityParams, + GlobalWorkerOptions, + renderTextLayer, + SVGGraphics, +}; diff --git a/src/pdf.worker.js b/src/pdf.worker.js index 2400d4611..ee44edd7e 100644 --- a/src/pdf.worker.js +++ b/src/pdf.worker.js @@ -12,13 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* eslint-disable no-unused-vars */ -"use strict"; +import { WorkerMessageHandler } from "./core/worker.js"; +/* eslint-disable-next-line no-unused-vars */ const pdfjsVersion = PDFJSDev.eval("BUNDLE_VERSION"); +/* eslint-disable-next-line no-unused-vars */ const pdfjsBuild = PDFJSDev.eval("BUNDLE_BUILD"); -const pdfjsCoreWorker = require("./core/worker.js"); - -exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; +export { WorkerMessageHandler };