Skip to content

Commit 58c3a39

Browse files
committed
LibWeb+LibWasm: Reject module instantiation with correct error type
The spec tells us to reject the promise with a RuntimeError instead of a LinkError whenever the module's start function fails during module instantiation. Fixes 1 WPT subtest in `wasm/core`.
1 parent 35ca7f8 commit 58c3a39

File tree

6 files changed

+128
-4
lines changed

6 files changed

+128
-4
lines changed

Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,11 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
387387
if (module.start_section().function().has_value()) {
388388
auto& functions = main_module_instance.functions();
389389
auto index = module.start_section().function()->index();
390-
if (functions.size() <= index.value()) {
390+
if (functions.size() <= index.value())
391391
return InstantiationError { ByteString::formatted("Start section function referenced invalid index {} of max {} entries", index.value(), functions.size()) };
392-
}
393392
auto result = invoke(functions[index.value()], {});
394393
if (result.is_trap())
395-
return InstantiationError { "Start function trapped", move(result.trap()) };
394+
return InstantiationError { "Start function trapped", move(result.trap()), InstantiationErrorSource::StartFunction };
396395
}
397396

398397
return InstantiationResult { move(main_module_instance_pointer) };

Libraries/LibWasm/AbstractMachine/AbstractMachine.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,15 @@ class Result {
260260
Variant<Vector<Value>, Trap> m_result;
261261
};
262262

263+
enum class InstantiationErrorSource : u8 {
264+
Linking,
265+
StartFunction,
266+
};
267+
263268
struct InstantiationError {
264269
ByteString error { "Unknown error" };
265270
Optional<Trap> relevant_trap {};
271+
InstantiationErrorSource source { InstantiationErrorSource::Linking };
266272
};
267273

268274
using ExternValue = Variant<FunctionAddress, TableAddress, MemoryAddress, GlobalAddress>;

Libraries/LibWeb/WebAssembly/WebAssembly.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,17 @@ JS::ThrowCompletionOr<NonnullOwnPtr<Wasm::ModuleInstance>> instantiate_module(JS
397397
return vm.throw_completion<LinkError>(MUST(builder.to_string()));
398398
}
399399

400+
// https://webassembly.github.io/spec/js-api/index.html#instantiate-the-core-of-a-webassembly-module
400401
auto instance_result = cache.abstract_machine().instantiate(module, link_result.release_value());
401402
if (instance_result.is_error()) {
402-
return vm.throw_completion<LinkError>(instance_result.error().error);
403+
auto instantiation_error = instance_result.release_error();
404+
switch (instantiation_error.source) {
405+
case Wasm::InstantiationErrorSource::Linking:
406+
return vm.throw_completion<LinkError>(instantiation_error.error);
407+
case Wasm::InstantiationErrorSource::StartFunction:
408+
return vm.throw_completion<RuntimeError>(instantiation_error.error);
409+
}
410+
VERIFY_NOT_REACHED();
403411
}
404412

