diff --git a/lib/stream/StreamHelper.js b/lib/stream/StreamHelper.js index 08888283..09958deb 100644 --- a/lib/stream/StreamHelper.js +++ b/lib/stream/StreamHelper.js @@ -18,24 +18,19 @@ if (support.nodestream) { * Apply the final transformation of the data. If the user wants a Blob for * example, it's easier to work with an U8intArray and finally do the * ArrayBuffer/Blob conversion. - * @param {String} resultType the name of the final type - * @param {String} chunkType the type of the data in the given array. - * @param {Array} dataArray the array containing the data chunks to concatenate + * @param {String} type the name of the final type * @param {String|Uint8Array|Buffer} content the content to transform * @param {String} mimeType the mime type of the content, if applicable. * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. */ -function transformZipOutput(resultType, chunkType, dataArray, mimeType) { - var content = null; - switch(resultType) { +function transformZipOutput(type, content, mimeType) { + switch(type) { case "blob" : - return utils.newBlob(dataArray, mimeType); + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); case "base64" : - content = concat(chunkType, dataArray); return base64.encode(content); default : - content = concat(chunkType, dataArray); - return utils.transformTo(resultType, content); + return utils.transformTo(type, content); } } @@ -98,7 +93,7 @@ function accumulate(helper, updateCallback) { }) .on('end', function (){ try { - var result = transformZipOutput(resultType, chunkType, dataArray, mimeType); + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); resolve(result); } catch (e) { reject(e); @@ -120,8 +115,6 @@ function StreamHelper(worker, outputType, mimeType) { var internalType = outputType; switch(outputType) { case "blob": - internalType = "arraybuffer"; - break; case "arraybuffer": internalType = "uint8array"; break; diff --git a/lib/utils.js b/lib/utils.js index 4173645f..f2185150 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -26,18 +26,23 @@ function string2binary(str) { /** * Create a new blob with the given content and the given type. - * @param {Array[String|ArrayBuffer]} parts the content to put in the blob. DO NOT use + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use * an Uint8Array because the stock browser of android 4 won't accept it (it * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * * @param {String} type the mime type of the blob. * @return {Blob} the created blob. */ -exports.newBlob = function(parts, type) { +exports.newBlob = function(part, type) { exports.checkSupport("blob"); try { // Blob constructor - return new Blob(parts, { + return new Blob([part], { type: type }); } @@ -47,9 +52,7 @@ exports.newBlob = function(parts, type) { // deprecated, browser only, old way var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; var builder = new Builder(); - for (var i = 0; i < parts.length; i++) { - builder.append(parts[i]); - } + builder.append(part); return builder.getBlob(type); } catch (e) { @@ -268,13 +271,7 @@ transform["uint8array"] = { return arrayLikeToArrayLike(input, new Array(input.length)); }, "arraybuffer": function(input) { - // copy the uint8array: DO NOT propagate the original ArrayBuffer, it - // can be way larger (the whole zip file for example). - var copy = new Uint8Array(input.length); - if (input.length) { - copy.set(input, 0); - } - return copy.buffer; + return input.buffer; }, "uint8array": identity, "nodebuffer": function(input) {