Fix silent failure of WebAssembly.instantiate() (#2548)

By making WASM compilation synchronous. We'll have to do more work to
make it properly async.
This commit is contained in:
Ryan Dahl 2019-06-20 09:04:34 -07:00 committed by GitHub
parent 6a5177dc11
commit f2c50fae84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 1 deletions

View file

@ -117,6 +117,13 @@ void deno_init() {
platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
// TODO(ry) This makes WASM compile synchronously. Eventually we should
// remove this to make it work asynchronously too. But that requires getting
// PumpMessageLoop and RunMicrotasks setup correctly.
// See https://github.com/denoland/deno/issues/2544
const char* argv[2] = {"", "--no-wasm-async-compilation"};
int argc = 2;
v8::V8::SetFlagsFromCommandLine(&argc, const_cast<char**>(argv), false);
}
}

View file

@ -159,7 +159,6 @@ TEST(LibDenoTest, CheckPromiseErrors) {
EXPECT_EQ(deno_last_exception(d), nullptr);
deno_execute(d, nullptr, "a.js", "CheckPromiseErrors()");
EXPECT_EQ(nullptr, deno_last_exception(d));
EXPECT_EQ(deno_last_exception(d), nullptr);
EXPECT_EQ(count, 1);
// We caught the exception. So still no errors after calling
// deno_check_promise_errors().
@ -261,3 +260,23 @@ TEST(LibDenoTest, SharedAtomics) {
EXPECT_EQ(s[2], 2);
deno_delete(d);
}
TEST(LibDenoTest, WasmInstantiate) {
static int count = 0;
auto recv_cb = [](auto _, auto buf, auto zero_copy_buf) {
EXPECT_EQ(buf.data_len, 1u);
EXPECT_EQ(buf.data_ptr[0], 42);
count++;
};
Deno* d = deno_new(deno_config{0, snapshot, empty, recv_cb, nullptr});
EXPECT_EQ(deno_last_exception(d), nullptr);
deno_execute(d, nullptr, "a.js", "WasmInstantiate()");
EXPECT_EQ(nullptr, deno_last_exception(d));
deno_check_promise_errors(d);
EXPECT_EQ(nullptr, deno_last_exception(d));
EXPECT_EQ(count, 3);
deno_delete(d);
}

View file

@ -219,3 +219,37 @@ global.LibDenoPrintInvalidArgument = () => {
assert(e.message === "Invalid Argument");
}
};
global.WasmInstantiate = () => {
// The following blob can be created by taking the following s-expr and pass
// it through wat2wasm.
// (module
// (func $add (param $a i32) (param $b i32) (result i32)
// local.get $a
// local.get $b
// i32.add)
// (export "add" (func $add))
// )
// prettier-ignore
const bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60,
0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01,
0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20,
0x00, 0x20, 0x01, 0x6a, 0x0b
]);
(async () => {
Deno.core.send(new Uint8Array([42]));
const wasm = await WebAssembly.instantiate(bytes);
Deno.core.send(new Uint8Array([42]));
const result = wasm.instance.exports.add(1, 3);
if (result != 4) {
throw Error("bad");
}
// To signal success, we send back a fixed buffer.
Deno.core.send(new Uint8Array([42]));
})();
};

27
tests/wasm_async.js Normal file
View file

@ -0,0 +1,27 @@
// The following blob can be created by taking the following s-expr and pass
// it through wat2wasm.
// (module
// (func $add (param $a i32) (param $b i32) (result i32)
// local.get $a
// local.get $b
// i32.add)
// (export "add" (func $add))
// )
// prettier-ignore
const bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60,
0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01,
0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20,
0x00, 0x20, 0x01, 0x6a, 0x0b
]);
async function main() {
let wasm = await WebAssembly.instantiate(bytes);
let result = wasm.instance.exports.add(1, 3);
console.log("1 + 3 =", result);
if (result != 4) {
throw Error("bad");
}
}
main();

1
tests/wasm_async.out Normal file
View file

@ -0,0 +1 @@
1 + 3 = 4

2
tests/wasm_async.test Normal file
View file

@ -0,0 +1,2 @@
args: tests/wasm_async.js
output: tests/wasm_async.out