// =============================================================================
// JavaScript Evaluation for BiDi script.evaluate
// =============================================================================

///|
/// FFI: Evaluate JavaScript expression and return BiDi remote value JSON
/// Returns: { "type": "success"|"exception", "result"|"exceptionDetails": ..., "consoleEntries": [...] }
extern "js" fn js_evaluate_expression(
  expression : String,
  capture_console : Bool,
  user_activation : Bool,
  root_ownership : Bool,
  serialization_options_json : String,
) -> String =
  #| (expression, captureConsole, userActivation, rootOwnership, serializationOptionsJson) => {
  #|   const consoleEntries = [];
  #|   let originalConsole = null;
  #|   const resolveCurrentLogUrl = () => {
  #|     try {
  #|       if (globalThis.location && typeof globalThis.location.href === "string" && globalThis.location.href !== "") {
  #|         return String(globalThis.location.href);
  #|       }
  #|     } catch (_e) {}
  #|     try {
  #|       if (typeof globalThis.__pageUrl === "string" && globalThis.__pageUrl !== "") {
  #|         return String(globalThis.__pageUrl);
  #|       }
  #|     } catch (_e) {}
  #|     return "about:blank";
  #|   };
  #|   const resolveInlineScriptOffsets = () => {
  #|     const url = resolveCurrentLogUrl();
  #|     if (!url.startsWith("data:")) {
  #|       return { lineOffset: 0, columnOffset: 0 };
  #|     }
  #|     try {
  #|       const comma = url.indexOf(",");
  #|       if (comma < 0) return { lineOffset: 0, columnOffset: 0 };
  #|       const meta = url.slice(0, comma).toLowerCase();
  #|       const payload = url.slice(comma + 1);
  #|       let decoded = "";
  #|       if (meta.includes(";base64")) {
  #|         decoded = atob(payload);
  #|       } else {
  #|         decoded = decodeURIComponent(payload);
  #|       }
  #|       const lines = decoded.replace(/\r\n/g, "\n").split("\n");
  #|       let inScript = false;
  #|       for (let index = 0; index < lines.length; index++) {
  #|         const line = String(lines[index] || "");
  #|         const lower = line.toLowerCase();
  #|         if (!inScript) {
  #|           if (lower.includes(" {
  #|     const frames = [];
  #|     const stack = String(stackText || "");
  #|     const lines = stack.split("\n");
  #|     for (let i = 0; i < lines.length; i++) {
  #|       const rawLine = String(lines[i] || "").trim();
  #|       if (!rawLine.startsWith("at ")) continue;
  #|       const body = rawLine.slice(3);
  #|       let functionName = "";
  #|       let location = body;
  #|       const withParens = body.match(/^(.*?)\s+\((.*)\)$/);
  #|       if (withParens) {
  #|         functionName = String(withParens[1] || "");
  #|         location = String(withParens[2] || "");
  #|       } else {
  #|         functionName = "";
  #|         location = body;
  #|       }
  #|       if (
  #|         functionName.includes("pushConsoleEntry") ||
  #|         functionName.includes("makeInterceptor")
  #|       ) {
  #|         continue;
  #|       }
  #|       let lineNumber = 0;
  #|       let columnNumber = 0;
  #|       let url = resolveCurrentLogUrl();
  #|       const anonymousLocationMatch = location.match(/:(\d+):(\d+)$/);
  #|       if (anonymousLocationMatch) {
  #|         const leadingColumnOffset = frames.length === 0
  #|           ? Number(inlineScriptOffsets.columnOffset || 0)
  #|           : 0;
  #|         lineNumber = Number(anonymousLocationMatch[1]) + Number(inlineScriptOffsets.lineOffset || 0);
  #|         columnNumber = Math.max(
  #|           0,
  #|           Number(anonymousLocationMatch[2]) + leadingColumnOffset - 1,
  #|         );
  #|       } else {
  #|         const locationMatch = location.match(/^(.*):(\d+):(\d+)$/);
  #|         if (!locationMatch) continue;
  #|         url = String(locationMatch[1] || "");
  #|         if (url.includes("bidi_main.js")) continue;
  #|         lineNumber = Number(locationMatch[2]);
  #|         columnNumber = Math.max(0, Number(locationMatch[3]) - 1);
  #|       }
  #|       if (functionName === "eval") {
  #|         functionName = "";
  #|       }
  #|       frames.push({
  #|         columnNumber,
  #|         functionName,
  #|         lineNumber,
  #|         url,
  #|       });
  #|       if (frames.length >= 3) break;
  #|     }
  #|     return { callFrames: frames };
  #|   };
  #|   const pushJavascriptErrorEntry = (errorValue) => {
  #|     if (!captureConsole) return;
  #|     const stackTrace = buildStackTraceFromStack(errorValue && errorValue.stack ? errorValue.stack : "");
  #|     const entry = {
  #|       type: "javascript",
  #|       level: "error",
  #|       text: String(errorValue),
  #|       timestamp: Date.now(),
  #|       realm: String(globalThis.__bidiCurrentRealm || ""),
  #|     };
  #|     if (Array.isArray(stackTrace.callFrames) && stackTrace.callFrames.length > 0) {
  #|       entry.stackTrace = stackTrace;
  #|     }
  #|     consoleEntries.push(entry);
  #|   };
  #|   globalThis.__bidiPushJavascriptErrorEntry = pushJavascriptErrorEntry;
  #|   if (captureConsole) {
  #|     originalConsole = {
  #|       target: console,
  #|       log: console.log,
  #|       warn: console.warn,
  #|       error: console.error,
  #|       info: console.info,
  #|       debug: console.debug,
  #|       assert: console.assert,
  #|       table: console.table,
  #|       trace: console.trace,
  #|       time: console.time,
  #|       timeEnd: console.timeEnd
  #|     };
  #|
  #|     const consoleArgToText = (arg) => {
  #|       if (typeof arg === "string") return arg;
  #|       if (arg === undefined) return "undefined";
  #|       if (typeof arg === "bigint") return `${arg}n`;
  #|       try {
  #|         const json = JSON.stringify(arg);
  #|         if (json !== undefined) return json;
  #|       } catch (_e) {}
  #|       return String(arg);
  #|     };
  #|
  #|     const pushConsoleEntry = (level, method, args, textArgs = args) => {
  #|       const stackTrace = buildStackTraceFromStack(new Error().stack || "");
  #|       const entry = {
  #|         type: "console",
  #|         level,
  #|         method,
  #|         text: textArgs.map(consoleArgToText).join(" "),
  #|         args: args.map(toBidiValue),
  #|         timestamp: Date.now(),
  #|         realm: String(globalThis.__bidiCurrentRealm || ""),
  #|       };
  #|       if (Array.isArray(stackTrace.callFrames) && stackTrace.callFrames.length > 0) {
  #|         entry.stackTrace = stackTrace;
  #|       }
  #|       consoleEntries.push(entry);
  #|     };
  #|
  #|     // Intercept console calls
  #|     const makeInterceptor = (level, method) => (...args) => {
  #|       pushConsoleEntry(level, method, args);
  #|     };
  #|
  #|     console.log = makeInterceptor('info', 'log');
  #|     console.warn = makeInterceptor('warn', 'warn');
  #|     console.error = makeInterceptor('error', 'error');
  #|     console.info = makeInterceptor('info', 'info');
  #|     console.debug = makeInterceptor('debug', 'debug');
  #|     console.table = makeInterceptor('info', 'table');
  #|     console.trace = makeInterceptor('debug', 'trace');
  #|     console.assert = (...args) => {
  #|       if (args.length > 0 && args[0]) {
  #|         return;
  #|       }
  #|       const textArgs = args.length > 1 ? args.slice(1) : ["Assertion failed"];
  #|       pushConsoleEntry("error", "assert", textArgs);
  #|     };
  #|     console.time = (...args) => {
  #|     };
  #|     console.timeEnd = (...args) => {
  #|       const textArgs = args.length > 0 ? args : ["default"];
  #|       pushConsoleEntry("info", "timeEnd", textArgs);
  #|     };
  #|   }
  #|
  #|   let serializationOptions = {};
  #|   try {
  #|     serializationOptions =
  #|       serializationOptionsJson && serializationOptionsJson.length > 0
  #|         ? JSON.parse(serializationOptionsJson)
  #|         : {};
  #|   } catch (_e) {
  #|     serializationOptions = {};
  #|   }
  #|   const hasMaxDomDepth = Object.prototype.hasOwnProperty.call(serializationOptions, "maxDomDepth");
  #|   const hasMaxObjectDepth = Object.prototype.hasOwnProperty.call(serializationOptions, "maxObjectDepth");
  #|   const rawMaxDomDepth = hasMaxDomDepth ? serializationOptions.maxDomDepth : undefined;
  #|   const rawMaxObjectDepth = hasMaxObjectDepth ? serializationOptions.maxObjectDepth : undefined;
  #|   const maxDomDepth =
  #|     rawMaxDomDepth === null
  #|       ? null
  #|       : (typeof rawMaxDomDepth === "number" && rawMaxDomDepth >= 0 ? rawMaxDomDepth : undefined);
  #|   const maxObjectDepth =
  #|     rawMaxObjectDepth === null
  #|       ? null
  #|       : (typeof rawMaxObjectDepth === "number" && rawMaxObjectDepth >= 0 ? rawMaxObjectDepth : undefined);
  #|   const includeShadowTree =
  #|     serializationOptions.includeShadowTree === "open" || serializationOptions.includeShadowTree === "all"
  #|       ? serializationOptions.includeShadowTree
  #|       : "none";
  #|
  #|   const applyUserActivation = (active) => {
  #|     const isActive = !!active;
  #|     globalThis.__bidiUserActivation = isActive;
  #|     if (!globalThis.navigator) globalThis.navigator = {};
  #|     globalThis.navigator.userActivation = {
  #|       isActive,
  #|       hasBeenActive: isActive
  #|     };
  #|     if (globalThis.document) {
  #|       globalThis.document.execCommand = function(command) {
  #|         const cmd = String(command || '').toLowerCase();
  #|         if (cmd === 'selectall') return true;
  #|         if (cmd === 'copy') return !!globalThis.__bidiUserActivation;
  #|         return false;
  #|       };
  #|     }
  #|     if (globalThis.document && typeof globalThis.__bidiEnsureDocumentRange === "function") {
  #|       globalThis.__bidiEnsureDocumentRange(globalThis.document);
  #|       if (globalThis.window && typeof globalThis.window === "object") {
  #|         globalThis.window.document = globalThis.document;
  #|       }
  #|     }
  #|   };
  #|
  #|   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 in
  #|       // the reserved set, the per-eval window→globalThis sync would
  #|       // delete them (when window doesn't carry them) right before the
  #|       // user expression runs.
  #|       "IntersectionObserver", "ResizeObserver", "MutationObserver",
  #|       // Network primitives provided natively by Node 22+. Reserving them
  #|       // ensures the per-eval sync doesn't drop the WebSocket / EventSource
  #|       // constructors that real-time apps need.
  #|       "WebSocket", "EventSource",
  #|       // File upload surface — Blob/File are native in Node 22, FileReader
  #|       // is shimmed below. Real apps' upload UIs touch all three.
  #|       "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();
  #|
  #|   // Setup Mock DOM if not already present
  #|   if (!globalThis.document) {
  #|     // MutationObserver implementation
  #|     const _mutationObservers = [];
  #|     let _mutationScheduled = false;
  #|     const _pendingMutations = new Map();
  #|
  #|     const shouldNotify = (mutatedNode, observedTarget, options, type) => {
  #|       if (type === 'childList' && !options.childList) return false;
  #|       if (type === 'attributes' && !options.attributes) return false;
  #|       if (type === 'characterData' && !options.characterData) return false;
  #|       if (mutatedNode === observedTarget) return true;
  #|       if (options.subtree) {
  #|         let node = mutatedNode;
  #|         while (node) {
  #|           if (node === observedTarget) return true;
  #|           node = node._parent;
  #|         }
  #|       }
  #|       return false;
  #|     };
  #|
  #|     const createMutationRecord = (type, target, opts = {}) => ({
  #|       type,
  #|       target,
  #|       addedNodes: opts.addedNodes || [],
  #|       removedNodes: opts.removedNodes || [],
  #|       previousSibling: opts.previousSibling || null,
  #|       nextSibling: opts.nextSibling || null,
  #|       attributeName: opts.attributeName || null,
  #|       attributeNamespace: opts.attributeNamespace || null,
  #|       oldValue: opts.oldValue || null
  #|     });
  #|
  #|     const notifyMutation = (record) => {
  #|       for (const observer of _mutationObservers) {
  #|         for (const { target, options } of observer._targets) {
  #|           if (shouldNotify(record.target, target, options, record.type)) {
  #|             if (!_pendingMutations.has(observer)) {
  #|               _pendingMutations.set(observer, []);
  #|             }
  #|             _pendingMutations.get(observer).push(record);
  #|             break;
  #|           }
  #|         }
  #|       }
  #|       // Schedule microtask to batch notifications
  #|       if (!_mutationScheduled && _pendingMutations.size > 0) {
  #|         _mutationScheduled = true;
  #|         // Use Promise.resolve for microtask scheduling (works in Deno)
  #|         Promise.resolve().then(() => {
  #|           _mutationScheduled = false;
  #|           for (const [observer, records] of _pendingMutations) {
  #|             if (records.length > 0) {
  #|               try {
  #|                 observer._callback(records, observer);
  #|               } catch (e) {
  #|                 console.error('MutationObserver callback error:', e);
  #|               }
  #|             }
  #|           }
  #|           _pendingMutations.clear();
  #|         });
  #|       }
  #|     };
  #|
  #|     globalThis.MutationObserver = class MutationObserver {
  #|       constructor(callback) {
  #|         this._callback = callback;
  #|         this._targets = [];
  #|       }
  #|       observe(target, options = {}) {
  #|         this._targets.push({ target, options });
  #|         if (!_mutationObservers.includes(this)) {
  #|           _mutationObservers.push(this);
  #|         }
  #|       }
  #|       disconnect() {
  #|         this._targets = [];
  #|         const idx = _mutationObservers.indexOf(this);
  #|         if (idx !== -1) _mutationObservers.splice(idx, 1);
  #|         _pendingMutations.delete(this);
  #|       }
  #|       takeRecords() {
  #|         const records = _pendingMutations.get(this) || [];
  #|         _pendingMutations.delete(this);
  #|         return records;
  #|       }
  #|     };
  #|
  #|     const toCollection = (items, collectionType) => {
  #|       if (!Array.isArray(items)) return items;
  #|       if (collectionType) {
  #|         Object.defineProperty(items, "__bidiCollectionType", {
  #|           value: String(collectionType),
  #|           configurable: true,
  #|           enumerable: false,
  #|           writable: true
  #|         });
  #|       }
  #|       if (typeof items.item !== "function") {
  #|         items.item = function(index) {
  #|           return this[index] ?? null;
  #|         };
  #|       }
  #|       return items;
  #|     };
  #|
  #|     // Minimal Mock DOM for Preact compatibility
  #|     const getContainingShadowRoot = (node) => {
  #|       let current = node;
  #|       while (current) {
  #|         if (current._isShadowRoot) return current;
  #|         current = current._parent || current.parentNode || null;
  #|       }
  #|       return null;
  #|     };
  #|     const getFocusAttr = (node, name) => {
  #|       if (!node || typeof node !== "object") return null;
  #|       try {
  #|         if (typeof node.getAttribute === "function") {
  #|           const value = node.getAttribute(name);
  #|           if (value !== null && value !== undefined) return String(value);
  #|         }
  #|       } catch (_e) {}
  #|       if (node._attrs && Object.prototype.hasOwnProperty.call(node._attrs, name)) {
  #|         const value = node._attrs[name];
  #|         return value === null || value === undefined ? null : String(value);
  #|       }
  #|       return null;
  #|     };
  #|     const getFocusChildren = (node) => {
  #|       if (!node || typeof node !== "object") return [];
  #|       if (Array.isArray(node._children)) return node._children;
  #|       if (Array.isArray(node.children)) return Array.from(node.children);
  #|       if (Array.isArray(node.childNodes)) return Array.from(node.childNodes);
  #|       return [];
  #|     };
  #|     const nodeContains = (root, node) => {
  #|       if (!root || !node) return false;
  #|       if (root === node) return true;
  #|       try {
  #|         if (typeof root.contains === "function") return !!root.contains(node);
  #|       } catch (_e) {}
  #|       const children = getFocusChildren(root);
  #|       for (let i = 0; i < children.length; i += 1) {
  #|         if (nodeContains(children[i], node)) return true;
  #|       }
  #|       return false;
  #|     };
  #|     const isSlotElementForFocus = (node) => {
  #|       if (!node || node.nodeType !== 1) return false;
  #|       const localName = String(node.localName || node.tagName || node.nodeName || "").toLowerCase();
  #|       return localName === "slot";
  #|     };
  #|     const findFirstSlotForFocusName = (root, slotName) => {
  #|       const children = getFocusChildren(root);
  #|       for (let i = 0; i < children.length; i += 1) {
  #|         const child = children[i];
  #|         if (!child || child.nodeType !== 1) continue;
  #|         if (isSlotElementForFocus(child) && String(getFocusAttr(child, "name") || "") === slotName) {
  #|           return child;
  #|         }
  #|         const nested = findFirstSlotForFocusName(child, slotName);
  #|         if (nested) return nested;
  #|       }
  #|       return null;
  #|     };
  #|     const getAssignedChildrenForFocusSlot = (slot) => {
  #|       const shadowRoot = getContainingShadowRoot(slot);
  #|       if (!shadowRoot || !shadowRoot.host) return getFocusChildren(slot);
  #|       const slotName = String(getFocusAttr(slot, "name") || "");
  #|       const firstMatch = findFirstSlotForFocusName(shadowRoot, slotName);
  #|       if (firstMatch && firstMatch !== slot) return [];
  #|       const assigned = [];
  #|       const hostChildren = getFocusChildren(shadowRoot.host);
  #|       for (let i = 0; i < hostChildren.length; i += 1) {
  #|         const child = hostChildren[i];
  #|         if (!child) continue;
  #|         const childSlotName = String(getFocusAttr(child, "slot") || "");
  #|         if (childSlotName === slotName) assigned.push(child);
  #|       }
  #|       return assigned.length > 0 ? assigned : getFocusChildren(slot);
  #|     };
  #|     const getDelegatesFocusChildren = (node) => {
  #|       if (!node || typeof node !== "object") return [];
  #|       if (isSlotElementForFocus(node)) return getAssignedChildrenForFocusSlot(node);
  #|       const shadowRoot = node.shadowRoot || null;
  #|       if (shadowRoot) return getFocusChildren(shadowRoot);
  #|       return getFocusChildren(node);
  #|     };
  #|     const hasExplicitSequentialTabIndexForFocus = (node) => {
  #|       if (!node || typeof node !== "object") return false;
  #|       try {
  #|         if (typeof node.getAttribute === "function" && node.getAttribute("tabindex") !== null) {
  #|           return true;
  #|         }
  #|       } catch (_e) {}
  #|       return !!(node._attrs && Object.prototype.hasOwnProperty.call(node._attrs, "tabindex"));
  #|     };
  #|     const isSequentiallyFocusableForFocus = (node) => {
  #|       if (!node || node.nodeType !== 1) return false;
  #|       if (node.disabled || node.hidden) return false;
  #|       const style = node.style || {};
  #|       if (style.display === "none" || style.visibility === "hidden") return false;
  #|       if (hasExplicitSequentialTabIndexForFocus(node)) {
  #|         try {
  #|           return Number(node.tabIndex) >= 0;
  #|         } catch (_e) {
  #|           return false;
  #|         }
  #|       }
  #|       const tag = String(node.tagName || node.nodeName || "").toLowerCase();
  #|       if (["input", "textarea", "select", "button"].includes(tag)) return true;
  #|       if (tag === "a") {
  #|         try {
  #|           return !!(typeof node.getAttribute === "function" ? node.getAttribute("href") : null);
  #|         } catch (_e) {
  #|           return false;
  #|         }
  #|       }
  #|       return !!node.isContentEditable;
  #|     };
  #|     const findDelegatesFocusTarget = (node) => {
  #|       const shadowRoot = node && node.shadowRoot ? node.shadowRoot : null;
  #|       if (!shadowRoot || !shadowRoot.delegatesFocus) return null;
  #|       const visit = (current) => {
  #|         const children = getDelegatesFocusChildren(current);
  #|         for (let i = 0; i < children.length; i += 1) {
  #|           const child = children[i];
  #|           if (!child || child.nodeType !== 1) continue;
  #|           if (isSequentiallyFocusableForFocus(child)) return child;
  #|           const nested = visit(child);
  #|           if (nested) return nested;
  #|         }
  #|         return null;
  #|       };
  #|       return visit(shadowRoot);
  #|     };
  #|     const clearDocumentActiveChain = (doc) => {
  #|       if (!doc) return;
  #|       const current = doc.activeElement || null;
  #|       if (current && current.shadowRoot && current.shadowRoot.activeElement) {
  #|         current.shadowRoot.activeElement = null;
  #|       }
  #|       doc.activeElement = doc.body || null;
  #|     };
  #|     const getDeepActiveElement = (doc) => {
  #|       if (!doc) return null;
  #|       let current = doc.activeElement || null;
  #|       const visited = new Set();
  #|       while (current && !visited.has(current)) {
  #|         visited.add(current);
  #|         const next =
  #|           current.shadowRoot && current.shadowRoot.activeElement
  #|             ? current.shadowRoot.activeElement
  #|             : null;
  #|         if (!next) break;
  #|         current = next;
  #|       }
  #|       return current;
  #|     };
  #|     const retargetEventTarget = (originalTarget, currentTarget) => {
  #|       let candidate = originalTarget;
  #|       while (candidate) {
  #|         const shadowRoot = getContainingShadowRoot(candidate);
  #|         if (!shadowRoot) return candidate;
  #|         if (currentTarget === shadowRoot || nodeContains(shadowRoot, currentTarget)) {
  #|           return candidate;
  #|         }
  #|         candidate = shadowRoot.host || candidate;
  #|         if (!shadowRoot.host) return candidate;
  #|       }
  #|       return originalTarget;
  #|     };
  #|     const prepareEventForCurrentTarget = (event, currentTarget) => {
  #|       const originalTarget = event.__originalTarget || event.target || currentTarget;
  #|       const originalRelatedTarget =
  #|         event.__originalRelatedTarget !== undefined
  #|           ? event.__originalRelatedTarget
  #|           : (event.relatedTarget || null);
  #|       event.__originalTarget = originalTarget;
  #|       event.__originalRelatedTarget = originalRelatedTarget;
  #|       const adjustedTarget = retargetEventTarget(originalTarget, currentTarget);
  #|       const adjustedRelatedTarget = originalRelatedTarget
  #|         ? retargetEventTarget(originalRelatedTarget, currentTarget)
  #|         : null;
  #|       event.__retargetSuppressed =
  #|         !!(adjustedTarget && adjustedRelatedTarget && adjustedTarget === adjustedRelatedTarget);
  #|       try { event.target = adjustedTarget; } catch (_e) {}
  #|       try { event.relatedTarget = adjustedRelatedTarget; } catch (_e) {}
  #|       try { event.currentTarget = currentTarget; } catch (_e) {}
  #|     };
  #|     const dispatchFocusFamilyEvent = (target, type, bubbles, relatedTarget) => {
  #|       if (!target || typeof target.dispatchEvent !== "function") return;
  #|       const event = globalThis.__bidiCreateEvent(type, {
  #|         bubbles: !!bubbles,
  #|         cancelable: false,
  #|       });
  #|       event.relatedTarget = relatedTarget || null;
  #|       event.__originalRelatedTarget = relatedTarget || null;
  #|       target.dispatchEvent(event);
  #|     };
  #|     const focusNode = (node) => {
  #|       const doc = node && node.ownerDocument ? node.ownerDocument : globalThis.document;
  #|       if (!doc) return;
  #|       const delegatedTarget = findDelegatesFocusTarget(node);
  #|       if (delegatedTarget && delegatedTarget !== node) {
  #|         focusNode(delegatedTarget);
  #|         return;
  #|       }
  #|       const previous = getDeepActiveElement(doc);
  #|       if (previous === node) return;
  #|       if (previous) {
  #|         dispatchFocusFamilyEvent(previous, "blur", false, node);
  #|         dispatchFocusFamilyEvent(previous, "focusout", true, node);
  #|       }
  #|       clearDocumentActiveChain(doc);
  #|       const shadowRoot = getContainingShadowRoot(node);
  #|       if (shadowRoot && shadowRoot.host) {
  #|         shadowRoot.activeElement = node;
  #|         doc.activeElement = shadowRoot.host;
  #|       } else {
  #|         doc.activeElement = node;
  #|       }
  #|       dispatchFocusFamilyEvent(node, "focus", false, previous);
  #|       dispatchFocusFamilyEvent(node, "focusin", true, previous);
  #|     };
  #|     const blurNode = (node) => {
  #|       const doc = node && node.ownerDocument ? node.ownerDocument : globalThis.document;
  #|       if (!doc) return;
  #|       let target = node;
  #|       const ownShadowRoot = node && node.shadowRoot ? node.shadowRoot : null;
  #|       if (ownShadowRoot && ownShadowRoot.activeElement) {
  #|         target = ownShadowRoot.activeElement;
  #|       }
  #|       const active = getDeepActiveElement(doc);
  #|       if (active && active !== target && active !== node) return;
  #|       const shadowRoot = getContainingShadowRoot(target);
  #|       dispatchFocusFamilyEvent(target, "blur", false, null);
  #|       dispatchFocusFamilyEvent(target, "focusout", true, null);
  #|       if (shadowRoot && shadowRoot.activeElement === target) {
  #|         shadowRoot.activeElement = null;
  #|         if (doc.activeElement === shadowRoot.host) {
  #|           doc.activeElement = doc.body || null;
  #|         }
  #|       }
  #|       if (doc.activeElement === target || doc.activeElement === node) {
  #|         doc.activeElement = doc.body || null;
  #|       }
  #|     };
  #|
  #|     const toCamelStyleName = (name) =>
  #|       String(name || "").replace(/-([a-z])/g, (_, c) => c.toUpperCase());
  #|     const toKebabStyleName = (name) =>
  #|       String(name || "").replace(/([A-Z])/g, "-$1").toLowerCase();
  #|     const getStylePropertyValue = (style, name) => {
  #|       const prop = String(name || "");
  #|       if (!prop) return "";
  #|       if (prop.startsWith("--")) return style[prop] ?? "";
  #|       const camel = toCamelStyleName(prop);
  #|       const kebab = toKebabStyleName(prop);
  #|       return style[prop] ?? style[camel] ?? style[kebab] ?? "";
  #|     };
  #|     const setStylePropertyValue = (style, name, value) => {
  #|       const prop = String(name || "");
  #|       if (!prop) return;
  #|       const next = value == null ? "" : String(value);
  #|       if (prop.startsWith("--")) {
  #|         style[prop] = next;
  #|         return;
  #|       }
  #|       const camel = toCamelStyleName(prop);
  #|       const kebab = toKebabStyleName(prop);
  #|       style[prop] = next;
  #|       style[camel] = next;
  #|       style[kebab] = next;
  #|     };
  #|     const removeStylePropertyValue = (style, name) => {
  #|       const prop = String(name || "");
  #|       const previous = getStylePropertyValue(style, prop);
  #|       if (!prop) return previous;
  #|       if (prop.startsWith("--")) {
  #|         delete style[prop];
  #|         return previous;
  #|       }
  #|       delete style[prop];
  #|       delete style[toCamelStyleName(prop)];
  #|       delete style[toKebabStyleName(prop)];
  #|       return previous;
  #|     };
  #|     const clearStyleProperties = (style) => {
  #|       for (const key of Object.keys(style)) delete style[key];
  #|     };
  #|     const parseStyleTextInto = (style, text) => {
  #|       clearStyleProperties(style);
  #|       String(text || "").split(";").forEach((part) => {
  #|         const index = part.indexOf(":");
  #|         if (index < 0) return;
  #|         const prop = part.slice(0, index).trim();
  #|         const value = part.slice(index + 1).trim();
  #|         if (prop) setStylePropertyValue(style, prop, value);
  #|       });
  #|     };
  #|     const serializeStyleText = (style) => {
  #|       const seen = new Set();
  #|       const parts = [];
  #|       for (const key of Object.keys(style)) {
  #|         const prop = key.startsWith("--") ? key : toKebabStyleName(key);
  #|         if (!prop || seen.has(prop)) continue;
  #|         seen.add(prop);
  #|         const value = getStylePropertyValue(style, key);
  #|         if (value !== "") parts.push(`${prop}: ${value};`);
  #|       }
  #|       return parts.join(" ");
  #|     };
  #|     const createStyleDeclaration = (element) => {
  #|       const style = element._style || (element._style = {});
  #|       return new Proxy(style, {
  #|         get(target, prop) {
  #|           if (prop === "setProperty") {
  #|             return (name, value) => setStylePropertyValue(target, name, value);
  #|           }
  #|           if (prop === "getPropertyValue") {
  #|             return (name) => getStylePropertyValue(target, name);
  #|           }
  #|           if (prop === "removeProperty") {
  #|             return (name) => removeStylePropertyValue(target, name);
  #|           }
  #|           if (prop === "cssText") return serializeStyleText(target);
  #|           if (prop === "item") {
  #|             return (index) => Object.keys(target)[Number(index)] || "";
  #|           }
  #|           if (prop === "length") return Object.keys(target).length;
  #|           if (typeof prop !== "string") return target[prop];
  #|           return getStylePropertyValue(target, prop);
  #|         },
  #|         set(target, prop, value) {
  #|           if (prop === "cssText") {
  #|             parseStyleTextInto(target, value);
  #|             return true;
  #|           }
  #|           if (typeof prop !== "string") {
  #|             target[prop] = value;
  #|             return true;
  #|           }
  #|           setStylePropertyValue(target, prop, value);
  #|           return true;
  #|         },
  #|         has(target, prop) {
  #|           if (typeof prop !== "string") return prop in target;
  #|           return prop in target || getStylePropertyValue(target, prop) !== "";
  #|         },
  #|         ownKeys(target) {
  #|           return Reflect.ownKeys(target);
  #|         },
  #|         getOwnPropertyDescriptor(target, prop) {
  #|           if (typeof prop !== "string") return Object.getOwnPropertyDescriptor(target, prop);
  #|           return {
  #|             value: getStylePropertyValue(target, prop),
  #|             writable: true,
  #|             enumerable: true,
  #|             configurable: true,
  #|           };
  #|         }
  #|       });
  #|     };
  #|
  #|     // ---- HTML form submission helpers (used by createMockElement('form')) ----
  #|     const descendsFrom = (node, ancestor) => {
  #|       let cur = node && (node._parent || node.parentNode || null);
  #|       while (cur) {
  #|         if (cur === ancestor) return true;
  #|         cur = cur._parent || cur.parentNode || null;
  #|       }
  #|       return false;
  #|     };
  #|     const collectFormControls = (formEl) => {
  #|       const out = [];
  #|       const stack = [formEl];
  #|       const allowed = new Set(['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON']);
  #|       while (stack.length) {
  #|         const node = stack.pop();
  #|         if (!node) continue;
  #|         const kids = node._children || node.childNodes || [];
  #|         for (let i = kids.length - 1; i >= 0; i--) stack.push(kids[i]);
  #|         if (node === formEl) continue;
  #|         if (node.nodeType !== 1) continue;
  #|         if (!allowed.has(String(node.tagName || ''))) continue;
  #|         const attrs = node._attrs || {};
  #|         if ('disabled' in attrs) continue;
  #|         const name = attrs.name;
  #|         if (typeof name !== 'string' || name.length === 0) continue;
  #|         out.push(node);
  #|       }
  #|       return out;
  #|     };
  #|     const optionEffectiveValue = (option) => {
  #|       const oAttrs = option._attrs || {};
  #|       if (typeof oAttrs.value === 'string') return oAttrs.value;
  #|       // Fall back to the option's text content (concatenated descendant text).
  #|       const collectText = (node) => {
  #|         if (!node) return '';
  #|         if (node.nodeType === 3) {
  #|           if (typeof node.data === 'string') return node.data;
  #|           if (typeof node.nodeValue === 'string') return node.nodeValue;
  #|           return '';
  #|         }
  #|         const kids = node._children || node.childNodes || [];
  #|         let buf = '';
  #|         for (let i = 0; i < kids.length; i++) buf += collectText(kids[i]);
  #|         return buf;
  #|       };
  #|       return collectText(option);
  #|     };
  #|     const collectSelectOptions = (selectEl) => {
  #|       const out = [];
  #|       const stack = [selectEl];
  #|       while (stack.length) {
  #|         const node = stack.pop();
  #|         if (!node) continue;
  #|         const kids = node._children || node.childNodes || [];
  #|         for (let i = kids.length - 1; i >= 0; i--) stack.push(kids[i]);
  #|         if (node === selectEl) continue;
  #|         if (node.nodeType !== 1) continue;
  #|         if (String(node.tagName || '') === 'OPTION') out.push(node);
  #|       }
  #|       return out;
  #|     };
  #|     const controlEffectiveValue = (control) => {
  #|       const attrs = control._attrs || {};
  #|       const tag = String(control.tagName || '');
  #|       const type = String(attrs.type || '').toLowerCase();
  #|       if (tag === 'INPUT' && (type === 'checkbox' || type === 'radio')) {
  #|         if (typeof attrs.value === 'string' && attrs.value !== '') return attrs.value;
  #|         return 'on';
  #|       }
  #|       if (tag === 'SELECT') {
  #|         // Multi-select: return every selected option's effective value as
  #|         // an array; serializer emits one name=value pair per entry per
  #|         // https://html.spec.whatwg.org/#constructing-the-form-data-set.
  #|         const isMultiple =
  #|           !!attrs.multiple ||
  #|           control.multiple === true ||
  #|           (typeof control.multiple === 'string' && control.multiple !== '');
  #|         if (isMultiple) {
  #|           const options = collectSelectOptions(control);
  #|           const values = [];
  #|           for (const opt of options) {
  #|             const oAttrs = opt._attrs || {};
  #|             const selected = opt.selected === true ||
  #|               (opt.selected === undefined && !!oAttrs.selected);
  #|             if (selected) values.push(optionEffectiveValue(opt));
  #|           }
  #|           return values;
  #|         }
  #|         if (typeof control.value === 'string' && control.value !== '') return control.value;
  #|         if (typeof attrs.value === 'string' && attrs.value !== '') return attrs.value;
  #|         const options = collectSelectOptions(control);
  #|         if (options.length === 0) return '';
  #|         for (const opt of options) {
  #|           const oAttrs = opt._attrs || {};
  #|           const selected = opt.selected === true ||
  #|             (opt.selected === undefined && !!oAttrs.selected);
  #|           if (selected) return optionEffectiveValue(opt);
  #|         }
  #|         // HTML default: first option is selected if none marked.
  #|         return optionEffectiveValue(options[0]);
  #|       }
  #|       if (typeof control.value === 'string' && control.value !== '') return control.value;
  #|       if (typeof attrs.value === 'string') return attrs.value;
  #|       return '';
  #|     };
  #|     const isSubmissionExcluded = (control, submitter) => {
  #|       const tag = String(control.tagName || '');
  #|       const type = String((control._attrs && control._attrs.type) || '').toLowerCase();
  #|       if (tag === 'BUTTON') {
  #|         // Only the explicit submitter contributes; buttons without type default to submit.
  #|         if (control === submitter) return false;
  #|         return true;
  #|       }
  #|       if (tag === 'INPUT') {
  #|         if (type === 'button' || type === 'reset' || type === 'image' || type === 'file') {
  #|           return control !== submitter;
  #|         }
  #|         if (type === 'submit') return control !== submitter;
  #|         if (type === 'checkbox' || type === 'radio') {
  #|           return !control._attrs || !control._attrs.checked;
  #|         }
  #|       }
  #|       return false;
  #|     };
  #|     const serializeFormDataUrlEncoded = (controls, submitter) => {
  #|       const parts = [];
  #|       const enc = (s) => encodeURIComponent(String(s));
  #|       for (const c of controls) {
  #|         if (isSubmissionExcluded(c, submitter)) continue;
  #|         const attrs = c._attrs || {};
  #|         const name = attrs.name;
  #|         if (typeof name !== 'string' || name.length === 0) continue;
  #|         const value = controlEffectiveValue(c);
  #|         if (Array.isArray(value)) {
  #|           //