// META: global=window,dedicatedworker,jsshell,shadowrealm // META: script=/wasm/jsapi/memory/assertions.js test(() => { const argument = { "initial": 0 }; const memory = new WebAssembly.Memory(argument); assert_throws_js(TypeError, () => memory.grow()); }, "Missing arguments"); test(t => { const thisValues = [ undefined, null, true, "", Symbol(), 1, {}, WebAssembly.Memory, WebAssembly.Memory.prototype, ]; const argument = { valueOf: t.unreached_func("Should not touch the argument (valueOf)"), toString: t.unreached_func("Should not touch the argument (toString)"), }; const fn = WebAssembly.Memory.prototype.grow; for (const thisValue of thisValues) { assert_throws_js(TypeError, () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`); } }, "Branding"); test(() => { const argument = { "initial": 0 }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing"); const result = memory.grow(2); assert_equals(result, 0); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing"); assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing"); }, "Zero initial"); test(() => { const argument = { "initial": { valueOf() { return 0 } } }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing"); const result = memory.grow({ valueOf() { return 2 } }); assert_equals(result, 0); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing"); assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing"); }, "Zero initial with valueOf"); test(() => { const argument = { "initial": 3 }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 3 }, "Buffer before growing"); const result = memory.grow(2); assert_equals(result, 3); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing"); assert_ArrayBuffer(newMemory, { "size": 5 }, "New buffer after growing"); }, "Non-zero initial"); test(() => { const argument = { "initial": 0, "maximum": 2 }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing"); const result = memory.grow(2); assert_equals(result, 0); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing"); assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing"); }, "Zero initial with respected maximum"); test(() => { const argument = { "initial": 0, "maximum": 2 }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing"); const result = memory.grow(1); assert_equals(result, 0); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing once"); assert_ArrayBuffer(newMemory, { "size": 1 }, "New buffer after growing once"); const result2 = memory.grow(1); assert_equals(result2, 1); const newestMemory = memory.buffer; assert_not_equals(newMemory, newestMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "New buffer after growing twice"); assert_ArrayBuffer(newMemory, { "detached": true }, "New buffer after growing twice"); assert_ArrayBuffer(newestMemory, { "size": 2 }, "Newest buffer after growing twice"); }, "Zero initial with respected maximum grown twice"); test(() => { const argument = { "initial": 1, "maximum": 2 }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 1 }, "Buffer before growing"); assert_throws_js(RangeError, () => memory.grow(2)); assert_equals(memory.buffer, oldMemory); assert_ArrayBuffer(memory.buffer, { "size": 1 }, "Buffer before trying to grow"); }, "Zero initial growing too much"); const outOfRangeValues = [ undefined, NaN, Infinity, -Infinity, -1, 0x100000000, 0x1000000000, "0x100000000", { valueOf() { return 0x100000000; } }, ]; for (const value of outOfRangeValues) { test(() => { const argument = { "initial": 0 }; const memory = new WebAssembly.Memory(argument); assert_throws_js(TypeError, () => memory.grow(value)); }, `Out-of-range argument: ${format_value(value)}`); } test(() => { const argument = { "initial": 0 }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing"); const result = memory.grow(2, {}); assert_equals(result, 0); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing"); assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing"); }, "Stray argument"); test(() => { const argument = { "initial": 1, "maximum": 2, "shared": true }; const memory = new WebAssembly.Memory(argument); const oldMemory = memory.buffer; assert_ArrayBuffer(oldMemory, { "size": 1, "shared": true }, "Buffer before growing"); const result = memory.grow(1); assert_equals(result, 1); const newMemory = memory.buffer; assert_not_equals(oldMemory, newMemory); assert_ArrayBuffer(oldMemory, { "size": 1, "shared": true }, "Old buffer after growing"); assert_ArrayBuffer(newMemory, { "size": 2, "shared": true }, "New buffer after growing"); // The old and new buffers must have the same value for the // [[ArrayBufferData]] internal slot. const oldArray = new Uint8Array(oldMemory); const newArray = new Uint8Array(newMemory); assert_equals(oldArray[0], 0, "old first element"); assert_equals(newArray[0], 0, "new first element"); oldArray[0] = 1; assert_equals(oldArray[0], 1, "old first element"); assert_equals(newArray[0], 1, "new first element"); }, "Growing shared memory does not detach old buffer");