///|
/// Reset JS-side runtime globals between WebSocket sessions.
extern "js" fn reset_runtime_js_state() -> Unit =
  #| () => {
  #|   try {
  #|     globalThis.__bidiCurrentContext = "default-context";
  #|     globalThis.__bidiContextWindows = new Map();
  #|     globalThis.__bidiContextViewportState = new Map();
  #|     const installWindowGlobalSync = () => {
  #|       if (typeof globalThis.__bidiSyncWindowPropertiesToGlobal === "function") return;
  #|       const reserved = new Set([
  #|         "window", "self", "parent", "top", "frames",
  #|         "document", "location", "navigator", "history",
  #|         "screen", "matchMedia",
  #|         "innerWidth", "innerHeight", "outerWidth", "outerHeight",
  #|         "devicePixelRatio", "pageXOffset", "pageYOffset",
  #|         "localStorage", "sessionStorage",
  #|         "alert", "confirm", "prompt", "console", "performance", "crypto",
  #|         "setTimeout", "clearTimeout", "setInterval", "clearInterval",
  #|         "requestAnimationFrame", "cancelAnimationFrame", "queueMicrotask",
  #|         "fetch", "Response", "Request", "Headers", "Blob", "FormData",
  #|         "URL", "URLSearchParams",
  #|         "getComputedStyle", "matchMedia", "Event", "UIEvent", "MouseEvent",
  #|         "PointerEvent", "FocusEvent", "KeyboardEvent", "InputEvent",
  #|         "CompositionEvent", "CustomEvent", "MessageEvent", "StorageEvent",
  #|         "DragEvent", "ClipboardEvent", "DataTransfer", "DOMParser",
  #|         "DOMException", "Node", "Attr", "Element", "HTMLElement", "Document",
  #|         // Observer APIs shimmed by bidi_runtime_eval.mbt. Without
  #|         // these, the per-eval window→globalThis sync would clear them.
  #|         "IntersectionObserver", "ResizeObserver", "MutationObserver",
  #|         // Network primitives provided natively by Node 22+.
  #|         "WebSocket", "EventSource",
  #|         // File upload surface (Blob/File native in Node 22, FileReader
  #|         // shimmed by bidi_runtime_eval.mbt).
  #|         "Blob", "File", "FileReader", "FileList",
  #|       ]);
  #|       globalThis.__bidiSyncWindowPropertiesToGlobal = (win) => {
  #|         const source = win && typeof win === "object" ? win : globalThis.window;
  #|         if (!source || source === globalThis || typeof source !== "object") return;
  #|         const syncedKeys = globalThis.__bidiSyncedWindowKeys instanceof Set
  #|           ? globalThis.__bidiSyncedWindowKeys
  #|           : (globalThis.__bidiSyncedWindowKeys = new Set());
  #|         for (const key of Array.from(syncedKeys)) {
  #|           if (reserved.has(key) || String(key).startsWith("__bidi")) {
  #|             syncedKeys.delete(key);
  #|             continue;
  #|           }
  #|           if (!Object.prototype.hasOwnProperty.call(source, key)) {
  #|             try { delete globalThis[key]; } catch (_e) {}
  #|             syncedKeys.delete(key);
  #|           }
  #|         }
  #|         for (const key of Object.keys(source)) {
  #|           if (reserved.has(key) || String(key).startsWith("__bidi")) continue;
  #|           let value;
  #|           try { value = source[key]; } catch (_e) { continue; }
  #|           try {
  #|             Object.defineProperty(globalThis, key, {
  #|               configurable: true,
  #|               enumerable: true,
  #|               writable: true,
  #|               value,
  #|             });
  #|           } catch (_e) {
  #|             try { globalThis[key] = value; } catch (_e2) {}
  #|           }
  #|           syncedKeys.add(key);
  #|         }
  #|       };
  #|     };
  #|     installWindowGlobalSync();
  #|     const installContextWindowApi = () => {
  #|       if (typeof globalThis.__bidiInstallContextWindowApi === "function") return;
  #|       const nativeTimers = globalThis.__bidiNativeWindowTimers || {
  #|         setTimeout: typeof globalThis.setTimeout === "function" ? globalThis.setTimeout : undefined,
  #|         clearTimeout: typeof globalThis.clearTimeout === "function" ? globalThis.clearTimeout : undefined,
  #|         setInterval: typeof globalThis.setInterval === "function" ? globalThis.setInterval : undefined,
  #|         clearInterval: typeof globalThis.clearInterval === "function" ? globalThis.clearInterval : undefined,
  #|         queueMicrotask: typeof globalThis.queueMicrotask === "function" ? globalThis.queueMicrotask : undefined,
  #|         requestAnimationFrame: typeof globalThis.requestAnimationFrame === "function" ? globalThis.requestAnimationFrame : undefined,
  #|         cancelAnimationFrame: typeof globalThis.cancelAnimationFrame === "function" ? globalThis.cancelAnimationFrame : undefined,
  #|       };
  #|       globalThis.__bidiNativeWindowTimers = nativeTimers;
  #|       const nativeFetch = globalThis.__bidiNativeWindowFetch || (
  #|         typeof globalThis.fetch === "function" ? globalThis.fetch : undefined
  #|       );
  #|       globalThis.__bidiNativeWindowFetch = nativeFetch;
  #|       const bindNative = (name, fallback) => {
  #|         const fn = nativeTimers[name];
  #|         return typeof fn === "function" ? fn.bind(globalThis) : fallback;
  #|       };
  #|       globalThis.__bidiInstallContextWindowApi = (win) => {
  #|         if (!win || typeof win !== "object") return win;
  #|         win.window = win;
  #|         win.self = win;
  #|         if (!win.parent) win.parent = win;
  #|         if (!win.top) win.top = win;
  #|         win.setTimeout = bindNative("setTimeout", (handler, timeout) => {
  #|           if (typeof handler === "function") handler();
  #|           return 0;
  #|         });
  #|         win.clearTimeout = bindNative("clearTimeout", (_id) => undefined);
  #|         win.setInterval = bindNative("setInterval", win.setTimeout);
  #|         win.clearInterval = bindNative("clearInterval", win.clearTimeout);
  #|         win.queueMicrotask = bindNative("queueMicrotask", (callback) => Promise.resolve().then(callback));
  #|         win.requestAnimationFrame = bindNative("requestAnimationFrame", (callback) =>
  #|           win.setTimeout(() => {
  #|             if (typeof callback === "function") callback(Date.now());
  #|           }, 16)
  #|         );
  #|         win.cancelAnimationFrame = bindNative("cancelAnimationFrame", win.clearTimeout);
  #|         win.fetch = function(url, options) {
  #|           const fetchFn = globalThis.__craterUseObservableFetch
  #|             ? (globalThis.__craterObservableFetch || globalThis.__fetchInternal)
  #|             : globalThis.__fetchInternal;
  #|           const fallback = globalThis.fetch !== win.fetch ? globalThis.fetch : nativeFetch;
  #|           const target = fetchFn || fallback;
  #|           if (typeof target !== "function") return Promise.reject(new TypeError("fetch is not available"));
  #|           return target.call(globalThis, url, options);
  #|         };
  #|         for (const name of [
  #|           "Response", "Request", "Headers", "Blob", "FormData", "URL", "URLSearchParams",
  #|           "getComputedStyle", "matchMedia", "Event", "UIEvent", "MouseEvent", "PointerEvent",
  #|           "FocusEvent", "KeyboardEvent", "InputEvent", "CompositionEvent", "CustomEvent",
  #|           "MessageEvent", "StorageEvent", "DragEvent", "ClipboardEvent", "DataTransfer",
  #|           "DOMParser", "DOMException", "Node", "Attr", "Element", "HTMLElement", "Document",
  #|         ]) {
  #|           if (win[name] === undefined && globalThis[name] !== undefined) win[name] = globalThis[name];
  #|         }
  #|         return win;
  #|       };
  #|     };
  #|     installContextWindowApi();
  #|     globalThis.__bidiPatchNavigatorTarget = (target, patch) => {
  #|       if (!target || typeof target !== "object") return null;
  #|       const current = target.navigator && typeof target.navigator === "object"
  #|         ? target.navigator
  #|         : null;
  #|       const next = (() => {
  #|         try {
  #|           const proto = current && typeof current === "object"
  #|             ? Object.getPrototypeOf(current)
  #|             : Object.prototype;
  #|           const value = Object.create(proto || Object.prototype);
  #|           if (current && typeof current === "object") {
  #|             try {
  #|               Object.defineProperties(value, Object.getOwnPropertyDescriptors(current));
  #|             } catch (_e) {
  #|               for (const key of Object.keys(current)) {
  #|                 try { value[key] = current[key]; } catch (_e2) {}
  #|               }
  #|             }
  #|           }
  #|           return value;
  #|         } catch (_e) {
  #|           const value = {};
  #|           if (current && typeof current === "object") {
  #|             for (const key of Object.keys(current)) {
  #|               try { value[key] = current[key]; } catch (_e2) {}
  #|             }
  #|           }
  #|           return value;
  #|         }
  #|       })();
  #|       const setField = (holder, name, value) => {
  #|         if (!holder || typeof holder !== "object") return;
  #|         try {
  #|           Object.defineProperty(holder, name, {
  #|             configurable: true,
  #|             enumerable: true,
  #|             writable: true,
  #|             value,
  #|           });
  #|           return;
  #|         } catch (_e) {}
  #|         try { holder[name] = value; } catch (_e) {}
  #|       };
  #|       const resolvedLanguage = String(
  #|         patch && patch.language !== undefined
  #|           ? patch.language
  #|           : (current && current.language !== undefined ? current.language : "en-US")
  #|       );
  #|       const resolvedLanguages =
  #|         patch && Array.isArray(patch.languages)
  #|           ? Array.from(patch.languages)
  #|           : (
  #|             current && Array.isArray(current.languages)
  #|               ? Array.from(current.languages)
  #|               : [resolvedLanguage]
  #|           );
  #|       setField(
  #|         next,
  #|         "userAgent",
  #|         String(
  #|           patch && patch.userAgent !== undefined
  #|             ? patch.userAgent
  #|             : (current && current.userAgent !== undefined
  #|                 ? current.userAgent
  #|                 : "Crater/1.0 (MoonBit; BiDi)")
  #|         ),
  #|       );
  #|       setField(
  #|         next,
  #|         "platform",
  #|         String(current && current.platform !== undefined ? current.platform : "Crater"),
  #|       );
  #|       setField(next, "language", resolvedLanguage);
  #|       setField(next, "languages", resolvedLanguages);
  #|       setField(
  #|         next,
  #|         "onLine",
  #|         patch && patch.onLine !== undefined
  #|           ? !!patch.onLine
  #|           : (current ? current.onLine !== false : true),
  #|       );
  #|       setField(
  #|         next,
  #|         "cookieEnabled",
  #|         Boolean(current && current.cookieEnabled !== undefined ? current.cookieEnabled : false),
  #|       );
  #|       const userActivation =
  #|         current && current.userActivation && typeof current.userActivation === "object"
  #|           ? { ...current.userActivation }
  #|           : { isActive: false, hasBeenActive: false };
  #|       setField(next, "userActivation", userActivation);
  #|       try {
  #|         Object.defineProperty(target, "navigator", {
  #|           configurable: true,
  #|           enumerable: true,
  #|           writable: true,
  #|           value: next,
  #|         });
  #|         return next;
  #|       } catch (_e) {}
  #|       try {
  #|         target.navigator = next;
  #|         return target.navigator;
  #|       } catch (_e) {}
  #|       if (current && typeof current === "object") {
  #|         for (const name of ["userAgent", "platform", "language", "languages", "onLine", "cookieEnabled", "userActivation"]) {
  #|           try { setField(current, name, next[name]); } catch (_e) {}
  #|         }
  #|         return current;
  #|       }
  #|       return null;
  #|     };
  #|     if (!globalThis.__bidiProxyInstances) {
  #|       globalThis.__bidiProxyInstances = new WeakSet();
  #|     }
  #|     globalThis.allEvents = undefined;
  #|     globalThis.recordedEvents = undefined;
  #|     globalThis._shadowRoot = undefined;
  #|     globalThis.__bidiLastClickHref = undefined;
  #|     globalThis.__bidiChannelMessages = [];
  #|     globalThis.__bidiSharedNodeStore = new Map();
  #|     globalThis.__bidiHandleStore = new Map();
  #|     globalThis.__bidiNextHandleId = 1;
  #|     // Drop the realm-scoped fetch-shim install-once flag and the
  #|     // __rawFetch indirection it pairs with so the next
  #|     // js_evaluate_expression re-wraps fetch cleanly. Otherwise a
  #|     // browsingContext.create / destroy cycle that reuses the same JS
  #|     // realm would inherit the flag without re-wrapping, leaving
  #|     // __rawFetch pointing at the previous session's stub.
  #|     try { delete globalThis.__bidiFetchShimInstalled; } catch (_e) {}
  #|     try { delete globalThis.__rawFetch; } catch (_e) {}
  #|     // Also drop the per-realm preflight cache so stale entries from
  #|     // the previous session do not bleed cross-origin allow-lists
  #|     // into a fresh session.
  #|     try { delete globalThis.__bidiPreflightCache; } catch (_e) {}
  #|   } catch (_e) {}
  #| }

///|
/// Ensure JS-side navigator patch helper exists for runtime emulation overrides.
extern "js" fn ensure_runtime_navigator_patch_helper() -> Unit =
  #| () => {
  #|   if (typeof globalThis.__bidiPatchNavigatorTarget === "function") return;
  #|   try { globalThis.__bidiCurrentContext = globalThis.__bidiCurrentContext || "default-context"; } catch (_e) {}
  #|   try { globalThis.__bidiContextWindows = globalThis.__bidiContextWindows || new Map(); } catch (_e) {}
  #|   try {
  #|     globalThis.__bidiPatchNavigatorTarget = (target, patch) => {
  #|       if (!target || typeof target !== "object") return null;
  #|       const current = target.navigator && typeof target.navigator === "object"
  #|         ? target.navigator
  #|         : null;
  #|       const next = (() => {
  #|         try {
  #|           const proto = current && typeof current === "object"
  #|             ? Object.getPrototypeOf(current)
  #|             : Object.prototype;
  #|           const value = Object.create(proto || Object.prototype);
  #|           if (current && typeof current === "object") {
  #|             try {
  #|               Object.defineProperties(value, Object.getOwnPropertyDescriptors(current));
  #|             } catch (_e) {
  #|               for (const key of Object.keys(current)) {
  #|                 try { value[key] = current[key]; } catch (_e2) {}
  #|               }
  #|             }
  #|           }
  #|           return value;
  #|         } catch (_e) {
  #|           const value = {};
  #|           if (current && typeof current === "object") {
  #|             for (const key of Object.keys(current)) {
  #|               try { value[key] = current[key]; } catch (_e2) {}
  #|             }
  #|           }
  #|           return value;
  #|         }
  #|       })();
  #|       const setField = (holder, name, value) => {
  #|         if (!holder || typeof holder !== "object") return;
  #|         try {
  #|           Object.defineProperty(holder, name, {
  #|             configurable: true,
  #|             enumerable: true,
  #|             writable: true,
  #|             value,
  #|           });
  #|           return;
  #|         } catch (_e) {}
  #|         try { holder[name] = value; } catch (_e) {}
  #|       };
  #|       const resolvedLanguage = String(
  #|         patch && patch.language !== undefined
  #|           ? patch.language
  #|           : (current && current.language !== undefined ? current.language : "en-US")
  #|       );
  #|       const resolvedLanguages =
  #|         patch && Array.isArray(patch.languages)
  #|           ? Array.from(patch.languages)
  #|           : (
  #|             current && Array.isArray(current.languages)
  #|               ? Array.from(current.languages)
  #|               : [resolvedLanguage]
  #|           );
  #|       setField(
  #|         next,
  #|         "userAgent",
  #|         String(
  #|           patch && patch.userAgent !== undefined
  #|             ? patch.userAgent
  #|             : (current && current.userAgent !== undefined
  #|                 ? current.userAgent
  #|                 : "Crater/1.0 (MoonBit; BiDi)")
  #|         ),
  #|       );
  #|       setField(
  #|         next,
  #|         "platform",
  #|         String(current && current.platform !== undefined ? current.platform : "Crater"),
  #|       );
  #|       setField(next, "language", resolvedLanguage);
  #|       setField(next, "languages", resolvedLanguages);
  #|       setField(
  #|         next,
  #|         "onLine",
  #|         patch && patch.onLine !== undefined
  #|           ? !!patch.onLine
  #|           : (current ? current.onLine !== false : true),
  #|       );
  #|       setField(
  #|         next,
  #|         "cookieEnabled",
  #|         Boolean(current && current.cookieEnabled !== undefined ? current.cookieEnabled : false),
  #|       );
  #|       const userActivation =
  #|         current && current.userActivation && typeof current.userActivation === "object"
  #|           ? { ...current.userActivation }
  #|           : { isActive: false, hasBeenActive: false };
  #|       setField(next, "userActivation", userActivation);
  #|       try {
  #|         Object.defineProperty(target, "navigator", {
  #|           configurable: true,
  #|           enumerable: true,
  #|           writable: true,
  #|           value: next,
  #|         });
  #|         return next;
  #|       } catch (_e) {}
  #|       try {
  #|         target.navigator = next;
  #|         return target.navigator;
  #|       } catch (_e) {}
  #|       if (current && typeof current === "object") {
  #|         for (const name of ["userAgent", "platform", "language", "languages", "onLine", "cookieEnabled", "userActivation"]) {
  #|           try { setField(current, name, next[name]); } catch (_e) {}
  #|         }
  #|         return current;
  #|       }
  #|       return null;
  #|     };
  #|   } catch (_e) {}
  #| }

///|
/// Set current BiDi context for value serialization helpers.
extern "js" fn js_set_runtime_context(ctx_id : String) -> Unit =
  #| (ctxId) => {
  #|   globalThis.__bidiCurrentContext = ctxId;
  #|   if (!globalThis.__bidiContextWindows) globalThis.__bidiContextWindows = new Map();
  #|   if (!globalThis.__bidiContextViewportState) globalThis.__bidiContextViewportState = new Map();
  #|   const resolveViewportState = (id) => {
  #|     const fallback = { width: 1024, height: 768, devicePixelRatio: 1 };
  #|     const map = globalThis.__bidiContextViewportState;
  #|     if (!map || !map.has(id)) return fallback;
  #|     const raw = map.get(id) || {};
  #|     const width = Number(raw.width);
  #|     const height = Number(raw.height);
  #|     const dpr = Number(raw.devicePixelRatio);
  #|     return {
  #|       width: Number.isFinite(width) && width >= 0 ? width : fallback.width,
  #|       height: Number.isFinite(height) && height >= 0 ? height : fallback.height,
  #|       devicePixelRatio: Number.isFinite(dpr) && dpr > 0 ? dpr : fallback.devicePixelRatio,
  #|     };
  #|   };
  #|   const resolveScreenOrientationState = (id) => {
  #|     const fallback = { type: "portrait-primary", angle: 0 };
  #|     const map = globalThis.__bidiContextScreenOrientationState;
  #|     if (!map || !map.has(id)) return fallback;
  #|     const raw = map.get(id) || {};
  #|     const type = typeof raw.type === "string" && raw.type ? raw.type : fallback.type;
  #|     const angle = Number(raw.angle);
  #|     return {
  #|       type,
  #|       angle: Number.isFinite(angle) ? angle : fallback.angle,
  #|     };
  #|   };
  #|   const resolveScreenAreaState = (id, fallbackMetrics) => {
  #|     const fallback = {
  #|       width: fallbackMetrics.width,
  #|       height: fallbackMetrics.height,
  #|       availWidth: fallbackMetrics.width,
  #|       availHeight: fallbackMetrics.height,
  #|     };
  #|     const map = globalThis.__bidiContextScreenAreaState;
  #|     if (!map || !map.has(id)) return fallback;
  #|     const raw = map.get(id) || {};
  #|     const width = Number(raw.width);
  #|     const height = Number(raw.height);
  #|     const availWidth = Number(raw.availWidth);
  #|     const availHeight = Number(raw.availHeight);
  #|     return {
  #|       width: Number.isFinite(width) && width >= 0 ? width : fallback.width,
  #|       height: Number.isFinite(height) && height >= 0 ? height : fallback.height,
  #|       availWidth: Number.isFinite(availWidth) && availWidth >= 0 ? availWidth : fallback.availWidth,
  #|       availHeight: Number.isFinite(availHeight) && availHeight >= 0 ? availHeight : fallback.availHeight,
  #|     };
  #|   };
  #|   const ensureOrientationTarget = (orientation, state) => {
  #|     const target = orientation && typeof orientation === "object" ? orientation : {};
  #|     target.type = state.type;
  #|     target.angle = state.angle;
  #|     if (!target._listeners || typeof target._listeners !== "object") target._listeners = {};
  #|     if (typeof target.addEventListener !== "function") {
  #|       target.addEventListener = function(type, fn) {
  #|         if (!this._listeners[type]) this._listeners[type] = [];
  #|         this._listeners[type].push(fn);
  #|       };
  #|     }
  #|     if (typeof target.removeEventListener !== "function") {
  #|       target.removeEventListener = function(type, fn) {
  #|         if (!this._listeners[type]) return;
  #|         this._listeners[type] = this._listeners[type].filter((entry) => entry !== fn);
  #|       };
  #|     }
  #|     if (typeof target.dispatchEvent !== "function") {
  #|       target.dispatchEvent = function(event) {
  #|         try { event.currentTarget = this; } catch (_e) {}
  #|         try { event.target = this; } catch (_e) {}
  #|         const listeners = this._listeners[event.type] || [];
  #|         for (const fn of listeners) {
  #|           try { fn.call(this, event); } catch (_e) {}
  #|         }
  #|         return !event.defaultPrevented;
  #|       };
  #|     }
  #|     return target;
  #|   };
  #|   const ensureScreenObject = (win, orientationState, screenMetrics) => {
  #|     if (!win || typeof win !== "object") return null;
  #|     const screen = win.screen && typeof win.screen === "object" ? win.screen : {};
  #|     screen.width = screenMetrics.width;
  #|     screen.height = screenMetrics.height;
  #|     screen.availWidth = screenMetrics.availWidth;
  #|     screen.availHeight = screenMetrics.availHeight;
  #|     screen.orientation = ensureOrientationTarget(screen.orientation, orientationState);
  #|     win.screen = screen;
  #|     return screen;
  #|   };
  #|   const metrics = resolveViewportState(String(ctxId));
  #|   const screenOrientationState = resolveScreenOrientationState(String(ctxId));
  #|   const screenAreaState = resolveScreenAreaState(String(ctxId), metrics);
  #|   if (!globalThis.__bidiContextWindows.has(ctxId)) {
  #|     const win = {};
  #|     win.__bidiContextId = String(ctxId);
  #|     win.window = win;
  #|     win.innerWidth = metrics.width;
  #|     win.innerHeight = metrics.height;
  #|     win.outerWidth = metrics.width;
  #|     win.outerHeight = metrics.height;
  #|     win.devicePixelRatio = metrics.devicePixelRatio;
  #|     win.pageXOffset = 0;
  #|     win.pageYOffset = 0;
  #|     win._listeners = {};
  #|     win.addEventListener = function(type, fn) {
  #|       if (!this._listeners[type]) this._listeners[type] = [];
  #|       this._listeners[type].push(fn);
  #|     };
  #|     win.removeEventListener = function(type, fn) {
  #|       if (!this._listeners[type]) return;
  #|       this._listeners[type] = this._listeners[type].filter((f) => f !== fn);
  #|     };
  #|     win.dispatchEvent = function(event) {
  #|       try { event.currentTarget = this; } catch (_e) {}
  #|       const listeners = this._listeners[event.type] || [];
  #|       for (const fn of listeners) {
  #|         try { fn.call(this, event); } catch (_e) {}
  #|       }
  #|       return !event.defaultPrevented;
  #|     };
  #|     if (typeof globalThis.__bidiInstallContextWindowApi === "function") {
  #|       globalThis.__bidiInstallContextWindowApi(win);
  #|     }
  #|     globalThis.__bidiContextWindows.set(ctxId, win);
  #|   }
  #|   const contextWindow = globalThis.__bidiContextWindows.get(ctxId);
  #|   if (contextWindow) {
  #|     if (typeof globalThis.__bidiInstallContextWindowApi === "function") {
  #|       globalThis.__bidiInstallContextWindowApi(contextWindow);
  #|     }
  #|     if (!contextWindow.window) contextWindow.window = contextWindow;
  #|     contextWindow.innerWidth = metrics.width;
  #|     contextWindow.innerHeight = metrics.height;
  #|     contextWindow.outerWidth = metrics.width;
  #|     contextWindow.outerHeight = metrics.height;
  #|     contextWindow.devicePixelRatio = metrics.devicePixelRatio;
  #|     const screen = ensureScreenObject(contextWindow, screenOrientationState, screenAreaState);
  #|     const frameWindows = Array.isArray(contextWindow.frames) ? contextWindow.frames : [];
  #|     globalThis.window = contextWindow;
  #|     globalThis.self = contextWindow;
  #|     globalThis.parent = contextWindow.parent || contextWindow;
  #|     globalThis.top = contextWindow.top || contextWindow;
  #|     contextWindow.matchMedia = globalThis.matchMedia;
  #|     globalThis.frames = frameWindows;
  #|     globalThis.screen = screen;
  #|     globalThis.innerWidth = metrics.width;
  #|     globalThis.innerHeight = metrics.height;
  #|     globalThis.outerWidth = metrics.width;
  #|     globalThis.outerHeight = metrics.height;
  #|     globalThis.devicePixelRatio = metrics.devicePixelRatio;
  #|     if (!globalThis.__bidiContextStorage) globalThis.__bidiContextStorage = new Map();
  #|     const ensureStorage = (kind) => {
  #|       const key = String(ctxId) + ":" + String(kind);
  #|       if (!globalThis.__bidiContextStorage.has(key)) {
  #|         globalThis.__bidiContextStorage.set(key, {});
  #|       }
  #|       const backing = globalThis.__bidiContextStorage.get(key);
  #|       return {
  #|         getItem(name) {
  #|           const storageKey = String(name);
  #|           return Object.prototype.hasOwnProperty.call(backing, storageKey)
  #|             ? backing[storageKey]
  #|             : null;
  #|         },
  #|         setItem(name, value) {
  #|           backing[String(name)] = String(value);
  #|         },
  #|         removeItem(name) {
  #|           delete backing[String(name)];
  #|         },
  #|         clear() {
  #|           for (const storageKey of Object.keys(backing)) {
  #|             delete backing[storageKey];
  #|           }
  #|         },
  #|         get length() {
  #|           return Object.keys(backing).length;
  #|         },
  #|         key(index) {
  #|           const keys = Object.keys(backing);
  #|           return keys[Number(index)] || null;
  #|         }
  #|       };
  #|     };
  #|     if (!contextWindow.localStorage) contextWindow.localStorage = ensureStorage("localStorage");
  #|     if (!contextWindow.sessionStorage) contextWindow.sessionStorage = ensureStorage("sessionStorage");
  #|     globalThis.localStorage = contextWindow.localStorage;
  #|     globalThis.sessionStorage = contextWindow.sessionStorage;
  #|     // alert / confirm / prompt — wire to the BiDi user-prompt bridge.
  #|     // A page-side call queues a userPromptOpened observation and returns
  #|     // the resolved value per the context's unhandledPromptBehavior (snapshot
  #|     // pushed via __bidiPromptHandlers). The MoonBit drain runs at every
  #|     // script.evaluate boundary and emits the deferred BiDi event so
  #|     // Playwright's `page.on('dialog')` consumers observe the dialog.
  #|     //
  #|     // Limitation: real browsers BLOCK the page on alert/confirm/prompt
  #|     // until the user (or driver) answers. Crater's headless realm can't
  #|     // synchronously park JS waiting for an out-of-realm decision, so the
  #|     // resolution is taken from the snapshot at call time — accept ⇒ true /
  #|     // default-value, dismiss ⇒ false / null. Drivers that need control
  #|     // over the response set the behavior via session.new
  #|     // `unhandledPromptBehavior` BEFORE the page calls alert/confirm/prompt.
  #|     const resolvePromptHandler = (promptType) => {
  #|       const handlers = globalThis.__bidiPromptHandlers;
  #|       if (handlers && typeof handlers === "object") {
  #|         const direct = handlers[promptType];
  #|         if (typeof direct === "string") return direct;
  #|         const fallback = handlers.default;
  #|         if (typeof fallback === "string") return fallback;
  #|       }
  #|       return "dismiss";
  #|     };
  #|     const enqueueUserPrompt = (promptType, message, defaultValue) => {
  #|       if (!Array.isArray(globalThis.__bidiPendingUserPrompts)) {
  #|         globalThis.__bidiPendingUserPrompts = [];
  #|       }
  #|       const handler = resolvePromptHandler(promptType);
  #|       const ctx = String(globalThis.__bidiCurrentContext || "default-context");
  #|       globalThis.__bidiPendingUserPrompts.push({
  #|         ctx,
  #|         type: promptType,
  #|         message: message === undefined || message === null ? "" : String(message),
  #|         defaultValue: defaultValue === undefined || defaultValue === null ? null : String(defaultValue),
  #|         handler,
  #|       });
  #|       return handler;
  #|     };
  #|     if (typeof contextWindow.alert !== "function") {
  #|       contextWindow.alert = function(message) {
  #|         enqueueUserPrompt("alert", message, null);
  #|         // alert returns undefined regardless of handler — accepting vs
  #|         // dismissing only changes whether the page knew the user saw it.
  #|         return undefined;
  #|       };
  #|     }
  #|     if (typeof contextWindow.confirm !== "function") {
  #|       contextWindow.confirm = function(message) {
  #|         const handler = enqueueUserPrompt("confirm", message, null);
  #|         return handler === "accept" || handler === "accept and notify";
  #|       };
  #|     }
  #|     if (typeof contextWindow.prompt !== "function") {
  #|       contextWindow.prompt = function(message, defaultValue) {
  #|         const handler = enqueueUserPrompt("prompt", message, defaultValue);
  #|         if (handler === "accept" || handler === "accept and notify") {
  #|           return defaultValue === undefined || defaultValue === null
  #|             ? ""
  #|             : String(defaultValue);
  #|         }
  #|         // dismiss / dismiss and notify / ignore → null per HTML spec
  #|         return null;
  #|       };
  #|     }
  #|     globalThis.alert = contextWindow.alert.bind(contextWindow);
  #|     globalThis.confirm = contextWindow.confirm.bind(contextWindow);
  #|     globalThis.prompt = contextWindow.prompt.bind(contextWindow);
  #|     if (contextWindow.document && typeof contextWindow.document === "object") {
  #|       globalThis.document = contextWindow.document;
  #|     } else if (globalThis.document && typeof globalThis.document === "object") {
  #|       contextWindow.document = globalThis.document;
  #|     }
  #|     if (globalThis.document && typeof globalThis.__bidiEnsureDocumentRange === "function") {
  #|       globalThis.__bidiEnsureDocumentRange(globalThis.document);
  #|       contextWindow.document = globalThis.document;
  #|     }
  #|     if (contextWindow.location && typeof contextWindow.location === "object") {
  #|       globalThis.location = contextWindow.location;
  #|       try { globalThis.__pageUrl = String(contextWindow.location.href || "about:blank"); } catch (_e) {}
  #|     } else {
  #|       const locationHref = "about:blank";
  #|       contextWindow.location = {
  #|         href: locationHref,
  #|         origin: '',
  #|         protocol: 'about:',
  #|         host: '',
  #|         hostname: '',
  #|         port: '',
  #|         pathname: 'blank',
  #|         search: '',
  #|         hash: '',
  #|         assign: function(url) { const next = String(url); globalThis.__pageUrl = next; this.href = next; },
  #|         replace: function(url) { const next = String(url); globalThis.__pageUrl = next; this.href = next; },
  #|         reload: function() {}
  #|       };
  #|       globalThis.location = contextWindow.location;
  #|       globalThis.__pageUrl = locationHref;
  #|     }
  #|     if (Object.prototype.hasOwnProperty.call(contextWindow, "__lastHTML")) {
  #|       globalThis.__lastHTML = contextWindow.__lastHTML;
  #|     }
  #|     if (contextWindow.__lastParsed) {
  #|       globalThis.__lastParsed = contextWindow.__lastParsed;
  #|     }
  #|     if (Object.prototype.hasOwnProperty.call(contextWindow, "__craterPaintCaptureSource")) {
  #|       globalThis.__craterPaintCaptureSource = contextWindow.__craterPaintCaptureSource;
  #|     }
  #|   }
  #| }

///|
/// Set current BiDi context for value serialization helpers.
pub fn set_runtime_context(ctx_id : String) -> Unit {
  js_set_runtime_context(ctx_id)
}

///|
/// Reset runtime event buffers/listeners for a specific context.
extern "js" fn js_reset_runtime_event_buffers(ctx_id : String) -> Unit =
  #| (ctxId) => {
  #|   try {
  #|     if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|       const win = globalThis.__bidiContextWindows.get(ctxId);
  #|       if (win && typeof win === "object") {
  #|         if (!win.allEvents || !Array.isArray(win.allEvents.events)) {
  #|           win.allEvents = { events: [] };
  #|         } else {
  #|           win.allEvents.events.length = 0;
  #|         }
  #|         if (win._listeners && typeof win._listeners === "object") {
  #|           win._listeners = {};
  #|         }
  #|         try { win.__bidiFocusedElement = null; } catch (_e) {}
  #|         win.__craterAllEventsFallbackInit = false;
  #|         win.__bidiLastClickHref = null;
  #|       }
  #|     }
  #|     if (globalThis.allEvents && Array.isArray(globalThis.allEvents.events)) {
  #|       globalThis.allEvents.events.length = 0;
  #|     } else {
  #|       globalThis.allEvents = { events: [] };
  #|     }
  #|     if (
  #|       globalThis.document &&
  #|       globalThis.document._listeners &&
  #|       typeof globalThis.document._listeners === "object"
  #|     ) {
  #|       globalThis.document._listeners = {};
  #|     }
  #|     try { globalThis.__bidiFocusedElement = null; } catch (_e) {}
  #|     globalThis.__bidiLastClickHref = null;
  #|   } catch (_e) {}
  #| }

///|
/// Reset runtime event buffers/listeners for a specific context.
pub fn reset_runtime_event_buffers(ctx_id : String) -> Unit {
  js_reset_runtime_event_buffers(ctx_id)
}

///|
/// Set frame window contexts for current runtime context.
extern "js" fn js_set_runtime_context_frames(
  ctx_id : String,
  frame_ctx_ids : Array[String],
) -> Unit =
  #| (ctxId, frameCtxIds) => {
  #|   if (!globalThis.__bidiContextWindows) globalThis.__bidiContextWindows = new Map();
  #|   if (!globalThis.__bidiContextViewportState) globalThis.__bidiContextViewportState = new Map();
  #|   const resolveViewportState = (id) => {
  #|     const fallback = { width: 1024, height: 768, devicePixelRatio: 1 };
  #|     const map = globalThis.__bidiContextViewportState;
  #|     if (!map || !map.has(id)) return fallback;
  #|     const raw = map.get(id) || {};
  #|     const width = Number(raw.width);
  #|     const height = Number(raw.height);
  #|     const dpr = Number(raw.devicePixelRatio);
  #|     return {
  #|       width: Number.isFinite(width) && width >= 0 ? width : fallback.width,
  #|       height: Number.isFinite(height) && height >= 0 ? height : fallback.height,
  #|       devicePixelRatio: Number.isFinite(dpr) && dpr > 0 ? dpr : fallback.devicePixelRatio,
  #|     };
  #|   };
  #|   const ensureWindow = (id) => {
  #|     if (!globalThis.__bidiContextWindows.has(id)) {
  #|       const metrics = resolveViewportState(String(id));
  #|       const win = {};
  #|       win.__bidiContextId = String(id);
  #|       win.window = win;
  #|       win.innerWidth = metrics.width;
  #|       win.innerHeight = metrics.height;
  #|       win.outerWidth = metrics.width;
  #|       win.outerHeight = metrics.height;
  #|       win.devicePixelRatio = metrics.devicePixelRatio;
  #|       win.pageXOffset = 0;
  #|       win.pageYOffset = 0;
  #|       win._listeners = {};
  #|       win.addEventListener = function(type, fn) {
  #|         if (!this._listeners[type]) this._listeners[type] = [];
  #|         this._listeners[type].push(fn);
  #|       };
  #|       win.removeEventListener = function(type, fn) {
  #|         if (!this._listeners[type]) return;
  #|         this._listeners[type] = this._listeners[type].filter((f) => f !== fn);
  #|       };
  #|       win.dispatchEvent = function(event) {
  #|         try { event.currentTarget = this; } catch (_e) {}
  #|         const listeners = this._listeners[event.type] || [];
  #|         for (const fn of listeners) {
  #|           try { fn.call(this, event); } catch (_e) {}
  #|         }
  #|         return !event.defaultPrevented;
  #|       };
  #|       globalThis.__bidiContextWindows.set(id, win);
  #|     }
  #|     return globalThis.__bidiContextWindows.get(id);
  #|   };
  #|   const currentWindow = ensureWindow(ctxId);
  #|   const frames = Array.isArray(frameCtxIds)
  #|     ? frameCtxIds.map((id) => ensureWindow(String(id)))
  #|     : [];
  #|   currentWindow.frames = frames;
  #|   globalThis.frames = frames;
  #| }

///|
/// Set frame window contexts for current runtime context.
pub fn set_runtime_context_frames(
  ctx_id : String,
  frame_ctx_ids : Array[String],
) -> Unit {
  js_set_runtime_context_frames(ctx_id, frame_ctx_ids)
}

///|
/// Set runtime viewport metrics for a specific context.
extern "js" fn js_set_runtime_context_viewport(
  ctx_id : String,
  width : Int,
  height : Int,
  device_pixel_ratio : Double,
) -> Unit =
  #| (ctxId, width, height, devicePixelRatio) => {
  #|   if (!globalThis.__bidiContextViewportState) globalThis.__bidiContextViewportState = new Map();
  #|   const w = Number(width);
  #|   const h = Number(height);
  #|   const dpr = Number(devicePixelRatio);
  #|   const normalized = {
  #|     width: Number.isFinite(w) && w >= 0 ? w : 1024,
  #|     height: Number.isFinite(h) && h >= 0 ? h : 768,
  #|     devicePixelRatio: Number.isFinite(dpr) && dpr > 0 ? dpr : 1,
  #|   };
  #|   globalThis.__bidiContextViewportState.set(String(ctxId), normalized);
  #|   if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|     const win = globalThis.__bidiContextWindows.get(ctxId);
  #|     if (win && typeof win === "object") {
  #|       win.innerWidth = normalized.width;
  #|       win.innerHeight = normalized.height;
  #|       win.outerWidth = normalized.width;
  #|       win.outerHeight = normalized.height;
  #|       win.devicePixelRatio = normalized.devicePixelRatio;
  #|     }
  #|   }
  #|   if (String(globalThis.__bidiCurrentContext || "") === String(ctxId)) {
  #|     globalThis.innerWidth = normalized.width;
  #|     globalThis.innerHeight = normalized.height;
  #|     globalThis.outerWidth = normalized.width;
  #|     globalThis.outerHeight = normalized.height;
  #|     globalThis.devicePixelRatio = normalized.devicePixelRatio;
  #|   }
  #| }

///|
/// Set runtime viewport metrics for a specific context.
pub fn set_runtime_context_viewport(
  ctx_id : String,
  width : Int,
  height : Int,
  device_pixel_ratio : Double,
) -> Unit {
  js_set_runtime_context_viewport(ctx_id, width, height, device_pixel_ratio)
}

///|
/// Set runtime navigator.userAgent for a specific context.
extern "js" fn js_set_runtime_context_user_agent(
  ctx_id : String,
  user_agent : String,
) -> Unit =
  #| (ctxId, userAgent) => {
  #|   const normalized = String(userAgent ?? "Crater/1.0 (MoonBit; BiDi)");
  #|   const patchNavigator = globalThis.__bidiPatchNavigatorTarget;
  #|   if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|     const win = globalThis.__bidiContextWindows.get(ctxId);
  #|     if (win && typeof win === "object") {
  #|       patchNavigator(win, { userAgent: normalized });
  #|     }
  #|   }
  #|   if (String(globalThis.__bidiCurrentContext || "") === String(ctxId)) {
  #|     patchNavigator(globalThis, { userAgent: normalized });
  #|   }
  #| }

///|
/// Set runtime navigator.userAgent for a specific context.
pub fn set_runtime_context_user_agent(
  ctx_id : String,
  user_agent : String,
) -> Unit {
  ensure_runtime_navigator_patch_helper()
  js_set_runtime_context_user_agent(ctx_id, user_agent)
}

///|
/// Set runtime navigator.language(s) for a specific context.
extern "js" fn js_set_runtime_context_locale(
  ctx_id : String,
  locale : String,
) -> Unit =
  #| (ctxId, locale) => {
  #|   const normalized = String(locale ?? "en-US");
  #|   const languages = [normalized];
  #|   const patchNavigator = globalThis.__bidiPatchNavigatorTarget;
  #|   if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|     const win = globalThis.__bidiContextWindows.get(ctxId);
  #|     if (win && typeof win === "object") {
  #|       patchNavigator(win, { language: normalized, languages });
  #|     }
  #|   }
  #|   if (String(globalThis.__bidiCurrentContext || "") === String(ctxId)) {
  #|     patchNavigator(globalThis, { language: normalized, languages });
  #|   }
  #| }

///|
/// Set runtime navigator.language(s) for a specific context.
pub fn set_runtime_context_locale(ctx_id : String, locale : String) -> Unit {
  ensure_runtime_navigator_patch_helper()
  js_set_runtime_context_locale(ctx_id, locale)
}

