From ed8be6f88243056830f6f8e797cde25c11cadc90 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Wed, 5 Apr 2023 10:40:19 +0200 Subject: [PATCH 1/4] [api-minor] Update the minimum supported Node.js version to 18 This patch updates the minimum supported environments as follows: - Node.js 18, which was released on 2022-04-19; see https://en.wikipedia.org/wiki/Node.js#Releases Note also that Node.js 16 will soon reach EOL, and thus no longer receive any security updates. --- gulpfile.js | 5 ++--- package-lock.json | 18 +----------------- package.json | 3 +-- src/core/worker.js | 8 ++------ src/shared/compatibility.js | 16 +++------------- 5 files changed, 9 insertions(+), 41 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index c7863c0753c58..4d574269fa86f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -80,7 +80,7 @@ const ENV_TARGETS = [ "Chrome >= 88", "Firefox ESR", "Safari >= 14.1", - "Node >= 16", + "Node >= 18", "> 1%", "not IE > 0", "not dead", @@ -2168,7 +2168,6 @@ function packageJson() { }, dependencies: { "path2d-polyfill": "^2.0.1", - "web-streams-polyfill": "^3.2.1", }, browser: { canvas: false, @@ -2184,7 +2183,7 @@ function packageJson() { url: DIST_REPO_URL, }, engines: { - node: ">=16", + node: ">=18", }, }; diff --git a/package-lock.json b/package-lock.json index 1feb190a257fc..1c5469733f3de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,14 +62,13 @@ "typogr": "^0.6.8", "vinyl": "^3.0.0", "vinyl-fs": "^3.0.3", - "web-streams-polyfill": "^3.2.1", "webpack": "^5.80.0", "webpack-stream": "^7.0.0", "wintersmith": "^2.5.0", "yargs": "^17.7.1" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@ampproject/remapping": { @@ -18622,15 +18621,6 @@ "node": ">=10.13.0" } }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -33566,12 +33556,6 @@ "graceful-fs": "^4.1.2" } }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true - }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index cdb42c66fa21d..c3fd6999d2056 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "typogr": "^0.6.8", "vinyl": "^3.0.0", "vinyl-fs": "^3.0.3", - "web-streams-polyfill": "^3.2.1", "webpack": "^5.80.0", "webpack-stream": "^7.0.0", "wintersmith": "^2.5.0", @@ -69,7 +68,7 @@ "url": "git://github.com/mozilla/pdf.js.git" }, "engines": { - "node": ">=16" + "node": ">=18" }, "license": "Apache-2.0" } diff --git a/src/core/worker.js b/src/core/worker.js index 14f5a576a3bb2..b5b2f5059b504 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -133,14 +133,10 @@ class WorkerMessageHandler { // Ensure that (primarily) Node.js users won't accidentally attempt to use // a non-translated/non-polyfilled build of the library, since that would // quickly fail anyway because of missing functionality. - if ( - (isNodeJS && typeof Path2D === "undefined") || - typeof ReadableStream === "undefined" - ) { + if (isNodeJS && typeof Path2D === "undefined") { const partialMsg = "The browser/environment lacks native support for critical " + - "functionality used by the PDF.js library " + - "(e.g. `Path2D` and/or `ReadableStream`); "; + "functionality used by the PDF.js library (e.g. `Path2D`); "; if (isNodeJS) { throw new Error(partialMsg + "please use a `legacy`-build instead."); diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js index 8375e62a78bf8..35a42ab4bac1c 100644 --- a/src/shared/compatibility.js +++ b/src/shared/compatibility.js @@ -36,17 +36,7 @@ import { isNodeJS } from "./is_node.js"; polyfillPath2D(globalThis); })(); -// Support: Node.js<18.0.0 -(function checkReadableStream() { - if (globalThis.ReadableStream || !isNodeJS) { - return; - } - globalThis.ReadableStream = __non_webpack_require__( - "web-streams-polyfill/dist/ponyfill.js" - ).ReadableStream; -})(); - -// Support: Firefox<90, Chrome<92, Safari<15.4, Node.js<16.6.0 +// Support: Chrome<92, Safari<15.4 (function checkArrayAt() { if (Array.prototype.at) { return; @@ -54,7 +44,7 @@ import { isNodeJS } from "./is_node.js"; require("core-js/es/array/at.js"); })(); -// Support: Firefox<90, Chrome<92, Safari<15.4, Node.js<16.6.0 +// Support: Chrome<92, Safari<15.4 (function checkTypedArrayAt() { if (Uint8Array.prototype.at) { return; @@ -62,7 +52,7 @@ import { isNodeJS } from "./is_node.js"; require("core-js/es/typed-array/at.js"); })(); -// Support: Firefox<94, Chrome<98, Safari<15.4, Node.js<17.0.0 +// Support: Chrome<98, Safari<15.4 (function checkStructuredClone() { if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("IMAGE_DECODERS")) { // The current image decoders are synchronous, hence `structuredClone` From 1753e321cd1b62198925741ba902e8e92de19e6c Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 14 Apr 2023 21:32:09 +0200 Subject: [PATCH 2/4] Remove the compatibility checks in `WorkerMessageHandler.createDocumentHandler` For some time these checks have only targeted Node.js environments, since the features in question exist in all supported browsers (even when a `legacy`-build is used). Now that we've updated the minimum supported Node.js version to 18, a number of polyfills are thus (finally) no longer necessary in that environment. Hence for certain *basic* functionality, such as e.g. text-extraction, it's now possible to use either a modern- or a `legacy`-build of the PDF.js library in Node.js environments. *Please note:* For e.g. canvas-rendering in Node.js environments it's still necessary to use a `legacy`-build, since that functionality requires various polyfills. --- gulpfile.js | 2 -- src/core/worker.js | 14 -------------- 2 files changed, 16 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 4d574269fa86f..a25dd399cdb19 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2165,8 +2165,6 @@ function packageJson() { license: DIST_LICENSE, optionalDependencies: { canvas: "^2.11.2", - }, - dependencies: { "path2d-polyfill": "^2.0.1", }, browser: { diff --git a/src/core/worker.js b/src/core/worker.js index b5b2f5059b504..d4b02815660a1 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -129,20 +129,6 @@ class WorkerMessageHandler { "; thus breaking e.g. `for...in` iteration of `Array`s." ); } - - // Ensure that (primarily) Node.js users won't accidentally attempt to use - // a non-translated/non-polyfilled build of the library, since that would - // quickly fail anyway because of missing functionality. - if (isNodeJS && typeof Path2D === "undefined") { - const partialMsg = - "The browser/environment lacks native support for critical " + - "functionality used by the PDF.js library (e.g. `Path2D`); "; - - if (isNodeJS) { - throw new Error(partialMsg + "please use a `legacy`-build instead."); - } - throw new Error(partialMsg + "please update to a supported browser."); - } } const workerHandlerName = docId + "_worker"; let handler = new MessageHandler(workerHandlerName, docId, port); From f79f48c2b43688f284425887b492a9bc42c3d185 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 15 Apr 2023 17:01:03 +0200 Subject: [PATCH 3/4] Remove the IMAGE_DECODERS special-case when polyfilling `structuredClone` Originally we only used the `structuredClone` polyfill in the `LoopbackPort`-implementation, and that obviously isn't used anywhere within the various image decoders. At this point in time we've started to use `structuredClone` a little bit more, hence it seems overall simpler to just bundle the polyfill even in the `legacy`-version of the IMAGE_DECODERS built-target. --- src/shared/compatibility.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js index 35a42ab4bac1c..cf623e0c55f5c 100644 --- a/src/shared/compatibility.js +++ b/src/shared/compatibility.js @@ -54,11 +54,6 @@ import { isNodeJS } from "./is_node.js"; // Support: Chrome<98, Safari<15.4 (function checkStructuredClone() { - if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("IMAGE_DECODERS")) { - // The current image decoders are synchronous, hence `structuredClone` - // shouldn't need to be polyfilled for the IMAGE_DECODERS build target. - return; - } if (globalThis.structuredClone) { return; } From dcd55a71647d9cfc4914a55a27c7df450f78c1b7 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 25 Apr 2023 17:19:59 +0200 Subject: [PATCH 4/4] Enable `unicorn/prefer-at` unconditionally (PR 15014 follow-up) Now that Node.js version 18 is required, we should be able to use `Array.prototype.at()` everywhere in the code-base. --- external/.eslintrc | 4 ---- external/builder/builder.js | 2 +- external/builder/preprocessor2.js | 4 ++-- external/cmapscompress/compress.js | 2 +- external/cmapscompress/optimize.js | 5 +---- test/test.js | 6 ++---- 6 files changed, 7 insertions(+), 16 deletions(-) diff --git a/external/.eslintrc b/external/.eslintrc index 0eb7db3175cb4..e3523dce526ed 100644 --- a/external/.eslintrc +++ b/external/.eslintrc @@ -6,8 +6,4 @@ "env": { "node": true, }, - - "rules": { - "unicorn/prefer-at": "off", - }, } diff --git a/external/builder/builder.js b/external/builder/builder.js index 5eb9d70bb08fd..cb56978d9b7f0 100644 --- a/external/builder/builder.js +++ b/external/builder/builder.js @@ -72,7 +72,7 @@ function preprocess(inFilename, outFilename, defines) { ? outFilename : function (line) { if (!line || AllWhitespaceRegexp.test(line)) { - const prevLine = out[out.length - 1]; + const prevLine = out.at(-1); if (!prevLine || AllWhitespaceRegexp.test(prevLine)) { return; // Avoid adding consecutive blank lines. } diff --git a/external/builder/preprocessor2.js b/external/builder/preprocessor2.js index 58177d09b9abc..8833cf323a5fd 100644 --- a/external/builder/preprocessor2.js +++ b/external/builder/preprocessor2.js @@ -244,8 +244,8 @@ function postprocessNode(ctx, node) { const block = node.body; if ( block.body.length > 0 && - block.body[block.body.length - 1].type === "ReturnStatement" && - !block.body[block.body.length - 1].argument + block.body.at(-1).type === "ReturnStatement" && + !block.body.at(-1).argument ) { // Function body ends with return without arg -- removing it. block.body.pop(); diff --git a/external/cmapscompress/compress.js b/external/cmapscompress/compress.js index 2fe83e0780c75..a0bf221bf243c 100644 --- a/external/cmapscompress/compress.js +++ b/external/cmapscompress/compress.js @@ -215,7 +215,7 @@ function parseCMap(binaryData) { }, readHexSigned(size) { const num = this.readHexNumber(size); - const sign = fromHexDigit(num[num.length - 1]) & 1 ? 15 : 0; + const sign = fromHexDigit(num.at(-1)) & 1 ? 15 : 0; let c = 0; let result = ""; for (const digit of num) { diff --git a/external/cmapscompress/optimize.js b/external/cmapscompress/optimize.js index 69840af7d2963..75716059ccdf5 100644 --- a/external/cmapscompress/optimize.js +++ b/external/cmapscompress/optimize.js @@ -151,10 +151,7 @@ exports.optimizeCMap = function (data) { const maxDistance = 100, minItems = 10, itemsPerBucket = 50; - if ( - subitems.length > minItems && - codes[codes.length - 1] - codes[0] > maxDistance - ) { + if (subitems.length > minItems && codes.at(-1) - codes[0] > maxDistance) { const gapsCount = Math.max(2, (subitems.length / itemsPerBucket) | 0); const gaps = []; for (let q = 0; q < gapsCount; q++) { diff --git a/test/test.js b/test/test.js index 4eae960f8865b..504c98e12ad01 100644 --- a/test/test.js +++ b/test/test.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* eslint-disable no-var, unicorn/prefer-at */ +/* eslint-disable no-var */ "use strict"; @@ -750,9 +750,7 @@ function refTestPostHandler(req, res) { }); } - var isDone = - taskResults[taskResults.length - 1] && - taskResults[taskResults.length - 1][lastPageNum - 1]; + var isDone = taskResults.at(-1) && taskResults.at(-1)[lastPageNum - 1]; if (isDone) { checkRefTestResults(browser, id, taskResults); session.remaining--;