UNPKG

2.69 kBJavaScriptView Raw
1import { assert, assertEquals } from "../deps/deno.land/std@0.134.0/testing/asserts.js";
2/**
3 * @typedef {object} WasmExports
4 * @property {WebAssembly.Memory} memory
5 * @property {function} asyncify_get_state
6 * @property {function} asyncify_start_unwind
7 * @property {function} asyncify_stop_unwind
8 * @property {function} asyncify_start_rewind
9 * @property {function} asyncify_stop_rewind
10 */
11/**
12 * @type {WasmExports}
13 */
14let wasm;
15/**
16 * @param {WasmExports} wasmExports
17 */
18function setWasmExports(wasmExports) {
19 wasm = wasmExports;
20}
21/**
22 * @type {Int32Array}
23 */
24let cachedInt32Memory = null;
25/**
26 * @returns {Int32Array}
27 */
28function getInt32Memory() {
29 if (cachedInt32Memory === null ||
30 cachedInt32Memory.buffer !== wasm.memory.buffer) {
31 cachedInt32Memory = new Int32Array(wasm.memory.buffer);
32 }
33 return cachedInt32Memory;
34}
35// https://github.com/WebAssembly/binaryen/blob/fb9de9d391a7272548dcc41cd8229076189d7398/src/passes/Asyncify.cpp#L99
36const State = {
37 NONE: 0,
38 UNWINDING: 1,
39 REWINDING: 2,
40};
41function assertNoneState() {
42 assertEquals(wasm.asyncify_get_state(), State.NONE);
43}
44/**
45 * Maps `HTMLRewriter`s (their `asyncifyStackPtr`s) to `Promise`s.
46 * `asyncifyStackPtr` acts as unique reference to `HTMLRewriter`.
47 * Each rewriter MUST have AT MOST ONE pending promise at any time.
48 * @type {Map<number, Promise>}
49 */
50const promises = new Map();
51/**
52 * @param {number} stackPtr
53 * @param {Promise} promise
54 */
55function awaitPromise(stackPtr, promise) {
56 if (wasm.asyncify_get_state() === State.REWINDING) {
57 wasm.asyncify_stop_rewind();
58 return;
59 }
60 assertNoneState();
61 // https://github.com/WebAssembly/binaryen/blob/fb9de9d391a7272548dcc41cd8229076189d7398/src/passes/Asyncify.cpp#L106
62 assertEquals(stackPtr % 4, 0);
63 getInt32Memory().set([stackPtr + 8, stackPtr + 1024], stackPtr / 4);
64 wasm.asyncify_start_unwind(stackPtr);
65 assert(!promises.has(stackPtr));
66 promises.set(stackPtr, promise);
67}
68/**
69 * @param {HTMLRewriter} rewriter
70 * @param {Function} fn
71 * @param args
72 */
73async function wrap(rewriter, fn, ...args) {
74 const stackPtr = rewriter.asyncifyStackPtr;
75 assertNoneState();
76 let result = fn(...args);
77 while (wasm.asyncify_get_state() === State.UNWINDING) {
78 wasm.asyncify_stop_unwind();
79 assertNoneState();
80 assert(promises.has(stackPtr));
81 await promises.get(stackPtr);
82 promises.delete(stackPtr);
83 assertNoneState();
84 wasm.asyncify_start_rewind(stackPtr);
85 result = fn();
86 }
87 assertNoneState();
88 return result;
89}
90export { awaitPromise, setWasmExports, wrap };
91//# sourceMappingURL=asyncify.js.map
\No newline at end of file