From 8f47d06d075f6c803f43f22fee8bdc3930c33b17 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Mon, 14 Oct 2024 14:26:11 +0200 Subject: [PATCH] Add helper functions to allow using new `Uint8Array` methods This allows using the new methods in browsers that support them, e.g. Firefox 133+, while still providing fallbacks where necessary; see https://github.com/tc39/proposal-arraybuffer-base64 *Please note:* These are not actual polyfills, but only implements what we need in the PDF.js code-base. Eventually this patch should be reverted, once support is generally available. --- src/core/document.js | 5 +++-- src/core/xfa/template.js | 4 ++-- src/display/font_loader.js | 3 ++- src/shared/util.js | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/core/document.js b/src/core/document.js index 625c7f903de63..434cbac2a6325 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -26,6 +26,7 @@ import { stringToBytes, stringToPDFString, stringToUTF8String, + toHexUtil, unreachable, Util, warn, @@ -1572,8 +1573,8 @@ class PDFDocument { } return shadow(this, "fingerprints", [ - hashOriginal.toHex(), - hashModified?.toHex() ?? null, + toHexUtil(hashOriginal), + hashModified ? toHexUtil(hashModified) : null, ]); } diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js index 454ceb5f0fca2..96d18930c1c53 100644 --- a/src/core/xfa/template.js +++ b/src/core/xfa/template.js @@ -90,6 +90,7 @@ import { XFAObject, XFAObjectArray, } from "./xfa_object.js"; +import { fromBase64Util, Util, warn } from "../../shared/util.js"; import { getBBox, getColor, @@ -102,7 +103,6 @@ import { getStringOption, HTMLResult, } from "./utils.js"; -import { Util, warn } from "../../shared/util.js"; import { getMetrics } from "./fonts.js"; import { recoverJsURL } from "../core_utils.js"; import { searchNode } from "./som.js"; @@ -3427,7 +3427,7 @@ class Image extends StringObject { } if (!buffer && this.transferEncoding === "base64") { - buffer = Uint8Array.fromBase64(this[$content]); + buffer = fromBase64Util(this[$content]); } if (!buffer) { diff --git a/src/display/font_loader.js b/src/display/font_loader.js index 4115a71eb5d79..1ec7160c8500a 100644 --- a/src/display/font_loader.js +++ b/src/display/font_loader.js @@ -19,6 +19,7 @@ import { isNodeJS, shadow, string32, + toBase64Util, unreachable, warn, } from "../shared/util.js"; @@ -399,7 +400,7 @@ class FontFaceObject { return null; } // Add the @font-face rule to the document. - const url = `url(data:${this.mimetype};base64,${this.data.toBase64()});`; + const url = `url(data:${this.mimetype};base64,${toBase64Util(this.data)});`; let rule; if (!this.cssFontInfo) { rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`; diff --git a/src/shared/util.js b/src/shared/util.js index eccd578974b92..700f9f87104bb 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -1097,6 +1097,35 @@ const FontRenderOps = { TRANSLATE: 8, }; +// TODO: Remove this once `Uint8Array.prototype.toHex` is generally available. +function toHexUtil(arr) { + if (Uint8Array.prototype.toHex) { + return arr.toHex(); + } + const buf = []; + for (const num of arr) { + buf.push(num.toString(16).padStart(2, "0")); + } + return buf.join(""); +} + +// TODO: Remove this once `Uint8Array.prototype.toBase64` is generally +// available. +function toBase64Util(arr) { + if (Uint8Array.prototype.toBase64) { + return arr.toBase64(); + } + return btoa(bytesToString(arr)); +} + +// TODO: Remove this once `Uint8Array.fromBase64` is generally available. +function fromBase64Util(str) { + if (Uint8Array.fromBase64) { + return Uint8Array.fromBase64(str); + } + return stringToBytes(atob(str)); +} + export { AbortException, AnnotationActionEventType, @@ -1120,6 +1149,7 @@ export { FONT_IDENTITY_MATRIX, FontRenderOps, FormatError, + fromBase64Util, getModificationDate, getUuid, getVerbosityLevel, @@ -1149,6 +1179,8 @@ export { stringToPDFString, stringToUTF8String, TextRenderingMode, + toBase64Util, + toHexUtil, UnexpectedResponseException, UnknownErrorException, unreachable,