| // META: global=window,dedicatedworker,jsshell |
| // META: script=/wasm/jsapi/wasm-module-builder.js |
| // META: script=/wasm/jsapi/assertions.js |
| |
| const type_if_fi = makeSig([kWasmF64, kWasmI32], [kWasmI32, kWasmF64]); |
| |
| promise_test(async () => { |
| const builder = new WasmModuleBuilder(); |
| |
| builder |
| .addFunction("swap", type_if_fi) |
| .addBody([ |
| kExprLocalGet, 1, |
| kExprLocalGet, 0, |
| kExprReturn, |
| ]) |
| .exportFunc(); |
| |
| const buffer = builder.toBuffer(); |
| |
| const result = await WebAssembly.instantiate(buffer); |
| const swapped = result.instance.exports.swap(4.2, 7); |
| assert_true(Array.isArray(swapped)); |
| assert_equals(Object.getPrototypeOf(swapped), Array.prototype); |
| assert_array_equals(swapped, [7, 4.2]); |
| }, "multiple return values from wasm to js"); |
| |
| promise_test(async () => { |
| const builder = new WasmModuleBuilder(); |
| |
| const swap = builder |
| .addFunction("swap", type_if_fi) |
| .addBody([ |
| kExprLocalGet, 1, |
| kExprLocalGet, 0, |
| kExprReturn, |
| ]); |
| builder |
| .addFunction("callswap", kSig_i_v) |
| .addBody([ |
| ...wasmF64Const(4.2), |
| ...wasmI32Const(7), |
| kExprCallFunction, swap.index, |
| kExprDrop, |
| kExprReturn, |
| ]) |
| .exportFunc(); |
| |
| const buffer = builder.toBuffer(); |
| |
| const result = await WebAssembly.instantiate(buffer); |
| const swapped = result.instance.exports.callswap(); |
| assert_equals(swapped, 7); |
| }, "multiple return values inside wasm"); |
| |
| promise_test(async () => { |
| const builder = new WasmModuleBuilder(); |
| |
| const fnIndex = builder.addImport("module", "fn", type_if_fi); |
| builder |
| .addFunction("callfn", kSig_i_v) |
| .addBody([ |
| ...wasmF64Const(4.2), |
| ...wasmI32Const(7), |
| kExprCallFunction, fnIndex, |
| kExprDrop, |
| kExprReturn, |
| ]) |
| .exportFunc(); |
| |
| const buffer = builder.toBuffer(); |
| |
| const actual = []; |
| const imports = { |
| "module": { |
| fn(f32, i32) { |
| assert_equals(f32, 4.2); |
| assert_equals(i32, 7); |
| const result = [2, 7.3]; |
| let i = 0; |
| return { |
| get [Symbol.iterator]() { |
| actual.push("@@iterator getter"); |
| return function iterator() { |
| actual.push("@@iterator call"); |
| return { |
| get next() { |
| actual.push("next getter"); |
| return function next(...args) { |
| assert_array_equals(args, []); |
| let j = ++i; |
| actual.push(`next call ${j}`); |
| if (j > result.length) { |
| return { |
| get done() { |
| actual.push(`done call ${j}`); |
| return true; |
| } |
| }; |
| } |
| return { |
| get done() { |
| actual.push(`done call ${j}`); |
| return false; |
| }, |
| get value() { |
| actual.push(`value call ${j}`); |
| return { |
| get valueOf() { |
| actual.push(`valueOf get ${j}`); |
| return function() { |
| actual.push(`valueOf call ${j}`); |
| return result[j - 1]; |
| }; |
| } |
| }; |
| } |
| }; |
| }; |
| } |
| }; |
| } |
| }, |
| }; |
| }, |
| } |
| }; |
| |
| const { instance } = await WebAssembly.instantiate(buffer, imports); |
| const result = instance.exports.callfn(); |
| assert_equals(result, 2); |
| assert_array_equals(actual, [ |
| "@@iterator getter", |
| "@@iterator call", |
| "next getter", |
| "next call 1", |
| "done call 1", |
| "value call 1", |
| "next call 2", |
| "done call 2", |
| "value call 2", |
| "next call 3", |
| "done call 3", |
| "valueOf get 1", |
| "valueOf call 1", |
| "valueOf get 2", |
| "valueOf call 2", |
| ]); |
| }, "multiple return values from js to wasm"); |
| |
| promise_test(async () => { |
| const builder = new WasmModuleBuilder(); |
| |
| const fnIndex = builder.addImport("module", "fn", type_if_fi); |
| builder |
| .addFunction("callfn", kSig_i_v) |
| .addBody([ |
| ...wasmF64Const(4.2), |
| ...wasmI32Const(7), |
| kExprCallFunction, fnIndex, |
| kExprDrop, |
| kExprReturn, |
| ]) |
| .exportFunc(); |
| |
| const buffer = builder.toBuffer(); |
| |
| const imports = { |
| "module": { |
| fn(f32, i32) { |
| assert_equals(f32, 4.2); |
| assert_equals(i32, 7); |
| return [2]; |
| }, |
| } |
| }; |
| |
| const { instance } = await WebAssembly.instantiate(buffer, imports); |
| assert_throws(new TypeError(), () => instance.exports.callfn()); |
| }, "Too few results returned from js to wasm"); |
| |
| promise_test(async () => { |
| const builder = new WasmModuleBuilder(); |
| |
| const fnIndex = builder.addImport("module", "fn", type_if_fi); |
| builder |
| .addFunction("callfn", kSig_i_v) |
| .addBody([ |
| ...wasmF64Const(4.2), |
| ...wasmI32Const(7), |
| kExprCallFunction, fnIndex, |
| kExprDrop, |
| kExprReturn, |
| ]) |
| .exportFunc(); |
| |
| const buffer = builder.toBuffer(); |
| |
| const imports = { |
| "module": { |
| fn(f32, i32) { |
| assert_equals(f32, 4.2); |
| assert_equals(i32, 7); |
| return [2, 4.2, undefined]; |
| }, |
| } |
| }; |
| |
| const { instance } = await WebAssembly.instantiate(buffer, imports); |
| assert_throws(new TypeError(), () => instance.exports.callfn()); |
| }, "Too many results returned from js to wasm"); |