From 2f0b78ce2b83290eb984510ea408c7b4deb49d17 Mon Sep 17 00:00:00 2001 From: Antti Palola Date: Mon, 22 Mar 2021 14:11:58 +0200 Subject: [PATCH] Improve performance of arrayBufferToBinaryString * Skip expensive buffer overflows * Use TextDecoder when possible to speed up conversion --- src/modules/addimage.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/modules/addimage.js b/src/modules/addimage.js index d0295d0ca..b30361fd0 100644 --- a/src/modules/addimage.js +++ b/src/modules/addimage.js @@ -43,6 +43,10 @@ import { atob, btoa } from "../libs/AtobBtoa.js"; var UNKNOWN = "UNKNOWN"; + // Heuristic limit after which String.fromCharCode will start to overflow. + // Need to change to StringDecoder. + var ARRAY_BUFFER_LIMIT = 6e6; + var imageFileTypeHeaders = { PNG: [[0x89, 0x50, 0x4e, 0x47]], TIFF: [ @@ -730,20 +734,28 @@ import { atob, btoa } from "../libs/AtobBtoa.js"; var arrayBufferToBinaryString = (jsPDFAPI.__addimage__.arrayBufferToBinaryString = function( buffer ) { - try { - return atob(btoa(String.fromCharCode.apply(null, buffer))); - } catch (e) { - if ( - typeof Uint8Array !== "undefined" && - typeof Uint8Array.prototype.reduce !== "undefined" - ) { - return new Uint8Array(buffer) - .reduce(function(data, byte) { - return data.push(String.fromCharCode(byte)), data; - }, []) - .join(""); + // Skip direct conversion as it might take many hundred milliseconds before throwing. + if (buffer.length < ARRAY_BUFFER_LIMIT) { + try { + return atob(btoa(String.fromCharCode.apply(null, buffer))); + } catch (e) { + // Buffer was overflown, fall back to other methods } } + // Text decoder is much faster than string concatenation or reduce/join. + if (typeof TextDecoder !== "undefined") { + var decoder = new TextDecoder("ascii"); + return decoder.decode(buffer); + } else if ( + typeof Uint8Array !== "undefined" && + typeof Uint8Array.prototype.reduce !== "undefined" + ) { + return new Uint8Array(buffer) + .reduce(function(data, byte) { + return data.push(String.fromCharCode(byte)), data; + }, []) + .join(""); + } }); /**