Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| skip-if: !('toResizableBuffer' in WebAssembly.Memory.prototype)
let mem = new WebAssembly.Memory({initial: 20, maximum: 50});
// Utils for testing
let ins = wasmEvalText(`(module
(import "" "mem" (memory 20 50))
(func (export "check") (param i32 i32 i32) (result i32)
block
loop
local.get 0
i32.load
local.get 2
i32.eq
i32.eqz
br_if 1
local.get 1
i32.const 1
i32.sub
local.set 1
local.get 0
i32.const 4
i32.add
local.set 0
local.get 1
br_if 0
i32.const 1
return
end
end
i32.const 0
)
(func (export "fill") (param i32 i32 i32)
loop
local.get 0
local.get 2
i32.store
local.get 1
i32.const 1
i32.sub
local.set 1
local.get 0
i32.const 4
i32.add
local.set 0
local.get 1
br_if 0
end
)
)`, {"": {mem,}});
function check(off, count, value) {
const arr = new Int32Array(mem.buffer);
for (let i = 0; i < count; i++) {
assertEq(arr[(off >> 2) + i], value);
}
}
function fill(off, count, value) {
const arr = new Int32Array(mem.buffer);
for (let i = 0; i < count; i++) {
arr[i] = value;
}
}
fill(0, 10, 1);
assertEq(ins.exports.check(0, 10, 1), 1);
// Convert to resizable array, back to fixed-length, again to resizable,
// and attempt to resize using JS.
let ab = mem.buffer;
assertEq(ab.resizable, false);
assertEq(ab.maxByteLength, 20 << 16);
// Make .buffer resizable, detaching the old one.
let rab = mem.toResizableBuffer();
assertEq(rab.resizable, true);
assertEq(mem.buffer, rab);
assertEq(ab.detached, true);
assertEq(rab.maxByteLength, 50 << 16);
assertEq(ins.exports.check(0, 10, 1), 1);
ins.exports.fill(0, 10, 3);
check(0, 10, 3);
// We can go back if we choose.
let ab2 = mem.toFixedLengthBuffer();
assertEq(ab2.resizable, false);
assertEq(mem.buffer, ab2);
assertEq(ab2 !== ab, true);
assertEq(rab.detached, true);
assertEq(ab2.byteLength, 20 << 16);
assertEq(ab2.maxByteLength, 20 << 16);
assertEq(ins.exports.check(0, 10, 3), 1);
ins.exports.fill(0, 10, 2);
check(0, 10, 2);
assertThrowsInstanceOf(
() => ins.exports.check(20 * 65536 - 4, 2, 0), WebAssembly.RuntimeError);
ins.exports.fill(20 * 65536 - 4, 1, 20);
// Let's go back to resizable. Memory#grow no longer detaches .buffer when it's resizable.
rab = mem.toResizableBuffer();
let oldLen = rab.byteLength;
mem.grow(8);
assertEq(rab.detached, false);
assertEq(rab.byteLength, oldLen + (8 * 65536))
assertEq(rab.maxByteLength, 50 << 16);
ins.exports.check(20 * 65536 - 4, 1, 20);
ins.exports.check(20 * 65536, 1, 0);
assertThrowsInstanceOf(
() => ins.exports.check(28 * 65536 - 4, 2, 0), WebAssembly.RuntimeError);
assertEq(ins.exports.check(0, 10, 2), 1);
ins.exports.fill(0, 10, 5);
check(0, 10, 5);
// Try to resize JS way.
rab.resize(65536 * 30);
assertEq(rab.byteLength, 30 * 65536);
ins.exports.fill(30 * 65536 - 10*4, 10, 6);
check(30 * 65536 - 10 * 4, 10, 6);
// RAB#resize throws when trying to shrink or grow by non-page multiples
// for WebAssembly.Memory-vended RABs.
assertThrowsInstanceOf(() => rab.resize(rab.byteLength - 65536), RangeError);
assertThrowsInstanceOf(() => rab.resize(rab.byteLength + 10), RangeError);
// No allow to make buffer resizable when max in not specified.
mem = new WebAssembly.Memory({initial: 20});
assertThrowsInstanceOf(() => mem.toResizableBuffer(), TypeError);
// Test the JS API with a resizable and shared buffer.
a = new WebAssembly.Memory({
initial: 2,
maximum: 4,
shared: true
})
a.toResizableBuffer();
setSharedObject(a);
// Testing the limits of our implementation.
let big_memory = new WebAssembly.Memory({address: 'i64', initial: 0n, maximum: BigInt(MaxMemory64PagesValidation), shared: false});
let buffer = big_memory.toResizableBuffer();
// Asserts that buffer.maxByteLength is less than MAX_SAFE_INTEGER.
assertEq(buffer.maxByteLength <= Number.MAX_SAFE_INTEGER, true);
// Create a new Memory without a maximum and accessing maxByteLength.
new WebAssembly.Memory({ initial: 10 }).buffer.maxByteLength;
// toResizableBuffer and toFixedLengthBuffer throw when the buffer length is pinned.
mem = new WebAssembly.Memory({initial: 1, maximum: 4});
pinArrayBufferOrViewLength(mem.buffer, true);
assertThrowsInstanceOf(() => mem.toResizableBuffer(), RangeError);
pinArrayBufferOrViewLength(mem.buffer, false);
rab = mem.toResizableBuffer();
pinArrayBufferOrViewLength(rab, true);
assertThrowsInstanceOf(() => mem.toFixedLengthBuffer(), RangeError);
pinArrayBufferOrViewLength(rab, false);