1
0
Fork 0
mirror of https://github.com/codedread/bitjs synced 2025-10-03 17:49:16 +02:00

Experiment with marking ArrayBuffers are Transferable across the Worker thread boundary for unzip.

This commit is contained in:
Jeff Schiller 2021-12-12 12:15:29 -08:00
parent 2a90e32c89
commit 85dcee80ec
3 changed files with 36 additions and 20 deletions

View file

@ -41,20 +41,20 @@ export const UnarchiveEventType = {
} }
/** /**
* Updates all Archiver listeners with the updated bytes. * Updates all Archiver listeners that an append has occurred.
*/ */
export class UnarchiveAppendEvent extends UnarchiveEvent { export class UnarchiveAppendEvent extends UnarchiveEvent {
/** /**
* @param {ArrayBuffer} ab The new bytes * @param {number} numBytes The number of bytes appended.
*/ */
constructor(ab) { constructor(numBytes) {
super(UnarchiveEventType.APPEND); super(UnarchiveEventType.APPEND);
/** /**
* The appended bytes. * The number of appended bytes.
* @type {ArrayBuffer} * @type {number}
*/ */
this.ab = ab; this.numBytes = numBytes;
} }
} }
@ -169,7 +169,9 @@ export class UnarchiveExtractEvent extends UnarchiveEvent {
*/ */
export class Unarchiver { export class Unarchiver {
/** /**
* @param {ArrayBuffer} arrayBuffer The Array Buffer. * @param {ArrayBuffer} arrayBuffer The Array Buffer. Note that this ArrayBuffer must not be
* referenced once it is sent to the Unarchiver, since it is marked as Transferable and sent
* to the Worker.
* @param {Function(string):Worker} createWorkerFn A function that creates a Worker from a script file. * @param {Function(string):Worker} createWorkerFn A function that creates a Worker from a script file.
* @param {Object|string} options An optional object of options, or a string representing where * @param {Object|string} options An optional object of options, or a string representing where
* the BitJS files are located. The string version of this argument is deprecated. * the BitJS files are located. The string version of this argument is deprecated.
@ -349,7 +351,7 @@ export class UnarchiveExtractEvent extends UnarchiveEvent {
this.worker_.postMessage({ this.worker_.postMessage({
file: ab, file: ab,
logToConsole: this.debugMode_, logToConsole: this.debugMode_,
}); }, [ab]);
this.ab = null; this.ab = null;
} }
} }
@ -358,14 +360,25 @@ export class UnarchiveExtractEvent extends UnarchiveEvent {
/** /**
* Adds more bytes to the unarchiver's Worker thread. * Adds more bytes to the unarchiver's Worker thread.
* @param {ArrayBuffer} ab The ArrayBuffer with more bytes in it. * @param {ArrayBuffer} ab The ArrayBuffer with more bytes in it. If opt_transferable is
* set to true, this ArrayBuffer must not be referenced after calling update(), since it
* is marked as Transferable and sent to the Worker.
* @param {boolean=} opt_transferable Optional boolean whether to mark this ArrayBuffer
* as a Tranferable object, which means it can no longer be referenced outside of
* the Worker thread.
*/ */
update(ab) { update(ab, opt_transferable = false) {
const numBytes = ab.byteLength;
if (this.worker_) { if (this.worker_) {
// Send the ArrayBuffer over, and mark it as a Transferable object if necessary.
if (opt_transferable) {
this.worker_.postMessage({ bytes: ab }, [ab]);
} else {
this.worker_.postMessage({ bytes: ab }); this.worker_.postMessage({ bytes: ab });
} }
}
if (this.listeners_[UnarchiveEventType.APPEND]) { if (this.listeners_[UnarchiveEventType.APPEND]) {
const evt = new UnarchiveAppendEvent(ab); const evt = new UnarchiveAppendEvent(numBytes);
this.listeners_[UnarchiveEventType.APPEND].forEach(listener => listener(evt)); this.listeners_[UnarchiveEventType.APPEND].forEach(listener => listener(evt));
} }
} }

View file

@ -30,12 +30,12 @@ export {
/** /**
* All extracted files returned by an Unarchiver will implement * All extracted files returned by an Unarchiver will implement
* the following interface: * the following interface:
* */
* interface UnarchivedFile {
* string filename /**
* TypedArray fileData * @typedef UnarchivedFile
* } * @property {string} filename
* * @property {Uint8Array} fileData
*/ */
/** /**
@ -72,7 +72,9 @@ export class Untarrer extends UntarrerInternal {
/** /**
* Factory method that creates an unarchiver based on the byte signature found * Factory method that creates an unarchiver based on the byte signature found
* in the arrayBuffer. * in the arrayBuffer.
* @param {ArrayBuffer} ab * @param {ArrayBuffer} ab The ArrayBuffer to unarchive. Note that this ArrayBuffer
* must not be referenced after calling this method, as the ArrayBuffer is marked
* as Transferable and sent to a Worker thread once start() is called.
* @param {Object|string} options An optional object of options, or a string * @param {Object|string} options An optional object of options, or a string
* representing where the path to the unarchiver script files. * representing where the path to the unarchiver script files.
* @return {Unarchiver} * @return {Unarchiver}

View file

@ -109,6 +109,7 @@ class ZipLocalFile {
} }
// Read in the compressed data if we have no data descriptor. // Read in the compressed data if we have no data descriptor.
/** @type {Uint8Array} */
this.fileData = null; this.fileData = null;
let descriptorSize = 0; let descriptorSize = 0;
if (this.hasDataDescriptor) { if (this.hasDataDescriptor) {
@ -622,7 +623,7 @@ function archiveUnzip() {
oneLocalFile.unzip(); oneLocalFile.unzip();
if (oneLocalFile.fileData != null) { if (oneLocalFile.fileData != null) {
postMessage({ type: 'extract', unarchivedFile: oneLocalFile }); postMessage({ type: 'extract', unarchivedFile: oneLocalFile }, [oneLocalFile.fileData.buffer]);
postProgress(); postProgress();
} }
} }