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.
This commit is contained in:
Jonas Jenwald 2023-02-09 22:01:23 +01:00
parent 5ba596786c
commit c56f25409d
3 changed files with 34 additions and 46 deletions

View File

@ -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;

View File

@ -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");
}

View File

@ -598,51 +598,39 @@ function stringToBytes(str) {
}
/**
* Gets length of the array (Array, Uint8Array, or string) in bytes.
* @param {Array<any>|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<Array<any>|Uint8Array|string>} arr - the array of the arrays
* (Array, Uint8Array, or string).
* Combines multiple ArrayBuffers into a single Uint8Array.
* @param {Array<ArrayBuffer>} 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,