/** * `@llui/dom/ssr/linkedom` — linkedom-backed `DomEnv` factory. * * Linkedom is a lightweight JSDOM alternative — smaller bundle, works * on Cloudflare Workers and other strict-isolate runtimes where jsdom's * transitive `whatwg-url` / `tr46` / `punycode` chain fails to resolve. */ import type { DomEnv } from '../dom-env.js' // Linkedom exposes a `parseHTML` function that returns a window-like // object with DOM constructors and a `document`. The exact shape is // narrower than JSDOM's but matches the DomEnv surface we need. interface LinkedomWindow { document: { createElement: (tag: string) => Element createElementNS: (ns: string, tag: string) => Element createTextNode: (text: string) => Text createComment: (text: string) => Comment createDocumentFragment: () => DocumentFragment createRange: () => Range querySelector: (selector: string) => Element | null } Element: typeof Element Node: typeof Node Text: typeof Text Comment: typeof Comment DocumentFragment: typeof DocumentFragment HTMLElement: typeof HTMLElement HTMLTemplateElement: typeof HTMLTemplateElement HTMLSelectElement: typeof HTMLSelectElement ShadowRoot: typeof ShadowRoot MouseEvent: typeof MouseEvent } // Tracks whether we've installed the HTMLSelectElement.value setter // patch for a given prototype. Linkedom instances share prototype // objects across `parseHTML` calls, so the patch only needs to run // once per prototype — the WeakSet key keeps it idempotent without // scanning existing descriptors on every linkedomEnv() call. const patchedSelectProtos = new WeakSet() /** * Linkedom's `HTMLSelectElement.prototype.value` is a get-only accessor * — assigning `select.value = 'foo'` throws * `TypeError: Cannot set property value of [object Object] which has * only a getter`. LLui's reactive attribute bindings call the IDL * setter at render time to mirror the matching `