@llui/dom 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hmr.js CHANGED
@@ -213,6 +213,11 @@ function makeReplacementHandle(name, entry, typedInst) {
213
213
  const [state, effects] = typedInst.def.update(typedInst.state, msg);
214
214
  return { state, effects: effects };
215
215
  },
216
+ setOnBindingError(hook) {
217
+ if (disposed)
218
+ return;
219
+ typedInst._onBindingError = hook ?? undefined;
220
+ },
216
221
  };
217
222
  }
218
223
  function captureFocus(root) {
package/dist/hmr.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle } from './types.js'\nimport type { ComponentInstance } from './update-loop.js'\nimport { flushInstance } from './update-loop.js'\nimport { createLifetime, disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { unregisterInstance } from './runtime.js'\nimport { _setHmrModule } from './mount.js'\nimport { createView } from './view-helpers.js'\n\n/**\n * Enable HMR state preservation. Called by compiler-generated dev code.\n * Importing this module registers it with mountApp for hot-swapping.\n */\nexport function enableHmr(): void {\n _setHmrModule({\n enableHmr,\n registerForHmr,\n registerForAnchor,\n unregisterForHmr,\n replaceComponent,\n })\n}\n\n// ── HMR Registry ─────────────────────────────────────────────────\n\ntype HmrEntry =\n | {\n kind: 'container'\n inst: ComponentInstance\n container: HTMLElement\n }\n | {\n kind: 'anchor'\n inst: ComponentInstance\n anchor: Comment\n endSentinel: Comment\n }\n\nconst hmrRegistry = new Map<string, HmrEntry[]>()\n\nexport function registerForHmr(name: string, inst: object, container: HTMLElement): void {\n const entries = hmrRegistry.get(name) ?? []\n entries.push({ kind: 'container', inst: inst as ComponentInstance, container })\n hmrRegistry.set(name, entries)\n}\n\nexport function registerForAnchor(\n name: string,\n inst: object,\n anchor: Comment,\n endSentinel: Comment,\n): void {\n const entries = hmrRegistry.get(name) ?? []\n entries.push({ kind: 'anchor', inst: inst as ComponentInstance, anchor, endSentinel })\n hmrRegistry.set(name, entries)\n}\n\nexport function unregisterForHmr(name: string, inst: object): void {\n const entries = hmrRegistry.get(name)\n if (!entries) return\n const idx = entries.findIndex((e) => e.inst === inst)\n if (idx !== -1) entries.splice(idx, 1)\n if (entries.length === 0) hmrRegistry.delete(name)\n}\n\n/**\n * Hot-swap a component definition on all live instances.\n *\n * Preserves the current state. Replaces update, view, onEffect, and __dirty.\n * Disposes the old scope tree (removing old DOM and bindings),\n * re-runs view(currentState, send) to rebuild fresh DOM.\n *\n * Returns an AppHandle for the first instance (for mountApp compatibility),\n * or null if no instances are registered (first mount).\n */\nexport function replaceComponent<S, M, E, D = void>(\n name: string,\n newDef: ComponentDef<S, M, E, D>,\n): AppHandle | null {\n const entries = hmrRegistry.get(name)\n if (!entries || entries.length === 0) return null\n\n let handle: AppHandle | null = null\n\n for (const entry of entries) {\n const typedInst = entry.inst as ComponentInstance<S, M, E>\n\n typedInst.def = {\n ...typedInst.def,\n update: newDef.update,\n view: newDef.view,\n onEffect: newDef.onEffect,\n __dirty: newDef.__dirty,\n __update: newDef.__update,\n __handlers: newDef.__handlers,\n }\n\n // Snapshot focus + selection + scroll BEFORE disposal — once the\n // root lifetime tears down its DOM, the activeElement and any\n // scrollable subtree are detached and can't be queried. We\n // restore best-effort after the new view renders. The cost of\n // skipping this step is the every-edit experience: the user\n // types in an input, saves, the input rebuilds and loses focus\n // and cursor position. That kills incremental editing flow.\n const ownerRoot: ParentNode | null =\n entry.kind === 'container' ? entry.container : (entry.anchor.parentElement ?? null)\n const focusSnapshot = ownerRoot ? captureFocus(ownerRoot) : null\n const scrollSnapshot = ownerRoot ? captureScroll(ownerRoot) : null\n\n disposeLifetime(typedInst.rootLifetime)\n\n // Clear the owned region per-kind.\n if (entry.kind === 'container') {\n entry.container.textContent = ''\n } else {\n // anchor kind — wipe siblings between anchor and endSentinel, keep the\n // anchor AND the end sentinel (they bracket the fresh render).\n let sib = entry.anchor.nextSibling\n while (sib !== null && sib !== entry.endSentinel) {\n const next = sib.nextSibling\n sib.parentNode!.removeChild(sib)\n sib = next\n }\n }\n\n typedInst.rootLifetime = createLifetime(null)\n typedInst.rootLifetime._kind = 'root'\n typedInst.allBindings = []\n typedInst.structuralBlocks = []\n\n setFlatBindings(typedInst.allBindings)\n setRenderContext({\n rootLifetime: typedInst.rootLifetime,\n state: typedInst.state,\n allBindings: typedInst.allBindings,\n structuralBlocks: typedInst.structuralBlocks,\n dom: typedInst.dom,\n container:\n entry.kind === 'container' ? entry.container : (entry.anchor.parentElement ?? undefined),\n send: typedInst.send as (msg: unknown) => void,\n instance: typedInst as ComponentInstance,\n })\n const nodes = typedInst.def.view(createView<S, M>(typedInst.send))\n clearRenderContext()\n setFlatBindings(null)\n\n if (entry.kind === 'container') {\n for (const node of nodes) {\n entry.container.appendChild(node)\n }\n } else {\n for (const node of nodes) {\n entry.anchor.parentNode!.insertBefore(node, entry.endSentinel)\n }\n }\n\n // Restore focus, selection, and scroll positions in the freshly\n // rendered DOM. Best-effort: when the new view's DOM has diverged\n // structurally (different IDs, different element ordering, the\n // input that was focused no longer exists), the restorers no-op\n // silently. This is the right tradeoff — failing loudly on\n // structural divergence would just mean every meaningful view\n // edit prints an error.\n if (ownerRoot) {\n if (focusSnapshot) restoreFocus(ownerRoot, focusSnapshot)\n if (scrollSnapshot) restoreScroll(ownerRoot, scrollSnapshot)\n }\n\n if (!handle) {\n handle = makeReplacementHandle(name, entry, typedInst)\n }\n }\n\n console.log(`[LLui HMR] ${name} updated — state preserved`)\n\n return handle\n}\n\nfunction makeReplacementHandle<S, M, E>(\n name: string,\n entry: HmrEntry,\n typedInst: ComponentInstance<S, M, E>,\n): AppHandle {\n const listeners = new Set<(s: unknown) => void>()\n typedInst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n let disposed = false\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n typedInst._onCommit = undefined\n unregisterForHmr(name, entry.inst)\n entry.inst.abortController.abort()\n unregisterInstance(entry.inst)\n disposeLifetime(typedInst.rootLifetime)\n if (entry.kind === 'container') {\n entry.container.textContent = ''\n } else {\n let sib = entry.anchor.nextSibling\n while (sib !== null && sib !== entry.endSentinel) {\n const next = sib.nextSibling\n sib.parentNode!.removeChild(sib)\n sib = next\n }\n entry.endSentinel.parentNode?.removeChild(entry.endSentinel)\n }\n },\n flush() {\n flushInstance(entry.inst)\n },\n send(msg: unknown) {\n ;(typedInst.send as (m: unknown) => void)(msg)\n },\n getState() {\n return typedInst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n if (disposed) return []\n return getBindingDescriptors(typedInst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n flushInstance(entry.inst)\n ;(typedInst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(typedInst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n const [state, effects] = (\n typedInst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(typedInst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n }\n}\n\n// ── Focus / selection / scroll preservation across HMR ──────────\n\n/**\n * What we record before disposing the root DOM. The locator is a\n * structural pointer: prefer `id` (resilient to view restructuring),\n * fall back to a child-index path through the rendered subtree. If\n * the new DOM doesn't match either, the restore call no-ops.\n */\ntype FocusSnapshot = {\n /** The element's `id` if it had one, else `null`. */\n id: string | null\n /** Sibling-index path from `ownerRoot` down to the focused element. */\n path: number[]\n /** Selection range if the focused element is a text input/textarea. */\n selection: { start: number; end: number; direction: 'forward' | 'backward' | 'none' } | null\n}\n\ntype ScrollSnapshot = Array<{\n id: string | null\n path: number[]\n scrollTop: number\n scrollLeft: number\n}>\n\nfunction captureFocus(root: ParentNode): FocusSnapshot | null {\n const doc = (root as Element).ownerDocument ?? globalThis.document\n if (!doc) return null\n const active = doc.activeElement\n if (!active || active === doc.body) return null\n // Only capture focus for elements inside our owned subtree —\n // anything outside is not ours to restore.\n if (!(root as ParentNode & Node).contains(active)) return null\n\n const path = pathFromAncestor(root as Node, active)\n if (path === null) return null\n\n let selection: FocusSnapshot['selection'] = null\n if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) {\n // Some input types (number, email, etc.) reject selectionStart access.\n // Wrapper try/catch keeps the snapshot resilient to those cases.\n try {\n if (active.selectionStart !== null && active.selectionEnd !== null) {\n selection = {\n start: active.selectionStart,\n end: active.selectionEnd,\n direction: (active.selectionDirection ?? 'none') as 'forward' | 'backward' | 'none',\n }\n }\n } catch {\n selection = null\n }\n }\n\n return {\n id: active.id || null,\n path,\n selection,\n }\n}\n\nfunction restoreFocus(root: ParentNode, snap: FocusSnapshot): void {\n const target = locate(root, snap.id, snap.path)\n if (!target || !(target instanceof HTMLElement)) return\n try {\n target.focus({ preventScroll: true })\n } catch {\n return\n }\n if (\n snap.selection &&\n (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)\n ) {\n try {\n target.setSelectionRange(snap.selection.start, snap.selection.end, snap.selection.direction)\n } catch {\n // Some input types throw on setSelectionRange; ignore.\n }\n }\n}\n\nfunction captureScroll(root: ParentNode): ScrollSnapshot {\n // Walk the subtree and snapshot every element with non-zero\n // scroll. Most subtrees have at most a handful, so the per-edit\n // cost is small. Capturing all-zeroes wastes the restore work for\n // no benefit; the filter keeps things tight.\n const out: ScrollSnapshot = []\n const walk = (node: Node): void => {\n if (node instanceof HTMLElement) {\n if (node.scrollTop !== 0 || node.scrollLeft !== 0) {\n const path = pathFromAncestor(root as Node, node)\n if (path !== null) {\n out.push({\n id: node.id || null,\n path,\n scrollTop: node.scrollTop,\n scrollLeft: node.scrollLeft,\n })\n }\n }\n }\n for (let c = node.firstChild; c !== null; c = c.nextSibling) {\n walk(c)\n }\n }\n walk(root as Node)\n return out\n}\n\nfunction restoreScroll(root: ParentNode, snap: ScrollSnapshot): void {\n for (const s of snap) {\n const target = locate(root, s.id, s.path)\n if (!target || !(target instanceof HTMLElement)) continue\n target.scrollTop = s.scrollTop\n target.scrollLeft = s.scrollLeft\n }\n}\n\n/**\n * Compute the child-index path from `ancestor` down to `target`, or\n * `null` if `target` isn't in the subtree. The path is what gets\n * walked on restore — no document-wide selectors, no string-encoded\n * selectors that can break on punctuation in IDs.\n */\nfunction pathFromAncestor(ancestor: Node, target: Node): number[] | null {\n const path: number[] = []\n let cur: Node | null = target\n while (cur !== null && cur !== ancestor) {\n const parent: Node | null = cur.parentNode\n if (parent === null) return null\n let idx = 0\n let sib: Node | null = parent.firstChild\n while (sib !== null && sib !== cur) {\n idx++\n sib = sib.nextSibling\n }\n if (sib === null) return null\n path.push(idx)\n cur = parent\n }\n if (cur !== ancestor) return null\n return path.reverse()\n}\n\n/**\n * Restore lookup: try `id` first (cheap and resilient to structural\n * change), then walk the captured child-index path. Returns `null`\n * if neither lookup succeeds — the restore caller silently no-ops.\n */\nfunction locate(root: ParentNode, id: string | null, path: number[]): Element | null {\n if (id) {\n const doc = (root as Element).ownerDocument ?? globalThis.document\n if (doc) {\n const byId = doc.getElementById(id)\n if (byId && (root as ParentNode & Node).contains(byId)) return byId\n }\n }\n let cur: Node = root as Node\n for (const idx of path) {\n let child = cur.firstChild\n let i = 0\n while (child && i < idx) {\n child = child.nextSibling\n i++\n }\n if (!child) return null\n cur = child\n }\n return cur instanceof Element ? cur : null\n}\n"]}
1
+ {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle } from './types.js'\nimport type { ComponentInstance } from './update-loop.js'\nimport { flushInstance } from './update-loop.js'\nimport { createLifetime, disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { unregisterInstance } from './runtime.js'\nimport { _setHmrModule } from './mount.js'\nimport { createView } from './view-helpers.js'\n\n/**\n * Enable HMR state preservation. Called by compiler-generated dev code.\n * Importing this module registers it with mountApp for hot-swapping.\n */\nexport function enableHmr(): void {\n _setHmrModule({\n enableHmr,\n registerForHmr,\n registerForAnchor,\n unregisterForHmr,\n replaceComponent,\n })\n}\n\n// ── HMR Registry ─────────────────────────────────────────────────\n\ntype HmrEntry =\n | {\n kind: 'container'\n inst: ComponentInstance\n container: HTMLElement\n }\n | {\n kind: 'anchor'\n inst: ComponentInstance\n anchor: Comment\n endSentinel: Comment\n }\n\nconst hmrRegistry = new Map<string, HmrEntry[]>()\n\nexport function registerForHmr(name: string, inst: object, container: HTMLElement): void {\n const entries = hmrRegistry.get(name) ?? []\n entries.push({ kind: 'container', inst: inst as ComponentInstance, container })\n hmrRegistry.set(name, entries)\n}\n\nexport function registerForAnchor(\n name: string,\n inst: object,\n anchor: Comment,\n endSentinel: Comment,\n): void {\n const entries = hmrRegistry.get(name) ?? []\n entries.push({ kind: 'anchor', inst: inst as ComponentInstance, anchor, endSentinel })\n hmrRegistry.set(name, entries)\n}\n\nexport function unregisterForHmr(name: string, inst: object): void {\n const entries = hmrRegistry.get(name)\n if (!entries) return\n const idx = entries.findIndex((e) => e.inst === inst)\n if (idx !== -1) entries.splice(idx, 1)\n if (entries.length === 0) hmrRegistry.delete(name)\n}\n\n/**\n * Hot-swap a component definition on all live instances.\n *\n * Preserves the current state. Replaces update, view, onEffect, and __dirty.\n * Disposes the old scope tree (removing old DOM and bindings),\n * re-runs view(currentState, send) to rebuild fresh DOM.\n *\n * Returns an AppHandle for the first instance (for mountApp compatibility),\n * or null if no instances are registered (first mount).\n */\nexport function replaceComponent<S, M, E, D = void>(\n name: string,\n newDef: ComponentDef<S, M, E, D>,\n): AppHandle | null {\n const entries = hmrRegistry.get(name)\n if (!entries || entries.length === 0) return null\n\n let handle: AppHandle | null = null\n\n for (const entry of entries) {\n const typedInst = entry.inst as ComponentInstance<S, M, E>\n\n typedInst.def = {\n ...typedInst.def,\n update: newDef.update,\n view: newDef.view,\n onEffect: newDef.onEffect,\n __dirty: newDef.__dirty,\n __update: newDef.__update,\n __handlers: newDef.__handlers,\n }\n\n // Snapshot focus + selection + scroll BEFORE disposal — once the\n // root lifetime tears down its DOM, the activeElement and any\n // scrollable subtree are detached and can't be queried. We\n // restore best-effort after the new view renders. The cost of\n // skipping this step is the every-edit experience: the user\n // types in an input, saves, the input rebuilds and loses focus\n // and cursor position. That kills incremental editing flow.\n const ownerRoot: ParentNode | null =\n entry.kind === 'container' ? entry.container : (entry.anchor.parentElement ?? null)\n const focusSnapshot = ownerRoot ? captureFocus(ownerRoot) : null\n const scrollSnapshot = ownerRoot ? captureScroll(ownerRoot) : null\n\n disposeLifetime(typedInst.rootLifetime)\n\n // Clear the owned region per-kind.\n if (entry.kind === 'container') {\n entry.container.textContent = ''\n } else {\n // anchor kind — wipe siblings between anchor and endSentinel, keep the\n // anchor AND the end sentinel (they bracket the fresh render).\n let sib = entry.anchor.nextSibling\n while (sib !== null && sib !== entry.endSentinel) {\n const next = sib.nextSibling\n sib.parentNode!.removeChild(sib)\n sib = next\n }\n }\n\n typedInst.rootLifetime = createLifetime(null)\n typedInst.rootLifetime._kind = 'root'\n typedInst.allBindings = []\n typedInst.structuralBlocks = []\n\n setFlatBindings(typedInst.allBindings)\n setRenderContext({\n rootLifetime: typedInst.rootLifetime,\n state: typedInst.state,\n allBindings: typedInst.allBindings,\n structuralBlocks: typedInst.structuralBlocks,\n dom: typedInst.dom,\n container:\n entry.kind === 'container' ? entry.container : (entry.anchor.parentElement ?? undefined),\n send: typedInst.send as (msg: unknown) => void,\n instance: typedInst as ComponentInstance,\n })\n const nodes = typedInst.def.view(createView<S, M>(typedInst.send))\n clearRenderContext()\n setFlatBindings(null)\n\n if (entry.kind === 'container') {\n for (const node of nodes) {\n entry.container.appendChild(node)\n }\n } else {\n for (const node of nodes) {\n entry.anchor.parentNode!.insertBefore(node, entry.endSentinel)\n }\n }\n\n // Restore focus, selection, and scroll positions in the freshly\n // rendered DOM. Best-effort: when the new view's DOM has diverged\n // structurally (different IDs, different element ordering, the\n // input that was focused no longer exists), the restorers no-op\n // silently. This is the right tradeoff — failing loudly on\n // structural divergence would just mean every meaningful view\n // edit prints an error.\n if (ownerRoot) {\n if (focusSnapshot) restoreFocus(ownerRoot, focusSnapshot)\n if (scrollSnapshot) restoreScroll(ownerRoot, scrollSnapshot)\n }\n\n if (!handle) {\n handle = makeReplacementHandle(name, entry, typedInst)\n }\n }\n\n console.log(`[LLui HMR] ${name} updated — state preserved`)\n\n return handle\n}\n\nfunction makeReplacementHandle<S, M, E>(\n name: string,\n entry: HmrEntry,\n typedInst: ComponentInstance<S, M, E>,\n): AppHandle {\n const listeners = new Set<(s: unknown) => void>()\n typedInst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n let disposed = false\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n typedInst._onCommit = undefined\n unregisterForHmr(name, entry.inst)\n entry.inst.abortController.abort()\n unregisterInstance(entry.inst)\n disposeLifetime(typedInst.rootLifetime)\n if (entry.kind === 'container') {\n entry.container.textContent = ''\n } else {\n let sib = entry.anchor.nextSibling\n while (sib !== null && sib !== entry.endSentinel) {\n const next = sib.nextSibling\n sib.parentNode!.removeChild(sib)\n sib = next\n }\n entry.endSentinel.parentNode?.removeChild(entry.endSentinel)\n }\n },\n flush() {\n flushInstance(entry.inst)\n },\n send(msg: unknown) {\n ;(typedInst.send as (m: unknown) => void)(msg)\n },\n getState() {\n return typedInst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n if (disposed) return []\n return getBindingDescriptors(typedInst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n flushInstance(entry.inst)\n ;(typedInst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(typedInst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n const [state, effects] = (\n typedInst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(typedInst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n setOnBindingError(hook) {\n if (disposed) return\n typedInst._onBindingError = hook ?? undefined\n },\n }\n}\n\n// ── Focus / selection / scroll preservation across HMR ──────────\n\n/**\n * What we record before disposing the root DOM. The locator is a\n * structural pointer: prefer `id` (resilient to view restructuring),\n * fall back to a child-index path through the rendered subtree. If\n * the new DOM doesn't match either, the restore call no-ops.\n */\ntype FocusSnapshot = {\n /** The element's `id` if it had one, else `null`. */\n id: string | null\n /** Sibling-index path from `ownerRoot` down to the focused element. */\n path: number[]\n /** Selection range if the focused element is a text input/textarea. */\n selection: { start: number; end: number; direction: 'forward' | 'backward' | 'none' } | null\n}\n\ntype ScrollSnapshot = Array<{\n id: string | null\n path: number[]\n scrollTop: number\n scrollLeft: number\n}>\n\nfunction captureFocus(root: ParentNode): FocusSnapshot | null {\n const doc = (root as Element).ownerDocument ?? globalThis.document\n if (!doc) return null\n const active = doc.activeElement\n if (!active || active === doc.body) return null\n // Only capture focus for elements inside our owned subtree —\n // anything outside is not ours to restore.\n if (!(root as ParentNode & Node).contains(active)) return null\n\n const path = pathFromAncestor(root as Node, active)\n if (path === null) return null\n\n let selection: FocusSnapshot['selection'] = null\n if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) {\n // Some input types (number, email, etc.) reject selectionStart access.\n // Wrapper try/catch keeps the snapshot resilient to those cases.\n try {\n if (active.selectionStart !== null && active.selectionEnd !== null) {\n selection = {\n start: active.selectionStart,\n end: active.selectionEnd,\n direction: (active.selectionDirection ?? 'none') as 'forward' | 'backward' | 'none',\n }\n }\n } catch {\n selection = null\n }\n }\n\n return {\n id: active.id || null,\n path,\n selection,\n }\n}\n\nfunction restoreFocus(root: ParentNode, snap: FocusSnapshot): void {\n const target = locate(root, snap.id, snap.path)\n if (!target || !(target instanceof HTMLElement)) return\n try {\n target.focus({ preventScroll: true })\n } catch {\n return\n }\n if (\n snap.selection &&\n (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)\n ) {\n try {\n target.setSelectionRange(snap.selection.start, snap.selection.end, snap.selection.direction)\n } catch {\n // Some input types throw on setSelectionRange; ignore.\n }\n }\n}\n\nfunction captureScroll(root: ParentNode): ScrollSnapshot {\n // Walk the subtree and snapshot every element with non-zero\n // scroll. Most subtrees have at most a handful, so the per-edit\n // cost is small. Capturing all-zeroes wastes the restore work for\n // no benefit; the filter keeps things tight.\n const out: ScrollSnapshot = []\n const walk = (node: Node): void => {\n if (node instanceof HTMLElement) {\n if (node.scrollTop !== 0 || node.scrollLeft !== 0) {\n const path = pathFromAncestor(root as Node, node)\n if (path !== null) {\n out.push({\n id: node.id || null,\n path,\n scrollTop: node.scrollTop,\n scrollLeft: node.scrollLeft,\n })\n }\n }\n }\n for (let c = node.firstChild; c !== null; c = c.nextSibling) {\n walk(c)\n }\n }\n walk(root as Node)\n return out\n}\n\nfunction restoreScroll(root: ParentNode, snap: ScrollSnapshot): void {\n for (const s of snap) {\n const target = locate(root, s.id, s.path)\n if (!target || !(target instanceof HTMLElement)) continue\n target.scrollTop = s.scrollTop\n target.scrollLeft = s.scrollLeft\n }\n}\n\n/**\n * Compute the child-index path from `ancestor` down to `target`, or\n * `null` if `target` isn't in the subtree. The path is what gets\n * walked on restore — no document-wide selectors, no string-encoded\n * selectors that can break on punctuation in IDs.\n */\nfunction pathFromAncestor(ancestor: Node, target: Node): number[] | null {\n const path: number[] = []\n let cur: Node | null = target\n while (cur !== null && cur !== ancestor) {\n const parent: Node | null = cur.parentNode\n if (parent === null) return null\n let idx = 0\n let sib: Node | null = parent.firstChild\n while (sib !== null && sib !== cur) {\n idx++\n sib = sib.nextSibling\n }\n if (sib === null) return null\n path.push(idx)\n cur = parent\n }\n if (cur !== ancestor) return null\n return path.reverse()\n}\n\n/**\n * Restore lookup: try `id` first (cheap and resilient to structural\n * change), then walk the captured child-index path. Returns `null`\n * if neither lookup succeeds — the restore caller silently no-ops.\n */\nfunction locate(root: ParentNode, id: string | null, path: number[]): Element | null {\n if (id) {\n const doc = (root as Element).ownerDocument ?? globalThis.document\n if (doc) {\n const byId = doc.getElementById(id)\n if (byId && (root as ParentNode & Node).contains(byId)) return byId\n }\n }\n let cur: Node = root as Node\n for (const idx of path) {\n let child = cur.firstChild\n let i = 0\n while (child && i < idx) {\n child = child.nextSibling\n i++\n }\n if (!child) return null\n cur = child\n }\n return cur instanceof Element ? cur : null\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,KAAK,MAAM,EAAc,MAAM,cAAc,CAAA;AA4CtD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KACxB;CACF;AAoCD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAA;IACzB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAClC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAiIZ;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACtC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAsFZ;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC/C,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAyEX;AAuJD,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC1C,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CA8EX"}
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,KAAK,MAAM,EAAc,MAAM,cAAc,CAAA;AA4CtD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KACxB;CACF;AAoCD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAA;IACzB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAClC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAiIZ;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACtC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAsFZ;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC/C,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAyEX;AA2JD,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC1C,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CA8EX"}
package/dist/mount.js CHANGED
@@ -461,6 +461,11 @@ function buildAppHandle(inst, hmrName, domCleanup) {
461
461
  const [state, effects] = inst.def.update(inst.state, msg);
462
462
  return { state, effects: effects };
463
463
  },
464
+ setOnBindingError(hook) {
465
+ if (disposed)
466
+ return;
467
+ inst._onBindingError = hook ?? undefined;
468
+ },
464
469
  };
465
470
  }
