Skip to content

Split get typed array methods in loader to safe and unsafe (view) #1047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions lib/loader/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,62 @@ interface ASUtil {
_start(): void;
/** Allocates a new string in the module's memory and returns a reference (pointer) to it. */
__allocString(str: string): number;
/** Reads (copies) the value of a string from the module's memory. */
__getString(ptr: number): string;
/** Allocates a new array in the module's memory and returns a reference (pointer) to it. */
__allocArray(id: number, values: ArrayLike<number>): number;

/** Reads (copies) the value of a string from the module's memory. */
__getString(ptr: number): string;
/** Reads (copies) the values of an array from the module's memory. */
__getArray(ptr: number): number[];
/** Gets a view on the values of an array in the module's memory. */
__getArrayView(ptr: number): ArrayBufferView;
/** Reads the values of Int8Array from the module's memory. */

/** Reads (copies) the values of Int8Array from the module's memory. */
__getInt8Array(ptr: number): Int8Array;
/** Reads the values of Uint8Array from the module's memory. */
/** Reads (copies) the values of Uint8Array from the module's memory. */
__getUint8Array(ptr: number): Uint8Array;
/** Reads the values of Uint8Array from the module's memory. */
/** Reads (copies) the values of Uint8Array from the module's memory. */
__getUint8ClampedArray(ptr: number): Uint8ClampedArray;
/** Reads the values of Int16Array from the module's memory. */
/** Reads (copies) the values of Int16Array from the module's memory. */
__getInt16Array(ptr: number): Int16Array;
/** Reads the values of Uint16Array from the module's memory. */
/** Reads (copies) the values of Uint16Array from the module's memory. */
__getUint16Array(ptr: number): Uint16Array;
/** Reads the values of Int32Array from the module's memory. */
/** Reads (copies) the values of Int32Array from the module's memory. */
__getInt32Array(ptr: number): Int32Array;
/** Reads the values of Uint32Array from the module's memory. */
/** Reads (copies) the values of Uint32Array from the module's memory. */
__getUint32Array(ptr: number): Uint32Array;
/** Reads the values of Int32Array from the module's memory. */
/** Reads (copies) the values of Int32Array from the module's memory. */
__getInt64Array?(ptr: number): BigInt64Array;
/** Reads the values of Uint32Array from the module's memory. */
/** Reads (copies) the values of Uint32Array from the module's memory. */
__getUint64Array?(ptr: number): BigUint64Array;
/** Reads the values of Float32Array from the module's memory. */
/** Reads (copies) the values of Float32Array from the module's memory. */
__getFloat32Array(ptr: number): Float32Array;
/** Reads the values of Float64Array from the module's memory. */
/** Reads (copies) the values of Float64Array from the module's memory. */
__getFloat64Array(ptr: number): Float64Array;

/** Reads the values of Int8Array from the module's memory. */
__getInt8ArrayView(ptr: number): Int8Array;
/** Reads the values of Uint8Array from the module's memory. */
__getUint8ArrayView(ptr: number): Uint8Array;
/** Reads the values of Uint8Array from the module's memory. */
__getUint8ClampedArrayView(ptr: number): Uint8ClampedArray;
/** Reads the values of Int16Array from the module's memory. */
__getInt16ArrayView(ptr: number): Int16Array;
/** Reads the values of Uint16Array from the module's memory. */
__getUint16ArrayView(ptr: number): Uint16Array;
/** Reads the values of Int32Array from the module's memory. */
__getInt32ArrayView(ptr: number): Int32Array;
/** Reads the values of Uint32Array from the module's memory. */
__getUint32ArrayView(ptr: number): Uint32Array;
/** Reads the values of Int32Array from the module's memory. */
__getInt64ArrayView?(ptr: number): BigInt64Array;
/** Reads the values of Uint32Array from the module's memory. */
__getUint64ArrayView?(ptr: number): BigUint64Array;
/** Reads the values of Float32Array from the module's memory. */
__getFloat32ArrayView(ptr: number): Float32Array;
/** Reads the values of Float64Array from the module's memory. */
__getFloat64ArrayView(ptr: number): Float64Array;

