From 51606591f1befd5a5bfe683ddfd987a5ce84594d Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Wed, 22 Dec 2021 11:57:20 +0100 Subject: [PATCH] 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:* This patch can't/shouldn't land until `structuredClone` becomes available in *at least* the release versions of both Mozilla Firefox and Google Chrome; see https://developer.mozilla.org/en-US/docs/Web/API/structuredClone#browser_compatibility --- .eslintrc | 1 + src/display/api.js | 88 ++----------------------------------- src/shared/compatibility.js | 13 ++++++ 3 files changed, 17 insertions(+), 85 deletions(-) diff --git a/.eslintrc b/.eslintrc index 22ade7ddb1c1c7..acd6331c570626 100644 --- a/.eslintrc +++ b/.eslintrc @@ -28,6 +28,7 @@ "globals": { "PDFJSDev": false, "exports": false, + "structuredClone": false, "SystemJS": false, }, diff --git a/src/display/api.js b/src/display/api.js index beb6ba9f255aeb..65bce574869648 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1913,91 +1913,9 @@ 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: 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 f418f8f1e4042d..f38286ec34338a 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