405413
return instance_result.release_value();
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Harness status: OK
2+
3+
Found 27 tests
4+
5+
27 Pass
6+
Pass #1 Reinitialize the default imports
7+
Pass #2 Test that WebAssembly compilation fails
8+
Pass #3 Test that WebAssembly compilation fails
9+
Pass #4 Test that WebAssembly compilation fails
10+
Pass #5 Test that WebAssembly compilation fails
11+
Pass #6 Reinitialize the default imports
12+
Pass #7 Test that WebAssembly compilation fails
13+
Pass #8 Test that WebAssembly compilation fails
14+
Pass #9 Test that WebAssembly compilation fails
15+
Pass #10 Test that WebAssembly instantiation succeeds
16+
Pass #11 Test that a WebAssembly code returns a specific result
17+
Pass #12 Run a WebAssembly test without special assertions
18+
Pass #13 Test that a WebAssembly code returns a specific result
19+
Pass #14 Run a WebAssembly test without special assertions
20+
Pass #15 Test that a WebAssembly code returns a specific result
21+
Pass #16 Test that WebAssembly instantiation succeeds
22+
Pass #17 Test that a WebAssembly code returns a specific result
23+
Pass #18 Run a WebAssembly test without special assertions
24+
Pass #19 Test that a WebAssembly code returns a specific result
25+
Pass #20 Run a WebAssembly test without special assertions
26+
Pass #21 Test that a WebAssembly code returns a specific result
27+
Pass #22 Test that WebAssembly instantiation succeeds
28+
Pass #23 Test that WebAssembly instantiation succeeds
29+
Pass #24 Test that WebAssembly instantiation succeeds
30+
Pass #25 Test that WebAssembly instantiation fails
31+
Pass #26 Test that a WebAssembly module is uninstantiable
32+
Pass #27 Test that WebAssembly compilation fails
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
(function start_wast_js() {
2+
3+
// start.wast:1
4+
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x08\x81\x80\x80\x80\x00\x01\x0a\x88\x80\x80\x80\x00\x01\x82\x80\x80\x80\x00\x00\x0b");
5+
6+
// start.wast:6
7+
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x00\x01\x7f\x03\x82\x80\x80\x80\x00\x01\x00\x08\x81\x80\x80\x80\x00\x00\x0a\x8b\x80\x80\x80\x00\x01\x85\x80\x80\x80\x00\x00\x41\x00\x0f\x0b");
8+
9+
// start.wast:13
10+
assert_invalid("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80\x80\x00\x01\x60\x01\x7f\x00\x03\x82\x80\x80\x80\x00\x01\x00\x08\x81\x80\x80\x80\x00\x00\x0a\x88\x80\x80\x80\x00\x01\x82\x80\x80\x80\x00\x00\x0b");
11+
12+
// start.wast:21
13+
let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x88\x80\x80\x80\x00\x02\x60\x00\x00\x60\x00\x01\x7f\x03\x84\x80\x80\x80\x00\x03\x00\x01\x00\x05\x84\x80\x80\x80\x00\x01\x01\x01\x01\x07\x8d\x80\x80\x80\x00\x02\x03\x69\x6e\x63\x00\x00\x03\x67\x65\x74\x00\x01\x08\x81\x80\x80\x80\x00\x02\x0a\xaf\x80\x80\x80\x00\x03\x8f\x80\x80\x80\x00\x00\x41\x00\x41\x00\x2d\x00\x00\x41\x01\x6a\x3a\x00\x00\x0b\x88\x80\x80\x80\x00\x00\x41\x00\x2d\x00\x00\x0f\x0b\x88\x80\x80\x80\x00\x00\x10\x00\x10\x00\x10\x00\x0b\x0b\x87\x80\x80\x80\x00\x01\x00\x41\x00\x0b\x01\x41");
14+
15+
// start.wast:45
16+
assert_return(() => call($1, "get", []), 68);
17+
18+
// start.wast:46
19+
run(() => call($1, "inc", []));
20+
21+
// start.wast:47
22+
assert_return(() => call($1, "get", []), 69);
23+
24+
// start.wast:48
25+
run(() => call($1, "inc", []));
26+
27+
// start.wast:49
28+
assert_return(() => call($1, "get", []), 70);
29+
30+
// start.wast:51
31+
let $2 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x88\x80\x80\x80\x00\x02\x60\x00\x00\x60\x00\x01\x7f\x03\x84\x80\x80\x80\x00\x03\x00\x01\x00\x05\x84\x80\x80\x80\x00\x01\x01\x01\x01\x07\x8d\x80\x80\x80\x00\x02\x03\x69\x6e\x63\x00\x00\x03\x67\x65\x74\x00\x01\x08\x81\x80\x80\x80\x00\x02\x0a\xaf\x80\x80\x80\x00\x03\x8f\x80\x80\x80\x00\x00\x41\x00\x41\x00\x2d\x00\x00\x41\x01\x6a\x3a\x00\x00\x0b\x88\x80\x80\x80\x00\x00\x41\x00\x2d\x00\x00\x0f\x0b\x88\x80\x80\x80\x00\x00\x10\x00\x10\x00\x10\x00\x0b\x0b\x87\x80\x80\x80\x00\x01\x00\x41\x00\x0b\x01\x41");
32+
33+
// start.wast:74
34+
assert_return(() => call($2, "get", []), 68);
35+
36+
// start.wast:75
37+
run(() => call($2, "inc", []));
38+
39+
// start.wast:76
40+
assert_return(() => call($2, "get", []), 69);
41+
42+
// start.wast:77
43+
run(() => call($2, "inc", []));
44+
45+
// start.wast:78
46+
assert_return(() => call($2, "get", []), 70);
47+
48+
// start.wast:80
49+
let $3 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x88\x80\x80\x80\x00\x02\x60\x01\x7f\x00\x60\x00\x00\x02\x96\x80\x80\x80\x00\x01\x08\x73\x70\x65\x63\x74\x65\x73\x74\x09\x70\x72\x69\x6e\x74\x5f\x69\x33\x32\x00\x00\x03\x82\x80\x80\x80\x00\x01\x01\x08\x81\x80\x80\x80\x00\x01\x0a\x8c\x80\x80\x80\x00\x01\x86\x80\x80\x80\x00\x00\x41\x01\x10\x00\x0b");
50+
51+
// start.wast:86
52+
let $4 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x88\x80\x80\x80\x00\x02\x60\x01\x7f\x00\x60\x00\x00\x02\x96\x80\x80\x80\x00\x01\x08\x73\x70\x65\x63\x74\x65\x73\x74\x09\x70\x72\x69\x6e\x74\x5f\x69\x33\x32\x00\x00\x03\x82\x80\x80\x80\x00\x01\x01\x08\x81\x80\x80\x80\x00\x01\x0a\x8c\x80\x80\x80\x00\x01\x86\x80\x80\x80\x00\x00\x41\x02\x10\x00\x0b");
53+
54+
// start.wast:92
55+
let $5 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x02\x92\x80\x80\x80\x00\x01\x08\x73\x70\x65\x63\x74\x65\x73\x74\x05\x70\x72\x69\x6e\x74\x00\x00\x08\x81\x80\x80\x80\x00\x00");
56+
57+
// start.wast:97
58+
assert_uninstantiable("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x84\x80\x80\x80\x00\x01\x60\x00\x00\x03\x82\x80\x80\x80\x00\x01\x00\x08\x81\x80\x80\x80\x00\x00\x0a\x89\x80\x80\x80\x00\x01\x83\x80\x80\x80\x00\x00\x00\x0b");
59+
60+
// start.wast:102
61+
assert_malformed("\x3c\x6d\x61\x6c\x66\x6f\x72\x6d\x65\x64\x20\x71\x75\x6f\x74\x65\x3e");
62+
reinitializeRegistry();
63+
})();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>WebAssembly Web Platform Test</title>
6+
</head>
7+
<body>
8+
9+
<script src="../../resources/testharness.js"></script>
10+
<script src="../../resources/testharnessreport.js"></script>
11+
<script src="./js/harness/async_index.js"></script>
12+
13+
<div id=log></div>
14+
<script src="./js/start.wast.js"></script>
15+
</body>
16+
</html>

0 commit comments

Comments
 (0)