From d7a35d19b7eacbcc9d980a4a46e512b121b1a66a Mon Sep 17 00:00:00 2001 From: Cheng Shao <terrorjack@type.dance> Date: Mon, 16 Sep 2024 06:08:19 +0000 Subject: [PATCH] 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 71a471e7495f1fbf6b44cfbe4e930c99131c583e) --- hadrian/src/Base.hs | 2 +- hadrian/src/Rules/Generate.hs | 2 +- utils/jsffi/post-link.mjs | 11 ++-- utils/jsffi/{prelude.js => prelude.mjs} | 69 +++++++++++++------------ 4 files changed, 44 insertions(+), 40 deletions(-) rename utils/jsffi/{prelude.js => prelude.mjs} (63%) diff --git a/hadrian/src/Base.hs b/hadrian/src/Base.hs index b12b717f66e..98c64ce1edd 100644 --- a/hadrian/src/Base.hs +++ b/hadrian/src/Base.hs @@ -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) diff --git a/hadrian/src/Rules/Generate.hs b/hadrian/src/Rules/Generate.hs index 5fde5ca742d..7c5b3452753 100644 --- a/hadrian/src/Rules/Generate.hs +++ b/hadrian/src/Rules/Generate.hs @@ -215,7 +215,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" diff --git a/utils/jsffi/post-link.mjs b/utils/jsffi/post-link.mjs index abd55622581..5de39fdc400 100755 --- a/utils/jsffi/post-link.mjs +++ b/utils/jsffi/post-link.mjs @@ -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));`; diff --git a/utils/jsffi/prelude.js b/utils/jsffi/prelude.mjs similarity index 63% rename from utils/jsffi/prelude.js rename to utils/jsffi/prelude.mjs index e54a2927901..c9cd6a447d4 100644 --- a/utils/jsffi/prelude.js +++ b/utils/jsffi/prelude.mjs @@ -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); })(); -- GitLab