Skip to content
Prev Previous commit
Next Next commit
Revert changes for Blob.slice() to previous approach.
  • Loading branch information
octet-stream committed Oct 16, 2021
commit e0f5895bc199fccdf92f8caa01df2e93dc43cee1
87 changes: 43 additions & 44 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,48 +42,6 @@ async function * toIterator (parts, clone = true) {
}
}

/**
* @param {Blob | NodeBlob | Uint8Array} blobParts
* @param {number} blobSize
* @param {number} start
* @param {number} end
*/
function* sliceBlob(blobParts, blobSize, start, end) {
let relativeStart = start < 0 ? Math.max(blobSize + start, 0) : Math.min(start, blobSize);
let relativeEnd = end < 0 ? Math.max(blobSize + end, 0) : Math.min(end, blobSize);

const span = Math.max(relativeEnd - relativeStart, 0);

let added = 0;
for (const part of blobParts) {
if (added >= span) {
break;
}

const partSize = ArrayBuffer.isView(part) ? part.byteLength : part.size;
if (relativeStart && partSize <= relativeStart) {
// Skip the beginning and change the relative
// start & end position as we skip the unwanted parts
relativeStart -= partSize;
relativeEnd -= partSize;
} else {
let chunk;
if (ArrayBuffer.isView(part)) {
chunk = part.subarray(relativeStart, Math.min(partSize, relativeEnd));
added += chunk.byteLength;
} else {
chunk = part.slice(relativeStart, Math.min(partSize, relativeEnd));
added += chunk.size;
}

relativeEnd -= partSize;
relativeStart = 0; // All next sequential parts should start at 0

yield chunk;
}
}
}

const _Blob = class Blob {

/** @type {Array.<(Blob|Uint8Array)>} */
Expand Down Expand Up @@ -219,8 +177,49 @@ const _Blob = class Blob {
* @param {number} [end]
* @param {string} [type]
*/
slice(start = 0, end = this.size, type = '') {
return new Blob(sliceBlob(this.#parts, this.size, start, end), {type})
slice(start = 0, end = this.size, type = '') {
const {size} = this;

let relativeStart = start < 0 ? Math.max(size + start, 0) : Math.min(start, size);
let relativeEnd = end < 0 ? Math.max(size + end, 0) : Math.min(end, size);

const span = Math.max(relativeEnd - relativeStart, 0);
const parts = this.#parts;
const blobParts = [];
let added = 0;

for (const part of parts) {
// don't add the overflow to new blobParts
if (added >= span) {
break;
}

const size = ArrayBuffer.isView(part) ? part.byteLength : part.size;
if (relativeStart && size <= relativeStart) {
// Skip the beginning and change the relative
// start & end position as we skip the unwanted parts
relativeStart -= size;
relativeEnd -= size;
} else {
let chunk
if (ArrayBuffer.isView(part)) {
chunk = part.subarray(relativeStart, Math.min(size, relativeEnd));
added += chunk.byteLength
} else {
chunk = part.slice(relativeStart, Math.min(size, relativeEnd));
added += chunk.size
}
relativeEnd -= size;
blobParts.push(chunk);
relativeStart = 0; // All next sequential parts should start at 0
}
}

const blob = new Blob([], {type: String(type).toLowerCase()});
blob.#size = span;
blob.#parts = blobParts;

return blob;
}

get [Symbol.toStringTag]() {
Expand Down