From d5b30bbe62a79cda6ecba27be4edaf9a80f78897 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Sun, 12 Oct 2025 20:32:11 +0200 Subject: [PATCH 1/3] [interpreter] Catch failing string conversion in JS harness --- interpreter/script/js.ml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index f2d523e24c..e46e3854c7 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -161,6 +161,8 @@ function assert_return(action, loc, ...expected) { throw new Error(expected.length + " value(s) expected, got " + actual.length); } for (let i = 0; i < actual.length; ++i) { + let actual_i; + try { actual_i = "" + actual[i] } catch (e) { actual_i = typeof actual[i] } switch (expected[i]) { case "nan:canonical": case "nan:arithmetic": @@ -168,12 +170,12 @@ function assert_return(action, loc, ...expected) { // Note that JS can't reliably distinguish different NaN values, // so there's no good way to test that it's a canonical NaN. if (!Number.isNaN(actual[i])) { - throw new Error("Wasm NaN return value expected, got " + actual[i]); + throw new Error("Wasm NaN return value expected, got " + actual_i); }; return; case "ref.i31": if (typeof actual[i] !== "number" || (actual[i] & 0x7fffffff) !== actual[i]) { - throw new Error("Wasm i31 return value expected, got " + actual[i]); + throw new Error("Wasm i31 return value expected, got " + actual_i); }; return; case "ref.any": @@ -183,27 +185,27 @@ function assert_return(action, loc, ...expected) { // For now, JS can't distinguish exported Wasm GC values, // so we only test for object. if (typeof actual[i] !== "object") { - throw new Error("Wasm object return value expected, got " + actual[i]); + throw new Error("Wasm object return value expected, got " + actual_i); }; return; case "ref.func": if (typeof actual[i] !== "function") { - throw new Error("Wasm function return value expected, got " + actual[i]); + throw new Error("Wasm function return value expected, got " + actual_i); }; return; case "ref.extern": if (actual[i] === null) { - throw new Error("Wasm reference return value expected, got " + actual[i]); + throw new Error("Wasm reference return value expected, got " + actual_i); }; return; case "ref.null": if (actual[i] !== null) { - throw new Error("Wasm null return value expected, got " + actual[i]); + throw new Error("Wasm null return value expected, got " + actual_i); }; return; default: if (!Object.is(actual[i], expected[i])) { - throw new Error("Wasm return value " + expected[i] + " expected, got " + actual[i]); + throw new Error("Wasm return value " + expected[i] + " expected, got " + actual_i); }; } } From 06c100fc494ada1ad5375469fa05549b72a330fd Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Oct 2025 15:18:29 +0200 Subject: [PATCH 2/3] Catch failing string conversion in other harnesses --- test/harness/async_index.js | 14 ++++++++------ test/harness/sync_index.js | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/test/harness/async_index.js b/test/harness/async_index.js index 94de545dd5..5418624a56 100644 --- a/test/harness/async_index.js +++ b/test/harness/async_index.js @@ -318,16 +318,18 @@ function assert_return(action, source, ...expected) { throw new Error(expected.length + " value(s) expected, got " + actual.length); } for (let i = 0; i < actual.length; ++i) { + let actual_i; + try { actual_i = "" + actual[i] } catch (e) { actual_i = typeof actual[i] } switch (expected[i]) { case "nan:canonical": case "nan:arithmetic": case "nan:any": // Note that JS can't reliably distinguish different NaN values, // so there's no good way to test that it's a canonical NaN. - assert_true(Number.isNaN(actual[i]), `expected NaN, observed ${actual[i]}.`); + assert_true(Number.isNaN(actual[i]), `expected NaN, observed ${actual_i}.`); return; case "ref.i31": - assert_true(typeof actual[i] === "number" && (actual[i] & 0x7fffffff) === actual[i], `expected Wasm i31, got ${actual[i]}`); + assert_true(typeof actual[i] === "number" && (actual[i] & 0x7fffffff) === actual[i], `expected Wasm i31, got ${actual_i}`); return; case "ref.any": case "ref.eq": @@ -335,16 +337,16 @@ function assert_return(action, source, ...expected) { case "ref.array": // For now, JS can't distinguish exported Wasm GC values, // so we only test for object. - assert_true(typeof actual[i] === "object", `expected Wasm GC object, got ${actual[i]}`); + assert_true(typeof actual[i] === "object", `expected Wasm GC object, got ${actual_i}`); return; case "ref.func": - assert_true(typeof actual[i] === "function", `expected Wasm function, got ${actual[i]}`); + assert_true(typeof actual[i] === "function", `expected Wasm function, got ${actual_i}`); return; case "ref.extern": - assert_true(actual[i] !== null, `expected Wasm reference, got ${actual[i]}`); + assert_true(actual[i] !== null, `expected Wasm reference, got ${actual_i}`); return; case "ref.null": - assert_true(actual[i] === null, `expected Wasm null reference, got ${actual[i]}`); + assert_true(actual[i] === null, `expected Wasm null reference, got ${actual_i}`); return; default: assert_equals(actual[i], expected[i], loc); diff --git a/test/harness/sync_index.js b/test/harness/sync_index.js index a984be4964..0785ae020b 100644 --- a/test/harness/sync_index.js +++ b/test/harness/sync_index.js @@ -387,16 +387,18 @@ function assert_return(action, source, ...expected) { return; expected[i] = expected[i].value; } + let actual_i; + try { actual_i = "" + actual[i] } catch (e) { actual_i = typeof actual[i] } switch (expected[i]) { case "nan:canonical": case "nan:arithmetic": case "nan:any": // Note that JS can't reliably distinguish different NaN values, // so there's no good way to test that it's a canonical NaN. - assert_true(Number.isNaN(actual[i]), `expected NaN, observed ${actual[i]}.`); + assert_true(Number.isNaN(actual[i]), `expected NaN, observed ${actual_i}.`); return; case "ref.i31": - assert_true(typeof actual[i] === "number" && (actual[i] & 0x7fffffff) === actual[i], `expected Wasm i31, got ${actual[i]}`); + assert_true(typeof actual[i] === "number" && (actual[i] & 0x7fffffff) === actual[i], `expected Wasm i31, got ${actual_i}`); return; case "ref.any": case "ref.eq": @@ -404,16 +406,16 @@ function assert_return(action, source, ...expected) { case "ref.array": // For now, JS can't distinguish exported Wasm GC values, // so we only test for object. - assert_true(typeof actual[i] === "object", `expected Wasm GC object, got ${actual[i]}`); + assert_true(typeof actual[i] === "object", `expected Wasm GC object, got ${actual_i}`); return; case "ref.func": - assert_true(typeof actual[i] === "function", `expected Wasm function, got ${actual[i]}`); + assert_true(typeof actual[i] === "function", `expected Wasm function, got ${actual_i}`); return; case "ref.extern": - assert_true(actual[i] !== null, `expected Wasm reference, got ${actual[i]}`); + assert_true(actual[i] !== null, `expected Wasm reference, got ${actual_i}`); return; case "ref.null": - assert_true(actual[i] === null, `expected Wasm null reference, got ${actual[i]}`); + assert_true(actual[i] === null, `expected Wasm null reference, got ${actual_i}`); return; default: assert_equals(actual[i], expected[i]); From d0aa1efa5c33461577cb611eef962fefea20bcfc Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 14 Oct 2025 15:48:39 +0200 Subject: [PATCH 3/3] Eps --- interpreter/script/js.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index e46e3854c7..ae4b5ac127 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -162,7 +162,7 @@ function assert_return(action, loc, ...expected) { } for (let i = 0; i < actual.length; ++i) { let actual_i; - try { actual_i = "" + actual[i] } catch (e) { actual_i = typeof actual[i] } + try { actual_i = "" + actual[i] } catch { actual_i = typeof actual[i] } switch (expected[i]) { case "nan:canonical": case "nan:arithmetic":