[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.
This commit is contained in:
Jonas Jenwald 2023-10-07 16:30:27 +02:00
parent e6c3257175
commit 8bd3cc0313
3 changed files with 19 additions and 27 deletions

View File

@ -214,7 +214,12 @@ function createWebpackConfig(
: [ : [
[ [
"@babel/preset-env", "@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 const babelPlugins = isModule

View File

@ -20,7 +20,7 @@ import { MurmurHash3_64 } from "../shared/murmurhash3.js";
const SerializableEmpty = Object.freeze({ const SerializableEmpty = Object.freeze({
map: null, map: null,
hash: "", hash: "",
transfers: undefined, transfer: undefined,
}); });
/** /**
@ -181,7 +181,7 @@ class AnnotationStorage {
} }
const map = new Map(), const map = new Map(),
hash = new MurmurHash3_64(), hash = new MurmurHash3_64(),
transfers = []; transfer = [];
const context = Object.create(null); const context = Object.create(null);
let hasBitmap = false; let hasBitmap = false;
@ -203,13 +203,13 @@ class AnnotationStorage {
// during serialization with SVG images. // during serialization with SVG images.
for (const value of map.values()) { for (const value of map.values()) {
if (value.bitmap) { if (value.bitmap) {
transfers.push(value.bitmap); transfer.push(value.bitmap);
} }
} }
} }
return map.size > 0 return map.size > 0
? { map, hash: hash.hexdigest(), transfers } ? { map, hash: hash.hexdigest(), transfer }
: SerializableEmpty; : SerializableEmpty;
} }
} }
@ -224,17 +224,11 @@ class PrintAnnotationStorage extends AnnotationStorage {
constructor(parent) { constructor(parent) {
super(); 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. // Create a *copy* of the data, since Objects are passed by reference in JS.
const clone = structuredClone( const clone = structuredClone(map, transfer ? { transfer } : null);
map,
(typeof PDFJSDev === "undefined" || this.#serializable = { map: clone, hash, transfer };
PDFJSDev.test("SKIP_BABEL || TESTING")) &&
transfers
? { transfer: transfers }
: null
);
this.#serializable = { map: clone, hash, transfers };
} }
/** /**

View File

@ -1802,7 +1802,7 @@ class PDFPageProxy {
'_pumpOperatorList: Expected valid "renderingIntent" argument.' '_pumpOperatorList: Expected valid "renderingIntent" argument.'
); );
} }
const { map, transfers } = annotationStorageSerializable; const { map, transfer } = annotationStorageSerializable;
const readableStream = this._transport.messageHandler.sendWithStream( const readableStream = this._transport.messageHandler.sendWithStream(
"GetOperatorList", "GetOperatorList",
@ -1812,7 +1812,7 @@ class PDFPageProxy {
cacheKey, cacheKey,
annotationStorage: map, annotationStorage: map,
}, },
transfers transfer
); );
const reader = readableStream.getReader(); const reader = readableStream.getReader();
@ -1942,14 +1942,7 @@ class LoopbackPort {
postMessage(obj, transfer) { postMessage(obj, transfer) {
const event = { const event = {
data: structuredClone( data: structuredClone(obj, transfer ? { transfer } : null),
obj,
(typeof PDFJSDev === "undefined" ||
PDFJSDev.test("SKIP_BABEL || TESTING")) &&
transfer
? { transfer }
: null
),
}; };
this.#deferred.then(() => { this.#deferred.then(() => {
@ -2853,7 +2846,7 @@ class WorkerTransport {
"please use the getData-method instead." "please use the getData-method instead."
); );
} }
const { map, transfers } = this.annotationStorage.serializable; const { map, transfer } = this.annotationStorage.serializable;
return this.messageHandler return this.messageHandler
.sendWithPromise( .sendWithPromise(
@ -2864,7 +2857,7 @@ class WorkerTransport {
annotationStorage: map, annotationStorage: map,
filename: this._fullReader?.filename ?? null, filename: this._fullReader?.filename ?? null,
}, },
transfers transfer
) )
.finally(() => { .finally(() => {
this.annotationStorage.resetModified(); this.annotationStorage.resetModified();