///|
extern "js" fn js_set_runtime_context_network_online(
  ctx_id : String,
  is_online : Bool,
) -> Unit =
  #| (ctxId, isOnline) => {
  #|   const normalized = !!isOnline;
  #|   const dispatchStateEvent = (target, type) => {
  #|     if (!target || typeof target.dispatchEvent !== "function") return;
  #|     let event;
  #|     if (typeof globalThis.__bidiCreateEvent === "function") {
  #|       event = globalThis.__bidiCreateEvent(type, { bubbles: false, cancelable: false });
  #|     } else {
  #|       event = { type, bubbles: false, cancelable: false, defaultPrevented: false };
  #|     }
  #|     try { event.isTrusted = true; } catch (_e) {}
  #|     try { target.dispatchEvent(event); } catch (_e) {}
  #|   };
  #|   const patchNavigator = globalThis.__bidiPatchNavigatorTarget;
  #|   const ensureNavigator = (target) => patchNavigator(target, { onLine: normalized });
  #|   let contextWindow = null;
  #|   let previousOnline = null;
  #|   if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|     contextWindow = globalThis.__bidiContextWindows.get(ctxId);
  #|     const navigator = ensureNavigator(contextWindow);
  #|     if (navigator) {
  #|       previousOnline = navigator.onLine !== false;
  #|       navigator.onLine = normalized;
  #|     }
  #|   }
  #|   if (String(globalThis.__bidiCurrentContext || "") === String(ctxId)) {
  #|     const globalNavigator = ensureNavigator(globalThis);
  #|     if (globalNavigator) globalNavigator.onLine = normalized;
  #|     const activeWindow = globalThis.window && typeof globalThis.window === "object"
  #|       ? globalThis.window
  #|       : null;
  #|     if (activeWindow && activeWindow !== contextWindow) {
  #|       const windowNavigator = ensureNavigator(activeWindow);
  #|       if (windowNavigator) {
  #|         const prev = windowNavigator.onLine !== false;
  #|         windowNavigator.onLine = normalized;
  #|         if (prev !== normalized) {
  #|           dispatchStateEvent(activeWindow, normalized ? "online" : "offline");
  #|         }
  #|       }
  #|     }
  #|   }
  #|   if (contextWindow && previousOnline !== null && previousOnline !== normalized) {
  #|     dispatchStateEvent(contextWindow, normalized ? "online" : "offline");
  #|   }
  #| }

///|
pub fn set_runtime_context_network_online(
  ctx_id : String,
  is_online : Bool,
) -> Unit {
  ensure_runtime_navigator_patch_helper()
  js_set_runtime_context_network_online(ctx_id, is_online)
}

///|
extern "js" fn js_set_runtime_context_screen_orientation(
  ctx_id : String,
  orientation_type : String,
  angle : Int,
) -> Unit =
  #| (ctxId, orientationType, angle) => {
  #|   if (!globalThis.__bidiContextScreenOrientationState) {
  #|     globalThis.__bidiContextScreenOrientationState = new Map();
  #|   }
  #|   const normalizedType =
  #|     typeof orientationType === "string" && orientationType
  #|       ? orientationType
  #|       : "portrait-primary";
  #|   const normalizedAngle = Number.isFinite(Number(angle)) ? Number(angle) : 0;
  #|   globalThis.__bidiContextScreenOrientationState.set(String(ctxId), {
  #|     type: normalizedType,
  #|     angle: normalizedAngle,
  #|   });
  #|   const dispatchChange = (target) => {
  #|     if (!target || typeof target.dispatchEvent !== "function") return;
  #|     let event;
  #|     if (typeof globalThis.__bidiCreateEvent === "function") {
  #|       event = globalThis.__bidiCreateEvent("change", { bubbles: false, cancelable: false });
  #|     } else {
  #|       event = { type: "change", bubbles: false, cancelable: false, defaultPrevented: false };
  #|     }
  #|     try { event.isTrusted = true; } catch (_e) {}
  #|     try { event.target = target; } catch (_e) {}
  #|     try { target.dispatchEvent(event); } catch (_e) {}
  #|   };
  #|   const ensureOrientationTarget = (orientation) => {
  #|     const target = orientation && typeof orientation === "object" ? orientation : {};
  #|     if (!target._listeners || typeof target._listeners !== "object") target._listeners = {};
  #|     if (typeof target.addEventListener !== "function") {
  #|       target.addEventListener = function(type, fn) {
  #|         if (!this._listeners[type]) this._listeners[type] = [];
  #|         this._listeners[type].push(fn);
  #|       };
  #|     }
  #|     if (typeof target.removeEventListener !== "function") {
  #|       target.removeEventListener = function(type, fn) {
  #|         if (!this._listeners[type]) return;
  #|         this._listeners[type] = this._listeners[type].filter((entry) => entry !== fn);
  #|       };
  #|     }
  #|     if (typeof target.dispatchEvent !== "function") {
  #|       target.dispatchEvent = function(event) {
  #|         try { event.currentTarget = this; } catch (_e) {}
  #|         try { event.target = this; } catch (_e) {}
  #|         const listeners = this._listeners[event.type] || [];
  #|         for (const fn of listeners) {
  #|           try { fn.call(this, event); } catch (_e) {}
  #|         }
  #|         return !event.defaultPrevented;
  #|       };
  #|     }
  #|     return target;
  #|   };
  #|   const ensureScreenObject = (target) => {
  #|     if (!target || typeof target !== "object") return null;
  #|     const screen = target.screen && typeof target.screen === "object" ? target.screen : {};
  #|     screen.orientation = ensureOrientationTarget(screen.orientation);
  #|     target.screen = screen;
  #|     return screen;
  #|   };
  #|   const apply = (target) => {
  #|     const screen = ensureScreenObject(target);
  #|     if (!screen || !screen.orientation) return;
  #|     const orientation = screen.orientation;
  #|     const previousType = typeof orientation.type === "string" ? orientation.type : "";
  #|     const previousAngle = Number.isFinite(Number(orientation.angle)) ? Number(orientation.angle) : 0;
  #|     orientation.type = normalizedType;
  #|     orientation.angle = normalizedAngle;
  #|     if (previousType !== normalizedType || previousAngle !== normalizedAngle) {
  #|       dispatchChange(orientation);
  #|     }
  #|   };
  #|   let contextWindow = null;
  #|   if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|     contextWindow = globalThis.__bidiContextWindows.get(ctxId);
  #|     apply(contextWindow);
  #|   }
  #|   if (String(globalThis.__bidiCurrentContext || "") === String(ctxId)) {
  #|     const activeWindow = globalThis.window && typeof globalThis.window === "object"
  #|       ? globalThis.window
  #|       : globalThis;
  #|     if (activeWindow !== contextWindow) {
  #|       apply(activeWindow);
  #|     }
  #|     if (globalThis.window && typeof globalThis.window === "object" && globalThis.window.screen) {
  #|       globalThis.screen = globalThis.window.screen;
  #|     }
  #|   }
  #| }

///|
pub fn set_runtime_context_screen_orientation(
  ctx_id : String,
  orientation_type : String,
  angle : Int,
) -> Unit {
  js_set_runtime_context_screen_orientation(ctx_id, orientation_type, angle)
}

///|
extern "js" fn js_set_runtime_context_screen_area(
  ctx_id : String,
  width : Int,
  height : Int,
  avail_width : Int,
  avail_height : Int,
) -> Unit =
  #| (ctxId, width, height, availWidth, availHeight) => {
  #|   if (!globalThis.__bidiContextScreenAreaState) {
  #|     globalThis.__bidiContextScreenAreaState = new Map();
  #|   }
  #|   const normalizedWidth = Number.isFinite(Number(width)) && Number(width) >= 0 ? Number(width) : 1024;
  #|   const normalizedHeight = Number.isFinite(Number(height)) && Number(height) >= 0 ? Number(height) : 768;
  #|   const normalizedAvailWidth = Number.isFinite(Number(availWidth)) && Number(availWidth) >= 0
  #|     ? Number(availWidth)
  #|     : normalizedWidth;
  #|   const normalizedAvailHeight = Number.isFinite(Number(availHeight)) && Number(availHeight) >= 0
  #|     ? Number(availHeight)
  #|     : normalizedHeight;
  #|   globalThis.__bidiContextScreenAreaState.set(String(ctxId), {
  #|     width: normalizedWidth,
  #|     height: normalizedHeight,
  #|     availWidth: normalizedAvailWidth,
  #|     availHeight: normalizedAvailHeight,
  #|   });
  #|   const apply = (target) => {
  #|     if (!target || typeof target !== "object") return null;
  #|     const screen = target.screen && typeof target.screen === "object" ? target.screen : {};
  #|     screen.width = normalizedWidth;
  #|     screen.height = normalizedHeight;
  #|     screen.availWidth = normalizedAvailWidth;
  #|     screen.availHeight = normalizedAvailHeight;
  #|     target.screen = screen;
  #|     return screen;
  #|   };
  #|   let contextWindow = null;
  #|   if (globalThis.__bidiContextWindows && globalThis.__bidiContextWindows.has(ctxId)) {
  #|     contextWindow = globalThis.__bidiContextWindows.get(ctxId);
  #|     apply(contextWindow);
  #|   }
  #|   if (String(globalThis.__bidiCurrentContext || "") === String(ctxId)) {
  #|     const activeWindow = globalThis.window && typeof globalThis.window === "object"
  #|       ? globalThis.window
  #|       : globalThis;
  #|     const screen = activeWindow === contextWindow ? activeWindow.screen : apply(activeWindow);
  #|     if (screen) {
  #|       globalThis.screen = screen;
  #|     }
  #|   }
  #| }

///|
pub fn set_runtime_context_screen_area(
  ctx_id : String,
  width : Int,
  height : Int,
  avail_width : Int,
  avail_height : Int,
) -> Unit {
  js_set_runtime_context_screen_area(
    ctx_id, width, height, avail_width, avail_height,
  )
}

