Skip to content
Snippets Groups Projects
Commit 1d5a2ff8 authored by Cheng Shao's avatar Cheng Shao
Browse files

rts: rename prelude.js to prelude.mjs

This commit renames prelude.js to prelude.mjs for wasm backend rts
jsbits, and slightly adjusts the jsbits contents. This is for
preparing the implementation of dyld.mjs that contains wasm dynamic
linker logic, which needs to import prelude.mjs as a proper ESM
module.

(cherry picked from commit 71a471e7)
parent f95de541
No related branches found
No related tags found
No related merge requests found
......@@ -154,7 +154,7 @@ ghcLibDeps stage iplace = do
, "ghc-usage.txt"
, "ghci-usage.txt"
, "post-link.mjs"
, "prelude.js"
, "prelude.mjs"
]
cxxStdLib <- systemCxxStdLibConfPath (PackageDbLoc stage iplace)
return (cxxStdLib : ps)
......
......@@ -238,7 +238,7 @@ copyRules = do
copyFile ("utils/jsffi" -/- makeRelative prefix file) file
makeExecutable file
prefix -/- "prelude.js" <~ pure "utils/jsffi"
prefix -/- "prelude.mjs" <~ pure "utils/jsffi"
prefix -/- "html/**" <~ return "utils/haddock/haddock-api/resources"
prefix -/- "latex/**" <~ return "utils/haddock/haddock-api/resources"
......
......@@ -52,11 +52,14 @@ function parseSections(mod) {
return recs;
}
export async function postLink(mod) {
let src = await fs.readFile(path.join(import.meta.dirname, "prelude.js"), {
encoding: "utf-8",
});
let src = (
await fs.readFile(path.join(import.meta.dirname, "prelude.mjs"), {
encoding: "utf-8",
})
).replaceAll("export ", ""); // we only use it as code template, don't export stuff
// Keep this in sync with dyld.mjs!
src = `${src}\nexport default (__exports) => {`;
src = `${src}\nconst __ghc_wasm_jsffi_jsval_manager = new JSValManager();`;
src = `${src}\nconst __ghc_wasm_jsffi_finalization_registry = new FinalizationRegistry(sp => __exports.rts_freeStablePtr(sp));`;
......
......@@ -5,7 +5,7 @@
// Manage a mapping from unique 32-bit ids to actual JavaScript
// values.
class JSValManager {
export class JSValManager {
#lastk = 0;
#kv = new Map();
......@@ -49,47 +49,48 @@ class JSValManager {
}
}
// 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;
}
// deno
try {
// deno
return (await import("node:timers")).setImmediate;
} catch {
// browsers
const sm = new SetImmediate();
return (cb, ...args) => sm.setImmediate(cb, ...args);
} catch {}
// https://developer.mozilla.org/en-US/docs/Web/API/Scheduler/postTask
if (globalThis.scheduler) {
return (cb, ...args) => scheduler.postTask(() => cb(...args));
}
// 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);
}
}
const sm = new SetImmediate();
return (cb, ...args) => sm.setImmediate(cb, ...args);
})();
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment