From 67303b16f1f708fd1c430eccd11719f4e4e8d65b Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Mon, 17 Jul 2023 15:44:30 +0200 Subject: [PATCH 1/2] [api-minor] Let Babel handle the necessary `core-js` polyfills automatically In the last couple of years we've been quicker to remove support for older browsers/environments, which means that at this point in time we don't bundle that many polyfills. (The polyfills are also generally simpler nowadays, ever since we removed support for e.g. Internet Explorer.) Rather than having to *manually* handle the polyfills, we can actually let Babel take care of bundling the necessary polyfills for us; please refer to https://babeljs.io/docs/babel-preset-env The only exception here is the Node.js-specific compatibility-code, which is moved into the `src/display/node_utils.js` file. This ought to be fine since workers are not available/used in Node.js-environments. *Please note:* For the `legacy`-builds this will increase the size of the *built* files, however that seems like a very small price to pay in order to simplify maintenance of the general PDF.js library. --- gulpfile.mjs | 10 ++++++++- src/display/node_utils.js | 21 +++++++++++++++++ src/shared/compatibility.js | 45 ------------------------------------- src/shared/util.js | 10 --------- 4 files changed, 30 insertions(+), 56 deletions(-) delete mode 100644 src/shared/compatibility.js diff --git a/gulpfile.mjs b/gulpfile.mjs index 160b1a953..5be216f8a 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -211,6 +211,14 @@ function createWebpackConfig( } const babelExcludeRegExp = new RegExp(`(${babelExcludes.join("|")})`); + const babelPresets = skipBabel + ? undefined + : [ + [ + "@babel/preset-env", + { corejs: "3.31.1", shippedProposals: true, useBuiltIns: "usage" }, + ], + ]; const babelPlugins = ["@babel/plugin-transform-modules-commonjs"]; const plugins = []; @@ -289,7 +297,7 @@ function createWebpackConfig( loader: "babel-loader", exclude: babelExcludeRegExp, options: { - presets: skipBabel ? undefined : ["@babel/preset-env"], + presets: babelPresets, plugins: babelPlugins, targets: BABEL_TARGETS, }, diff --git a/src/display/node_utils.js b/src/display/node_utils.js index e848ea543..e187c5aec 100644 --- a/src/display/node_utils.js +++ b/src/display/node_utils.js @@ -20,6 +20,7 @@ import { BaseFilterFactory, BaseStandardFontDataFactory, } from "./base_factory.js"; +import { isNodeJS } from "../shared/is_node.js"; if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { throw new Error( @@ -27,6 +28,26 @@ if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { ); } +if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("SKIP_BABEL")) { + (function checkDOMMatrix() { + if (globalThis.DOMMatrix || !isNodeJS) { + return; + } + globalThis.DOMMatrix = __non_webpack_require__("canvas").DOMMatrix; + })(); + + (function checkPath2D() { + if (globalThis.Path2D || !isNodeJS) { + return; + } + const { CanvasRenderingContext2D } = __non_webpack_require__("canvas"); + const { polyfillPath2D } = __non_webpack_require__("path2d-polyfill"); + + globalThis.CanvasRenderingContext2D = CanvasRenderingContext2D; + polyfillPath2D(globalThis); + })(); +} + const fetchData = function (url) { return new Promise((resolve, reject) => { const fs = __non_webpack_require__("fs"); diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js deleted file mode 100644 index 346024f77..000000000 --- a/src/shared/compatibility.js +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2017 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. - */ -/* globals __non_webpack_require__ */ - -import { isNodeJS } from "./is_node.js"; - -// Support: Node.js -(function checkDOMMatrix() { - if (globalThis.DOMMatrix || !isNodeJS) { - return; - } - globalThis.DOMMatrix = __non_webpack_require__("canvas").DOMMatrix; -})(); - -// Support: Node.js -(function checkPath2D() { - if (globalThis.Path2D || !isNodeJS) { - return; - } - const { CanvasRenderingContext2D } = __non_webpack_require__("canvas"); - const { polyfillPath2D } = __non_webpack_require__("path2d-polyfill"); - - globalThis.CanvasRenderingContext2D = CanvasRenderingContext2D; - polyfillPath2D(globalThis); -})(); - -// Support: Chrome<98 -(function checkStructuredClone() { - if (globalThis.structuredClone) { - return; - } - require("core-js/web/structured-clone.js"); -})(); diff --git a/src/shared/util.js b/src/shared/util.js index 70184dd8d..bbc692dd0 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -13,16 +13,6 @@ * limitations under the License. */ -// Skip compatibility checks for modern builds and if we already ran the module. -if ( - typeof PDFJSDev !== "undefined" && - !PDFJSDev.test("SKIP_BABEL") && - !globalThis._pdfjsCompatibilityChecked -) { - globalThis._pdfjsCompatibilityChecked = true; - require("./compatibility.js"); -} - const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; From 3a886e7264f15289e5cb391f3287c17fea5b3bb9 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Mon, 17 Jul 2023 16:33:06 +0200 Subject: [PATCH 2/2] Move the `isNodeJS`-helper into the `src/shared/util.js` file With the changes in the previous patch the `isNodeJS`-helper no longer needs to live in its own file, which helps get rid of a closure in the *built* files. --- src/core/worker.js | 2 +- src/display/api.js | 2 +- src/display/canvas.js | 2 +- src/display/font_loader.js | 2 +- src/display/node_utils.js | 2 +- src/display/svg.js | 2 +- src/shared/is_node.js | 28 --------------------------- src/shared/util.js | 13 +++++++++++++ test/unit/api_spec.js | 2 +- test/unit/clitests_helper.js | 7 +++++-- test/unit/display_svg_spec.js | 2 +- test/unit/display_utils_spec.js | 3 +-- test/unit/event_utils_spec.js | 2 +- test/unit/jasmine-boot.js | 2 +- test/unit/node_stream_spec.js | 3 +-- test/unit/pdf_find_controller_spec.js | 2 +- test/unit/test_utils.js | 2 +- test/unit/text_layer_spec.js | 2 +- test/unit/xfa_tohtml_spec.js | 2 +- 19 files changed, 34 insertions(+), 48 deletions(-) delete mode 100644 src/shared/is_node.js diff --git a/src/core/worker.js b/src/core/worker.js index 52479345d..7b04b8226 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -19,6 +19,7 @@ import { getVerbosityLevel, info, InvalidPDFException, + isNodeJS, MissingPDFException, PasswordException, PromiseCapability, @@ -39,7 +40,6 @@ import { LocalPdfManager, NetworkPdfManager } from "./pdf_manager.js"; import { AnnotationFactory } from "./annotation.js"; import { clearGlobalCaches } from "./cleanup_helper.js"; import { incrementalUpdate } from "./writer.js"; -import { isNodeJS } from "../shared/is_node.js"; import { MessageHandler } from "../shared/message_handler.js"; import { PDFWorkerStream } from "./worker_stream.js"; diff --git a/src/display/api.js b/src/display/api.js index 79e22de9e..d8dfd9886 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -25,6 +25,7 @@ import { info, InvalidPDFException, isArrayBuffer, + isNodeJS, MAX_IMAGE_SIZE_TO_CACHE, MissingPDFException, PasswordException, @@ -59,7 +60,6 @@ import { import { FontFaceObject, FontLoader } from "./font_loader.js"; import { CanvasGraphics } from "./canvas.js"; import { GlobalWorkerOptions } from "./worker_options.js"; -import { isNodeJS } from "../shared/is_node.js"; import { MessageHandler } from "../shared/message_handler.js"; import { Metadata } from "./metadata.js"; import { OptionalContentConfig } from "./optional_content_config.js"; diff --git a/src/display/canvas.js b/src/display/canvas.js index ba93deefc..1fbd6f28a 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -19,6 +19,7 @@ import { IDENTITY_MATRIX, ImageKind, info, + isNodeJS, OPS, shadow, TextRenderingMode, @@ -37,7 +38,6 @@ import { TilingPattern, } from "./pattern_helper.js"; import { convertBlackAndWhiteToRGBA } from "../shared/image_utils.js"; -import { isNodeJS } from "../shared/is_node.js"; // contexts store most of the state we need natively. // However, PDF needs a bit more state, which we store here. diff --git a/src/display/font_loader.js b/src/display/font_loader.js index 5df27c2b1..2beead5be 100644 --- a/src/display/font_loader.js +++ b/src/display/font_loader.js @@ -17,12 +17,12 @@ import { assert, bytesToString, FeatureTest, + isNodeJS, shadow, string32, unreachable, warn, } from "../shared/util.js"; -import { isNodeJS } from "../shared/is_node.js"; class FontLoader { #systemFonts = new Set(); diff --git a/src/display/node_utils.js b/src/display/node_utils.js index e187c5aec..bd1756aea 100644 --- a/src/display/node_utils.js +++ b/src/display/node_utils.js @@ -20,7 +20,7 @@ import { BaseFilterFactory, BaseStandardFontDataFactory, } from "./base_factory.js"; -import { isNodeJS } from "../shared/is_node.js"; +import { isNodeJS } from "../shared/util.js"; if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { throw new Error( diff --git a/src/display/svg.js b/src/display/svg.js index 97227be01..d0dfc0162 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -19,12 +19,12 @@ import { FONT_IDENTITY_MATRIX, IDENTITY_MATRIX, ImageKind, + isNodeJS, OPS, TextRenderingMode, Util, warn, } from "../shared/util.js"; -import { isNodeJS } from "../shared/is_node.js"; if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("GENERIC")) { throw new Error( diff --git a/src/shared/is_node.js b/src/shared/is_node.js deleted file mode 100644 index b8b142708..000000000 --- a/src/shared/is_node.js +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright 2018 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. - */ -/* globals process */ - -// NW.js / Electron is a browser context, but copies some Node.js objects; see -// http://docs.nwjs.io/en/latest/For%20Users/Advanced/JavaScript%20Contexts%20in%20NW.js/#access-nodejs-and-nwjs-api-in-browser-context -// https://www.electronjs.org/docs/api/process#processversionselectron-readonly -// https://www.electronjs.org/docs/api/process#processtype-readonly -const isNodeJS = - (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) && - typeof process === "object" && - process + "" === "[object process]" && - !process.versions.nw && - !(process.versions.electron && process.type && process.type !== "browser"); - -export { isNodeJS }; diff --git a/src/shared/util.js b/src/shared/util.js index bbc692dd0..d8759c579 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -12,6 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* globals process */ + +// NW.js / Electron is a browser context, but copies some Node.js objects; see +// http://docs.nwjs.io/en/latest/For%20Users/Advanced/JavaScript%20Contexts%20in%20NW.js/#access-nodejs-and-nwjs-api-in-browser-context +// https://www.electronjs.org/docs/api/process#processversionselectron-readonly +// https://www.electronjs.org/docs/api/process#processtype-readonly +const isNodeJS = + (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) && + typeof process === "object" && + process + "" === "[object process]" && + !process.versions.nw && + !(process.versions.electron && process.type && process.type !== "browser"); const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; @@ -1056,6 +1068,7 @@ export { InvalidPDFException, isArrayBuffer, isArrayEqual, + isNodeJS, LINE_DESCENT_FACTOR, LINE_FACTOR, MAX_IMAGE_SIZE_TO_CACHE, diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 5ea618544..3b42e32e1 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -19,6 +19,7 @@ import { AnnotationType, ImageKind, InvalidPDFException, + isNodeJS, MissingPDFException, objectSize, OPS, @@ -53,7 +54,6 @@ import { import { AutoPrintRegExp } from "../../web/ui_utils.js"; import { GlobalImageCache } from "../../src/core/image_utils.js"; import { GlobalWorkerOptions } from "../../src/display/worker_options.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; import { Metadata } from "../../src/display/metadata.js"; describe("api", function () { diff --git a/test/unit/clitests_helper.js b/test/unit/clitests_helper.js index 06b8568d3..d86eeacbb 100644 --- a/test/unit/clitests_helper.js +++ b/test/unit/clitests_helper.js @@ -13,8 +13,11 @@ * limitations under the License. */ -import { setVerbosityLevel, VerbosityLevel } from "../../src/shared/util.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { + isNodeJS, + setVerbosityLevel, + VerbosityLevel, +} from "../../src/shared/util.js"; // Sets longer timeout, similar to `jasmine-boot.js`. jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; diff --git a/test/unit/display_svg_spec.js b/test/unit/display_svg_spec.js index d612fc13f..f20c531e1 100644 --- a/test/unit/display_svg_spec.js +++ b/test/unit/display_svg_spec.js @@ -16,7 +16,7 @@ import { buildGetDocumentParams } from "./test_utils.js"; import { getDocument } from "../../src/display/api.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; import { SVGGraphics } from "../../src/display/svg.js"; const XLINK_NS = "http://www.w3.org/1999/xlink"; diff --git a/test/unit/display_utils_spec.js b/test/unit/display_utils_spec.js index d37399a32..374f4b24f 100644 --- a/test/unit/display_utils_spec.js +++ b/test/unit/display_utils_spec.js @@ -13,6 +13,7 @@ * limitations under the License. */ +import { bytesToString, isNodeJS } from "../../src/shared/util.js"; import { DOMCanvasFactory, DOMSVGFactory, @@ -21,8 +22,6 @@ import { isValidFetchUrl, PDFDateString, } from "../../src/display/display_utils.js"; -import { bytesToString } from "../../src/shared/util.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; describe("display_utils", function () { describe("DOMCanvasFactory", function () { diff --git a/test/unit/event_utils_spec.js b/test/unit/event_utils_spec.js index 50c7e8b5b..2bb1ff822 100644 --- a/test/unit/event_utils_spec.js +++ b/test/unit/event_utils_spec.js @@ -18,7 +18,7 @@ import { waitOnEventOrTimeout, WaitOnType, } from "../../web/event_utils.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; describe("event_utils", function () { describe("EventBus", function () { diff --git a/test/unit/jasmine-boot.js b/test/unit/jasmine-boot.js index c1c1fcefd..27ebf7a8a 100644 --- a/test/unit/jasmine-boot.js +++ b/test/unit/jasmine-boot.js @@ -41,7 +41,7 @@ "use strict"; import { GlobalWorkerOptions } from "pdfjs/display/worker_options.js"; -import { isNodeJS } from "pdfjs/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; import { TestReporter } from "./testreporter.js"; async function initializePDFJS(callback) { diff --git a/test/unit/node_stream_spec.js b/test/unit/node_stream_spec.js index 9f6119210..e70ff4b2b 100644 --- a/test/unit/node_stream_spec.js +++ b/test/unit/node_stream_spec.js @@ -14,8 +14,7 @@ */ /* globals __non_webpack_require__ */ -import { AbortException } from "../../src/shared/util.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { AbortException, isNodeJS } from "../../src/shared/util.js"; import { PDFNodeStream } from "../../src/display/node_stream.js"; // Ensure that these tests only run in Node.js environments. diff --git a/test/unit/pdf_find_controller_spec.js b/test/unit/pdf_find_controller_spec.js index c0100bd8b..6201c757f 100644 --- a/test/unit/pdf_find_controller_spec.js +++ b/test/unit/pdf_find_controller_spec.js @@ -17,7 +17,7 @@ import { FindState, PDFFindController } from "../../web/pdf_find_controller.js"; import { buildGetDocumentParams } from "./test_utils.js"; import { EventBus } from "../../web/event_utils.js"; import { getDocument } from "../../src/display/api.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; import { SimpleLinkService } from "../../web/pdf_link_service.js"; const tracemonkeyFileName = "tracemonkey.pdf"; diff --git a/test/unit/test_utils.js b/test/unit/test_utils.js index aa7af93af..16db2f28c 100644 --- a/test/unit/test_utils.js +++ b/test/unit/test_utils.js @@ -15,7 +15,7 @@ import { NullStream, StringStream } from "../../src/core/stream.js"; import { Page, PDFDocument } from "../../src/core/document.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; import { Ref } from "../../src/core/primitives.js"; const TEST_PDFS_PATH = isNodeJS ? "./test/pdfs/" : "../pdfs/"; diff --git a/test/unit/text_layer_spec.js b/test/unit/text_layer_spec.js index 0cc06ae0e..ca4a400e9 100644 --- a/test/unit/text_layer_spec.js +++ b/test/unit/text_layer_spec.js @@ -19,7 +19,7 @@ import { } from "../../src/display/text_layer.js"; import { buildGetDocumentParams } from "./test_utils.js"; import { getDocument } from "../../src/display/api.js"; -import { isNodeJS } from "../../src/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; describe("textLayer", function () { it("creates textLayer from ReadableStream", async function () { diff --git a/test/unit/xfa_tohtml_spec.js b/test/unit/xfa_tohtml_spec.js index 2d9c1bb77..36372e693 100644 --- a/test/unit/xfa_tohtml_spec.js +++ b/test/unit/xfa_tohtml_spec.js @@ -13,7 +13,7 @@ * limitations under the License. */ -import { isNodeJS } from "../../src/shared/is_node.js"; +import { isNodeJS } from "../../src/shared/util.js"; import { XFAFactory } from "../../src/core/xfa/factory.js"; describe("XFAFactory", function () {