///|
/// Push the partition cookie snapshot for a context into the JS realm and
/// install (if absent) the `globalThis.__bidiResolveCookies(url)` bridge that
/// the runtime fetch shim uses to attach a Cookie header. The snapshot is
/// re-pushed on every script.evaluate via
/// `apply_effective_viewport_to_runtime_context`, so stale jars between calls
/// are not a concern.
extern "js" fn js_set_runtime_context_cookies(
  ctx_id : String,
  cookies_json : String,
) -> Unit =
  #| (ctxId, cookiesJson) => {
  #|   if (!globalThis.__bidiContextCookies) {
  #|     globalThis.__bidiContextCookies = new Map();
  #|   }
  #|   let parsed = [];
  #|   try {
  #|     const raw = JSON.parse(String(cookiesJson || "[]"));
  #|     if (Array.isArray(raw)) parsed = raw;
  #|   } catch (_e) {}
  #|   globalThis.__bidiContextCookies.set(String(ctxId), parsed);
  #|   if (typeof globalThis.__bidiResolveCookies !== "function") {
  #|     const stripLeadingDot = (host) => host && host.charAt(0) === "." ? host.slice(1) : host;
  #|     const requestHost = (url) => {
  #|       try { return new URL(url, globalThis.__pageUrl || "about:blank").hostname.toLowerCase(); }
  #|       catch (_e) { return ""; }
  #|     };
  #|     const requestPath = (url) => {
  #|       try {
  #|         const path = new URL(url, globalThis.__pageUrl || "about:blank").pathname;
  #|         return path || "/";
  #|       } catch (_e) { return "/"; }
  #|     };
  #|     const requestScheme = (url) => {
  #|       try { return new URL(url, globalThis.__pageUrl || "about:blank").protocol; }
  #|       catch (_e) { return ""; }
  #|     };
  #|     const matchDomain = (cookieDomain, host) => {
  #|       const d = stripLeadingDot(String(cookieDomain || "").toLowerCase());
  #|       if (d.length === 0) return true;
  #|       return host === d || host.endsWith("." + d);
  #|     };
  #|     const matchPath = (cookiePath, path) => {
  #|       const cp = String(cookiePath || "/");
  #|       if (cp.length === 0 || cp === "/") return true;
  #|       if (path === cp) return true;
  #|       if (!path.startsWith(cp)) return false;
  #|       if (cp.endsWith("/")) return true;
  #|       if (path.length === cp.length) return true;
  #|       return path.charAt(cp.length) === "/";
  #|     };
  #|     globalThis.__bidiResolveCookies = function(url) {
  #|       try {
  #|         const ctx = String(globalThis.__bidiCurrentContext || "default-context");
  #|         const store = globalThis.__bidiContextCookies;
  #|         if (!store || !store.has(ctx)) return "";
  #|         const cookies = store.get(ctx) || [];
  #|         if (!Array.isArray(cookies) || cookies.length === 0) return "";
  #|         const host = requestHost(url);
  #|         const path = requestPath(url);
  #|         const scheme = requestScheme(url);
  #|         const parts = [];
  #|         for (const cookie of cookies) {
  #|           if (!cookie || typeof cookie !== "object") continue;
  #|           if (cookie.secure && scheme !== "https:") continue;
  #|           if (!matchDomain(cookie.domain, host)) continue;
  #|           if (!matchPath(cookie.path, path)) continue;
  #|           const name = String(cookie.name || "");
  #|           if (name.length === 0) continue;
  #|           parts.push(name + "=" + String(cookie.value == null ? "" : cookie.value));
  #|         }
  #|         return parts.join("; ");
  #|       } catch (_e) { return ""; }
  #|     };
  #|   }
  #| }

///|
/// Push the partition cookie snapshot for `ctx_id` into the JS realm.
fn set_runtime_context_cookies(ctx_id : String, cookies_json : String) -> Unit {
  js_set_runtime_context_cookies(ctx_id, cookies_json)
}

///|
/// Drain the `globalThis.__bidiPendingCookieIngest` buffer and return its
/// contents as JSON. The buffer is the fetch shim's record of inbound
/// `Set-Cookie` response headers; MoonBit calls this at every
/// `apply_effective_viewport_to_runtime_context` to ingest those cookies
/// back into the partition jar. Returns `"[]"` when the buffer is missing
/// or empty so MoonBit can use a single shape for both paths.
extern "js" fn js_drain_pending_cookie_ingest() -> String =
  #| () => {
  #|   const buf = globalThis.__bidiPendingCookieIngest;
  #|   if (!Array.isArray(buf) || buf.length === 0) return "[]";
  #|   const out = JSON.stringify(buf);
  #|   globalThis.__bidiPendingCookieIngest = [];
  #|   return out;
  #| }

///|
/// Drain the pending cookie ingest buffer to a JSON string. Each entry is
/// `{url, cookies: [setCookieHeaderValue, ...], ctx}`.
fn drain_pending_cookie_ingest() -> String {
  js_drain_pending_cookie_ingest()
}

///|
/// Push the per-context unhandledPromptBehavior snapshot into the JS realm.
/// Read by `resolvePromptHandler` inside alert/confirm/prompt to decide
/// the synchronous return value. Snapshot shape mirrors the spec
/// dictionary: `{ alert: "dismiss", confirm: "accept", prompt: "dismiss",
/// default: "dismiss" }`. Missing entries default to "dismiss".
pub extern "js" fn js_set_runtime_prompt_handlers(
  handlers_json : String,
) -> Unit =
  #| (handlersJson) => {
  #|   try {
  #|     const parsed = JSON.parse(handlersJson);
  #|     if (parsed && typeof parsed === "object") {
  #|       globalThis.__bidiPromptHandlers = parsed;
  #|       return;
  #|     }
  #|   } catch (_e) {}
  #|   globalThis.__bidiPromptHandlers = {};
  #| }

///|
fn set_runtime_prompt_handlers(handlers_json : String) -> Unit {
  js_set_runtime_prompt_handlers(handlers_json)
}

///|
/// Drain the pending user-prompt buffer. Each entry is
/// `{ctx, type, message, defaultValue, handler}` where `type` is one of
/// "alert" | "confirm" | "prompt" and `handler` is the resolved
/// unhandledPromptBehavior at the time alert/confirm/prompt was called.
/// MoonBit converts each entry to a `browsingContext.userPromptOpened`
/// event at the next script.evaluate boundary.
extern "js" fn js_drain_pending_user_prompts() -> String =
  #| () => {
  #|   const buf = globalThis.__bidiPendingUserPrompts;
  #|   if (!Array.isArray(buf) || buf.length === 0) return "[]";
  #|   const out = JSON.stringify(buf);
  #|   globalThis.__bidiPendingUserPrompts = [];
  #|   return out;
  #| }

///|
fn drain_pending_user_prompts() -> String {
  js_drain_pending_user_prompts()
}

///|
/// Push a synthetic-navigation marker onto the JS realm so the adapter's
/// `flushPendingNavigation` can mirror it onto `currentUrl` on the next
/// `script.evaluate` boundary. Used by server-side pointer-click
/// navigation (`input.performActions` path), where the in-realm shim
/// `click()` default action doesn't run. (#208)
pub extern "js" fn js_push_synthetic_navigation(url : String) -> Unit =
  #| (url) => {
  #|   if (typeof url !== "string" || url.length === 0) return;
  #|   globalThis.__craterPendingNavigation = {
  #|     url: url,
  #|     kind: "pointer-click",
  #|     urlOnly: true,
  #|   };
  #| }

///|
fn push_synthetic_navigation(url : String) -> Unit {
  js_push_synthetic_navigation(url)
}

///|
/// Check if runtime handle exists in current JS handle store.
extern "js" fn js_has_runtime_handle(handle_id : String) -> Bool =
  #| (handleId) => {
  #|   const store = globalThis.__bidiHandleStore;
  #|   if (!store || !store.has(handleId)) return false;
  #|   const contextStore = globalThis.__bidiHandleContextStore;
  #|   if (!contextStore || !contextStore.has(handleId)) return true;
  #|   return (
  #|     String(contextStore.get(handleId)) ===
  #|     String(globalThis.__bidiCurrentContext || "")
  #|   );
  #| }

///|
/// Check if runtime handle exists in current JS handle store.
pub fn has_runtime_handle(handle_id : String) -> Bool {
  js_has_runtime_handle(handle_id)
}

///|
/// Remove handle from current JS handle store (no-op when absent).
extern "js" fn js_delete_runtime_handle(handle_id : String) -> Unit =
  #| (handleId) => {
  #|   const store = globalThis.__bidiHandleStore;
  #|   if (!store) return;
  #|   const contextStore = globalThis.__bidiHandleContextStore;
  #|   if (contextStore && contextStore.has(handleId)) {
  #|     const owner = String(contextStore.get(handleId));
  #|     const current = String(globalThis.__bidiCurrentContext || "");
  #|     if (owner !== current) return;
  #|     contextStore.delete(handleId);
  #|   }
  #|   store.delete(handleId);
  #| }

///|
/// Remove handle from current JS handle store (no-op when absent).
pub fn delete_runtime_handle(handle_id : String) -> Unit {
  js_delete_runtime_handle(handle_id)
}

///|
/// Check if runtime shared node exists in current JS shared node store.
extern "js" fn js_has_runtime_shared_node(shared_id : String) -> Bool =
  #| (sharedId) => {
  #|   return !!(globalThis.__bidiSharedNodeStore && globalThis.__bidiSharedNodeStore.has(sharedId));
  #| }

///|
/// Check if runtime shared node exists in current JS shared node store.
pub fn has_runtime_shared_node(shared_id : String) -> Bool {
  js_has_runtime_shared_node(shared_id)
}

///|
/// Check if runtime shared node exists and is an element node.
extern "js" fn js_runtime_shared_node_is_element(shared_id : String) -> Bool =
  #| (sharedId) => {
  #|   const store = globalThis.__bidiSharedNodeStore;
  #|   if (!store) return false;
  #|   const node = store.get(sharedId);
  #|   return !!(node && node.nodeType === 1);
  #| }

///|
/// Check if runtime shared node exists and is an element node.
pub fn runtime_shared_node_is_element(shared_id : String) -> Bool {
  js_runtime_shared_node_is_element(shared_id)
}

///|
/// Check if runtime shared node exists and is a document node.
extern "js" fn js_runtime_shared_node_is_document(shared_id : String) -> Bool =
  #| (sharedId) => {
  #|   const store = globalThis.__bidiSharedNodeStore;
  #|   if (!store) return false;
  #|   const node = store.get(sharedId);
  #|   return !!(node && node.nodeType === 9);
  #| }

///|
/// Check if runtime shared node exists and is a document node.
pub fn runtime_shared_node_is_document(shared_id : String) -> Bool {
  js_runtime_shared_node_is_document(shared_id)
}

///|
/// Check if runtime shared node exists and is a shadow root node.
extern "js" fn js_runtime_shared_node_is_shadow_root(
  shared_id : String,
) -> Bool =
  #| (sharedId) => {
  #|   const store = globalThis.__bidiSharedNodeStore;
  #|   if (!store) return false;
  #|   const node = store.get(sharedId);
  #|   return !!(node && node.nodeType === 11 && node.host);
  #| }

///|
/// Check if runtime shared node exists and is a shadow root node.
pub fn runtime_shared_node_is_shadow_root(shared_id : String) -> Bool {
  js_runtime_shared_node_is_shadow_root(shared_id)
}

