107 lines
3.4 KiB
TypeScript
107 lines
3.4 KiB
TypeScript
import { addImportsToImports, Imports } from "./imports.js";
|
|
import { Exports } from "./exports.js";
|
|
import { getWasm, addWasiToImports } from "./helpers.js";
|
|
// @ts-ignore
|
|
import * as assert from 'assert';
|
|
|
|
function promiseChannel(): [Promise<void>, () => void] {
|
|
let resolveCallback = null;
|
|
const promise = new Promise((resolve, reject) => resolveCallback = resolve);
|
|
// @ts-ignore
|
|
return [promise, resolveCallback];
|
|
}
|
|
|
|
async function run() {
|
|
const importObj = {};
|
|
let hit = false;
|
|
|
|
const [concurrentPromise, resolveConcurrent] = promiseChannel();
|
|
const [unblockConcurrent1, resolveUnblockConcurrent1] = promiseChannel();
|
|
const [unblockConcurrent2, resolveUnblockConcurrent2] = promiseChannel();
|
|
const [unblockConcurrent3, resolveUnblockConcurrent3] = promiseChannel();
|
|
|
|
const imports: Imports = {
|
|
async thunk() {
|
|
if (hit) {
|
|
console.log('second time in thunk, throwing an error');
|
|
throw new Error('catch me');
|
|
} else {
|
|
console.log('first time in thunk');
|
|
await some_helper();
|
|
console.log('waited on the helper, returning from host thunk');
|
|
hit = true;
|
|
}
|
|
},
|
|
|
|
async concurrent1(val) {
|
|
console.log('wasm called concurrent1');
|
|
assert.equal(val, 1);
|
|
resolveUnblockConcurrent1();
|
|
console.log('concurrent1 to reenter back into the host');
|
|
await concurrentPromise;
|
|
console.log('concurrent1 returning to wasm');
|
|
return 11;
|
|
},
|
|
async concurrent2(val) {
|
|
console.log('wasm called concurrent2');
|
|
assert.equal(val, 2);
|
|
resolveUnblockConcurrent2();
|
|
console.log('concurrent2 to reenter back into the host');
|
|
await concurrentPromise;
|
|
console.log('concurrent2 returning to wasm');
|
|
return 12;
|
|
},
|
|
async concurrent3(val) {
|
|
console.log('wasm called concurrent3');
|
|
assert.equal(val, 3);
|
|
resolveUnblockConcurrent3();
|
|
console.log('concurrent3 to reenter back into the host');
|
|
await concurrentPromise;
|
|
console.log('concurrent3 returning to wasm');
|
|
return 13;
|
|
},
|
|
};
|
|
let instance: WebAssembly.Instance;
|
|
addImportsToImports(importObj, imports, name => instance.exports[name]);
|
|
const wasi = addWasiToImports(importObj);
|
|
|
|
const wasm = new Exports();
|
|
await wasm.instantiate(getWasm(), importObj);
|
|
wasi.start(wasm.instance);
|
|
instance = wasm.instance;
|
|
|
|
const initBytes = wasm.allocatedBytes();
|
|
console.log("calling initial async function");
|
|
await wasm.thunk();
|
|
assert.ok(hit, "import not called");
|
|
assert.equal(initBytes, wasm.allocatedBytes());
|
|
|
|
// Make sure that exceptions on the host make their way back to whomever's
|
|
// doing the actual `await`
|
|
try {
|
|
console.log('executing thunk export a second time');
|
|
await wasm.thunk();
|
|
throw new Error('expected an error to get thrown');
|
|
} catch (e) {
|
|
const err = e as Error;
|
|
console.log('caught error with', err.message);
|
|
assert.equal(err.message, 'catch me');
|
|
}
|
|
|
|
console.log('entering wasm');
|
|
const concurrentWasm = wasm.testConcurrent();
|
|
console.log('waiting for wasm to enter the host');
|
|
await unblockConcurrent1;
|
|
await unblockConcurrent2;
|
|
await unblockConcurrent3;
|
|
console.log('allowing host functions to finish');
|
|
resolveConcurrent();
|
|
console.log('waiting on host functions');
|
|
await concurrentWasm;
|
|
console.log('concurrent wasm finished');
|
|
}
|
|
|
|
async function some_helper() {}
|
|
|
|
await run()
|