Skip to content

Instantly share code, notes, and snippets.

@cdetrio
Created December 31, 2017 01:09
Show Gist options
  • Save cdetrio/7f5486004b0054b5c08e0496cf3ab21f to your computer and use it in GitHub Desktop.
Save cdetrio/7f5486004b0054b5c08e0496cf3ab21f to your computer and use it in GitHub Desktop.
async wasm imports don't work
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Async wasm doesnt work</title>
</head>
<script>
/*
// wasm code:
(module
(func $some_i32 (import "env" "some_func") (result i32))
(func $some_async_i32 (import "env" "some_func_doing_async") (result i32))
(func $test (param $p1 i32) (result i32)
(get_local $p1)
(if (result i32)
;; pass 55 as the $p1 param to $test to call import function $some_i32
;; pass anything else to call the import function $some_async_i32
(i32.ne (i32.const 55))
(then
;; call the imported function $some_async_i32 to get a number
;; whatever $some_async_i32 returns is left on the stack,
;; and is then returned as the result of $test
(call $some_async_i32)
)
(else
(call $some_i32)
;; (i32.const 88))) return a constant
)
)
)
(export "testFunc" (func $test))
)
*/
/*
// **** paste wasm and js code into wat2wasm:
https://cdn.rawgit.com/WebAssembly/wabt/aae5a4b7/demo/wat2wasm/
const importFunctions = {
env: {
some_func: function() { return 88; },
some_func_doing_async: function() { return Promise.resolve(99); }
}
};
const wasmInstance = new WebAssembly.Instance(wasmModule, importFunctions);
const { testFunc } = wasmInstance.exports;
console.log(testFunc(55)); // call some_func import
console.log(testFunc(3)); // call async import
*/
async function foo() {
// some function that does async work to get a result
return 99;
}
const importFunctions = {
env: {
some_func: function() { return 88; }, // synchronous return works
some_func_doing_async: function() { return foo(); }, // async return doesnt work
// some_func_doing_async: function() { return Promise.resolve(99); }, // promise doesnt work
}
};
fetch('asyncexample.wasm').then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importFunctions)
).then(w => {
console.log('synchronous wasm import returns:', w.instance.exports.testFunc(55)); // prints 88
console.log('async wasm import returned:', w.instance.exports.testFunc(3)); // prints value returned by some_func_doing_async
});
</script>
<body>
</body>
</html>
@cdetrio
Copy link
Author

cdetrio commented Dec 31, 2017

See related issue WebAssembly/design#720

@s1na
Copy link

s1na commented Jan 24, 2019

Update: This doesn't work in browser (when using browserify)

Tried this quick work-around, wasm blocks on calling the async function (via deasync), and then returns the correct result. Meanwhile, node can process other events (as shown by the setTimeout at the end):

const fs = require('fs')
const deasync = require('deasync')

const buf = fs.readFileSync('./esimple.wasm')

const myAsync = (cb) => {
  setTimeout(() => cb(null, 99), 1000)
}

const myDeasynced = deasync(myAsync)

const importFunctions = {
  env: {
    some_func: function() { return 88 },
    some_func_doing_async: function() {
      return myDeasynced()
    }
  }
}

WebAssembly.instantiate(buf, importFunctions).then((result) => {
  const { testFunc } = result.instance.exports
  console.log(testFunc(55)) // call some_func import
  console.log(testFunc(3)) // call async import
})

setTimeout(() => console.log('other event'), 300)

This logs:

88
other event
99

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment