diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index 6d70f1fb6a..b0be4384b1 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -53,7 +53,7 @@ function register(name, instance) { registry[name] = instance.exports; } -function module(bytes, valid = true) { +function module(bytes, loc, valid = true) { let buffer = new ArrayBuffer(bytes.length); let view = new Uint8Array(buffer); for (let i = 0; i < bytes.length; ++i) { @@ -92,8 +92,8 @@ function run(action) { action(); } -function assert_malformed(bytes) { - try { module(bytes, false) } catch (e) { +function assert_malformed(bytes, loc) { + try { module(bytes, loc, false) } catch (e) { if (e instanceof WebAssembly.CompileError) return; } throw new Error("Wasm decoding failure expected"); @@ -103,8 +103,8 @@ function assert_malformed_custom(bytes) { return; } -function assert_invalid(bytes) { - try { module(bytes, false) } catch (e) { +function assert_invalid(bytes, loc) { + try { module(bytes, loc, false) } catch (e) { if (e instanceof WebAssembly.CompileError) return; } throw new Error("Wasm validation failure expected"); @@ -128,7 +128,7 @@ function assert_uninstantiable(mod) { throw new Error("Wasm trap expected"); } -function assert_trap(action) { +function assert_trap(action, loc) { try { action() } catch (e) { if (e instanceof WebAssembly.RuntimeError) return; } @@ -150,7 +150,7 @@ function assert_exhaustion(action) { throw new Error("Wasm resource exhaustion expected"); } -function assert_return(action, ...expected) { +function assert_return(action, loc, ...expected) { let actual = action(); if (actual === undefined) { actual = []; @@ -749,7 +749,7 @@ let rec of_definition def = let of_wrapper env x_opt name wrap_action wrap_assertion at = let x = of_inst_opt env x_opt in let bs = wrap name wrap_action wrap_assertion at in - "call(instance(module(" ^ of_bytes bs ^ "), " ^ + "call(instance(module(" ^ of_bytes bs ^ ", \"wrapper\"), " ^ "exports(" ^ x ^ ")), " ^ " \"run\", [])" let of_action env act = @@ -775,9 +775,9 @@ let of_action env act = | _ -> None ) -let of_assertion' env act name args wrapper_opt = +let of_assertion' env act loc name args wrapper_opt = let act_js, act_wrapper_opt = of_action env act in - let js = name ^ "(() => " ^ act_js ^ String.concat ", " ("" :: args) ^ ")" in + let js = name ^ "(() => " ^ act_js ^ loc ^ String.concat ", " ("" :: args) ^ ")" in match act_wrapper_opt with | None -> js ^ ";" | Some (act_wrapper, out) -> @@ -785,35 +785,40 @@ let of_assertion' env act name args wrapper_opt = match wrapper_opt with | None -> name, run | Some wrapper -> "run", wrapper - in run_name ^ "(() => " ^ act_wrapper (wrapper out) act.at ^ "); // " ^ js + in run_name ^ "(() => " ^ act_wrapper (wrapper out) act.at ^ loc ^ "); // " ^ js let of_assertion env ass = + let loc = Filename.basename ass.at.left.file ^ + ":" ^ string_of_int ass.at.left.line in + let loc_as_arg = ", \"" ^ String.escaped loc ^ "\"" in match ass.it with | AssertMalformed (def, _) -> - "assert_malformed(" ^ of_definition def ^ ");" + "assert_malformed(" ^ of_definition def ^ loc_as_arg ^ ");" | AssertMalformedCustom (def, _) -> - "assert_malformed_custom(" ^ of_definition def ^ ");" + "assert_malformed_custom(" ^ of_definition def ^ loc_as_arg ^ ");" | AssertInvalid (def, _) -> - "assert_invalid(" ^ of_definition def ^ ");" + "assert_invalid(" ^ of_definition def ^ loc_as_arg ^ ");" | AssertInvalidCustom (def, _) -> - "assert_invalid_custom(" ^ of_definition def ^ ");" + "assert_invalid_custom(" ^ of_definition def ^ loc_as_arg ^ ");" | AssertUnlinkable (x_opt, _) -> "assert_unlinkable(" ^ of_mod_opt env x_opt ^ ");" | AssertUninstantiable (x_opt, _) -> "assert_uninstantiable(" ^ of_mod_opt env x_opt ^ ");" | AssertReturn (act, ress) -> - of_assertion' env act "assert_return" (List.map of_result ress) + of_assertion' env act loc_as_arg "assert_return" (List.map of_result ress) (Some (assert_return ress)) | AssertTrap (act, _) -> - of_assertion' env act "assert_trap" [] None + of_assertion' env act loc_as_arg "assert_trap" [] None | AssertExhaustion (act, _) -> - of_assertion' env act "assert_exhaustion" [] None + of_assertion' env act loc_as_arg "assert_exhaustion" [] None | AssertException act -> - of_assertion' env act "assert_exception" [] None + of_assertion' env act loc_as_arg "assert_exception" [] None let of_command env cmd = - "\n// " ^ Filename.basename cmd.at.left.file ^ - ":" ^ string_of_int cmd.at.left.line ^ "\n" ^ + let loc = String.escaped (Filename.basename cmd.at.left.file ^ + ":" ^ string_of_int cmd.at.left.line) in + let loc_as_arg = ", \"" ^ loc ^ "\"" in + "\n// " ^ loc ^ "\n" ^ match cmd.it with | Module (x_opt, def) -> let rec unquote def = @@ -823,7 +828,7 @@ let of_command env cmd = | Quoted (_, s) -> unquote (snd (Parse.Module.parse_string ~offset:s.at s.it)) in bind_mod env x_opt (unquote def); - "let " ^ current_mod env ^ " = module(" ^ of_definition def ^ ");\n" ^ + "let " ^ current_mod env ^ " = module(" ^ of_definition def ^ loc_as_arg ^ ");\n" ^ (if x_opt = None then "" else "let " ^ of_mod_opt env x_opt ^ " = " ^ current_mod env ^ ";\n") | Instance (x1_opt, x2_opt) -> @@ -835,7 +840,7 @@ let of_command env cmd = | Register (name, x_opt) -> "register(" ^ of_name name ^ ", " ^ of_inst_opt env x_opt ^ ")\n" | Action act -> - of_assertion' env act "run" [] None ^ "\n" + of_assertion' env act loc_as_arg "run" [] None ^ "\n" | Assertion ass -> of_assertion env ass ^ "\n" | Meta _ -> assert false diff --git a/test/harness/async_index.js b/test/harness/async_index.js index 8a01b21211..7b4fcd1ae4 100644 --- a/test/harness/async_index.js +++ b/test/harness/async_index.js @@ -150,10 +150,10 @@ function binary(bytes) { /** * Returns a compiled module, or throws if there was an error at compilation. */ -function module(bytes, valid = true) { - const test = valid - ? "Test that WebAssembly compilation succeeds" - : "Test that WebAssembly compilation fails"; +function module(bytes, source, valid = true) { + const test = `${ valid ? "Test that WebAssembly compilation succeeds" : + "Test that WebAssembly compilation fails"} (${source})`; + const loc = new Error().stack.toString().replace("Error", ""); let buffer = binary(bytes); let validated = WebAssembly.validate(buffer); @@ -167,6 +167,7 @@ function module(bytes, valid = true) { uniqueTest(_ => { assert_true(valid, loc); }, test); + module.source = source; return module; }, error => { @@ -181,26 +182,27 @@ function module(bytes, valid = true) { return chain; } -function assert_invalid(bytes) { - module(bytes, EXPECT_INVALID); +function assert_invalid(bytes, source) { + module(bytes, source, EXPECT_INVALID); } const assert_malformed = assert_invalid; -function assert_invalid_custom(bytes) { - module(bytes); +function assert_invalid_custom(bytes, source) { + module(bytes, source); } const assert_malformed_custom = assert_invalid_custom; function instance(module, imports, valid = true) { - const test = valid + let test = valid ? "Test that WebAssembly instantiation succeeds" : "Test that WebAssembly instantiation fails"; const loc = new Error().stack.toString().replace("Error", ""); chain = Promise.all([module, imports, chain]) .then(values => { let imports = values[1] ? values[1] : registry; + test += ` (${values[0].source})`; return WebAssembly.instantiate(values[0], imports); }) .then( @@ -235,8 +237,8 @@ function call(instance, name, args) { }); } -function run(action) { - const test = "Run a WebAssembly test without special assertions"; +function run(action, source) { + const test = `Run a WebAssembly test without special assertions (${source})`; const loc = new Error().stack.toString().replace("Error", ""); chain = Promise.all([chain, action()]) .then( @@ -256,8 +258,8 @@ function run(action) { .catch(_ => {}); } -function assert_trap(action) { - const test = "Test that a WebAssembly code traps"; +function assert_trap(action, source) { + const test = `Test that a WebAssembly code traps (${source})`; const loc = new Error().stack.toString().replace("Error", ""); chain = Promise.all([chain, action()]) .then( @@ -279,8 +281,8 @@ function assert_trap(action) { .catch(_ => {}); } -function assert_return(action, ...expected) { - const test = "Test that a WebAssembly code returns a specific result"; +function assert_return(action, source, ...expected) { + const test = `Test that a WebAssembly code returns a specific result (${source})`; const loc = new Error().stack.toString().replace("Error", ""); chain = Promise.all([action(), chain]) .then( diff --git a/test/harness/sync_index.js b/test/harness/sync_index.js index 5c4549be2e..77f601f590 100644 --- a/test/harness/sync_index.js +++ b/test/harness/sync_index.js @@ -150,7 +150,7 @@ function binary(bytes) { /** * Returns a compiled module, or throws if there was an error at compilation. */ -function module(bytes, valid = true) { +function module(bytes, source, valid = true) { let buffer = binary(bytes); let validated; @@ -176,6 +176,7 @@ function module(bytes, valid = true) { let module; try { module = new WebAssembly.Module(buffer); + module.source = source; } catch(e) { if (valid) throw new Error('WebAssembly.Module ctor unexpectedly throws ${typeof e}: ${e}${e.stack}'); @@ -189,32 +190,32 @@ function uniqueTest(func, desc) { test(func, testNum() + desc); } -function assert_invalid(bytes) { +function assert_invalid(bytes, source) { uniqueTest(() => { try { - module(bytes, /* valid */ false); + module(bytes, source, /* valid */ false); throw new Error('did not fail'); } catch(e) { assert_true(e instanceof WebAssembly.CompileError, "expected invalid failure:"); } - }, "A wast module that should be invalid or malformed."); + }, `A wast module that should be invalid or malformed. (${source})`); } const assert_malformed = assert_invalid; -function assert_invalid_custom(bytes) { +function assert_invalid_custom(bytes, source) { uniqueTest(() => { try { - module(bytes, /* valid */ true); + module(bytes, source, /* valid */ true); } catch(e) { throw new Error('failed on custom section error'); } - }, "A wast module that should have an invalid or malformed custom section."); + }, `A wast module that should have an invalid or malformed custom section. (${source})`); } const assert_malformed_custom = assert_invalid_custom; -function instance(mod, imports = registry, valid = true) { +function instance(module, imports = registry, valid = true) { if (imports instanceof Result) { if (imports.isError()) return imports; @@ -225,7 +226,7 @@ function instance(mod, imports = registry, valid = true) { let i; try { - i = new WebAssembly.Instance(mod, imports); + i = new WebAssembly.Instance(module, imports); } catch(e) { err = e; } @@ -234,7 +235,7 @@ function instance(mod, imports = registry, valid = true) { uniqueTest(() => { let instantiated = err === null; assert_true(instantiated, err); - }, "module successfully instantiated"); + }, `module successfully instantiated (${module.source})`); } return err !== null ? ErrorResult(err) : ValueResult(i); @@ -285,7 +286,7 @@ function exports(instance) { return ValueResult({ module: instance.value.exports, spectest: registry.spectest }); } -function run(action) { +function run(action, source) { let result = action(); _assert(result instanceof Result); @@ -293,7 +294,7 @@ function run(action) { uniqueTest(() => { if (result.isError()) throw result.value; - }, "A wast test that runs without any special assertion."); + }, `A wast test that runs without any special assertion. (${source})`); } function assert_unlinkable(bytes) { @@ -324,7 +325,7 @@ function assert_uninstantiable(bytes) { }, "A wast module that is uninstantiable."); } -function assert_trap(action) { +function assert_trap(action, source) { let result = action(); _assert(result instanceof Result); @@ -335,7 +336,7 @@ function assert_trap(action) { let e = result.value; assert_true(e instanceof WebAssembly.RuntimeError, `expected runtime error, observed ${e}:`); } - }, "A wast module that must trap at runtime."); + }, `A wast module that must trap at runtime. (${source})`); } let StackOverflow; @@ -355,7 +356,7 @@ function assert_exhaustion(action) { }, "A wast module that must exhaust the stack space."); } -function assert_return(action, ...expected) { +function assert_return(action, source, ...expected) { let result = action(); _assert(result instanceof Result); @@ -408,7 +409,7 @@ function assert_return(action, ...expected) { assert_equals(actual[i], expected[i]); } } - }, "A wast module that must return a particular value."); + }, `A wast module that must return a particular value. (${source})`); } function assert_return_nan(action) {