Last active
August 12, 2022 21:19
-
-
Save CraigglesO/6ef0ae00c3ff169822ae75b45141acd8 to your computer and use it in GitHub Desktop.
Zig using async/await in WASM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs') | |
const source = fs.readFileSync('./async.wasm') | |
function u32ToU8 (num) { | |
const resU32 = new Uint32Array([num]) | |
return new Uint8Array(resU32.buffer) | |
} | |
function getMemory (instance) { | |
return new Uint8Array(instance.exports.memory.buffer) | |
} | |
function asyncTimeout () { | |
return new Promise(resolve => { | |
setTimeout(() => { | |
resolve() | |
}, 1_000) | |
}) | |
} | |
function rand () { | |
return Math.floor(Math.random() * 100) + 1 | |
} | |
const mod = new WebAssembly.Module(source) | |
const instance = new WebAssembly.Instance(mod, { | |
env: { | |
memoryBase: 0, | |
tableBase: 0, | |
memory: new WebAssembly.Memory({ | |
initial: 512 | |
}), | |
printNum: (num) => { console.log(`The num is ${num}`) }, | |
printError: (err) => { console.log(`The error is ${err}`) }, | |
jsAsyncFnCall: async (frame, ptr) => { | |
console.log(frame, ptr) | |
await asyncTimeout() | |
const buf = u32ToU8(rand()) | |
const view = getMemory(instance) | |
const len = buf.byteLength | |
view.subarray(ptr, ptr + len).set(buf) | |
instance.exports.wasmResume(frame) | |
} | |
} | |
}) | |
const { wasmAsync } = instance.exports | |
wasmAsync() | |
wasmAsync() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const allocator = std.heap.page_allocator; | |
extern fn printNum(num: u32) void; | |
extern fn jsAsyncFnCall(store: *anyopaque, resPtr: *u32) void; | |
pub fn jsAsync () u32 { | |
var res: u32 = 0; | |
suspend { | |
jsAsyncFnCall(@frame(), &res); | |
} | |
return res; | |
} | |
pub fn jsAwait () void { | |
var frame = async jsAsync(); | |
printNum(await frame); | |
} | |
export fn wasmResume (frame: *anyopaque) callconv(.C) void { | |
resume @ptrCast(anyframe, @alignCast(4, frame)); | |
} | |
export fn wasmAsync () void { | |
const frame = allocator.create(@Frame(jsAwait)) catch return; | |
frame.* = async jsAwait(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
zig build-lib async.zig -target wasm32-freestanding -dynamic -O ReleaseSmall --strip
then
node async.js