From d02291271924ea5afe2ee4fbb400a5ae4f3157ef Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 13 Jul 2023 11:58:16 +0200 Subject: [PATCH 1/2] Remove most build-time `require`-calls from the `src/display/`-folder By leveraging import maps we can get rid of *most* of the remaining `require`-calls in the `src/display/`-folder, since we should strive to use modern `import`-statements wherever possible. The only remaining cases are Node.js-specific dependencies, since those seem very difficult to convert unless we start producing a bundle *specifically* for Node.js environments. --- .eslintrc | 2 +- gulpfile.mjs | 26 ++++++++++++- src/display/annotation_layer.js | 2 +- src/display/api.js | 65 ++++++++++++++------------------- src/display/node_stream.js | 12 +++--- src/display/stubs.js | 36 ++++++++++++++++++ src/pdf.js | 6 +-- test/unit/pdf_spec.js | 6 +-- test/unit/unit_test.html | 7 ++++ web/viewer-geckoview.html | 7 ++++ web/viewer.html | 7 ++++ 11 files changed, 122 insertions(+), 54 deletions(-) create mode 100644 src/display/stubs.js diff --git a/.eslintrc b/.eslintrc index 54d490b7bcd80..bec3bdcde0be4 100644 --- a/.eslintrc +++ b/.eslintrc @@ -42,7 +42,7 @@ "import/no-mutable-exports": "error", "import/no-self-import": "error", "import/no-unresolved": ["error", { - "ignore": ["pdfjs", "pdfjs-lib", "pdfjs-web", "web"] + "ignore": ["display", "pdfjs", "pdfjs-lib", "pdfjs-web", "web"] }], "mozilla/avoid-removeChild": "error", "mozilla/use-includes-instead-of-indexOf": "error", diff --git a/gulpfile.mjs b/gulpfile.mjs index 5be216f8a0c36..0aa6dc898bae9 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -239,6 +239,14 @@ function createWebpackConfig( "pdfjs-web": "web", "pdfjs-lib": "web/pdfjs", }; + const libraryAlias = { + "display-fetch_stream": "src/display/stubs.js", + "display-l10n_utils": "src/display/stubs.js", + "display-network": "src/display/stubs.js", + "display-node_stream": "src/display/stubs.js", + "display-node_utils": "src/display/stubs.js", + "display-svg": "src/display/stubs.js", + }; const viewerAlias = { "web-annotation_editor_params": "web/annotation_editor_params.js", "web-com": "", @@ -256,9 +264,19 @@ function createWebpackConfig( "web-toolbar": "web/toolbar.js", }; if (bundleDefines.CHROME) { + libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js"; + libraryAlias["display-network"] = "src/display/network.js"; + viewerAlias["web-com"] = "web/chromecom.js"; viewerAlias["web-print_service"] = "web/pdf_print_service.js"; } else if (bundleDefines.GENERIC) { + libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js"; + libraryAlias["display-l10n_utils"] = "web/l10n_utils.js"; + libraryAlias["display-network"] = "src/display/network.js"; + libraryAlias["display-node_stream"] = "src/display/node_stream.js"; + libraryAlias["display-node_utils"] = "src/display/node_utils.js"; + libraryAlias["display-svg"] = "src/display/svg.js"; + viewerAlias["web-com"] = "web/genericcom.js"; viewerAlias["web-print_service"] = "web/pdf_print_service.js"; } else if (bundleDefines.MOZCENTRAL) { @@ -274,7 +292,7 @@ function createWebpackConfig( } viewerAlias["web-com"] = "web/firefoxcom.js"; } - const alias = { ...basicAlias, ...viewerAlias }; + const alias = { ...basicAlias, ...libraryAlias, ...viewerAlias }; for (const key in alias) { alias[key] = path.join(__dirname, alias[key]); } @@ -1575,6 +1593,12 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) { defines: bundleDefines, map: { "pdfjs-lib": "../pdf", + "display-fetch_stream": "./fetch_stream", + "display-l10n_utils": "../web/l10n_utils", + "display-network": "./network", + "display-node_stream": "./node_stream", + "display-node_utils": "./node_utils", + "display-svg": "./svg", }, }; const licenseHeaderLibre = fs diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index a9d219bc8ff11..89700d1bc2245 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -39,6 +39,7 @@ import { } from "./display_utils.js"; import { AnnotationStorage } from "./annotation_storage.js"; import { ColorConverters } from "../shared/scripting_utils.js"; +import { NullL10n } from "display-l10n_utils"; import { XfaLayer } from "./xfa_layer.js"; const DEFAULT_TAB_INDEX = 1000; @@ -2872,7 +2873,6 @@ class AnnotationLayer { typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC && !TESTING") ) { - const { NullL10n } = require("pdfjs-web/l10n_utils.js"); this.l10n ||= NullL10n; } if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) { diff --git a/src/display/api.js b/src/display/api.js index d8dfd988687cd..8ce1cfb36d6d6 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -58,12 +58,22 @@ import { StatTimer, } from "./display_utils.js"; import { FontFaceObject, FontLoader } from "./font_loader.js"; +import { + NodeCanvasFactory, + NodeCMapReaderFactory, + NodeFilterFactory, + NodeStandardFontDataFactory, +} from "display-node_utils"; import { CanvasGraphics } from "./canvas.js"; import { GlobalWorkerOptions } from "./worker_options.js"; import { MessageHandler } from "../shared/message_handler.js"; import { Metadata } from "./metadata.js"; import { OptionalContentConfig } from "./optional_content_config.js"; import { PDFDataTransportStream } from "./transport_stream.js"; +import { PDFFetchStream } from "display-fetch_stream"; +import { PDFNetworkStream } from "display-network"; +import { PDFNodeStream } from "display-node_stream"; +import { SVGGraphics } from "display-svg"; import { XfaText } from "./xfa_text.js"; const DEFAULT_RANGE_CHUNK_SIZE = 65536; // 2^16 = 65536 @@ -72,54 +82,21 @@ const DELAYED_CLEANUP_TIMEOUT = 5000; // ms const DefaultCanvasFactory = typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS - ? require("./node_utils.js").NodeCanvasFactory + ? NodeCanvasFactory : DOMCanvasFactory; const DefaultCMapReaderFactory = typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS - ? require("./node_utils.js").NodeCMapReaderFactory + ? NodeCMapReaderFactory : DOMCMapReaderFactory; const DefaultFilterFactory = typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS - ? require("./node_utils.js").NodeFilterFactory + ? NodeFilterFactory : DOMFilterFactory; const DefaultStandardFontDataFactory = typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS - ? require("./node_utils.js").NodeStandardFontDataFactory + ? NodeStandardFontDataFactory : DOMStandardFontDataFactory; -let createPDFNetworkStream; -if (typeof PDFJSDev === "undefined") { - const streamsPromise = Promise.all([ - import("./network.js"), - import("./fetch_stream.js"), - ]); - - createPDFNetworkStream = async params => { - const [{ PDFNetworkStream }, { PDFFetchStream }] = await streamsPromise; - - return isValidFetchUrl(params.url) - ? new PDFFetchStream(params) - : new PDFNetworkStream(params); - }; -} else if (PDFJSDev.test("GENERIC || CHROME")) { - if (PDFJSDev.test("GENERIC") && isNodeJS) { - const { PDFNodeStream } = require("./node_stream.js"); - - createPDFNetworkStream = params => { - return new PDFNodeStream(params); - }; - } else { - const { PDFNetworkStream } = require("./network.js"); - const { PDFFetchStream } = require("./fetch_stream.js"); - - createPDFNetworkStream = params => { - return isValidFetchUrl(params.url) - ? new PDFFetchStream(params) - : new PDFNetworkStream(params); - }; - } -} - /** * @typedef { Int8Array | Uint8Array | Uint8ClampedArray | * Int16Array | Uint16Array | @@ -448,6 +425,19 @@ function getDocument(src) { if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { throw new Error("Not implemented: createPDFNetworkStream"); } + const createPDFNetworkStream = params => { + if ( + typeof PDFJSDev !== "undefined" && + PDFJSDev.test("GENERIC") && + isNodeJS + ) { + return new PDFNodeStream(params); + } + return isValidFetchUrl(params.url) + ? new PDFFetchStream(params) + : new PDFNetworkStream(params); + }; + networkStream = createPDFNetworkStream({ url, length, @@ -3454,5 +3444,6 @@ export { PDFWorker, PDFWorkerUtil, RenderTask, + SVGGraphics, version, }; diff --git a/src/display/node_stream.js b/src/display/node_stream.js index e63c3c7788552..62e72ad0b632a 100644 --- a/src/display/node_stream.js +++ b/src/display/node_stream.js @@ -31,14 +31,10 @@ if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { ); } -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) { + const url = __non_webpack_require__("url"); const parsedUrl = url.parse(sourceUrl); if (parsedUrl.protocol === "file:" || parsedUrl.host) { return parsedUrl; @@ -344,11 +340,13 @@ class PDFNodeStreamFullReader extends BaseFullReader { this._request = null; if (this._url.protocol === "http:") { + const http = __non_webpack_require__("http"); this._request = http.request( createRequestOptions(this._url, stream.httpHeaders), handleResponse ); } else { + const https = __non_webpack_require__("https"); this._request = https.request( createRequestOptions(this._url, stream.httpHeaders), handleResponse @@ -391,11 +389,13 @@ class PDFNodeStreamRangeReader extends BaseRangeReader { this._request = null; if (this._url.protocol === "http:") { + const http = __non_webpack_require__("http"); this._request = http.request( createRequestOptions(this._url, this._httpHeaders), handleResponse ); } else { + const https = __non_webpack_require__("https"); this._request = https.request( createRequestOptions(this._url, this._httpHeaders), handleResponse @@ -420,6 +420,7 @@ class PDFNodeStreamFsFullReader extends BaseFullReader { path = path.replace(/^\//, ""); } + const fs = __non_webpack_require__("fs"); fs.lstat(path, (error, stat) => { if (error) { if (error.code === "ENOENT") { @@ -449,6 +450,7 @@ class PDFNodeStreamFsRangeReader extends BaseRangeReader { path = path.replace(/^\//, ""); } + const fs = __non_webpack_require__("fs"); this._setReadableStream(fs.createReadStream(path, { start, end: end - 1 })); } } diff --git a/src/display/stubs.js b/src/display/stubs.js new file mode 100644 index 0000000000000..3ac497b61ba87 --- /dev/null +++ b/src/display/stubs.js @@ -0,0 +1,36 @@ +/* Copyright 2023 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const NodeCanvasFactory = null; +const NodeCMapReaderFactory = null; +const NodeFilterFactory = null; +const NodeStandardFontDataFactory = null; +const NullL10n = null; +const PDFFetchStream = null; +const PDFNetworkStream = null; +const PDFNodeStream = null; +const SVGGraphics = null; + +export { + NodeCanvasFactory, + NodeCMapReaderFactory, + NodeFilterFactory, + NodeStandardFontDataFactory, + NullL10n, + PDFFetchStream, + PDFNetworkStream, + PDFNodeStream, + SVGGraphics, +}; diff --git a/src/pdf.js b/src/pdf.js index 1d1473e78386c..6e097586b1221 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -50,6 +50,7 @@ import { getDocument, PDFDataRangeTransport, PDFWorker, + SVGGraphics, version, } from "./display/api.js"; import { @@ -78,11 +79,6 @@ const pdfjsVersion = const pdfjsBuild = typeof PDFJSDev !== "undefined" ? PDFJSDev.eval("BUNDLE_BUILD") : void 0; -const SVGGraphics = - typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") - ? require("./display/svg.js").SVGGraphics - : null; - export { AbortException, AnnotationEditorLayer, diff --git a/test/unit/pdf_spec.js b/test/unit/pdf_spec.js index cc4e8e0deb8cf..3f2fd210acb07 100644 --- a/test/unit/pdf_spec.js +++ b/test/unit/pdf_spec.js @@ -39,6 +39,7 @@ import { getDocument, PDFDataRangeTransport, PDFWorker, + SVGGraphics, version, } from "../../src/display/api.js"; import { @@ -110,10 +111,7 @@ describe("pdfjs_api", function () { renderTextLayer, setLayerDimensions, shadow, - SVGGraphics: - typeof PDFJSDev !== "undefined" && PDFJSDev.test("LIB") - ? require("../../display/svg.js").SVGGraphics - : null, + SVGGraphics, UnexpectedResponseException, updateTextLayer, Util, diff --git a/test/unit/unit_test.html b/test/unit/unit_test.html index 622ff00eee8d2..193aa3a762b62 100644 --- a/test/unit/unit_test.html +++ b/test/unit/unit_test.html @@ -17,6 +17,13 @@ "pdfjs-web/": "../../web/", "pdfjs-test/": "../", + "display-fetch_stream": "../../src/display/fetch_stream.js", + "display-l10n_utils": "../../src/display/stubs.js", + "display-network": "../../src/display/network.js", + "display-node_stream": "../../src/display/stubs.js", + "display-node_utils": "../../src/display/stubs.js", + "display-svg": "../../src/display/stubs.js", + "web-annotation_editor_params": "../../web/annotation_editor_params.js", "web-com": "../../web/genericcom.js", "web-pdf_attachment_viewer": "../../web/pdf_attachment_viewer.js", diff --git a/web/viewer-geckoview.html b/web/viewer-geckoview.html index 4204de77059de..e61578fb2aa29 100644 --- a/web/viewer-geckoview.html +++ b/web/viewer-geckoview.html @@ -49,6 +49,13 @@ "pdfjs-lib": "../src/pdf.js", "pdfjs-web/": "./", + "display-fetch_stream": "../src/display/fetch_stream.js", + "display-l10n_utils": "../src/display/stubs.js", + "display-network": "../src/display/network.js", + "display-node_stream": "../src/display/stubs.js", + "display-node_utils": "../src/display/stubs.js", + "display-svg": "../src/display/stubs.js", + "web-annotation_editor_params": "./stubs-geckoview.js", "web-com": "./genericcom.js", "web-pdf_attachment_viewer": "./stubs-geckoview.js", diff --git a/web/viewer.html b/web/viewer.html index b94f1d8e23c56..bf4ef41fbd945 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -60,6 +60,13 @@ "pdfjs-lib": "../src/pdf.js", "pdfjs-web/": "./", + "display-fetch_stream": "../src/display/fetch_stream.js", + "display-l10n_utils": "../src/display/stubs.js", + "display-network": "../src/display/network.js", + "display-node_stream": "../src/display/stubs.js", + "display-node_utils": "../src/display/stubs.js", + "display-svg": "../src/display/stubs.js", + "web-annotation_editor_params": "./annotation_editor_params.js", "web-com": "./genericcom.js", "web-pdf_attachment_viewer": "./pdf_attachment_viewer.js", From d9350c38997b31ee9f0058f438b332997eb53e07 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 18 Jul 2023 09:07:32 +0200 Subject: [PATCH 2/2] Temporarily stop running `gulp typestest` in GitHub Actions This is necessary to unblock the previous patch, which removes more build-time `require`-calls from the `src/display/` folder. --- gulpfile.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gulpfile.mjs b/gulpfile.mjs index 0aa6dc898bae9..af35561fd6cd7 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -2455,7 +2455,6 @@ gulp.task( "ci-test", gulp.series( gulp.parallel("lint", "externaltest", "unittestcli"), - "lint-chromium", - "typestest" + "lint-chromium" ) );