466
471
  export function hydrateApp(container, def, serverState, options) {
package/dist/mount.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle, Lifetime } from './types.js'\nimport { type DomEnv, browserEnv } from './dom-env.js'\nimport { createComponentInstance, flushInstance, type ComponentInstance } from './update-loop.js'\nimport { disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { registerInstance, unregisterInstance } from './runtime.js'\nimport { createView } from './view-helpers.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js'\n\n// ── Sentinel-region helpers (used by anchor-based mount primitives) ─────\n\n/**\n * Remove every sibling from `anchor.nextSibling` up to but not including\n * `stopBefore`. Used by anchor-based mount primitives and their HMR\n * swap path to clear the owned DOM region between the pair.\n */\nfunction _removeBetween(anchor: Comment, stopBefore: Comment): void {\n const parent = anchor.parentNode\n if (parent === null) return\n while (anchor.nextSibling !== null && anchor.nextSibling !== stopBefore) {\n parent.removeChild(anchor.nextSibling)\n }\n}\n\n/**\n * Walk forward from `anchor.nextSibling` looking for an existing\n * `<!-- llui-mount-end -->` sentinel. Used by mount/hydrate at anchor\n * to reuse a server-emitted (or stale) sentinel rather than synthesizing\n * a duplicate. Returns null if no matching comment is found before the\n * end of the parent's children.\n */\nfunction _findEndSentinel(anchor: Comment): Comment | null {\n let node: Node | null = anchor.nextSibling\n while (node !== null) {\n if (node.nodeType === 8 && (node as Comment).nodeValue === 'llui-mount-end') {\n return node as Comment\n }\n node = node.nextSibling\n }\n return null\n}\n\n// Vite injects import.meta.env.DEV — declare the shape for TypeScript\ndeclare global {\n interface ImportMeta {\n env?: { DEV?: boolean }\n }\n}\n\n// ── HMR (dev only) ──────────────────────────────────────────────\n// Set by enableHmr() from '@llui/dom/hmr' — never imported in production.\n\nlet hmrModule: typeof import('./hmr') | null = null\n\n/**\n * @internal Called by enableHmr in the hmr module. Tests use this\n * (paired with `_getHmrModule`) to snapshot/restore prior state across\n * suite boundaries — pass `null` to clear.\n */\nexport function _setHmrModule(m: typeof import('./hmr') | null): void {\n hmrModule = m\n}\n\n/** @internal Read the currently-installed HMR module (or null). */\nexport function _getHmrModule(): typeof import('./hmr') | null {\n return hmrModule\n}\n\n// ── DevTools auto-install (dev only) ────────────────────────────\n// Set by enableDevTools() from '@llui/dom/devtools' — never imported in production.\n\nlet devToolsInstall: ((inst: object) => void) | null = null\n\n/** @internal Called by enableDevTools in the devtools module */\nexport function _setDevToolsInstall(fn: ((inst: object) => void) | null): void {\n devToolsInstall = fn\n}\n\n/** @internal Read the currently-installed devtools-install hook (or null). */\nexport function _getDevToolsInstall(): ((inst: object) => void) | null {\n return devToolsInstall\n}\n\nexport interface MountOptions {\n devTools?: boolean\n /**\n * Parent scope for the mounted component's rootLifetime. When provided,\n * the rootLifetime is created as a child of this scope — context lookups\n * from within the component walk up through the parent's scope tree,\n * and disposing the parent scope cascades into this instance's scope.\n * Used by `@llui/vike`'s persistent-layout machinery to mount a page\n * as a true scope-tree child of its enclosing layout, so layout-\n * provided contexts flow naturally into pages via `useContext`.\n *\n * When omitted (the default), the rootLifetime is detached — same as\n * every `mountApp` call before persistent layouts existed.\n */\n parentLifetime?: Lifetime\n /**\n * DOM env override. Defaults to `browserEnv()` — wraps the browser\n * globals. Specify only when mounting into a non-browser DOM (e.g.\n * a jsdom instance held by a test harness, or isolated DOM per\n * shadow root).\n */\n env?: DomEnv\n /**\n * **`hydrateApp` / `hydrateAtAnchor` only.** When `true`, fire the\n * effects that `init()` returned during hydration the same way\n * `mountApp` does on a fresh mount. Defaults to `false` because the\n * SSR render already ran `init()` on the server, and re-running its\n * effects on the client typically produces duplicate work — an\n * `httpGet` issued from `init()` would fetch on the server *and* on\n * hydration; a subscription would attach twice; etc.\n *\n * Opt in only when:\n * - `init()` returns no effects, OR\n * - all returned effects are idempotent / client-only (e.g.\n * wiring a `window` event listener, opening a `WebSocket`), AND\n * - the SSR path didn't run them (typically when `init()` checks a\n * `loaded` flag in state and returns `[]` on the server).\n *\n * Pre-0.0.31 behavior was to always run init effects on hydrate;\n * the option preserves it on demand for projects that depended on\n * it. The default-off direction matches the safer expectation that\n * \"hydration should be cheap and side-effect-free.\"\n */\n runInitEffectsOnHydrate?: boolean\n}\n\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n // HMR: if this component is already mounted (module re-execution\n // during hot update), swap the definition instead of creating a new instance.\n // HMR swap bypasses parentLifetime — HMR re-mounts the outermost app handle,\n // which in a layout setup means the layout re-mounts at the root and the\n // rest of the chain is re-established via the normal mount path.\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponent(def.name, def)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import\n if (devToolsInstall) devToolsInstall(inst)\n\n // Dev-only: warn if initial state contains non-serializable values.\n // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n // Run view() within a render context so primitives can register bindings.\n // Also collect onMount callbacks in a queue we'll flush synchronously\n // after node insertion — prevents the race where a user event fires\n // between mount and the queueMicrotask callback running.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout-invalidating operation\n // instead of N individual appendChild calls on a live container element.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n container.appendChild(frag)\n } else if (nodes.length === 1) {\n container.appendChild(nodes[0]!)\n }\n\n // Flush onMount callbacks SYNCHRONOUSLY now that the DOM is in place.\n // Any listeners they attach are ready before this function returns,\n // so a synchronous dispatchEvent in the caller's next line fires\n // against a fully-wired tree.\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForHmr(def.name, inst, container)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n container.textContent = ''\n })\n}\n\n// Walks an object graph looking for non-JSON-serializable values. Returns the\n// first offender found (depth-first), or null if everything is fine. Stops at\n// depth 6 to bound runtime cost for large states.\nfunction findNonSerializable(\n v: unknown,\n path = 'state',\n depth = 0,\n seen = new WeakSet<object>(),\n): { path: string; value: unknown } | null {\n if (depth > 6) return null\n if (v === null || v === undefined) return null\n const t = typeof v\n if (t === 'string' || t === 'number' || t === 'boolean') return null\n if (t === 'function') return { path, value: v }\n if (t === 'symbol' || t === 'bigint') return { path, value: v }\n if (t !== 'object') return null\n const obj = v as object\n if (seen.has(obj)) return null\n seen.add(obj)\n if (obj instanceof Date) return { path: `${path} (Date)`, value: v }\n if (obj instanceof Map) return { path: `${path} (Map)`, value: v }\n if (obj instanceof Set) return { path: `${path} (Set)`, value: v }\n if (obj instanceof RegExp) return { path: `${path} (RegExp)`, value: v }\n if (obj instanceof Promise) return { path: `${path} (Promise)`, value: v }\n // Plain objects/arrays have Object.prototype / Array.prototype. Class instances\n // have a different prototype.\n const proto = Object.getPrototypeOf(obj)\n if (proto !== null && proto !== Object.prototype && proto !== Array.prototype) {\n return { path: `${path} (${proto?.constructor?.name ?? 'class instance'})`, value: v }\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const r = findNonSerializable(v[i], `${path}[${i}]`, depth + 1, seen)\n if (r) return r\n }\n return null\n }\n for (const k of Object.keys(obj)) {\n const r = findNonSerializable(\n (obj as Record<string, unknown>)[k],\n `${path}.${k}`,\n depth + 1,\n seen,\n )\n if (r) return r\n }\n return null\n}\n\n/**\n * Mount a component relative to a comment anchor rather than inside a\n * container element. Inserts a synthesized end sentinel (`<!-- llui-mount-end -->`)\n * immediately after the anchor and places the component's nodes between\n * the pair. The anchor must already be attached to a live DOM tree.\n *\n * Unlike `mountApp`, the caller's anchor node is preserved across the\n * handle's lifetime — only the content between the pair (and the end\n * sentinel itself) is disposed. Used by `@llui/vike` persistent layouts\n * to mount chain layers without a wrapper element.\n *\n * If a pre-existing `<!-- llui-mount-end -->` is found after the anchor\n * (e.g. stale from an undisposed prior mount), the content between the\n * anchor and that sentinel is swept and the sentinel is reused. Dev mode\n * warns in that case.\n */\nexport function mountAtAnchor<S, M, E>(\n anchor: Comment,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] mountAtAnchor: anchor comment must be attached to a live DOM tree before mount`,\n )\n }\n\n // Locate or synthesize the end sentinel.\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n if (import.meta.env?.DEV) {\n console.warn(\n `[LLui] mountAtAnchor: anchor has a pre-existing end sentinel. ` +\n `A prior mount was not disposed — sweeping stale siblings and reusing the sentinel.`,\n )\n }\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n // Use the caller-provided env if any — end-sentinel creation happens\n // before `inst` exists, so we pick the env directly from options.\n // (browserEnv() fallback matches what createComponentInstance will\n // use below when options.env is undefined.)\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n if (devToolsInstall) devToolsInstall(inst)\n\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout pass instead of N.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\n/**\n * Hydrate a component relative to a comment anchor rather than inside a\n * container element. Analogous to `hydrateApp` — uses `serverState` as\n * the initial state (not `init()`'s output) while preserving `init()`'s\n * effects for post-mount dispatch.\n *\n * The DOM-handling path is identical to `mountAtAnchor`: reuses a\n * pre-existing end sentinel when present, synthesizes one otherwise.\n * Atomic-swaps the owned region whether or not server content is there\n * to replace. No error for a missing end sentinel — the vike chain's\n * outer `hydrateApp`'s `replaceChildren` wipes inner layers' sentinels,\n * so inner-layer `hydrateAtAnchor` calls routinely find nothing to\n * reuse, and that's normal.\n */\nexport function hydrateAtAnchor<S, M, E, D = void>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] hydrateAtAnchor: anchor comment must be attached to a live DOM tree before hydrate`,\n )\n }\n\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n // Run original init() to capture effects, then override state with server's.\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n if (devToolsInstall) devToolsInstall(inst)\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true`.\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateAtAnchor')\n }\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\nfunction dispatchInitialEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n): void {\n if (inst.initialEffects.length === 0 || !inst.def.onEffect) return\n for (const effect of inst.initialEffects) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n inst.initialEffects = []\n}\n\n/**\n * Dev-only warning when a hydrate path silently drops a non-empty\n * `initialEffects` array. The default-skip behavior is deliberate (the\n * server already ran them), but if `init()` produces effects that\n * weren't run on the server — typically client-only init pipelines —\n * silent drop is a footgun. Surface the count and the opt-in.\n */\nfunction warnDroppedInitEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n via: 'hydrateApp' | 'hydrateAtAnchor',\n): void {\n if (!import.meta.env?.DEV) return\n if (inst.initialEffects.length === 0) return\n const name = inst.def.name ?? '<anonymous>'\n console.warn(\n `[LLui] ${via}: skipped ${inst.initialEffects.length} init effect(s) for \"${name}\". ` +\n `Hydration drops init effects by default since the server already ran them. ` +\n `If these effects only fire on the client, pass \\`runInitEffectsOnHydrate: true\\` to opt in.`,\n )\n}\n\n/**\n * Build the `AppHandle` returned by every mount/hydrate path. Captures\n * the `_onCommit` listener registry, the `disposed` flag, and the\n * standard `flush` / `send` / `getState` / `subscribe` shape — all\n * code that was previously duplicated four times across `mountApp`,\n * `mountAtAnchor`, `hydrateApp`, and `hydrateAtAnchor`.\n *\n * Variation lives in the two parameters:\n * - `hmrName` — the def's name used to call `hmrModule.unregisterForHmr`\n * on dispose. Pass `null` to skip HMR unregistration (no current\n * mount path needs that, but it keeps the helper honest).\n * - `domCleanup` — final teardown step that detaches mounted nodes.\n * Container-rooted paths set `container.textContent = ''`;\n * anchor-rooted paths call `_removeBetween(anchor, endSentinel)`\n * and detach the end sentinel. Runs LAST in the dispose chain to\n * match the historical ordering exactly (lifetime is disposed\n * before nodes are detached, so binding teardown sees attached\n * DOM until the very end).\n *\n * The mount-path-parity test in `mount-path-parity.test.ts` enforces\n * that each public entry point produces structurally identical\n * AppHandle behavior — this helper is the realisation of that\n * promise.\n */\nfunction buildAppHandle<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n hmrName: string | null,\n domCleanup: () => void,\n): AppHandle {\n let disposed = false\n const listeners = new Set<(s: unknown) => void>()\n\n inst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n inst._onCommit = undefined\n if (hmrModule && hmrName) hmrModule.unregisterForHmr(hmrName, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n // Tag the root scope so the disposer log reports app-level\n // teardown distinct from in-tree component-unmount events.\n inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n domCleanup()\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\n },\n send(msg: unknown) {\n if (disposed) return\n ;(inst.send as (m: unknown) => void)(msg)\n },\n getState() {\n if (disposed) {\n throw new Error(\n '[LLui] AppHandle.getState() called after dispose — handle is dead. ' +\n 'Detach your event listener / cancel your timer when the handle ' +\n 'is disposed to avoid stale reads.',\n )\n }\n return inst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n if (disposed) return []\n return getBindingDescriptors(inst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n // Drain pending messages with the OLD update first — anything\n // already in the queue was constructed under the old contract,\n // and re-routing it through a new reducer mid-flight could mix\n // half of one transition with half of another (e.g. a payload\n // shape the new update no longer accepts).\n flushInstance(inst)\n // Mutate the def in place so subsequent `inst.def.update`\n // reads — including the per-message read in `flushInstance`'s\n // generic loop — pick up the new function. We deliberately\n // don't replace `inst.def` itself: existing closures, the\n // `__update` fast path, and `__handlers` all stay valid; only\n // the user-visible reducer function changes.\n ;(inst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(inst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n // Direct invocation against current state. No subscribe, no\n // flush, no effect handler. The reducer's contract per TEA is\n // a pure function — calling it twice with the same args is a\n // no-op other than allocations. Returning the raw tuple\n // shape lets the agent inspect both halves without interpreting.\n const [state, effects] = (\n inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(inst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n }\n}\n\nexport function hydrateApp<S, M, E, D = void>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n // Run the original init once to capture its effects. The state it\n // returns is discarded — we use `serverState` (what the server\n // rendered with) instead. The effects are preserved and dispatched\n // after the DOM is in place, so components that rely on \"load data\n // or wire subscriptions on mount\" behave consistently between fresh\n // mount and SSR+hydrate. If the original init has already-loaded\n // data for the hydration case, gate the effect emission inside init\n // itself (e.g. based on a `loaded` flag in state).\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools'\n // import. The other three mount paths (mountApp / mountAtAnchor /\n // hydrateAtAnchor) all call this; without it, the hydrated layout\n // never appears in `window.__lluiComponents`, never sets\n // `window.__lluiDebug`, and is invisible to MCP / agent client /\n // devtools console — so a vike SSR app's outermost layout silently\n // drops out of every observability surface.\n if (devToolsInstall) devToolsInstall(inst)\n\n // Build the component DOM and swap atomically with server HTML.\n // Server HTML remains visible until JS finishes — no flash.\n // onMount callbacks are collected in a queue and flushed synchronously\n // after the swap, matching mountApp's ordering.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Atomic swap — replaces server HTML with client DOM in one operation\n container.replaceChildren(...nodes)\n\n // Flush onMount callbacks synchronously now that the DOM is in place.\n flushMountQueue(onMountQueue)\n\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true` for projects that\n // need the post-swap dispatch (typically when `init()` is gated by\n // a `loaded` flag and returns `[]` on the server).\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateApp')\n }\n\n registerInstance(inst)\n // HMR registration — same as mountApp / mountAtAnchor /\n // hydrateAtAnchor. Without it, replaceComponent(name, newDef)\n // silently no-ops on the hydrated layout layer because the HMR\n // registry has no entry for it.\n if (hmrModule && hydrateDef.name) {\n hmrModule.registerForHmr(hydrateDef.name, inst, container)\n }\n return buildAppHandle(inst, hydrateDef.name ?? null, () => {\n container.textContent = ''\n })\n}\n"]}
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle, Lifetime } from './types.js'\nimport { type DomEnv, browserEnv } from './dom-env.js'\nimport { createComponentInstance, flushInstance, type ComponentInstance } from './update-loop.js'\nimport { disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { registerInstance, unregisterInstance } from './runtime.js'\nimport { createView } from './view-helpers.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js'\n\n// ── Sentinel-region helpers (used by anchor-based mount primitives) ─────\n\n/**\n * Remove every sibling from `anchor.nextSibling` up to but not including\n * `stopBefore`. Used by anchor-based mount primitives and their HMR\n * swap path to clear the owned DOM region between the pair.\n */\nfunction _removeBetween(anchor: Comment, stopBefore: Comment): void {\n const parent = anchor.parentNode\n if (parent === null) return\n while (anchor.nextSibling !== null && anchor.nextSibling !== stopBefore) {\n parent.removeChild(anchor.nextSibling)\n }\n}\n\n/**\n * Walk forward from `anchor.nextSibling` looking for an existing\n * `<!-- llui-mount-end -->` sentinel. Used by mount/hydrate at anchor\n * to reuse a server-emitted (or stale) sentinel rather than synthesizing\n * a duplicate. Returns null if no matching comment is found before the\n * end of the parent's children.\n */\nfunction _findEndSentinel(anchor: Comment): Comment | null {\n let node: Node | null = anchor.nextSibling\n while (node !== null) {\n if (node.nodeType === 8 && (node as Comment).nodeValue === 'llui-mount-end') {\n return node as Comment\n }\n node = node.nextSibling\n }\n return null\n}\n\n// Vite injects import.meta.env.DEV — declare the shape for TypeScript\ndeclare global {\n interface ImportMeta {\n env?: { DEV?: boolean }\n }\n}\n\n// ── HMR (dev only) ──────────────────────────────────────────────\n// Set by enableHmr() from '@llui/dom/hmr' — never imported in production.\n\nlet hmrModule: typeof import('./hmr') | null = null\n\n/**\n * @internal Called by enableHmr in the hmr module. Tests use this\n * (paired with `_getHmrModule`) to snapshot/restore prior state across\n * suite boundaries — pass `null` to clear.\n */\nexport function _setHmrModule(m: typeof import('./hmr') | null): void {\n hmrModule = m\n}\n\n/** @internal Read the currently-installed HMR module (or null). */\nexport function _getHmrModule(): typeof import('./hmr') | null {\n return hmrModule\n}\n\n// ── DevTools auto-install (dev only) ────────────────────────────\n// Set by enableDevTools() from '@llui/dom/devtools' — never imported in production.\n\nlet devToolsInstall: ((inst: object) => void) | null = null\n\n/** @internal Called by enableDevTools in the devtools module */\nexport function _setDevToolsInstall(fn: ((inst: object) => void) | null): void {\n devToolsInstall = fn\n}\n\n/** @internal Read the currently-installed devtools-install hook (or null). */\nexport function _getDevToolsInstall(): ((inst: object) => void) | null {\n return devToolsInstall\n}\n\nexport interface MountOptions {\n devTools?: boolean\n /**\n * Parent scope for the mounted component's rootLifetime. When provided,\n * the rootLifetime is created as a child of this scope — context lookups\n * from within the component walk up through the parent's scope tree,\n * and disposing the parent scope cascades into this instance's scope.\n * Used by `@llui/vike`'s persistent-layout machinery to mount a page\n * as a true scope-tree child of its enclosing layout, so layout-\n * provided contexts flow naturally into pages via `useContext`.\n *\n * When omitted (the default), the rootLifetime is detached — same as\n * every `mountApp` call before persistent layouts existed.\n */\n parentLifetime?: Lifetime\n /**\n * DOM env override. Defaults to `browserEnv()` — wraps the browser\n * globals. Specify only when mounting into a non-browser DOM (e.g.\n * a jsdom instance held by a test harness, or isolated DOM per\n * shadow root).\n */\n env?: DomEnv\n /**\n * **`hydrateApp` / `hydrateAtAnchor` only.** When `true`, fire the\n * effects that `init()` returned during hydration the same way\n * `mountApp` does on a fresh mount. Defaults to `false` because the\n * SSR render already ran `init()` on the server, and re-running its\n * effects on the client typically produces duplicate work — an\n * `httpGet` issued from `init()` would fetch on the server *and* on\n * hydration; a subscription would attach twice; etc.\n *\n * Opt in only when:\n * - `init()` returns no effects, OR\n * - all returned effects are idempotent / client-only (e.g.\n * wiring a `window` event listener, opening a `WebSocket`), AND\n * - the SSR path didn't run them (typically when `init()` checks a\n * `loaded` flag in state and returns `[]` on the server).\n *\n * Pre-0.0.31 behavior was to always run init effects on hydrate;\n * the option preserves it on demand for projects that depended on\n * it. The default-off direction matches the safer expectation that\n * \"hydration should be cheap and side-effect-free.\"\n */\n runInitEffectsOnHydrate?: boolean\n}\n\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n // HMR: if this component is already mounted (module re-execution\n // during hot update), swap the definition instead of creating a new instance.\n // HMR swap bypasses parentLifetime — HMR re-mounts the outermost app handle,\n // which in a layout setup means the layout re-mounts at the root and the\n // rest of the chain is re-established via the normal mount path.\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponent(def.name, def)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import\n if (devToolsInstall) devToolsInstall(inst)\n\n // Dev-only: warn if initial state contains non-serializable values.\n // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n // Run view() within a render context so primitives can register bindings.\n // Also collect onMount callbacks in a queue we'll flush synchronously\n // after node insertion — prevents the race where a user event fires\n // between mount and the queueMicrotask callback running.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout-invalidating operation\n // instead of N individual appendChild calls on a live container element.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n container.appendChild(frag)\n } else if (nodes.length === 1) {\n container.appendChild(nodes[0]!)\n }\n\n // Flush onMount callbacks SYNCHRONOUSLY now that the DOM is in place.\n // Any listeners they attach are ready before this function returns,\n // so a synchronous dispatchEvent in the caller's next line fires\n // against a fully-wired tree.\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForHmr(def.name, inst, container)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n container.textContent = ''\n })\n}\n\n// Walks an object graph looking for non-JSON-serializable values. Returns the\n// first offender found (depth-first), or null if everything is fine. Stops at\n// depth 6 to bound runtime cost for large states.\nfunction findNonSerializable(\n v: unknown,\n path = 'state',\n depth = 0,\n seen = new WeakSet<object>(),\n): { path: string; value: unknown } | null {\n if (depth > 6) return null\n if (v === null || v === undefined) return null\n const t = typeof v\n if (t === 'string' || t === 'number' || t === 'boolean') return null\n if (t === 'function') return { path, value: v }\n if (t === 'symbol' || t === 'bigint') return { path, value: v }\n if (t !== 'object') return null\n const obj = v as object\n if (seen.has(obj)) return null\n seen.add(obj)\n if (obj instanceof Date) return { path: `${path} (Date)`, value: v }\n if (obj instanceof Map) return { path: `${path} (Map)`, value: v }\n if (obj instanceof Set) return { path: `${path} (Set)`, value: v }\n if (obj instanceof RegExp) return { path: `${path} (RegExp)`, value: v }\n if (obj instanceof Promise) return { path: `${path} (Promise)`, value: v }\n // Plain objects/arrays have Object.prototype / Array.prototype. Class instances\n // have a different prototype.\n const proto = Object.getPrototypeOf(obj)\n if (proto !== null && proto !== Object.prototype && proto !== Array.prototype) {\n return { path: `${path} (${proto?.constructor?.name ?? 'class instance'})`, value: v }\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const r = findNonSerializable(v[i], `${path}[${i}]`, depth + 1, seen)\n if (r) return r\n }\n return null\n }\n for (const k of Object.keys(obj)) {\n const r = findNonSerializable(\n (obj as Record<string, unknown>)[k],\n `${path}.${k}`,\n depth + 1,\n seen,\n )\n if (r) return r\n }\n return null\n}\n\n/**\n * Mount a component relative to a comment anchor rather than inside a\n * container element. Inserts a synthesized end sentinel (`<!-- llui-mount-end -->`)\n * immediately after the anchor and places the component's nodes between\n * the pair. The anchor must already be attached to a live DOM tree.\n *\n * Unlike `mountApp`, the caller's anchor node is preserved across the\n * handle's lifetime — only the content between the pair (and the end\n * sentinel itself) is disposed. Used by `@llui/vike` persistent layouts\n * to mount chain layers without a wrapper element.\n *\n * If a pre-existing `<!-- llui-mount-end -->` is found after the anchor\n * (e.g. stale from an undisposed prior mount), the content between the\n * anchor and that sentinel is swept and the sentinel is reused. Dev mode\n * warns in that case.\n */\nexport function mountAtAnchor<S, M, E>(\n anchor: Comment,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] mountAtAnchor: anchor comment must be attached to a live DOM tree before mount`,\n )\n }\n\n // Locate or synthesize the end sentinel.\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n if (import.meta.env?.DEV) {\n console.warn(\n `[LLui] mountAtAnchor: anchor has a pre-existing end sentinel. ` +\n `A prior mount was not disposed — sweeping stale siblings and reusing the sentinel.`,\n )\n }\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n // Use the caller-provided env if any — end-sentinel creation happens\n // before `inst` exists, so we pick the env directly from options.\n // (browserEnv() fallback matches what createComponentInstance will\n // use below when options.env is undefined.)\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n if (devToolsInstall) devToolsInstall(inst)\n\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout pass instead of N.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\n/**\n * Hydrate a component relative to a comment anchor rather than inside a\n * container element. Analogous to `hydrateApp` — uses `serverState` as\n * the initial state (not `init()`'s output) while preserving `init()`'s\n * effects for post-mount dispatch.\n *\n * The DOM-handling path is identical to `mountAtAnchor`: reuses a\n * pre-existing end sentinel when present, synthesizes one otherwise.\n * Atomic-swaps the owned region whether or not server content is there\n * to replace. No error for a missing end sentinel — the vike chain's\n * outer `hydrateApp`'s `replaceChildren` wipes inner layers' sentinels,\n * so inner-layer `hydrateAtAnchor` calls routinely find nothing to\n * reuse, and that's normal.\n */\nexport function hydrateAtAnchor<S, M, E, D = void>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] hydrateAtAnchor: anchor comment must be attached to a live DOM tree before hydrate`,\n )\n }\n\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n // Run original init() to capture effects, then override state with server's.\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n if (devToolsInstall) devToolsInstall(inst)\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true`.\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateAtAnchor')\n }\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\nfunction dispatchInitialEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n): void {\n if (inst.initialEffects.length === 0 || !inst.def.onEffect) return\n for (const effect of inst.initialEffects) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n inst.initialEffects = []\n}\n\n/**\n * Dev-only warning when a hydrate path silently drops a non-empty\n * `initialEffects` array. The default-skip behavior is deliberate (the\n * server already ran them), but if `init()` produces effects that\n * weren't run on the server — typically client-only init pipelines —\n * silent drop is a footgun. Surface the count and the opt-in.\n */\nfunction warnDroppedInitEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n via: 'hydrateApp' | 'hydrateAtAnchor',\n): void {\n if (!import.meta.env?.DEV) return\n if (inst.initialEffects.length === 0) return\n const name = inst.def.name ?? '<anonymous>'\n console.warn(\n `[LLui] ${via}: skipped ${inst.initialEffects.length} init effect(s) for \"${name}\". ` +\n `Hydration drops init effects by default since the server already ran them. ` +\n `If these effects only fire on the client, pass \\`runInitEffectsOnHydrate: true\\` to opt in.`,\n )\n}\n\n/**\n * Build the `AppHandle` returned by every mount/hydrate path. Captures\n * the `_onCommit` listener registry, the `disposed` flag, and the\n * standard `flush` / `send` / `getState` / `subscribe` shape — all\n * code that was previously duplicated four times across `mountApp`,\n * `mountAtAnchor`, `hydrateApp`, and `hydrateAtAnchor`.\n *\n * Variation lives in the two parameters:\n * - `hmrName` — the def's name used to call `hmrModule.unregisterForHmr`\n * on dispose. Pass `null` to skip HMR unregistration (no current\n * mount path needs that, but it keeps the helper honest).\n * - `domCleanup` — final teardown step that detaches mounted nodes.\n * Container-rooted paths set `container.textContent = ''`;\n * anchor-rooted paths call `_removeBetween(anchor, endSentinel)`\n * and detach the end sentinel. Runs LAST in the dispose chain to\n * match the historical ordering exactly (lifetime is disposed\n * before nodes are detached, so binding teardown sees attached\n * DOM until the very end).\n *\n * The mount-path-parity test in `mount-path-parity.test.ts` enforces\n * that each public entry point produces structurally identical\n * AppHandle behavior — this helper is the realisation of that\n * promise.\n */\nfunction buildAppHandle<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n hmrName: string | null,\n domCleanup: () => void,\n): AppHandle {\n let disposed = false\n const listeners = new Set<(s: unknown) => void>()\n\n inst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n inst._onCommit = undefined\n if (hmrModule && hmrName) hmrModule.unregisterForHmr(hmrName, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n // Tag the root scope so the disposer log reports app-level\n // teardown distinct from in-tree component-unmount events.\n inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n domCleanup()\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\n },\n send(msg: unknown) {\n if (disposed) return\n ;(inst.send as (m: unknown) => void)(msg)\n },\n getState() {\n if (disposed) {\n throw new Error(\n '[LLui] AppHandle.getState() called after dispose — handle is dead. ' +\n 'Detach your event listener / cancel your timer when the handle ' +\n 'is disposed to avoid stale reads.',\n )\n }\n return inst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n if (disposed) return []\n return getBindingDescriptors(inst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n // Drain pending messages with the OLD update first — anything\n // already in the queue was constructed under the old contract,\n // and re-routing it through a new reducer mid-flight could mix\n // half of one transition with half of another (e.g. a payload\n // shape the new update no longer accepts).\n flushInstance(inst)\n // Mutate the def in place so subsequent `inst.def.update`\n // reads — including the per-message read in `flushInstance`'s\n // generic loop — pick up the new function. We deliberately\n // don't replace `inst.def` itself: existing closures, the\n // `__update` fast path, and `__handlers` all stay valid; only\n // the user-visible reducer function changes.\n ;(inst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(inst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n // Direct invocation against current state. No subscribe, no\n // flush, no effect handler. The reducer's contract per TEA is\n // a pure function — calling it twice with the same args is a\n // no-op other than allocations. Returning the raw tuple\n // shape lets the agent inspect both halves without interpreting.\n const [state, effects] = (\n inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(inst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n setOnBindingError(hook) {\n if (disposed) return\n inst._onBindingError = hook ?? undefined\n },\n }\n}\n\nexport function hydrateApp<S, M, E, D = void>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n // Run the original init once to capture its effects. The state it\n // returns is discarded — we use `serverState` (what the server\n // rendered with) instead. The effects are preserved and dispatched\n // after the DOM is in place, so components that rely on \"load data\n // or wire subscriptions on mount\" behave consistently between fresh\n // mount and SSR+hydrate. If the original init has already-loaded\n // data for the hydration case, gate the effect emission inside init\n // itself (e.g. based on a `loaded` flag in state).\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools'\n // import. The other three mount paths (mountApp / mountAtAnchor /\n // hydrateAtAnchor) all call this; without it, the hydrated layout\n // never appears in `window.__lluiComponents`, never sets\n // `window.__lluiDebug`, and is invisible to MCP / agent client /\n // devtools console — so a vike SSR app's outermost layout silently\n // drops out of every observability surface.\n if (devToolsInstall) devToolsInstall(inst)\n\n // Build the component DOM and swap atomically with server HTML.\n // Server HTML remains visible until JS finishes — no flash.\n // onMount callbacks are collected in a queue and flushed synchronously\n // after the swap, matching mountApp's ordering.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Atomic swap — replaces server HTML with client DOM in one operation\n container.replaceChildren(...nodes)\n\n // Flush onMount callbacks synchronously now that the DOM is in place.\n flushMountQueue(onMountQueue)\n\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true` for projects that\n // need the post-swap dispatch (typically when `init()` is gated by\n // a `loaded` flag and returns `[]` on the server).\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateApp')\n }\n\n registerInstance(inst)\n // HMR registration — same as mountApp / mountAtAnchor /\n // hydrateAtAnchor. Without it, replaceComponent(name, newDef)\n // silently no-ops on the hydrated layout layer because the HMR\n // registry has no entry for it.\n if (hmrModule && hydrateDef.name) {\n hmrModule.registerForHmr(hydrateDef.name, inst, container)\n }\n return buildAppHandle(inst, hydrateDef.name ?? null, () => {\n container.textContent = ''\n })\n}\n"]}
@@ -1,11 +1,23 @@
1
1
  /**
2
2
  * Read current state inside a render context and return the result of
3
3
  * `selector(state)`. No binding is created, no mask is assigned — this
4
- * is a one-shot imperative read.
4
+ * is a one-shot imperative read at view-construction time.
5
5
  *
6
- * Use when a builder needs the current state snapshot (e.g. to pass
7
- * an object to an imperative renderer), and a reactive binding would
8
- * be wrong semantically.
6
+ * **Don't use for variable-length lists.** Wrapping a list-render in
7
+ * `sample` looks idiomatic but silently breaks reactivity: the
8
+ * `.map(...)` runs once at construction, captures the row objects in
9
+ * closure, and never re-runs when state updates in place. The cells
10
+ * inside the captured rows show stale data; only a full structural
11
+ * rebuild (e.g. a parent `branch` swapping arms) will refresh them.
12
+ * Use `each` + `ItemAccessor` instead — see the "List of editable
13
+ * rows" recipe in the cookbook.
14
+ *
15
+ * **Use for** passing a state snapshot to an imperative renderer
16
+ * (foreign libraries, third-party canvas/svg builders), reading a
17
+ * value to compute a static piece of structure that doesn't need to
18
+ * react, or any case where a reactive binding would be semantically
19
+ * wrong (e.g. capturing a value at *this exact moment* for a
20
+ * one-shot side effect).
9
21
  *
10
22
  * Also exposed as `h.sample` on the View bag for destructure-from-`h`
11
23
  * ergonomics. The top-level import form works everywhere a render
@@ -1 +1 @@
1
- {"version":3,"file":"sample.d.ts","sourceRoot":"","sources":["../../src/primitives/sample.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAGrD"}
1
+ {"version":3,"file":"sample.d.ts","sourceRoot":"","sources":["../../src/primitives/sample.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAGrD"}
@@ -2,11 +2,23 @@ import { getRenderContext } from '../render-context.js';
2
2
  /**
3
3
  * Read current state inside a render context and return the result of
4
4
  * `selector(state)`. No binding is created, no mask is assigned — this
5
- * is a one-shot imperative read.
5
+ * is a one-shot imperative read at view-construction time.
6
6
  *
7
- * Use when a builder needs the current state snapshot (e.g. to pass
8
- * an object to an imperative renderer), and a reactive binding would
9
- * be wrong semantically.
7
+ * **Don't use for variable-length lists.** Wrapping a list-render in
8
+ * `sample` looks idiomatic but silently breaks reactivity: the
9
+ * `.map(...)` runs once at construction, captures the row objects in
10
+ * closure, and never re-runs when state updates in place. The cells
11
+ * inside the captured rows show stale data; only a full structural
12
+ * rebuild (e.g. a parent `branch` swapping arms) will refresh them.
13
+ * Use `each` + `ItemAccessor` instead — see the "List of editable
14
+ * rows" recipe in the cookbook.
15
+ *
16
+ * **Use for** passing a state snapshot to an imperative renderer
17
+ * (foreign libraries, third-party canvas/svg builders), reading a
18
+ * value to compute a static piece of structure that doesn't need to
19
+ * react, or any case where a reactive binding would be semantically
20
+ * wrong (e.g. capturing a value at *this exact moment* for a
21
+ * one-shot side effect).
10
22
  *
11
23
  * Also exposed as `h.sample` on the View bag for destructure-from-`h`
12
24
  * ergonomics. The top-level import form works everywhere a render
@@ -1 +1 @@
1
- {"version":3,"file":"sample.js","sourceRoot":"","sources":["../../src/primitives/sample.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,MAAM,CAAO,QAAqB;IAChD,MAAM,GAAG,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACtC,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAU,CAAC,CAAA;AACjC,CAAC","sourcesContent":["import { getRenderContext } from '../render-context.js'\n\n/**\n * Read current state inside a render context and return the result of\n * `selector(state)`. No binding is created, no mask is assigned — this\n * is a one-shot imperative read.\n *\n * Use when a builder needs the current state snapshot (e.g. to pass\n * an object to an imperative renderer), and a reactive binding would\n * be wrong semantically.\n *\n * Also exposed as `h.sample` on the View bag for destructure-from-`h`\n * ergonomics. The top-level import form works everywhere a render\n * context is live — including `each.render`, whose bag intentionally\n * does not carry View methods.\n *\n * Throws if called outside a render context.\n */\nexport function sample<S, R>(selector: (s: S) => R): R {\n const ctx = getRenderContext('sample')\n return selector(ctx.state as S)\n}\n"]}
1
+ {"version":3,"file":"sample.js","sourceRoot":"","sources":["../../src/primitives/sample.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,MAAM,CAAO,QAAqB;IAChD,MAAM,GAAG,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACtC,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAU,CAAC,CAAA;AACjC,CAAC","sourcesContent":["import { getRenderContext } from '../render-context.js'\n\n/**\n * Read current state inside a render context and return the result of\n * `selector(state)`. No binding is created, no mask is assigned — this\n * is a one-shot imperative read at view-construction time.\n *\n * **Don't use for variable-length lists.** Wrapping a list-render in\n * `sample` looks idiomatic but silently breaks reactivity: the\n * `.map(...)` runs once at construction, captures the row objects in\n * closure, and never re-runs when state updates in place. The cells\n * inside the captured rows show stale data; only a full structural\n * rebuild (e.g. a parent `branch` swapping arms) will refresh them.\n * Use `each` + `ItemAccessor` instead — see the \"List of editable\n * rows\" recipe in the cookbook.\n *\n * **Use for** passing a state snapshot to an imperative renderer\n * (foreign libraries, third-party canvas/svg builders), reading a\n * value to compute a static piece of structure that doesn't need to\n * react, or any case where a reactive binding would be semantically\n * wrong (e.g. capturing a value at *this exact moment* for a\n * one-shot side effect).\n *\n * Also exposed as `h.sample` on the View bag for destructure-from-`h`\n * ergonomics. The top-level import form works everywhere a render\n * context is live — including `each.render`, whose bag intentionally\n * does not carry View methods.\n *\n * Throws if called outside a render context.\n */\nexport function sample<S, R>(selector: (s: S) => R): R {\n const ctx = getRenderContext('sample')\n return selector(ctx.state as S)\n}\n"]}
@@ -24,5 +24,5 @@
24
24
  * reads. Phase 2 / Phase 1 skip the reconcile when no interesting bit
25
25
  * is set. Defaults to FULL_MASK for hand-written components.
26
26
  */
27
- export declare function unsafeHtml<S>(accessor: ((s: S) => string) | string, mask?: number): Node[];
27
+ export declare function unsafeHtml<S>(accessor: ((s: S) => string) | (() => string) | string, mask?: number): Node[];
28
28
  //# sourceMappingURL=unsafe-html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"unsafe-html.d.ts","sourceRoot":"","sources":["../../src/primitives/unsafe-html.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CA8C1F"}
1
+ {"version":3,"file":"unsafe-html.d.ts","sourceRoot":"","sources":["../../src/primitives/unsafe-html.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,EACtD,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,EAAE,CA8CR"}
@@ -1 +1 @@
1
- {"version":3,"file":"unsafe-html.js","sourceRoot":"","sources":["../../src/primitives/unsafe-html.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,UAAU,CAAI,QAAqC,EAAE,IAAa;IAChF,MAAM,GAAG,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAC1C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAA;IACnC,MAAM,SAAS,GAAG,IAAI,IAAI,SAAS,CAAA;IAEnC,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,CAAC,CAAA;IAClD,IAAI,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAU,CAAC,CAAA;IAC1C,IAAI,YAAY,GAAW,gBAAgB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;IAE7D,MAAM,KAAK,GAAoB;QAC7B,IAAI,EAAE,SAAS;QACf,SAAS,CAAC,KAAc;YACtB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAU,CAAC,CAAA;YACpC,8DAA8D;YAC9D,gEAAgE;YAChE,sDAAsD;YACtD,IAAI,OAAO,KAAK,WAAW;gBAAE,OAAM;YAEnC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;YAChC,IAAI,CAAC,MAAM;gBAAE,OAAM;YAEnB,MAAM,QAAQ,GAAG,YAAY,CAAA;YAC7B,YAAY,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YAC7C,WAAW,GAAG,OAAO,CAAA;YAErB,gEAAgE;YAChE,kEAAkE;YAClE,4DAA4D;YAC5D,kEAAkE;YAClE,qCAAqC;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAA;YAC9B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAChC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YAChC,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,IAAI,IAAI,CAAC,UAAU;oBAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YACxD,CAAC;QACH,CAAC;KACF,CAAA;IACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAElB,OAAO,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC,CAAA;AAClC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAiD,EAAE,IAAY;IACvF,oEAAoE;IACpE,oEAAoE;IACpE,iEAAiE;IACjE,sEAAsE;IACtE,0DAA0D;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAA;AAC/D,CAAC","sourcesContent":["import type { StructuralBlock } from '../structural.js'\nimport { getRenderContext } from '../render-context.js'\nimport { FULL_MASK } from '../update-loop.js'\n\n/**\n * Insert raw HTML into the DOM tree.\n *\n * **Security.** The caller is responsible for sanitizing `html`. Never\n * interpolate unsanitized user input — this is the XSS escape hatch and\n * the name carries the warning deliberately.\n *\n * **Opaque to the framework.** The parsed subtree is treated as a black\n * box by LLui — no bindings, events, `each`, `show`, or `child` inside\n * it will be discovered or driven by the framework. Use element helpers\n * for anything that needs to react to state or dispatch messages.\n *\n * **Static form.** `unsafeHtml('<b>hi</b>')` parses once at view time\n * and returns the parsed nodes. Zero reactive overhead.\n *\n * **Reactive form.** `unsafeHtml((s) => s.markdownHtml)` registers a\n * structural block that re-parses when the returned string differs\n * (strict `===`) from the previous value. Unchanged strings short-\n * circuit — existing DOM identity (focus, selection, listeners\n * attached outside LLui) is preserved.\n *\n * **Mask hint.** The second parameter mirrors `text()`: the compiler\n * passes a precise mask derived from which state fields the accessor\n * reads. Phase 2 / Phase 1 skip the reconcile when no interesting bit\n * is set. Defaults to FULL_MASK for hand-written components.\n */\nexport function unsafeHtml<S>(accessor: ((s: S) => string) | string, mask?: number): Node[] {\n const ctx = getRenderContext('unsafeHtml')\n if (typeof accessor === 'string') {\n return parseHtmlToNodes(ctx, accessor)\n }\n\n const blocks = ctx.structuralBlocks\n const blockMask = mask ?? FULL_MASK\n\n const anchor = ctx.dom.createComment('unsafeHtml')\n let currentHtml = accessor(ctx.state as S)\n let currentNodes: Node[] = parseHtmlToNodes(ctx, currentHtml)\n\n const block: StructuralBlock = {\n mask: blockMask,\n reconcile(state: unknown) {\n const newHtml = accessor(state as S)\n // Identity short-circuit — don't rebuild the subtree when the\n // author handed us the same string. Preserves focus, selection,\n // and any listeners outside LLui's view of the world.\n if (newHtml === currentHtml) return\n\n const parent = anchor.parentNode\n if (!parent) return\n\n const oldNodes = currentNodes\n currentNodes = parseHtmlToNodes(ctx, newHtml)\n currentHtml = newHtml\n\n // The anchor sits immediately before the current node range, so\n // `anchor.nextSibling` is the first old node (or whatever follows\n // when the old list is empty). Insert new nodes there, then\n // remove the old ones — matches `branch()`'s enter/leave order so\n // transitions can inspect both sets.\n const ref = anchor.nextSibling\n for (const node of currentNodes) {\n parent.insertBefore(node, ref)\n }\n for (const node of oldNodes) {\n if (node.parentNode) node.parentNode.removeChild(node)\n }\n },\n }\n blocks.push(block)\n\n return [anchor, ...currentNodes]\n}\n\nfunction parseHtmlToNodes(ctx: import('../render-context.js').RenderContext, html: string): Node[] {\n // Delegates to the env — jsdom/linkedom adapters may implement this\n // via DOMParser instead of the browser `<template>` trick, but both\n // return an inert DocumentFragment that doesn't execute scripts.\n // Snapshot — moving nodes to a parent drains fragment.childNodes, but\n // callers hold this array and we iterate it on reconcile.\n return Array.from(ctx.dom.parseHtmlFragment(html).childNodes)\n}\n"]}
1
+ {"version":3,"file":"unsafe-html.js","sourceRoot":"","sources":["../../src/primitives/unsafe-html.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,UAAU,CACxB,QAAsD,EACtD,IAAa;IAEb,MAAM,GAAG,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAC1C,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAA;IACnC,MAAM,SAAS,GAAG,IAAI,IAAI,SAAS,CAAA;IAEnC,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,CAAC,CAAA;IAClD,IAAI,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAU,CAAC,CAAA;IAC1C,IAAI,YAAY,GAAW,gBAAgB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;IAE7D,MAAM,KAAK,GAAoB;QAC7B,IAAI,EAAE,SAAS;QACf,SAAS,CAAC,KAAc;YACtB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAU,CAAC,CAAA;YACpC,8DAA8D;YAC9D,gEAAgE;YAChE,sDAAsD;YACtD,IAAI,OAAO,KAAK,WAAW;gBAAE,OAAM;YAEnC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;YAChC,IAAI,CAAC,MAAM;gBAAE,OAAM;YAEnB,MAAM,QAAQ,GAAG,YAAY,CAAA;YAC7B,YAAY,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YAC7C,WAAW,GAAG,OAAO,CAAA;YAErB,gEAAgE;YAChE,kEAAkE;YAClE,4DAA4D;YAC5D,kEAAkE;YAClE,qCAAqC;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAA;YAC9B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAChC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YAChC,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,IAAI,IAAI,CAAC,UAAU;oBAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YACxD,CAAC;QACH,CAAC;KACF,CAAA;IACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAElB,OAAO,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC,CAAA;AAClC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAiD,EAAE,IAAY;IACvF,oEAAoE;IACpE,oEAAoE;IACpE,iEAAiE;IACjE,sEAAsE;IACtE,0DAA0D;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAA;AAC/D,CAAC","sourcesContent":["import type { StructuralBlock } from '../structural.js'\nimport { getRenderContext } from '../render-context.js'\nimport { FULL_MASK } from '../update-loop.js'\n\n/**\n * Insert raw HTML into the DOM tree.\n *\n * **Security.** The caller is responsible for sanitizing `html`. Never\n * interpolate unsanitized user input — this is the XSS escape hatch and\n * the name carries the warning deliberately.\n *\n * **Opaque to the framework.** The parsed subtree is treated as a black\n * box by LLui — no bindings, events, `each`, `show`, or `child` inside\n * it will be discovered or driven by the framework. Use element helpers\n * for anything that needs to react to state or dispatch messages.\n *\n * **Static form.** `unsafeHtml('<b>hi</b>')` parses once at view time\n * and returns the parsed nodes. Zero reactive overhead.\n *\n * **Reactive form.** `unsafeHtml((s) => s.markdownHtml)` registers a\n * structural block that re-parses when the returned string differs\n * (strict `===`) from the previous value. Unchanged strings short-\n * circuit — existing DOM identity (focus, selection, listeners\n * attached outside LLui) is preserved.\n *\n * **Mask hint.** The second parameter mirrors `text()`: the compiler\n * passes a precise mask derived from which state fields the accessor\n * reads. Phase 2 / Phase 1 skip the reconcile when no interesting bit\n * is set. Defaults to FULL_MASK for hand-written components.\n */\nexport function unsafeHtml<S>(\n accessor: ((s: S) => string) | (() => string) | string,\n mask?: number,\n): Node[] {\n const ctx = getRenderContext('unsafeHtml')\n if (typeof accessor === 'string') {\n return parseHtmlToNodes(ctx, accessor)\n }\n\n const blocks = ctx.structuralBlocks\n const blockMask = mask ?? FULL_MASK\n\n const anchor = ctx.dom.createComment('unsafeHtml')\n let currentHtml = accessor(ctx.state as S)\n let currentNodes: Node[] = parseHtmlToNodes(ctx, currentHtml)\n\n const block: StructuralBlock = {\n mask: blockMask,\n reconcile(state: unknown) {\n const newHtml = accessor(state as S)\n // Identity short-circuit — don't rebuild the subtree when the\n // author handed us the same string. Preserves focus, selection,\n // and any listeners outside LLui's view of the world.\n if (newHtml === currentHtml) return\n\n const parent = anchor.parentNode\n if (!parent) return\n\n const oldNodes = currentNodes\n currentNodes = parseHtmlToNodes(ctx, newHtml)\n currentHtml = newHtml\n\n // The anchor sits immediately before the current node range, so\n // `anchor.nextSibling` is the first old node (or whatever follows\n // when the old list is empty). Insert new nodes there, then\n // remove the old ones — matches `branch()`'s enter/leave order so\n // transitions can inspect both sets.\n const ref = anchor.nextSibling\n for (const node of currentNodes) {\n parent.insertBefore(node, ref)\n }\n for (const node of oldNodes) {\n if (node.parentNode) node.parentNode.removeChild(node)\n }\n },\n }\n blocks.push(block)\n\n return [anchor, ...currentNodes]\n}\n\nfunction parseHtmlToNodes(ctx: import('../render-context.js').RenderContext, html: string): Node[] {\n // Delegates to the env — jsdom/linkedom adapters may implement this\n // via DOMParser instead of the browser `<template>` trick, but both\n // return an inert DocumentFragment that doesn't execute scripts.\n // Snapshot — moving nodes to a parent drains fragment.childNodes, but\n // callers hold this array and we iterate it on reconcile.\n return Array.from(ctx.dom.parseHtmlFragment(html).childNodes)\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -238,6 +238,29 @@ export interface AppHandle {
238
238
  state: unknown;
239
239
  effects: unknown[];
240
240
  } | null;
241
+ /**
242
+ * Install a hook called whenever a binding's accessor throws during
243
+ * the update cycle. The runtime catches the throw, leaves the
244
+ * binding's `lastValue` unchanged (DOM stays at its previous value
245
+ * rather than blanking), continues with sibling bindings, and
246
+ * notifies this hook with `{kind, key?, message, stack?}`.
247
+ *
248
+ * Used by `@llui/agent` to fold binding-evaluation throws into the
249
+ * dispatch envelope's `drain.errors` — so an LLM dispatching a Msg
250
+ * that breaks scoring doesn't get HTTP 500 + a frozen UI; instead
251
+ * the dispatch reports as `{status: 'dispatched', drain: {errors:
252
+ * [...]}}` with the rest of the page rendering normally.
253
+ *
254
+ * Pass `null` to remove the hook. Without a hook, throws fall back
255
+ * to `console.error` (dev mode) or `console.warn` (prod) so they
256
+ * aren't silently swallowed.
257
+ */
258
+ setOnBindingError(hook: ((info: {
259
+ kind: string;
260
+ key?: string;
261
+ message: string;
262
+ stack?: string;
263
+ }) => void) | null): void;
241
264
  }
242
265
  export interface Lifetime {
243
266
  id: number;
@@ -288,11 +311,19 @@ export interface TransitionOptions {
288
311
  }
289
312
  interface BranchOptionsBase extends TransitionOptions {
290
313
  }
314
+ /**
315
+ * Discriminant accessor — reads a string-keyed value either from the
316
+ * current state (`(s) => …`) or from a closed-over item accessor /
317
+ * memo (`() => item.kind()`). Both forms re-evaluate on every commit.
318
+ * The zero-arg form is the canonical shape for branching on per-row
319
+ * fields inside an `each.render` callback.
320
+ */
321
+ type Discriminant<S, K extends string> = ((s: S) => K) | (() => K);
291
322
  /**
292
323
  * All cases covered by `cases` — no default allowed (would be dead code).
293
324
  */
294
325
  type BranchOptionsExhaustive<S, M, K extends string> = BranchOptionsBase & {
295
- on: (s: S) => K;
326
+ on: Discriminant<S, K>;
296
327
  cases: {
297
328
  [P in K]: (h: View<S, M>) => Node[];
298
329
  };
@@ -302,7 +333,7 @@ type BranchOptionsExhaustive<S, M, K extends string> = BranchOptionsBase & {
302
333
  * `cases` may cover some but not all keys; `default` handles the rest.
303
334
  */
304
335
  type BranchOptionsNonExhaustive<S, M, K extends string> = BranchOptionsBase & {
305
- on: (s: S) => K;
336
+ on: Discriminant<S, K>;
306
337
  cases?: {
307
338
  [P in K]?: (h: View<S, M>) => Node[];
308
339
  };
@@ -316,7 +347,7 @@ type BranchOptionsNonExhaustive<S, M, K extends string> = BranchOptionsBase & {
316
347
  * `on`'s return type to a literal union.
317
348
  */
318
349
  type BranchOptionsWide<S, M> = BranchOptionsBase & {
319
- on: (s: S) => string;
350
+ on: Discriminant<S, string>;
320
351
  cases?: Record<string, (h: View<S, M>) => Node[]>;
321
352
  default?: (h: View<S, M>) => Node[];
322
353
  };
@@ -336,7 +367,15 @@ type BranchOptionsWide<S, M> = BranchOptionsBase & {
336
367
  */
337
368
  export type BranchOptions<S, M = unknown, K extends string = string> = string extends K ? BranchOptionsWide<S, M> : BranchOptionsExhaustive<S, M, K> | BranchOptionsNonExhaustive<S, M, K>;
338
369
  export interface ShowOptions<S, M = unknown> extends TransitionOptions {
339
- when: (s: S) => boolean;
370
+ /**
371
+ * Predicate evaluated on every commit. `(s) => …` reads from
372
+ * component state; `() => …` (zero-arg) reads from a closed-over
373
+ * source — typically `item.field()` inside an `each.render`
374
+ * callback. Both forms are reactive: the predicate runs against
375
+ * each new state and the rendered subtree mounts/unmounts on the
376
+ * boolean transition.
377
+ */
378
+ when: ((s: S) => boolean) | (() => boolean);
340
379
  render: (h: View<S, M>) => Node[];
341
380
  fallback?: (h: View<S, M>) => Node[];
342
381
  }
@@ -350,7 +389,13 @@ export interface ShowOptions<S, M = unknown> extends TransitionOptions {
350
389
  * one-shot current-state read.
351
390
  */
352
391
  export interface ScopeOptions<S, M = unknown> extends TransitionOptions {
353
- on: (s: S) => string;
392
+ /**
393
+ * Key accessor evaluated on every commit. `(s) => …` reads from
394
+ * component state; `() => …` (zero-arg) reads from a closed-over
395
+ * source. The render callback rebuilds whenever the returned key
396
+ * changes — fresh lifetime, fresh bindings.
397
+ */
398
+ on: ((s: S) => string) | (() => string);
354
399
  render: (h: View<S, M>) => Node[];
355
400
  }
356
401
  /**