///|
/// Check if runtime shared node has draggable attribute enabled.
extern "js" fn js_runtime_shared_node_is_draggable(shared_id : String) -> Bool =
  #| (sharedId) => {
  #|   const store = globalThis.__bidiSharedNodeStore;
  #|   if (!store) return false;
  #|   const node = store.get(sharedId);
  #|   if (!node || node.nodeType !== 1) return false;
  #|   let draggable = null;
  #|   if (typeof node.getAttribute === "function") {
  #|     try { draggable = node.getAttribute("draggable"); } catch (_e) {}
  #|   }
  #|   if ((draggable === null || draggable === undefined) && node._attrs) {
  #|     draggable = node._attrs.draggable;
  #|   }
  #|   if (draggable === null || draggable === undefined) return false;
  #|   if (draggable === true) return true;
  #|   const value = String(draggable).toLowerCase();
  #|   return value === "" || value === "true";
  #| }

///|
/// Check if runtime shared node has draggable attribute enabled.
pub fn runtime_shared_node_is_draggable(shared_id : String) -> Bool {
  js_runtime_shared_node_is_draggable(shared_id)
}

///|
/// Get center coordinate of shared element as JSON string.
extern "js" fn js_runtime_shared_node_center_json(shared_id : String) -> String =
  #| (sharedId) => {
  #|   const store = globalThis.__bidiSharedNodeStore;
  #|   const node = store && store.get(sharedId);
  #|   if (!node || node.nodeType !== 1) {
  #|     return JSON.stringify({ ok: false });
  #|   }
  #|   let x = 0;
  #|   let y = 0;
  #|   if (typeof node.getBoundingClientRect === "function") {
  #|     try {
  #|       const rect = node.getBoundingClientRect();
  #|       if (rect && typeof rect.left === "number" && typeof rect.top === "number") {
  #|         const left = Number(rect.left);
  #|         const top = Number(rect.top);
  #|         const right = typeof rect.right === "number"
  #|           ? Number(rect.right)
  #|           : left + (typeof rect.width === "number" ? Number(rect.width) : 0);
  #|         const bottom = typeof rect.bottom === "number"
  #|           ? Number(rect.bottom)
  #|           : top + (typeof rect.height === "number" ? Number(rect.height) : 0);
  #|         const viewportWidth =
  #|           Number(
  #|             (globalThis.window && globalThis.window.innerWidth) ||
  #|             (globalThis.document &&
  #|               globalThis.document.documentElement &&
  #|               globalThis.document.documentElement.clientWidth) ||
  #|             1024
  #|           );
  #|         const viewportHeight =
  #|           Number(
  #|             (globalThis.window && globalThis.window.innerHeight) ||
  #|             (globalThis.document &&
  #|               globalThis.document.documentElement &&
  #|               globalThis.document.documentElement.clientHeight) ||
  #|             768
  #|           );
  #|         const clippedLeft = Math.max(0, Math.min(left, right));
  #|         const clippedRight = Math.min(viewportWidth, Math.max(left, right));
  #|         const clippedTop = Math.max(0, Math.min(top, bottom));
  #|         const clippedBottom = Math.min(viewportHeight, Math.max(top, bottom));
  #|         if (clippedRight > clippedLeft && clippedBottom > clippedTop) {
  #|           x = (clippedLeft + clippedRight) / 2;
  #|           y = (clippedTop + clippedBottom) / 2;
  #|         } else {
  #|           x = (left + right) / 2;
  #|           y = (top + bottom) / 2;
  #|         }
  #|       }
  #|     } catch (_e) {}
  #|   }
  #|   if (x === 0 && y === 0) {
  #|     const style = node._style || node.style || {};
  #|     const left = Number.parseFloat(style.left ?? "0");
  #|     const top = Number.parseFloat(style.top ?? "0");
  #|     const width = Number.parseFloat(style.width ?? "0");
  #|     const height = Number.parseFloat(style.height ?? "0");
  #|     const safe = (n) => Number.isFinite(n) ? n : 0;
  #|     x = safe(left) + safe(width) / 2;
  #|     y = safe(top) + safe(height) / 2;
  #|   }
  #|   return JSON.stringify({ ok: true, x, y });
  #| }

///|
/// Get center coordinate of shared element as JSON string.
pub fn get_runtime_shared_node_center_json(shared_id : String) -> String {
  js_runtime_shared_node_center_json(shared_id)
}

///|
/// Resolve shared node at viewport point, allocating sharedId if needed.
extern "js" fn js_runtime_shared_node_at_point(
  x : Double,
  y : Double,
) -> String? =
  #| (x, y) => {
  #|   const doc = globalThis.document;
  #|   if (!doc || typeof doc.elementFromPoint !== "function") return null;
  #|   let node = null;
  #|   try { node = doc.elementFromPoint(Number(x), Number(y)); } catch (_e) {}
  #|   if (!node) return null;
  #|   const sharedIds = globalThis.__bidiNodeSharedIds || (globalThis.__bidiNodeSharedIds = new WeakMap());
  #|   const nodeStore = globalThis.__bidiSharedNodeStore || (globalThis.__bidiSharedNodeStore = new Map());
  #|   if (typeof globalThis.__bidiNextNodeSharedId !== "number") {
  #|     globalThis.__bidiNextNodeSharedId = 1;
  #|   }
  #|   let sharedId = sharedIds.get(node);
  #|   if (!sharedId) {
  #|     sharedId = `node-${globalThis.__bidiNextNodeSharedId++}`;
  #|     sharedIds.set(node, sharedId);
  #|   }
  #|   nodeStore.set(sharedId, node);
  #|   return sharedId;
  #| }

///|
/// Resolve shared node at viewport point, allocating sharedId if needed.
pub fn get_runtime_shared_node_at_point(x : Double, y : Double) -> String? {
  js_runtime_shared_node_at_point(x, y)
}

///|
/// Resolve href attribute from a shared element node.
extern "js" fn js_runtime_shared_node_href(shared_id : String) -> String? =
  #| (sharedId) => {
  #|   const store = globalThis.__bidiSharedNodeStore;
  #|   const node = store && store.get(sharedId);
  #|   if (!node || node.nodeType !== 1) return "";
  #|   let href = null;
  #|   try {
  #|     if (typeof node.getAttribute === "function") {
  #|       href = node.getAttribute("href");
  #|     }
  #|   } catch (_e) {}
  #|   if ((href === null || href === undefined || href === "") && node._attrs) {
  #|     href = node._attrs.href;
  #|   }
  #|   if (href === null || href === undefined || href === "") return "";
  #|   const rawHref = String(href);
  #|   try {
  #|     const base =
  #|       (globalThis.location && globalThis.location.href) ||
  #|       globalThis.__pageUrl ||
  #|       "about:blank";
  #|     return new URL(rawHref, base).href;
  #|   } catch (_e) {
  #|     return rawHref;
  #|   }
  #| }

///|
/// Resolve href attribute from a shared element node.
pub fn get_runtime_shared_node_href(shared_id : String) -> String? {
  js_runtime_shared_node_href(shared_id)
}

///|
/// Resolve absolute href from an anchor identified by id or global symbol.
extern "js" fn js_runtime_anchor_href_by_id(anchor_id : String) -> String? =
  #| (anchorId) => {
  #|   const id = String(anchorId || "");
  #|   if (!id) return "";
  #|   const doc = globalThis.document;
  #|   if (!doc) return "";
  #|   let node = null;
  #|   try {
  #|     if (typeof doc.getElementById === "function") {
  #|       node = doc.getElementById(id);
  #|     }
  #|   } catch (_e) {}
  #|   if (!node) {
  #|     try {
  #|       const candidate = globalThis[id];
  #|       if (candidate && typeof candidate === "object") {
  #|         node = candidate;
  #|       }
  #|     } catch (_e) {}
  #|   }
  #|   if (!node) return "";
  #|   let href = null;
  #|   try {
  #|     if (typeof node.getAttribute === "function") {
  #|       href = node.getAttribute("href");
  #|     }
  #|   } catch (_e) {}
  #|   if ((href === null || href === undefined || href === "") && node._attrs) {
  #|     href = node._attrs.href;
  #|   }
  #|   if (href === null || href === undefined || href === "") return "";
  #|   const rawHref = String(href);
  #|   try {
  #|     const base =
  #|       (globalThis.location && globalThis.location.href) ||
  #|       globalThis.__pageUrl ||
  #|       "about:blank";
  #|     return new URL(rawHref, base).href;
  #|   } catch (_e) {
  #|     return rawHref;
  #|   }
  #| }

///|
/// Resolve absolute href from an anchor identified by id or global symbol.
pub fn get_runtime_anchor_href_by_id(anchor_id : String) -> String? {
  js_runtime_anchor_href_by_id(anchor_id)
}

///|
/// Resolve `download` attribute value from an anchor identified by id or global symbol.
extern "js" fn js_runtime_anchor_download_attr_by_id(
  anchor_id : String,
) -> String? =
  #| (anchorId) => {
  #|   const id = String(anchorId || "");
  #|   if (!id) return "";
  #|   const doc = globalThis.document;
  #|   if (!doc) return "";
  #|   let node = null;
  #|   try {
  #|     if (typeof doc.getElementById === "function") {
  #|       node = doc.getElementById(id);
  #|     }
  #|   } catch (_e) {}
  #|   if (!node) {
  #|     try {
  #|       const candidate = globalThis[id];
  #|       if (candidate && typeof candidate === "object") {
  #|         node = candidate;
  #|       }
  #|     } catch (_e) {}
  #|   }
  #|   if (!node) return "";
  #|   let value = null;
  #|   try {
  #|     if (typeof node.getAttribute === "function") {
  #|       value = node.getAttribute("download");
  #|     }
  #|   } catch (_e) {}
  #|   if ((value === null || value === undefined) && node._attrs) {
  #|     value = node._attrs.download;
  #|   }
  #|   if (value === null || value === undefined) return "";
  #|   return String(value);
  #| }

///|
/// Resolve `download` attribute value from an anchor identified by id or global symbol.
pub fn get_runtime_anchor_download_attr_by_id(anchor_id : String) -> String? {
  js_runtime_anchor_download_attr_by_id(anchor_id)
}

///|
/// Extract query parameter value from an URL string.
extern "js" fn js_runtime_url_query_param(
  url : String,
  key : String,
) -> String? =
  #| (url, key) => {
  #|   const rawUrl = String(url || "");
  #|   const rawKey = String(key || "");
  #|   if (!rawUrl || !rawKey) return "";
  #|   try {
  #|     const base =
  #|       (globalThis.location && globalThis.location.href) ||
  #|       globalThis.__pageUrl ||
  #|       "about:blank";
  #|     const parsed = new URL(rawUrl, base);
  #|     const value = parsed.searchParams.get(rawKey);
  #|     if (value === null || value === undefined) return "";
  #|     return String(value);
  #|   } catch (_e) {
  #|     return "";
  #|   }
  #| }

///|
/// Extract query parameter value from an URL string.
pub fn get_runtime_url_query_param(url : String, key : String) -> String? {
  js_runtime_url_query_param(url, key)
}

