From c56f25409d8e74b14371730083a470955cc72bcd Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 9 Feb 2023 22:01:23 +0100 Subject: [PATCH] Re-factor the `arraysToBytes` helper function (PR 16032 follow-up) Currently this helper function only has two call-sites, and both of them only pass in `ArrayBuffer` data. Given how it's implemented there's a couple of code-paths that are completely unused (e.g. the "string" one), and in particular the intended fast-paths don't actually work. This patch re-factors and simplifies the helper function, and it'll no longer accept anything except `ArrayBuffer` data (hence why it's also re-named). Note that at the time when `arraysToBytes` was added we still supported browsers without TypedArray functionality, and we'd then simulate them using regular Arrays. --- src/core/chunked_stream.js | 4 +-- src/core/worker.js | 4 +-- src/shared/util.js | 72 ++++++++++++++++---------------------- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/core/chunked_stream.js b/src/core/chunked_stream.js index 561e70d57..4105dcd89 100644 --- a/src/core/chunked_stream.js +++ b/src/core/chunked_stream.js @@ -14,7 +14,7 @@ */ import { - arraysToBytes, + arrayBuffersToBytes, assert, createPromiseCapability, } from "../shared/util.js"; @@ -294,7 +294,7 @@ class ChunkedStreamManager { const readChunk = ({ value, done }) => { try { if (done) { - const chunkData = arraysToBytes(chunks); + const chunkData = arrayBuffersToBytes(chunks); chunks = null; resolve(chunkData); return; diff --git a/src/core/worker.js b/src/core/worker.js index 933ed3fb8..e82f7aef5 100644 --- a/src/core/worker.js +++ b/src/core/worker.js @@ -15,7 +15,7 @@ import { AbortException, - arraysToBytes, + arrayBuffersToBytes, assert, createPromiseCapability, getVerbosityLevel, @@ -281,7 +281,7 @@ class WorkerMessageHandler { let loaded = 0; const flushChunks = function () { - const pdfFile = arraysToBytes(cachedChunks); + const pdfFile = arrayBuffersToBytes(cachedChunks); if (length && pdfFile.length !== length) { warn("reported HTTP length is different from actual"); } diff --git a/src/shared/util.js b/src/shared/util.js index 770b42eb0..520341698 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -598,51 +598,39 @@ function stringToBytes(str) { } /** - * Gets length of the array (Array, Uint8Array, or string) in bytes. - * @param {Array|Uint8Array|string} arr - * @returns {number} - */ -// eslint-disable-next-line consistent-return -function arrayByteLength(arr) { - if (arr.length !== undefined) { - return arr.length; - } - if (arr.byteLength !== undefined) { - return arr.byteLength; - } - unreachable("Invalid argument for arrayByteLength"); -} - -/** - * Combines array items (arrays) into single Uint8Array object. - * @param {Array|Uint8Array|string>} arr - the array of the arrays - * (Array, Uint8Array, or string). + * Combines multiple ArrayBuffers into a single Uint8Array. + * @param {Array} arr - An array of ArrayBuffers. * @returns {Uint8Array} */ -function arraysToBytes(arr) { - const length = arr.length; - // Shortcut: if first and only item is Uint8Array, return it. - if (length === 1 && arr[0] instanceof Uint8Array) { - return arr[0]; - } - let resultLength = 0; - for (let i = 0; i < length; i++) { - resultLength += arrayByteLength(arr[i]); - } - let pos = 0; - const data = new Uint8Array(resultLength); - for (let i = 0; i < length; i++) { - let item = arr[i]; - if (!(item instanceof Uint8Array)) { - if (typeof item === "string") { - item = stringToBytes(item); - } else { - item = new Uint8Array(item); - } +function arrayBuffersToBytes(arr) { + if ( + typeof PDFJSDev === "undefined" || + PDFJSDev.test("!PRODUCTION || TESTING") + ) { + for (const item of arr) { + assert( + item instanceof ArrayBuffer, + "arrayBuffersToBytes - expected an ArrayBuffer." + ); } - const itemLength = item.byteLength; + } + const length = arr.length; + if (length === 0) { + return new Uint8Array(0); + } + if (length === 1) { + return new Uint8Array(arr[0]); + } + let dataLength = 0; + for (let i = 0; i < length; i++) { + dataLength += arr[i].byteLength; + } + const data = new Uint8Array(dataLength); + let pos = 0; + for (let i = 0; i < length; i++) { + const item = new Uint8Array(arr[i]); data.set(item, pos); - pos += itemLength; + pos += item.byteLength; } return data; } @@ -1115,7 +1103,7 @@ export { AnnotationReviewState, AnnotationStateModelType, AnnotationType, - arraysToBytes, + arrayBuffersToBytes, assert, BaseException, BASELINE_FACTOR,