/** Reads (copies) the data of an ArrayBuffer from the module's memory. */
__getArrayBuffer(ptr: number): ArrayBuffer;
/** Retains a reference to a managed object externally, making sure that it doesn't become collected prematurely. Returns the pointer. */
Expand Down
39 changes: 27 additions & 12 deletions lib/loader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,37 +217,52 @@ function postInstantiate(baseModule, instance) {

baseModule.__getArrayBuffer = __getArrayBuffer;

function getTypedArrayImpl(Type, alignLog2, ptr) {
function getTypedArrayView(Type, alignLog2, ptr) {
const buffer = memory.buffer;
const U32 = new Uint32Array(buffer);
const bufPtr = U32[ptr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2];
return new Type(buffer, bufPtr, U32[bufPtr + SIZE_OFFSET >>> 2] >>> alignLog2);
}

function getTypedArray(Type, alignLog2, ptr) {
return new Type(getTypedArrayView(Type, alignLog2, ptr));
}

/** Gets a view on the values of a known-to-be Int8Array in the module's memory. */
baseModule.__getInt8Array = getTypedArrayImpl.bind(null, Int8Array, 0);
baseModule.__getInt8Array = getTypedArray.bind(null, Int8Array, 0);
baseModule.__getInt8ArrayView = getTypedArrayView.bind(null, Int8Array, 0);
/** Gets a view on the values of a known-to-be Uint8Array in the module's memory. */
baseModule.__getUint8Array = getTypedArrayImpl.bind(null, Uint8Array, 0);
baseModule.__getUint8Array = getTypedArray.bind(null, Uint8Array, 0);
baseModule.__getUint8ArrayView = getTypedArrayView.bind(null, Uint8Array, 0);
/** Gets a view on the values of a known-to-be Uint8ClampedArray in the module's memory. */
baseModule.__getUint8ClampedArray = getTypedArrayImpl.bind(null, Uint8ClampedArray, 0);
baseModule.__getUint8ClampedArray = getTypedArray.bind(null, Uint8ClampedArray, 0);
baseModule.__getUint8ClampedArrayView = getTypedArrayView.bind(null, Uint8ClampedArray, 0);
/** Gets a view on the values of a known-to-be Int16Array in the module's memory. */
baseModule.__getInt16Array = getTypedArrayImpl.bind(null, Int16Array, 1);
baseModule.__getInt16Array = getTypedArray.bind(null, Int16Array, 1);
baseModule.__getInt16ArrayView = getTypedArrayView.bind(null, Int16Array, 1);
/** Gets a view on the values of a known-to-be Uint16Array in the module's memory. */
baseModule.__getUint16Array = getTypedArrayImpl.bind(null, Uint16Array, 1);
baseModule.__getUint16Array = getTypedArray.bind(null, Uint16Array, 1);
baseModule.__getUint16ArrayView = getTypedArrayView.bind(null, Uint16Array, 1);
/** Gets a view on the values of a known-to-be Int32Array in the module's memory. */
baseModule.__getInt32Array = getTypedArrayImpl.bind(null, Int32Array, 2);
baseModule.__getInt32Array = getTypedArray.bind(null, Int32Array, 2);
baseModule.__getInt32ArrayView = getTypedArrayView.bind(null, Int32Array, 2);
/** Gets a view on the values of a known-to-be Uint32Array in the module's memory. */
baseModule.__getUint32Array = getTypedArrayImpl.bind(null, Uint32Array, 2);
baseModule.__getUint32Array = getTypedArray.bind(null, Uint32Array, 2);
baseModule.__getUint32ArrayView = getTypedArrayView.bind(null, Uint32Array, 2);
if (BIGINT) {
/** Gets a view on the values of a known-to-be-Int64Array in the module's memory. */
baseModule.__getInt64Array = getTypedArrayImpl.bind(null, BigInt64Array, 3);
baseModule.__getInt64Array = getTypedArray.bind(null, BigInt64Array, 3);
baseModule.__getInt64ArrayView = getTypedArrayView.bind(null, BigInt64Array, 3);
/** Gets a view on the values of a known-to-be-Uint64Array in the module's memory. */
baseModule.__getUint64Array = getTypedArrayImpl.bind(null, BigUint64Array, 3);
baseModule.__getUint64Array = getTypedArray.bind(null, BigUint64Array, 3);
baseModule.__getUint64ArrayView = getTypedArrayView.bind(null, BigUint64Array, 3);
}
/** Gets a view on the values of a known-to-be Float32Array in the module's memory. */
baseModule.__getFloat32Array = getTypedArrayImpl.bind(null, Float32Array, 2);
baseModule.__getFloat32Array = getTypedArray.bind(null, Float32Array, 2);
baseModule.__getFloat32ArrayView = getTypedArrayView.bind(null, Float32Array, 2);
/** Gets a view on the values of a known-to-be Float64Array in the module's memory. */
baseModule.__getFloat64Array = getTypedArrayImpl.bind(null, Float64Array, 3);
baseModule.__getFloat64Array = getTypedArray.bind(null, Float64Array, 3);
baseModule.__getFloat64ArrayView = getTypedArrayView.bind(null, Float64Array, 3);

/** Tests whether an object is an instance of the class represented by the specified base id. */
function __instanceof(ptr, baseId) {
Expand Down
Binary file modified lib/loader/tests/build/untouched.wasm
Binary file not shown.
9 changes: 7 additions & 2 deletions lib/loader/tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ assert.strictEqual(module.__getString(module.COLOR), "red");
let ref = module.__retain(module.__allocArray(module.UINT32ARRAY_ID, arr));
assert(module.__instanceof(ref, module.UINT32ARRAY_ID));
assert.deepEqual(module.__getUint32Array(ref), new Uint32Array(arr));
assert.deepEqual(module.__getUint32ArrayView(ref), new Uint32Array(arr));
assert.deepEqual(module.__getArray(ref), arr);
module.__release(ref);
try { module.__release(ref); assert(false); } catch (e) {};
Expand All @@ -106,6 +107,7 @@ assert.strictEqual(module.__getString(module.COLOR), "red");
let ref = module.__retain(module.__allocArray(module.FLOAT32ARRAY_ID, arr));
assert(module.__instanceof(ref, module.FLOAT32ARRAY_ID));
assert.deepEqual(module.__getFloat32Array(ref), new Float32Array(arr));
assert.deepEqual(module.__getFloat32ArrayView(ref), new Float32Array(arr));
assert.deepEqual(module.__getArray(ref), arr);
module.__release(ref);
try { module.__release(ref); assert(false); } catch (e) {};
Expand Down Expand Up @@ -154,7 +156,7 @@ module.dotrace(42);

// should be able to mutate an array in place using getArrayView
{
let ptr = module.__retain(module.__allocArray(module.FLOAT32ARRAY_ID, [ 1, 2, 3]));
let ptr = module.__retain(module.__allocArray(module.FLOAT32ARRAY_ID, [1, 2, 3]));
let view = module.__getArrayView(ptr);
assert.deepEqual(view, new Float32Array([1, 2, 3]));
module.modifyFloat32Array(ptr, 0, 4);
Expand All @@ -165,12 +167,15 @@ module.dotrace(42);
// should be able to mutate an array in place using getFloat32Array
{
let ptr = module.newFloat32Array(3); // returns are pre-retained
let view = module.__getFloat32Array(ptr);
let view = module.__getFloat32ArrayView(ptr);
let arr = module.__getFloat32Array(ptr);
assert.deepEqual(view, new Float32Array([0, 0, 0]));
assert.deepEqual(arr, new Float32Array([0, 0, 0]));
module.modifyFloat32Array(ptr, 0, 3);
module.modifyFloat32Array(ptr, 1, 2);
module.modifyFloat32Array(ptr, 2, 1);
assert.deepEqual(view, new Float32Array([3, 2, 1]));
assert.deepEqual(arr, new Float32Array([0, 0, 0]));
module.__release(ptr);
}

Expand Down