///|
/// Write UTF-8 text file for synthetic download tests.
extern "js" fn js_runtime_write_text_file(
  path : String,
  content : String,
) -> Unit =
  #| (path, content) => {
  #|   const filePath = String(path || "");
  #|   if (!filePath) return;
  #|   try {
  #|     const deno = globalThis.Deno;
  #|     if (!deno || typeof deno.writeTextFileSync !== "function") return;
  #|     // Security: resolve to absolute path and reject path traversal
  #|     const resolved = deno.realPathSync ? (() => {
  #|       // Resolve parent directory to detect traversal
  #|       const sep = filePath.lastIndexOf("/");
  #|       if (sep <= 0) return filePath;
  #|       const dir = filePath.slice(0, sep);
  #|       const base = filePath.slice(sep + 1);
  #|       // Reject filenames with path separators or traversal
  #|       if (base.includes("/") || base.includes("\\") || base === ".." || base === ".") {
  #|         console.error("[security] rejected filename: " + base);
  #|         return null;
  #|       }
  #|       // Reject if directory contains traversal sequences
  #|       if (dir.includes("..")) {
  #|         console.error("[security] rejected path traversal in directory: " + dir);
  #|         return null;
  #|       }
  #|       return filePath;
  #|     })() : filePath;
  #|     if (!resolved) return;
  #|     const sep = resolved.lastIndexOf("/");
  #|     if (sep > 0 && typeof deno.mkdirSync === "function") {
  #|       const dir = resolved.slice(0, sep);
  #|       try { deno.mkdirSync(dir, { recursive: true }); } catch (_e) {}
  #|     }
  #|     deno.writeTextFileSync(resolved, String(content ?? ""));
  #|   } catch (_e) {}
  #| }

///|
/// Write UTF-8 text file for synthetic download tests.
pub fn runtime_write_text_file(path : String, content : String) -> Unit {
  js_runtime_write_text_file(path, content)
}

///|
/// Collect iframe src values from runtime document.
extern "js" fn js_runtime_iframe_sources() -> Array[String] =
  #| () => {
  #|   const doc = globalThis.document;
  #|   if (!doc || typeof doc.querySelectorAll !== "function") return [];
  #|   const nodes = doc.querySelectorAll("iframe");
  #|   const result = [];
  #|   for (const node of nodes) {
  #|     let src = null;
  #|     try {
  #|       if (node && typeof node.getAttribute === "function") {
  #|         src = node.getAttribute("src");
  #|       }
  #|     } catch (_e) {}
  #|     if ((src === null || src === undefined || src === "") && node && node._attrs) {
  #|       src = node._attrs.src;
  #|     }
  #|     if (src === null || src === undefined || src === "") {
  #|       result.push("about:blank");
  #|     } else {
  #|       result.push(String(src));
  #|     }
  #|   }
  #|   return result;
  #| }

///|
/// Collect iframe src values from runtime document.
pub fn get_runtime_iframe_sources() -> Array[String] {
  js_runtime_iframe_sources()
}

///|
/// Resolve href from the most recent synthetic click target.
extern "js" fn js_runtime_last_click_href() -> String? =
  #| () => {
  #|   const href = globalThis.__bidiLastClickHref;
  #|   if (href === null || href === undefined || href === "") return "";
  #|   return String(href);
  #| }

///|
/// Resolve href from the most recent synthetic click target.
pub fn get_runtime_last_click_href() -> String? {
  js_runtime_last_click_href()
}

///|
/// Resolve data/absolute URL assigned by inline event handlers like onkeydown/onmousedown.
extern "js" fn js_runtime_inline_navigation_url(
  attribute_name : String,
) -> String? =
  #| (attributeName) => {
  #|   const doc = globalThis.document;
  #|   if (!doc || typeof doc.querySelectorAll !== "function") return "";
  #|   const attr = String(attributeName || "");
  #|   if (attr === "") return "";
  #|   const selector = `[${attr}]`;
  #|   const nodes = doc.querySelectorAll(selector);
  #|   for (const node of nodes) {
  #|     let handler = "";
  #|     try {
  #|       if (node && typeof node.getAttribute === "function") {
  #|         handler = node.getAttribute(attr) || "";
  #|       }
  #|     } catch (_e) {}
  #|     if (!handler && node && node._attrs) {
  #|       handler = String(node._attrs[attr] || "");
  #|     }
  #|     if (!handler) continue;
  #|     const match = String(handler).match(/window\.location(?:\.href)?\s*=\s*["']([^"']+)["']/);
  #|     if (!match || !match[1]) continue;
  #|     const raw = String(match[1]);
  #|     try {
  #|       const base =
  #|         (globalThis.location && globalThis.location.href) ||
  #|         globalThis.__pageUrl ||
  #|         "about:blank";
  #|       return new URL(raw, base).href;
  #|     } catch (_e) {
  #|       return raw;
  #|     }
  #|   }
  #|   return "";
  #| }

///|
/// Resolve data/absolute URL assigned by inline event handlers like onkeydown/onmousedown.
pub fn get_runtime_inline_navigation_url(attribute_name : String) -> String? {
  js_runtime_inline_navigation_url(attribute_name)
}

///|
/// Resolve href from element under viewport coordinates.
extern "js" fn js_runtime_href_at_point(x : Double, y : Double) -> String? =
  #| (x, y) => {
  #|   const doc = globalThis.document;
  #|   if (!doc) return "";
  #|   let node = null;
  #|   if (typeof doc.elementFromPoint === "function") {
  #|     try {
  #|       node = doc.elementFromPoint(Number(x), Number(y));
  #|     } catch (_e) {}
  #|   }
  #|   const hrefFromNode = (candidate) => {
  #|     let current = candidate;
  #|     while (current) {
  #|       let href = null;
  #|       try {
  #|         if (typeof current.getAttribute === "function") {
  #|           href = current.getAttribute("href");
  #|         }
  #|       } catch (_e) {}
  #|       if ((href === null || href === undefined || href === "") && current._attrs) {
  #|         href = current._attrs.href;
  #|       }
  #|       if (href !== null && href !== undefined && href !== "") {
  #|         const rawHref = String(href);
  #|         try {
  #|           const base =
  #|             (globalThis.location && globalThis.location.href) ||
  #|             globalThis.__pageUrl ||
  #|             "about:blank";
  #|           return new URL(rawHref, base).href;
  #|         } catch (_e) {
  #|           return rawHref;
  #|         }
  #|       }
  #|       current = current._parent || current.parentNode || null;
  #|     }
  #|     return null;
  #|   };
  #|   let href = hrefFromNode(node);
  #|   if (href !== null && href !== undefined && href !== "") return href;
  #|   if (href === null || href === undefined || href === "") return "";
  #|   return href;
  #| }

///|
/// Resolve href from element under viewport coordinates.
pub fn get_runtime_href_at_point(x : Double, y : Double) -> String? {
  js_runtime_href_at_point(x, y)
}

///|
/// Push the per-context Authorization snapshot into the JS realm. The
/// snapshot is consumed by the auto-installed globalThis.__bidiResolveAuth
/// helper that the fetch shim calls before dispatching each outbound
/// request. Mirror of set_runtime_context_cookies.
pub extern "js" fn js_set_runtime_context_authorization(
  ctx_id : String,
  auth_json : String,
) -> Unit =
  #| (ctxId, authJson) => {
  #|   if (!globalThis.__bidiContextAuth) globalThis.__bidiContextAuth = {};
  #|   try {
  #|     globalThis.__bidiContextAuth[ctxId] = JSON.parse(authJson);
  #|   } catch (_e) {
  #|     globalThis.__bidiContextAuth[ctxId] = {};
  #|   }
  #|   if (typeof globalThis.__bidiResolveAuth !== 'function') {
  #|     globalThis.__bidiResolveAuth = function(url) {
  #|       const ctx = String(globalThis.__bidiCurrentContext || 'default-context');
  #|       const map = (globalThis.__bidiContextAuth || {})[ctx] || {};
  #|       try {
  #|         const u = new URL(url);
  #|         let origin = u.protocol + '//' + u.hostname;
  #|         if (
  #|           (u.protocol === 'http:'  && u.port && u.port !== '80') ||
  #|           (u.protocol === 'https:' && u.port && u.port !== '443')
  #|         ) origin += ':' + u.port;
  #|         return map[origin] || null;
  #|       } catch (_e) { return null; }
  #|     };
  #|   }
  #| }

///|
/// Push the per-context Authorization snapshot for `ctx_id` into the JS realm.
fn set_runtime_context_authorization(
  ctx_id : String,
  auth_json : String,
) -> Unit {
  js_set_runtime_context_authorization(ctx_id, auth_json)
}

///|
/// Push the per-context Digest credentials snapshot into the JS realm.
/// The snapshot shape is `{ origin: { username, password } }`. Consumed
/// by the fetch shim's 401 Digest auto-retry path via the auto-installed
/// `globalThis.__bidiResolveCredentials(url)` helper.
///
/// Credentials are passed by-value into the JS realm — there is no
/// indirection that would let the page read them ambient-style. The
/// runtime-side helper only returns the matching entry for the request's
/// origin AND only inside the retry path that already has a Digest
/// challenge in hand, so an attacker page on a different origin can't
/// silently extract a stored credential by issuing fetches.
pub extern "js" fn js_set_runtime_context_credentials(
  ctx_id : String,
  creds_json : String,
) -> Unit =
  #| (ctxId, credsJson) => {
  #|   if (!globalThis.__bidiContextCredentials) globalThis.__bidiContextCredentials = {};
  #|   try {
  #|     globalThis.__bidiContextCredentials[ctxId] = JSON.parse(credsJson);
  #|   } catch (_e) {
  #|     globalThis.__bidiContextCredentials[ctxId] = {};
  #|   }
  #|   if (typeof globalThis.__bidiResolveCredentials !== 'function') {
  #|     globalThis.__bidiResolveCredentials = function(url) {
  #|       const ctx = String(globalThis.__bidiCurrentContext || 'default-context');
  #|       const map = (globalThis.__bidiContextCredentials || {})[ctx] || {};
  #|       try {
  #|         const u = new URL(url);
  #|         let origin = u.protocol + '//' + u.hostname;
  #|         if (
  #|           (u.protocol === 'http:'  && u.port && u.port !== '80') ||
  #|           (u.protocol === 'https:' && u.port && u.port !== '443')
  #|         ) origin += ':' + u.port;
  #|         return map[origin] || null;
  #|       } catch (_e) { return null; }
  #|     };
  #|   }
  #| }

///|
/// Push the per-context credentials snapshot for `ctx_id` into the JS realm.
fn set_runtime_context_credentials(
  ctx_id : String,
  creds_json : String,
) -> Unit {
  js_set_runtime_context_credentials(ctx_id, creds_json)
}