wasmFullPass(` (module (import "env" "f" (func $f (result i32 i32 i32))) (func (export "run") (result i32) (call $f) i32.sub i32.sub))`, 42, { env: { f: () => [52, 10, 0] } }); wasmFullPass(` (module (import "env" "f" (func $f (result i64 i64 i64))) (func (export "run") (result i64) (call $f) i64.sub i64.sub))`, 42n, { env: { f: () => [52n, 10n, 0n] } }); wasmFullPass(` (module (import "env" "f" (func $f (result f32 f32 f32))) (func (export "run") (result i32) (call $f) f32.sub f32.sub i32.trunc_f32_s))`, 42, { env: { f: () => [52.25, 10.5, 0.25] } }); wasmFullPass(` (module (import "env" "f" (func $f (result f64 f64 f64))) (func (export "run") (result i32) (call $f) f64.sub f64.sub i32.trunc_f64_s))`, 42, { env: { f: () => [52.25, 10.5, 0.25] } }); // Multiple values are returned as an iterable; it doesn't have to be an array. function expectMultiValuePass(f) { wasmFullPass(` (module (import "env" "f" (func $f (result i32 i32 i32))) (func (export "run") (result i32) (call $f) i32.sub i32.sub))`, 42, { env: { f } }); } function expectMultiValueError(f, type, pattern) { let module = new WebAssembly.Module(wasmTextToBinary(` (module (import "env" "f" (func $f (result i32 i32 i32))) (func (export "run") (result i32) (call $f) i32.sub i32.sub))`)); let instance = new WebAssembly.Instance(module, { env: { f } } ); assertErrorMessage(() => instance.exports.run(), type, pattern); } expectMultiValuePass(() => [52, 10, 0]); expectMultiValuePass(() => [32, -10, 0]); expectMultiValuePass(() => [52.75, 10, 0.5]); // Values converted to i32 via ToInt32. expectMultiValuePass(() => [42, undefined, undefined]); expectMultiValuePass(() => (function*() { yield 52; yield 10; yield 0; })()); expectMultiValuePass(() => (function*() { yield '52'; yield '10'; yield 0; })()); // Multi-value result must be iterable. expectMultiValueError(() => 1, TypeError, /iterable/); expectMultiValueError(() => 1n, TypeError, /iterable/); // Check that the iterator's values are collected first, and that the // length of the result is correct. expectMultiValueError(() => [1], TypeError, /expected 3, got 1/); expectMultiValueError(() => [1n], TypeError, /expected 3, got 1/); expectMultiValueError(() => [52, 10, 0, 0], TypeError, /expected 3, got 4/); expectMultiValueError(() => (function*() { yield 52; yield 10; yield 0; yield 0; })(), TypeError, /expected 3, got 4/); // Check that side effects from conversions are done in order. { let calls = []; function log(x) { calls.push(x); return x; } function logged(x) { return { valueOf: () => log(x) } } expectMultiValuePass(() => [logged(52), logged(10), logged(0)]); assertEq(calls.join(','), '52,10,0'); } function expectMultiValueResult(text, expected) { let instance = wasmEvalText(text); assertDeepEq(instance.exports.run(), expected); } expectMultiValueResult(` (module (func (export "run") (result i32 i32 i32) (i32.const 0) (i32.const 52) (i32.const 10)))`, [0, 52, 10]); expectMultiValueResult(` (module (func (export "run") (result f32 f32 f32) (f32.const 0.5) (f32.const 52.5) (f32.const 10.5)))`, [0.5, 52.5, 10.5]); expectMultiValueResult(` (module (func (export "run") (result f64 f64 f64) (f64.const 0.5) (f64.const 52.5) (f64.const 10.5)))`, [0.5, 52.5, 10.5]); expectMultiValueResult(` (module (func (export "run") (result i32 i64 i32) (i32.const 0) (i64.const 52) (i32.const 10)))`, [0, 52n, 10]); expectMultiValueResult(` (module (func (export "run") (result i64 i32 i64) (i64.const 0) (i32.const 52) (i64.const 10)))`, [0n, 52, 10n]); expectMultiValueResult(` (module (func (export "run") (result i64 i64 i64) (i64.const 0) (i64.const 52) (i64.const 10)))`, [0n, 52n, 10n]);