-
Notifications
You must be signed in to change notification settings - Fork 0
/
pointfree-wasm.js
118 lines (107 loc) · 4.66 KB
/
pointfree-wasm.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// This file implements the JavaScript runtime logic for Haskell
// modules that use JSFFI. It is not an ESM module, but the template
// of one; the post-linker script will copy all contents into a new
// ESM module.
// Manage a mapping from unique 32-bit ids to actual JavaScript
// values.
class JSValManager {
#lastk = 0;
#kv = new Map();
constructor() {}
// Maybe just bump this.#lastk? For 64-bit ids that's sufficient,
// but better safe than sorry in the 32-bit case.
#allocKey() {
let k = this.#lastk;
while (true) {
if (!this.#kv.has(k)) {
this.#lastk = k;
return k;
}
k = (k + 1) | 0;
}
}
newJSVal(v) {
const k = this.#allocKey();
this.#kv.set(k, v);
return k;
}
// A separate has() call to ensure we can store undefined as a value
// too. Also, unconditionally check this since the check is cheap
// anyway, if the check fails then there's a use-after-free to be
// fixed.
getJSVal(k) {
if (!this.#kv.has(k)) {
throw new WebAssembly.RuntimeError(`getJSVal(${k})`);
}
return this.#kv.get(k);
}
// Check for double free as well.
freeJSVal(k) {
if (!this.#kv.delete(k)) {
throw new WebAssembly.RuntimeError(`freeJSVal(${k})`);
}
}
}
// A simple & fast setImmediate() implementation for browsers. It's
// not a drop-in replacement for node.js setImmediate() because:
// 1. There's no clearImmediate(), and setImmediate() doesn't return
// anything
// 2. There's no guarantee that callbacks scheduled by setImmediate()
// are executed in the same order (in fact it's the opposite lol),
// but you are never supposed to rely on this assumption anyway
class SetImmediate {
#fs = [];
#mc = new MessageChannel();
constructor() {
this.#mc.port1.addEventListener("message", () => {
this.#fs.pop()();
});
this.#mc.port1.start();
}
setImmediate(cb, ...args) {
this.#fs.push(() => cb(...args));
this.#mc.port2.postMessage(undefined);
}
}
// The actual setImmediate() to be used. This is a ESM module top
// level binding and doesn't pollute the globalThis namespace.
const setImmediate = await (async () => {
// https://developer.mozilla.org/en-US/docs/Web/API/Scheduler
if (globalThis.scheduler) {
return (cb, ...args) => scheduler.postTask(() => cb(...args));
}
// node, bun, or other scripts might have set this up in the browser
if (globalThis.setImmediate) {
return globalThis.setImmediate;
}
try {
// deno
return (await import("node:timers")).setImmediate;
} catch {
// browsers
const sm = new SetImmediate();
return (cb, ...args) => sm.setImmediate(cb, ...args);
}
})();
export default (__exports) => {
const __ghc_wasm_jsffi_jsval_manager = new JSValManager();
const __ghc_wasm_jsffi_finalization_registry = new FinalizationRegistry(sp => __exports.rts_freeStablePtr(sp));
return {
newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v),
getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k),
freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k),
scheduleWork: () => setImmediate(__exports.rts_schedulerLoop),
ZC1ZCpointfreezmwasmzm0zi1zminplacezmpointfreezmwasmZCPointfreeziWasmZC: ($1,$2) => ($1.push($2)),
ZC2ZCpointfreezmwasmzm0zi1zminplacezmpointfreezmwasmZCPointfreeziWasmZC: () => (new Array),
ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))),
ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.resolve($2)),
ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;},
ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => (`${$1.stack ? $1.stack : $1}`),
ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2) => ((new TextDecoder('utf-8', {fatal: true})).decode(new Uint8Array(__exports.memory.buffer, $1, $2))),
ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written),
ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => ($1.length),
ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => {if (!__ghc_wasm_jsffi_finalization_registry.unregister($1)) { throw new WebAssembly.RuntimeError('js_callback_unregister'); }},
ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC: ($1,$2) => ($1.then(() => __exports.rts_promiseResolveUnit($2), err => __exports.rts_promiseReject($2, err))),
ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))),
};
};