From 8bd3cc031359eab0ec175f677bfc62a1a9886f2f Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 7 Oct 2023 16:30:27 +0200 Subject: [PATCH] [api-minor] Stop polyfilling `structuredClone` in legacy builds Comparing the currently supported browsers/environments, see [the FAQ](https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#faq-support) and the [MDN compatibility data](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone#browser_compatibility), the `structuredClone` polyfill is *only* needed in Google Chrome versions < 98. Because of some limitations in the core-js polyfill we're currently forced to special-case the `transfer` handling to prevent bugs, and it'd be nice to avoid that. Note that `structuredClone`, with transfers, is only used in two spots: - The `LoopbackPort` class, which is only used with fake workers. Given that fake workers should *never* be used in browsers, breaking that edge-case in older Google Chrome versions seem fine. - The `AnnotationStorage` class, when Stamp-annotations have been added to the document. Given that Google Chrome isn't the main focus of development, breaking *part* of the editing-functionality in older Google Chrome versions should hopefully be acceptable. --- gulpfile.mjs | 7 ++++++- src/display/annotation_storage.js | 22 ++++++++-------------- src/display/api.js | 17 +++++------------ 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/gulpfile.mjs b/gulpfile.mjs index c4314bbf3..bf589fbc3 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -214,7 +214,12 @@ function createWebpackConfig( : [ [ "@babel/preset-env", - { corejs: "3.32.2", shippedProposals: true, useBuiltIns: "usage" }, + { + corejs: "3.32.2", + exclude: ["web.structured-clone"], + shippedProposals: true, + useBuiltIns: "usage", + }, ], ]; const babelPlugins = isModule diff --git a/src/display/annotation_storage.js b/src/display/annotation_storage.js index 05d19d804..e2a80b230 100644 --- a/src/display/annotation_storage.js +++ b/src/display/annotation_storage.js @@ -20,7 +20,7 @@ import { MurmurHash3_64 } from "../shared/murmurhash3.js"; const SerializableEmpty = Object.freeze({ map: null, hash: "", - transfers: undefined, + transfer: undefined, }); /** @@ -181,7 +181,7 @@ class AnnotationStorage { } const map = new Map(), hash = new MurmurHash3_64(), - transfers = []; + transfer = []; const context = Object.create(null); let hasBitmap = false; @@ -203,13 +203,13 @@ class AnnotationStorage { // during serialization with SVG images. for (const value of map.values()) { if (value.bitmap) { - transfers.push(value.bitmap); + transfer.push(value.bitmap); } } } return map.size > 0 - ? { map, hash: hash.hexdigest(), transfers } + ? { map, hash: hash.hexdigest(), transfer } : SerializableEmpty; } } @@ -224,17 +224,11 @@ class PrintAnnotationStorage extends AnnotationStorage { constructor(parent) { super(); - const { map, hash, transfers } = parent.serializable; + const { map, hash, transfer } = parent.serializable; // Create a *copy* of the data, since Objects are passed by reference in JS. - const clone = structuredClone( - map, - (typeof PDFJSDev === "undefined" || - PDFJSDev.test("SKIP_BABEL || TESTING")) && - transfers - ? { transfer: transfers } - : null - ); - this.#serializable = { map: clone, hash, transfers }; + const clone = structuredClone(map, transfer ? { transfer } : null); + + this.#serializable = { map: clone, hash, transfer }; } /** diff --git a/src/display/api.js b/src/display/api.js index 2d3837b25..e5ed6addb 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1802,7 +1802,7 @@ class PDFPageProxy { '_pumpOperatorList: Expected valid "renderingIntent" argument.' ); } - const { map, transfers } = annotationStorageSerializable; + const { map, transfer } = annotationStorageSerializable; const readableStream = this._transport.messageHandler.sendWithStream( "GetOperatorList", @@ -1812,7 +1812,7 @@ class PDFPageProxy { cacheKey, annotationStorage: map, }, - transfers + transfer ); const reader = readableStream.getReader(); @@ -1942,14 +1942,7 @@ class LoopbackPort { postMessage(obj, transfer) { const event = { - data: structuredClone( - obj, - (typeof PDFJSDev === "undefined" || - PDFJSDev.test("SKIP_BABEL || TESTING")) && - transfer - ? { transfer } - : null - ), + data: structuredClone(obj, transfer ? { transfer } : null), }; this.#deferred.then(() => { @@ -2853,7 +2846,7 @@ class WorkerTransport { "please use the getData-method instead." ); } - const { map, transfers } = this.annotationStorage.serializable; + const { map, transfer } = this.annotationStorage.serializable; return this.messageHandler .sendWithPromise( @@ -2864,7 +2857,7 @@ class WorkerTransport { annotationStorage: map, filename: this._fullReader?.filename ?? null, }, - transfers + transfer ) .finally(() => { this.annotationStorage.resetModified();