From 2fcd07f4008fc87ed29b25adb6e7423cfeb102a6 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 18 Jan 2022 12:23:22 +0100 Subject: [PATCH 1/3] Update Puppeteer to version `13.1.2` Note in particular https://github.com/puppeteer/puppeteer/releases/tag/v13.1.0 which includes an update to Chromium 98, which adds support for `structuredClone` in the browser. --- package-lock.json | 54 +++++++++++++++++++++++++++-------------------- package.json | 2 +- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7e389fae..41bece0bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "postcss": "^8.4.5", "postcss-calc": "^8.2.2", "prettier": "^2.5.1", - "puppeteer": "^13.0.1", + "puppeteer": "^13.1.2", "rimraf": "^3.0.2", "streamqueue": "^1.1.2", "stylelint": "^14.2.0", @@ -4259,9 +4259,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.937139", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.937139.tgz", - "integrity": "sha512-daj+rzR3QSxsPRy5vjjthn58axO8c11j58uY0lG5vvlJk/EiOdCWOptGdkXDjtuRHr78emKq0udHCXM4trhoDQ==", + "version": "0.0.948846", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.948846.tgz", + "integrity": "sha512-5fGyt9xmMqUl2VI7+rnUkKCiAQIpLns8sfQtTENy5L70ktbNw0Z3TFJ1JoFNYdx/jffz4YXU45VF75wKZD7sZQ==", "dev": true }, "node_modules/diagnostics": { @@ -9603,15 +9603,23 @@ "dev": true }, "node_modules/node-fetch": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", - "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-releases": { @@ -15225,17 +15233,17 @@ } }, "node_modules/puppeteer": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.0.1.tgz", - "integrity": "sha512-wqGIx59LzYqWhYcJQphMT+ux0sgatEUbjKG0lbjJxNVqVIT3ZC5m4Bvmq2gHE3qhb63EwS+rNkql08bm4BvO0A==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.1.2.tgz", + "integrity": "sha512-ozVM8Tdg0patMtm/xAr3Uh7rQ28vBpbTHLP+ECmoAxG/s4PKrVLN764H/poLux7Ln77jHThOd8OBJj5mTuA6Iw==", "dev": true, "hasInstallScript": true, "dependencies": { "debug": "4.3.2", - "devtools-protocol": "0.0.937139", + "devtools-protocol": "0.0.948846", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", - "node-fetch": "2.6.5", + "node-fetch": "2.6.7", "pkg-dir": "4.2.0", "progress": "2.0.3", "proxy-from-env": "1.1.0", @@ -21816,9 +21824,9 @@ "dev": true }, "devtools-protocol": { - "version": "0.0.937139", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.937139.tgz", - "integrity": "sha512-daj+rzR3QSxsPRy5vjjthn58axO8c11j58uY0lG5vvlJk/EiOdCWOptGdkXDjtuRHr78emKq0udHCXM4trhoDQ==", + "version": "0.0.948846", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.948846.tgz", + "integrity": "sha512-5fGyt9xmMqUl2VI7+rnUkKCiAQIpLns8sfQtTENy5L70ktbNw0Z3TFJ1JoFNYdx/jffz4YXU45VF75wKZD7sZQ==", "dev": true }, "diagnostics": { @@ -26043,9 +26051,9 @@ "dev": true }, "node-fetch": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", - "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dev": true, "requires": { "whatwg-url": "^5.0.0" @@ -30352,16 +30360,16 @@ "dev": true }, "puppeteer": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.0.1.tgz", - "integrity": "sha512-wqGIx59LzYqWhYcJQphMT+ux0sgatEUbjKG0lbjJxNVqVIT3ZC5m4Bvmq2gHE3qhb63EwS+rNkql08bm4BvO0A==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.1.2.tgz", + "integrity": "sha512-ozVM8Tdg0patMtm/xAr3Uh7rQ28vBpbTHLP+ECmoAxG/s4PKrVLN764H/poLux7Ln77jHThOd8OBJj5mTuA6Iw==", "dev": true, "requires": { "debug": "4.3.2", - "devtools-protocol": "0.0.937139", + "devtools-protocol": "0.0.948846", "extract-zip": "2.0.1", "https-proxy-agent": "5.0.0", - "node-fetch": "2.6.5", + "node-fetch": "2.6.7", "pkg-dir": "4.2.0", "progress": "2.0.3", "proxy-from-env": "1.1.0", diff --git a/package.json b/package.json index 33e6960c0..d41ac12fb 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "postcss": "^8.4.5", "postcss-calc": "^8.2.2", "prettier": "^2.5.1", - "puppeteer": "^13.0.1", + "puppeteer": "^13.1.2", "rimraf": "^3.0.2", "streamqueue": "^1.1.2", "stylelint": "^14.2.0", From 7cc761a8c0ff12217ff8478bdb5a2fce3a07833a Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 18 Jan 2022 13:07:39 +0100 Subject: [PATCH 2/3] Polyfill `structuredClone` with core-js (PR 13948 follow-up) This allows us to remove the manually implemented `structuredClone` polyfill, thus reducing the maintenance burden for the `LoopbackPort` class; refer to https://github.com/zloirock/core-js#structuredclone *Please note:* While `structuredClone` support landed already in Firefox 94, Google Chrome only added it in version 98 (currently in Beta). However, given that the `LoopbackPort` will only be used together with *fake workers* in browsers this shouldn't be too much of a problem.[1] For Node.js environments, where *fake workers* are unfortunately necessary, using a `legacy/`-build is already required which thus guarantees that the `structuredClone` polyfill is available. Also, the patch updates core-js to the latest version since that one includes `structuredClone` improvements; please see https://github.com/zloirock/core-js/releases/tag/v3.20.3 --- [1] Given that we only support browsers with proper worker support, if *fake workers* are being used that essentially indicates a configuration problem/error. --- .eslintrc | 1 + package-lock.json | 36 +++++++++----- package.json | 2 +- src/display/api.js | 93 ++++--------------------------------- src/shared/compatibility.js | 13 ++++++ 5 files changed, 47 insertions(+), 98 deletions(-) diff --git a/.eslintrc b/.eslintrc index 22ade7ddb..acd6331c5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -28,6 +28,7 @@ "globals": { "PDFJSDev": false, "exports": false, + "structuredClone": false, "SystemJS": false, }, diff --git a/package-lock.json b/package-lock.json index 41bece0bf..12632b8d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "autoprefixer": "^10.4.2", "babel-loader": "^8.2.3", "canvas": "^2.9.0", - "core-js": "^3.20.2", + "core-js": "^3.20.3", "cross-env": "^7.0.3", "dommatrix": "^0.0.24", "es-module-shims": "^1.4.1", @@ -3899,9 +3899,9 @@ } }, "node_modules/core-js": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.2.tgz", - "integrity": "sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw==", + "version": "3.20.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz", + "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==", "dev": true, "hasInstallScript": true, "funding": { @@ -12106,6 +12106,7 @@ }, "node_modules/npm/node_modules/lodash._baseindexof": { "version": "3.1.0", + "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -12121,16 +12122,19 @@ }, "node_modules/npm/node_modules/lodash._bindcallback": { "version": "3.0.1", + "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._cacheindexof": { "version": "3.0.2", + "extraneous": true, "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/lodash._createcache": { "version": "3.1.2", + "extraneous": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -12145,6 +12149,7 @@ }, "node_modules/npm/node_modules/lodash._getnative": { "version": "3.9.1", + "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -12162,6 +12167,7 @@ }, "node_modules/npm/node_modules/lodash.restparam": { "version": "3.6.1", + "extraneous": true, "inBundle": true, "license": "MIT" }, @@ -21554,9 +21560,9 @@ } }, "core-js": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.2.tgz", - "integrity": "sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw==", + "version": "3.20.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz", + "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==", "dev": true }, "core-js-compat": { @@ -27927,7 +27933,8 @@ }, "lodash._baseindexof": { "version": "3.1.0", - "bundled": true + "bundled": true, + "extraneous": true }, "lodash._baseuniq": { "version": "4.6.0", @@ -27940,15 +27947,18 @@ }, "lodash._bindcallback": { "version": "3.0.1", - "bundled": true + "bundled": true, + "extraneous": true }, "lodash._cacheindexof": { "version": "3.0.2", - "bundled": true + "bundled": true, + "extraneous": true }, "lodash._createcache": { "version": "3.1.2", "bundled": true, + "extraneous": true, "requires": { "lodash._getnative": "^3.0.0" } @@ -27960,7 +27970,8 @@ }, "lodash._getnative": { "version": "3.9.1", - "bundled": true + "bundled": true, + "extraneous": true }, "lodash._root": { "version": "3.0.1", @@ -27974,7 +27985,8 @@ }, "lodash.restparam": { "version": "3.6.1", - "bundled": true + "bundled": true, + "extraneous": true }, "lodash.union": { "version": "4.6.0", diff --git a/package.json b/package.json index d41ac12fb..ae431a577 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "autoprefixer": "^10.4.2", "babel-loader": "^8.2.3", "canvas": "^2.9.0", - "core-js": "^3.20.2", + "core-js": "^3.20.3", "cross-env": "^7.0.3", "dommatrix": "^0.0.24", "es-module-shims": "^1.4.1", diff --git a/src/display/api.js b/src/display/api.js index beb6ba9f2..67b3dd178 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1913,91 +1913,14 @@ class LoopbackPort { } postMessage(obj, transfers) { - function cloneValue(object) { - if ( - (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) || - globalThis.structuredClone - ) { - return globalThis.structuredClone(object, transfers); - } - - // Trying to perform a structured clone close to the spec, including - // transfers. - function fallbackCloneValue(value) { - if ( - typeof value === "function" || - typeof value === "symbol" || - value instanceof URL - ) { - throw new Error( - `LoopbackPort.postMessage - cannot clone: ${value?.toString()}` - ); - } - - if (typeof value !== "object" || value === null) { - return value; - } - if (cloned.has(value)) { - // already cloned the object - return cloned.get(value); - } - let buffer, result; - if ((buffer = value.buffer) && isArrayBuffer(buffer)) { - // We found object with ArrayBuffer (typed array). - if (transfers?.includes(buffer)) { - result = new value.constructor( - buffer, - value.byteOffset, - value.byteLength - ); - } else { - result = new value.constructor(value); - } - cloned.set(value, result); - return result; - } - if (value instanceof Map) { - result = new Map(); - cloned.set(value, result); // Adding to cache now for cyclic references. - for (const [key, val] of value) { - result.set(key, fallbackCloneValue(val)); - } - return result; - } - if (value instanceof Set) { - result = new Set(); - cloned.set(value, result); // Adding to cache now for cyclic references. - for (const val of value) { - result.add(fallbackCloneValue(val)); - } - return result; - } - result = Array.isArray(value) ? [] : Object.create(null); - cloned.set(value, result); // Adding to cache now for cyclic references. - // Cloning all value and object properties, however ignoring properties - // defined via getter. - for (const i in value) { - let desc, - p = value; - while (!(desc = Object.getOwnPropertyDescriptor(p, i))) { - p = Object.getPrototypeOf(p); - } - if (typeof desc.value === "undefined") { - continue; - } - if (typeof desc.value === "function" && !value.hasOwnProperty?.(i)) { - continue; - } - result[i] = fallbackCloneValue(desc.value); - } - return result; - } - - const cloned = new WeakMap(); - return fallbackCloneValue(object); - } - - const event = { data: cloneValue(obj) }; + const event = { + data: + typeof PDFJSDev === "undefined" || + PDFJSDev.test("SKIP_BABEL") || + transfers + ? structuredClone(obj, transfers) + : structuredClone(obj), + }; this._deferred.then(() => { for (const listener of this._listeners) { diff --git a/src/shared/compatibility.js b/src/shared/compatibility.js index f418f8f1e..3eed8a577 100644 --- a/src/shared/compatibility.js +++ b/src/shared/compatibility.js @@ -100,4 +100,17 @@ if ( globalThis.ReadableStream = require("web-streams-polyfill/dist/ponyfill.js").ReadableStream; })(); + + // Support: Firefox<94, Chrome<98, Safari, Node.js<17.0.0 + (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; + } + require("core-js/web/structured-clone.js"); + })(); } From d476186b9f8bd7178e2eb2436d1e6456f63eea72 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Wed, 19 Jan 2022 12:02:05 +0100 Subject: [PATCH 3/3] Temporarily disable the browser-tests in Google Chrome on the Windows bot Either the latest Chromium update, the latest Puppeteer update, or a combination of them both are now causing the Windows bot to timeout during the browser-tests. To unblock both the updates and other improvements (i.e. the `structuredClone` polyfill), let's simply disable the problematic configuration for now since this a Mozilla project after all. --- gulpfile.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index b0f38b90d..2f6b96154 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -555,11 +555,19 @@ function createTestSource(testsName, { bot = false, xfaOnly = false } = {}) { console.log("### Running " + testsName + " tests"); const PDF_TEST = process.env.PDF_TEST || "test_manifest.json"; + let forceNoChrome = false; const args = ["test.js"]; switch (testsName) { case "browser": if (!bot) { args.push("--reftest"); + } else { + const os = process.env.OS; + if (/windows/i.test(os)) { + // The browser-tests are too slow in Google Chrome on the Windows + // bot, causing a timeout, hence disabling them for now. + forceNoChrome = true; + } } if (xfaOnly) { args.push("--xfaOnly"); @@ -582,7 +590,7 @@ function createTestSource(testsName, { bot = false, xfaOnly = false } = {}) { if (bot) { args.push("--strictVerify"); } - if (process.argv.includes("--noChrome")) { + if (process.argv.includes("--noChrome") || forceNoChrome) { args.push("--noChrome"); }