kerfjs 0.13.0 → 0.15.0-beta.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  ## Unreleased
8
8
 
9
9
 
10
+ - KF-260 — **The snapshot list reconciler now updates a changed-but-stable row *in place* instead of replacing its DOM node.** When a re-render produces the same item refs in the same order (no insert/remove/move) but some rows' HTML changed, kerf morphs each changed row on its existing node — reusing the granular path's surgical attribute/text fast paths and `morph()` (with a `replaceChild` fallback only when the row's top-level tag changes) — rather than removing the old node and inserting a freshly-parsed one. Previously such a row was treated as "replaced": the node swap forced a full relayout, which in a large `<table>` is expensive even when only one attribute flipped. Two consequences: (1) **perf** — a selection model that keeps one external "selected id" and derives the row class via `each()`'s `cacheKey` (rather than a per-row flag) now updates select-row in the competitive range instead of several times slower, since it no longer node-swaps; (2) **behavior** — snapshot-path row updates (plain-array `each()` and `cacheKey`-driven re-renders) now preserve the row's DOM node, so focus, scroll position, IME composition, and in-progress CSS transitions on a changed row survive the update (matching the `arraySignal` granular path). Enter-animations keyed on element *creation* no longer re-fire for an in-place update, since the row is no longer recreated. Internal-only change (new `src/list-reconcile-inplace.ts`; the now-subsumed no-op snapshot fast path was removed); no public API change. A row that both moves *and* changes content in the same reconcile still takes the node-replacing path.
11
+ - KF-244 — **Each complete example app's docs page now opens with an animated SVG preview of the real app in action**, so a reader sees what the live demo does before clicking through. The five showcase apps (`todomvc`, `markdown-editor`, `kanban`, `chat`, `dashboard`) get a preview at the top of their page plus a gallery on the complete-examples index; the two migration-companion apps (`counter-store` on the Redux page, `cart-htmx` on the htmx page) get one inline next to their "Run live" link. Each preview is a self-contained, CSS-animated SVG (~60–100 KB) captured with [`domotion-svg`](https://github.com/brianwestphal/domotion) driving the real app through the same headline interaction its `tests/browser/example-apps.spec.ts` smoke spec exercises — they animate inside an `<img>` and scale crisply. New assets under `site/public/demos/`; the per-app capture configs + a `capture-demos.sh` regenerator live in `site/scripts/demo-captures/` (with a `site/scripts/build-demos-for-capture.mjs` helper that builds each app with a per-app base into a shared serve root). Docs-only change; no runtime or API impact.
12
+ - KF-243 — **`mount()` now adopts an inert-document `rootEl` into the live `document` before its first render** — defense-in-depth complementing the KF-240 `toElement()` fix. `toElement()` already adopts its own output, but a consumer can hand `mount()` an element built another way (their own `DOMParser`, a detached `<template>.content` child, `document.implementation.createHTMLDocument()` output) whose `ownerDocument` has no browsing context; `mount()`'s first-render `rootEl.innerHTML = …` on such a node would hit the same WebKit inert-document fragment-parsing bug. `mount()` now adopts it up front. Only genuinely inert owners (`defaultView === null`) are adopted — a live element in another realm (e.g. an iframe, `defaultView !== null`) is left in place, since `mount()` works on it as-is and must never move a node out of its own window. Normal live-document roots (the overwhelmingly common case) are untouched. No API change. New unit tests in `tests/unit/mount.test.ts` (adopts an inert root + renders correctly; leaves a live root's `ownerDocument`/parent untouched).
13
+ - KF-240 — **`toElement()` now adopts its result into the live `document` before returning it.** Both parse paths produced nodes owned by an *inert* document — the `<template>.content` path (HTML) yields nodes owned by the template-contents owner document, and the `DOMParser` path (SVG) yields nodes owned by the parser's document — neither being the document the caller renders into. Operating on such a node before it's inserted, most notably `mount()`'s first-render `rootEl.innerHTML = …`, runs against an inert-document element, which on **WebKit** trips a fragment-parsing bug: under rapid bursts (e.g. a feed mounting many `toElement(<div/>)` cards in one synchronous flush) the parser can hand back a *previous* parse's nodes, so a freshly-built element silently inherits unrelated DOM — the Safari-only "component renders pre-filled / in the wrong state on first paint" symptom diagnosed downstream. The render, the signals, and the produced HTML string were all correct; only the inert-document `innerHTML` parse diverged, and only on WebKit (Chromium never reproduced it). `toElement` now calls `document.adoptNode(...)` on the returned `Element` / `DocumentFragment` (identity- and namespace-preserving), so consumers can mount it / set `innerHTML` / otherwise mutate it before insertion without tripping engine-specific inert-document behavior. No API change — the returned shape is unchanged; the node is just guaranteed to belong to the live document. New deterministic regression guards in `tests/unit/toElement.test.ts` (`ownerDocument === document` for every return shape) + a real-browser spec `tests/browser/toelement-adopt.spec.ts` exercising the mount-before-insert burst across Chromium / Firefox / WebKit.
10
14
  - KF-238 — New opt-in dev-warn `KERF_DEV_WARN_DELEGATE_IN_EFFECT=1` fires once per process when `delegate()` or `delegateCapture()` is called inside an `effect()` body. Every effect re-run executes its body fresh, so a `delegate()` call inside the body installs a NEW root listener on each re-run; the effect's disposer cleans up the reactive subscription but not the side-effects the body produced, so listener count grows linearly with signal churn and each listener pins its handler closure. Implementation: `reactive.ts`'s `effect()` factory now wraps the user body in `enterEffect()` / `exitEffect()` calls (in a `try`/`finally` so a throwing body still decrements the counter) when the env var is set; `delegate.ts` calls `warnIfInsideEffect()` at the top of both helpers. Production (`NODE_ENV=production`) short-circuits before the wrap, so the bare `coreEffect` re-export stays the default path. New module `src/dev-delegate-warn.ts`; new test `tests/unit/dev-delegate-warn.internal.test.ts` (9 cases). Pairs with KF-237's docs gotchas section (§5.3 "When capturing the disposer still isn't enough" — scenario 2).
11
15
  - KF-237 — `docs/5-event-delegation.md` §5.3 gains a "When capturing the disposer still isn't enough" subsection covering five scenarios where capturing the disposer is necessary but not sufficient: `delegate()` rooted on a node inside a morph-managed tree (root at the outer `mount()` instead), `delegate()` called inside `effect()` (per-rerun listener stack — see KF-238 dev warn), `delegate()` on `toElement()` output that's later `replaceChildren()`-ed, disposer variables overwritten by reassignment, and nested-root confusion where the stable parent fools an AI into thinking a transient child is page-lifetime. Each scenario has wrong / right code pairs. Cross-linked from `docs/8-api-reference.md`'s `delegate()` entry, Hard Rule 5 in `docs/ai/usage-guide.md`, and two new rows in the common-errors table.
12
16
  - KF-236 — The `chat`, `todomvc`, `kanban`, and `markdown-editor` example apps now prefix their bare `delegate()` / `delegateCapture()` calls with the `void` opt-out sigil and carry an inline comment explaining the page-lifetime intent (matching the `counter-store` pattern shipped in KF-234). Downstream consumers who copy these examples and enable `kerfjs.configs.recommended` no longer see warnings from `kerfjs/require-delegate-disposer` on the canonical source.
@@ -24,6 +28,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
24
28
  - `kerfjs` npm package now bundles the drop-in AI-assistant configs at `ai/skill.md`, `ai/cursorrules`, and `ai/manifest.json` — so `npm install kerfjs` lands them directly on disk instead of asking consumers to find them on GitHub. The repo-root `kerf.claude-skill.md` / `kerf.cursorrules` remain the source of truth; `ai/` is regenerated by `scripts/sync-ai-bundle.mjs` and kept honest by the new `npm run check:ai-bundle-in-sync` gate (wired into `npm run check`). Each bundled file carries a `kerf-skill-version` line + a `KERF-APP-CANONICAL-END` marker so the new ESLint rule can detect drift and auto-fix only the kerf-maintained section while preserving consumer customizations below the marker. See `docs/12-ai-assistant-configs.md`.
25
29
  - `eslint-plugin-kerfjs` v0.9.0 adds `kerfjs/ai-assistant-configs` (`warn` in recommended config) — once per lint pass, checks the consumer's `.claude/skills/kerf-app/SKILL.md` and `.cursorrules` against the bundled `kerfjs/ai/manifest.json`. Reports `missing` / `stale` / `forked` states; `eslint --fix` writes the bundled canonical above the `KERF-APP-CANONICAL-END` marker and preserves the consumer's append zone below it (the "versioned-section preservation" strategy). Granular disable via `['warn', { claude: false, cursor: true }]`.
26
30
 
31
+ ## [0.14.0] - 2026-05-27
32
+
33
+
34
+ - Fix `toElement()` first-paint divergence in WebKit by adopting its result into the live document
35
+ - Fix `mount()` first render in WebKit by adopting an inert `rootEl` into the live document
36
+
27
37
  ## [0.13.0] - 2026-05-23
28
38
 
29
39
 
package/ai/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "kerfjsVersion": "0.13.0",
2
+ "kerfjsVersion": "0.14.0",
3
3
  "files": [
4
4
  {
5
5
  "name": "skill",
package/dist/index.d.ts CHANGED
@@ -327,6 +327,11 @@ declare function effect(fn: () => void | (() => void)): () => void;
327
327
  * insert, so `parent.replaceChildren(toElement(<>{ICON} label</>))` does the
328
328
  * obvious thing — parent gets the svg AND the text, no silent loss.
329
329
  *
330
+ * The returned node is always adopted into the live `document` before it's
331
+ * handed back (see `adopt()` below) — never left owned by the inert
332
+ * `<template>`/`DOMParser` document it was parsed in, which is unsafe to mutate
333
+ * before insertion on some engines.
334
+ *
330
335
  * SVG namespacing: the HTML5 parser handles `<svg>` as foreign content
331
336
  * correctly even when wrapped in a fragment, so multi-root inputs containing
332
337
  * SVGs come out namespaced correctly via the `<template>.innerHTML` path. For
package/dist/index.js CHANGED
@@ -951,17 +951,49 @@ function findOffendingChange(patches, changes) {
951
951
  return new Error("each(): bulk-update mismatch with no per-row offender (kerf bug).");
952
952
  }
953
953
 
954
+ // src/list-reconcile-inplace.ts
955
+ function tryInPlaceContentUpdate(binding, listSeg) {
956
+ const oldItems = binding.items;
957
+ const items = listSeg.items;
958
+ const n = items.length;
959
+ if (n === 0 || n !== oldItems.length) return false;
960
+ for (let i = 0; i < n; i++) {
961
+ if (items[i].ref !== oldItems[i].ref) return false;
962
+ }
963
+ const { liveParent } = binding;
964
+ const newRecord = new Array(n);
965
+ const focusSnap = captureFocus(liveParent);
966
+ for (let i = 0; i < n; i++) {
967
+ newRecord[i] = updateRowInPlace(liveParent, oldItems[i], items[i], i);
968
+ }
969
+ if (focusSnap !== null) restoreFocus(focusSnap);
970
+ binding.items = newRecord;
971
+ maybeWarnMissingRowKey(newRecord[0].node, 0, newRecord[0].html, binding);
972
+ return true;
973
+ }
974
+ function updateRowInPlace(liveParent, old, ni, index) {
975
+ if (old.html === ni.html || tryAttributeOnlyFastPath(old.node, old.html, ni.html) || tryTextContentFastPath(old.node, old.html, ni.html)) {
976
+ return { ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: old.node };
977
+ }
978
+ const newNode = parseSingleRow2(ni.html, index);
979
+ if (old.node.tagName === newNode.tagName) {
980
+ _morphElement(old.node, newNode);
981
+ return { ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: old.node };
982
+ }
983
+ liveParent.replaceChild(newNode, old.node);
984
+ return { ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: newNode };
985
+ }
986
+ function parseSingleRow2(html, index) {
987
+ const { tpl, count } = parseRowTemplate(html);
988
+ if (count !== 1) throw rowContractError(index, html);
989
+ return tpl.content.firstElementChild;
990
+ }
991
+
954
992
  // src/list-reconcile-snapshot.ts
955
993
  function reconcileSnapshot(binding, listSeg) {
994
+ if (tryInPlaceContentUpdate(binding, listSeg)) return;
956
995
  const { liveParent } = binding;
957
996
  const { newRecord, prevIdx, replacedNodes, freshIndices, freshHtmls } = classifyItems(binding.items, listSeg);
958
- if (replacedNodes.length === 0 && freshIndices.length === 0 && isInOrder(prevIdx)) {
959
- binding.items = newRecord;
960
- if (newRecord.length > 0) {
961
- maybeWarnMissingRowKey(newRecord[0].node, 0, newRecord[0].html, binding);
962
- }
963
- return;
964
- }
965
997
  const tailAnchor = endAnchor(binding);
966
998
  buildFreshNodes(newRecord, freshIndices, freshHtmls);
967
999
  const focusSnap = captureFocus(liveParent);
@@ -1073,12 +1105,6 @@ function lis(arr) {
1073
1105
  }
1074
1106
  return out;
1075
1107
  }
1076
- function isInOrder(prevIdx) {
1077
- for (let i = 0; i < prevIdx.length; i++) {
1078
- if (prevIdx[i] !== i) return false;
1079
- }
1080
- return true;
1081
- }
1082
1108
 
1083
1109
  // src/list-reconcile.ts
1084
1110
  function reconcileList(binding, listSeg) {
@@ -1130,6 +1156,10 @@ function mount(rootEl, render) {
1130
1156
  'mount: rootEl is null/undefined \u2014 pass the live element, e.g. mount(document.getElementById("app")!, render). A common cause is a typo in the id or selector that returns null at runtime even though the TypeScript types say HTMLElement.'
1131
1157
  );
1132
1158
  }
1159
+ const owner = rootEl.ownerDocument;
1160
+ if (owner !== document) {
1161
+ if (owner.defaultView === null) document.adoptNode(rootEl);
1162
+ }
1133
1163
  assertNotInsideMountedTree(rootEl);
1134
1164
  rootEl[MOUNTED_MARKER] = true;
1135
1165
  const listenerWarnObserver = installListenerRebuildWarn(rootEl);
@@ -1292,6 +1322,10 @@ function excerpt(html) {
1292
1322
  const trimmed = html.trim();
1293
1323
  return trimmed.length > EXCERPT_MAX_LEN ? `${trimmed.slice(0, EXCERPT_MAX_LEN)}\u2026` : trimmed;
1294
1324
  }
1325
+ function adopt(node) {
1326
+ document.adoptNode(node);
1327
+ return node;
1328
+ }
1295
1329
  function parseSvgOrThrow(html, label, originalHtml) {
1296
1330
  const doc = new DOMParser().parseFromString(html, "image/svg+xml");
1297
1331
  const err = doc.querySelector("parsererror");
@@ -1321,7 +1355,7 @@ function toElement(jsx) {
1321
1355
  if (single !== null) {
1322
1356
  const tag = single.tagName.toLowerCase();
1323
1357
  if (tag === "svg") {
1324
- return parseSvgOrThrow(html.trim(), "SVG", html).documentElement;
1358
+ return adopt(parseSvgOrThrow(html.trim(), "SVG", html).documentElement);
1325
1359
  }
1326
1360
  if (SVG_FRAGMENT_TAGS.has(tag)) {
1327
1361
  const wrapped = `<svg xmlns="${SVG_NS}">${html}</svg>`;
@@ -1329,9 +1363,9 @@ function toElement(jsx) {
1329
1363
  const first = doc.documentElement.firstElementChild;
1330
1364
  if (first === null) throw new Error(`toElement: SVG fragment produced no element
1331
1365
  input: ${excerpt(html)}`);
1332
- return first;
1366
+ return adopt(first);
1333
1367
  }
1334
- return single;
1368
+ return adopt(single);
1335
1369
  }
1336
1370
  if (content.childNodes.length === 0) {
1337
1371
  throw new Error(`toElement: produced no element
@@ -1341,7 +1375,7 @@ function toElement(jsx) {
1341
1375
  throw new Error(`toElement: produced no element
1342
1376
  input: ${excerpt(html)}`);
1343
1377
  }
1344
- return content;
1378
+ return adopt(content);
1345
1379
  }
1346
1380
 
1347
1381
  export { attr, delegate, delegateCapture, each, morph, mount, toElement };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/attrSelector.ts","../src/delegate.ts","../src/dev-each-warn.ts","../src/each.ts","../src/morph.ts","../src/dev-listener-warn.ts","../src/list-binding.ts","../src/list-reconcile-fast-paths.ts","../src/list-reconcile-focus.ts","../src/utils/rowContract.ts","../src/list-reconcile-granular.ts","../src/list-reconcile-snapshot.ts","../src/list-reconcile.ts","../src/mount.ts","../src/toElement.ts"],"names":["attr","isOptedIn","TEXT_NODE","ELEMENT_NODE","isUserAgentOwnedAttr"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `attr(name, value)` — create a pre-computed attribute descriptor (static form).\n * `attr(name)` — create a per-render factory for dynamic attribute values (dynamic form).\n *\n * **Static form** — best for fixed action names, filter keys, role values, etc.\n * Escapes once at module-load time; produces a full {@link AttrSpec} with\n * `.name`, `.value`, `.selector`, and `.attrs`.\n *\n * const ACTIONS = {\n * toggle: attr('data-action', 'toggle'),\n * remove: attr('data-action', 'remove'),\n * } as const satisfies Record<string, AttrSpec<'data-action'>>;\n *\n * // In JSX — spread .attrs (rename-safe; no hardcoded attribute name):\n * <button {...ACTIONS.toggle.attrs}>Toggle</button>\n *\n * // In delegate — use the pre-computed selector:\n * delegate(root, 'click', ACTIONS.toggle.selector, handler);\n *\n * **Dynamic form** — best for per-row data like `data-id`, where the value\n * changes per item but the attribute name is constant.\n * The name is validated and pre-escaped at definition time; calling the\n * returned factory is cheap (just escape the value and freeze the object).\n *\n * const ITEM = { id: attr('data-id') } as const;\n *\n * // In JSX — call the factory inline:\n * <li {...ITEM.id(String(item.id))}>…</li>\n *\n * For ad-hoc compound selectors, concatenate `.selector` strings:\n *\n * delegate(root, 'click',\n * ACTIONS.toggle.selector + attr('data-id', id).selector,\n * handler);\n *\n * Escaping:\n * - Attribute name: escaped as a CSS identifier via `cssEscapeIdent`, which is\n * an SSR-safe (no `CSS.escape`) adaptation of the Mathias Bynens polyfill\n * (https://github.com/nicktindall/cyclon.p2p-common, MIT licensed). Handles\n * control chars, leading digits, non-ASCII, and CSS metacharacters.\n * - Attribute value: embedded in double quotes as a CSS string. Backslashes and\n * double-quote characters are backslash-escaped; control characters are\n * hex-escaped per CSS Syntax Level 3 §3.4.\n *\n * Throws on an empty attribute name (not a valid CSS identifier).\n */\n\n/** Descriptor created by the static {@link attr} overload. */\nexport interface AttrSpec<N extends string = string, V extends string = string> {\n /** The raw attribute name passed to `attr()`. */\n readonly name: N;\n /** The raw attribute value passed to `attr()`. */\n readonly value: V;\n /** Pre-computed `[name=\"value\"]` CSS selector string, safe to pass to `delegate()`. */\n readonly selector: string;\n /** Spreadable JSX object — `{ [name]: value }` — keeps the attribute name out of JSX literals. */\n readonly attrs: { readonly [K in N]: V };\n}\n\n/**\n * Escape `value` as a CSS identifier (for attribute names, id fragments, etc.).\n * Adapted from the CSS.escape polyfill by Mathias Bynens (MIT).\n */\nfunction cssEscapeIdent(value: string): string {\n if (value === '') {\n throw new Error('attr: attribute name must not be empty');\n }\n const str = String(value);\n let result = '';\n for (let i = 0; i < str.length; i++) {\n const cp = str.charCodeAt(i);\n const ch = str.charAt(i);\n\n // U+0000 NULL → replacement character\n if (cp === 0x0000) {\n result += '�';\n continue;\n }\n // Control characters and DEL: hex-escape\n if ((cp >= 0x0001 && cp <= 0x001F) || cp === 0x007F) {\n result += '\\\\' + cp.toString(16) + ' ';\n continue;\n }\n // Leading digit: hex-escape to avoid \"-NN\" / \"3px\"-style ambiguity\n if (i === 0 && cp >= 0x0030 && cp <= 0x0039) {\n result += '\\\\' + cp.toString(16) + ' ';\n continue;\n }\n // Second char is a digit when first is '-' (e.g. \"-3foo\"): hex-escape digit\n if (\n i === 1 &&\n cp >= 0x0030 && cp <= 0x0039 &&\n str.charCodeAt(0) === 0x002D\n ) {\n result += '\\\\' + cp.toString(16) + ' ';\n continue;\n }\n // Non-ASCII, safe identifier chars (letters, digits, underscore, hyphen)\n if (\n cp >= 0x0080 ||\n cp === 0x002D || // `-`\n cp === 0x005F || // `_`\n (cp >= 0x0030 && cp <= 0x0039) || // 0-9\n (cp >= 0x0041 && cp <= 0x005A) || // A-Z\n (cp >= 0x0061 && cp <= 0x007A) // a-z\n ) {\n result += ch;\n continue;\n }\n // Everything else: backslash-escape\n result += '\\\\' + ch;\n }\n return result;\n}\n\n/**\n * Escape `value` as a CSS double-quoted string (for attribute values in\n * `[attr=\"value\"]` selectors).\n */\nfunction escapeCSSString(value: string): string {\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const cp = value.charCodeAt(i);\n const ch = value.charAt(i);\n if (cp === 0x0000) {\n result += '�';\n } else if ((cp >= 0x0001 && cp <= 0x001F) || cp === 0x007F) {\n // Control chars: hex-escape\n result += '\\\\' + cp.toString(16) + ' ';\n } else if (cp === 0x005C) {\n // Backslash\n result += '\\\\\\\\';\n } else if (cp === 0x0022) {\n // Double quote (the string delimiter we use)\n result += '\\\\\"';\n } else {\n result += ch;\n }\n }\n return result;\n}\n\n/**\n * Static overload — pre-computes the full descriptor at definition time.\n * Returns an {@link AttrSpec} with `.name`, `.value`, `.selector`, and `.attrs`.\n */\nexport function attr<N extends string, V extends string>(name: N, value: V): AttrSpec<N, V>;\n\n/**\n * Dynamic overload — pre-validates and pre-escapes the attribute name, returns a\n * factory that accepts a per-render value and produces a frozen spreadable object.\n * Use for per-row attributes like `data-id` where the value changes per item.\n * The optional `V` generic constrains which values the factory accepts:\n * `attr<'data-id', 'a'|'b'>('data-id')` → `(value: 'a'|'b') => { 'data-id': 'a'|'b' }`.\n * Leaving both generics off infers `N` from the argument and defaults `V` to `string`.\n */\nexport function attr<N extends string, V extends string = string>(name: N): (value: V) => { readonly [K in N]: V };\n\nexport function attr<N extends string, V extends string>(\n name: N,\n value?: V,\n): AttrSpec<N, V> | ((value: string) => { readonly [K in N]: string }) {\n const escapedName = cssEscapeIdent(name); // validates + pre-escapes name in both paths\n if (value !== undefined) {\n const selector = `[${escapedName}=\"${escapeCSSString(value)}\"]`;\n return Object.freeze({\n name,\n value,\n selector,\n attrs: Object.freeze({ [name]: value }) as { readonly [K in N]: V },\n }) as AttrSpec<N, V>;\n }\n return (v: string): { readonly [K in N]: string } =>\n Object.freeze({ [name]: v }) as { readonly [K in N]: string };\n}\n","/**\n * Tiny event-delegation helpers. Replace per-element `addEventListener` calls\n * (which don't survive morph re-renders for nodes the diff creates) with one\n * listener at the morph-root that dispatches via `closest()`.\n *\n * Three-tier listener model:\n *\n * - Tier 1 (bubbling events) — use `delegate()`.\n * click, input, change, submit, mousedown/up, keydown/up, pointerdown/up/move,\n * drag*, drop, contextmenu, wheel, copy/paste/cut, focusin/focusout.\n *\n * `delegate()` also auto-promotes the well-known non-bubbling event\n * types (`focus`, `blur`, `scroll`, `load`, `error`, `mouseenter`,\n * `mouseleave`) to the capture phase under the hood, so the call site\n * looks identical for \"interactive thing happens on a descendant\"\n * regardless of whether that event bubbles. Selector matching stays\n * `closest()`-style — the same as for bubbling events — so a wrapper\n * selector like `'.field-row'` still matches when the event fires on\n * a descendant `<input>`.\n *\n * - Tier 2 (explicit capture) — use `delegateCapture()`.\n * The escape hatch for cases the auto-promotion list doesn't cover, or\n * when you want capture-phase semantics and direct `matches()`-style\n * selector matching (no walk-up).\n *\n * - Tier 3 (per-element instances / library-owned subtrees) — mark the\n * host element with `data-morph-skip` and manage the library's\n * lifecycle directly. No delegation helper applies.\n */\n\nimport { warnIfInsideEffect } from './dev-delegate-warn.js';\n\n/**\n * Event types that don't bubble and so wouldn't reach a root-level\n * bubble-phase listener. `delegate()` flips to capture for these; the\n * caller doesn't need to know or care.\n *\n * Membership is conservative — it covers the cases that \"should obviously\n * work\" with delegate() but otherwise don't. For exotic non-bubbling events\n * (custom events, less-common DOM events) the explicit `delegateCapture()`\n * remains the escape hatch.\n */\nconst NON_BUBBLING = new Set<string>([\n 'focus',\n 'blur',\n 'scroll',\n 'load',\n 'error',\n 'mouseenter',\n 'mouseleave',\n]);\n\n/**\n * Validate a CSS selector at registration time, so a typo throws immediately\n * with the bad selector quoted instead of producing a cryptic DOMException\n * the first time a matching event fires.\n */\nfunction assertValidSelector(selector: string, fn: string): void {\n try {\n document.createElement('div').matches(selector);\n } catch {\n throw new Error(\n `${fn}: invalid selector \"${selector}\". `\n + 'Pass a valid CSS selector (e.g. \\'[data-action=\"add\"]\\', \\'.btn\\', \\'input\\').',\n );\n }\n}\n\n/**\n * Delegation that \"just works\" for both bubbling and the common non-bubbling\n * events. Installs ONE listener on `rootEl`; for known non-bubblers (see\n * `NON_BUBBLING` above) the listener is registered on the capture phase so\n * it actually reaches the target, otherwise on the bubble phase. Either way,\n * matching walks up from `event.target` via `closest(selector)` and fires\n * `handler(event, matched)` if the match is inside `rootEl`.\n *\n * The generic `T` narrows the second handler argument to the expected element\n * type — `delegate<HTMLButtonElement>(root, 'click', 'button', (e, btn) => btn.value)`\n * — so consumers can avoid casts. Defaults to `Element` for untyped calls.\n *\n * Returns a disposer that removes the listener.\n *\n * Usage (pseudo-code — see examples for live ones):\n * delegate(rootEl, 'click', '[data-action=\"add\"]', handlerFn);\n * delegate(rootEl, 'focus', 'input', handlerFn); // auto-capture\n */\nexport function delegate<T extends Element = Element>(\n rootEl: HTMLElement,\n type: string,\n selector: string,\n handler: (event: Event, target: T) => void,\n): () => void {\n assertValidSelector(selector, 'delegate');\n warnIfInsideEffect('delegate');\n const listener = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const matched = target.closest(selector);\n if (matched !== null && rootEl.contains(matched)) {\n handler(event, matched as T);\n }\n };\n const capture = NON_BUBBLING.has(type);\n rootEl.addEventListener(type, listener, capture);\n return () => {\n rootEl.removeEventListener(type, listener, capture);\n };\n}\n\n/**\n * Capture-phase delegation — for non-bubbling events (`focus`, `blur`,\n * `scroll`, `load`, `error`). Reaches descendants of `rootEl` that match\n * `selector` regardless of how many times the diff has rebuilt them.\n *\n * The generic `T` narrows the second handler argument to the expected element\n * type, mirroring `delegate<T>()`. Defaults to `Element` for untyped calls.\n *\n * Usage (pseudo-code — see examples for live ones):\n * delegateCapture(rootEl, 'focus', 'input, textarea', handlerFn);\n */\nexport function delegateCapture<T extends Element = Element>(\n rootEl: HTMLElement,\n type: string,\n selector: string,\n handler: (event: Event, target: T) => void,\n): () => void {\n assertValidSelector(selector, 'delegateCapture');\n warnIfInsideEffect('delegateCapture');\n const listener = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n if (target.matches(selector) && rootEl.contains(target)) {\n handler(event, target as T);\n }\n };\n rootEl.addEventListener(type, listener, true);\n return () => {\n rootEl.removeEventListener(type, listener, true);\n };\n}\n","/**\n * Dev-mode warning for `each()` inside `data-morph-skip` subtrees\n * (KERF_DEV_WARN_EACH_IN_MORPH_SKIP=1).\n *\n * When the opt-in env var is set, `mount()` calls `maybeWarnEachInMorphSkip()`\n * after establishing a list binding. The function walks from `liveParent` up to\n * `rootEl`; if any ancestor has `data-morph-skip`, it fires a one-shot warning.\n *\n * Why the pattern matters: `data-morph-skip` makes the morph short-circuit\n * before visiting the element's children, so any static JSX reading signals\n * inside the skipped subtree is silently frozen. `each()` rows are NOT frozen —\n * the keyed reconciler runs independently and still updates them. This asymmetry\n * (rows update, signal-reactive siblings don't) is surprising enough to warrant a\n * dev-time callout.\n *\n * Why opt-in: wrapping a library-owned subtree in `data-morph-skip` and\n * legitimately placing an `each()` inside is uncommon but possible (e.g., the\n * library expects to own the host while kerf manages the list). The opt-in keeps\n * the diagnostic available for projects that want it without penalising projects\n * that intentionally use this pattern.\n */\n\nconst warnedIds = new Set<string>();\n\nfunction isOptedIn(): boolean {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n if (proc?.env?.NODE_ENV === 'production') return false;\n return proc?.env?.KERF_DEV_WARN_EACH_IN_MORPH_SKIP === '1';\n}\n\nfunction hasMorphSkipAncestor(el: Element, root: Element): boolean {\n let ancestor: Element | null = el.parentElement;\n while (ancestor !== null && ancestor !== root) {\n if ((ancestor as HTMLElement).dataset.morphSkip !== undefined) return true;\n ancestor = ancestor.parentElement;\n }\n return false;\n}\n\nexport function maybeWarnEachInMorphSkip(\n id: string,\n liveParent: Element,\n rootEl: Element,\n): void {\n if (!isOptedIn()) return;\n /* c8 ignore next — mount() gates on bindings.has(id) before calling this; doubly-guards direct callers */\n if (warnedIds.has(id)) return;\n if (!hasMorphSkipAncestor(liveParent, rootEl)) return;\n warnedIds.add(id);\n console.warn(\n `kerf: each() list '${id}' is inside a data-morph-skip subtree. `\n + 'The keyed reconciler still updates the list rows, but any static signal-reactive JSX '\n + 'inside the same skipped ancestor (e.g. <p>{count.value}</p>) is frozen — '\n + 'the morph never visits it. Remove data-morph-skip from any element that contains '\n + 'reactive JSX content and reserve it for truly library-owned hosts. '\n + 'Set KERF_DEV_WARN_EACH_IN_MORPH_SKIP=0 (or unset it) to silence this warning.',\n );\n}\n\n/** Test helper — resets the one-shot dedup set for unit tests. */\nexport function _resetWarnedForTests(): void {\n warnedIds.clear();\n}\n\n// ---------------------------------------------------------------------------\n// KERF_DEV_WARN_DUPLICATE_EACH_KEYS — duplicate cacheKey values warning\n// ---------------------------------------------------------------------------\n\nconst warnedDupIds = new Set<string>();\n\nfunction isOptedInDupKeys(): boolean {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n if (proc?.env?.NODE_ENV === 'production') return false;\n return proc?.env?.KERF_DEV_WARN_DUPLICATE_EACH_KEYS === '1';\n}\n\n/**\n * Warn when two or more items in the same `each()` list produce the same\n * `cacheKey` value. Duplicate cacheKey values don't cause incorrect DOM\n * behavior (the per-item HTML cache is keyed by object identity, not cacheKey),\n * but they're a reliable signal that the cacheKey function doesn't uniquely\n * identify rows — which means kerf can't tell apart the affected rows for\n * memoization purposes, and external-state-driven re-renders may return stale\n * cached HTML for some items.\n *\n * Called from `eachSnapshotById` only when a `cacheKey` function was provided.\n * `segItems` carries the already-computed cacheKey value per item, so this\n * function never calls `cacheKey(item, i)` a second time.\n */\nexport function maybeWarnDuplicateCacheKeys(\n id: string,\n segItems: readonly { cacheKey: unknown }[],\n): void {\n if (!isOptedInDupKeys()) return;\n if (warnedDupIds.has(id)) return;\n const seen = new Set<unknown>();\n for (const si of segItems) {\n if (seen.has(si.cacheKey)) {\n warnedDupIds.add(id);\n console.warn(\n `kerf: each() list '${id}' has duplicate cacheKey values (duplicate: ${String(si.cacheKey)}). `\n + 'The cacheKey function should return a unique value per row so kerf can tell apart items '\n + 'for memoization — duplicate values cause some rows to return stale cached HTML when '\n + 'external state that affects their render changes. '\n + 'Set KERF_DEV_WARN_DUPLICATE_EACH_KEYS=0 (or unset it) to silence this warning.',\n );\n return;\n }\n seen.add(si.cacheKey);\n }\n}\n\n/** Test helper — resets the duplicate-key dedup set for unit tests. */\nexport function _resetDupWarnedForTests(): void {\n warnedDupIds.clear();\n}\n","/**\n * `each(items, render, cacheKey?)` — keyed list iteration with per-item memoization.\n *\n * Drops in as the body of a list-rendering JSX expression inside a `mount()`\n * render function. Returns a `SafeHtml` carrying a structured list segment,\n * so `mount()` can run a native keyed reconciler instead of the general-\n * purpose morph for these children.\n *\n * Two layers of optimization:\n *\n * 1. Per-item memoization. `render(item)` is skipped for items whose object\n * identity (and optional `cacheKey`) are unchanged since the previous\n * call. Their HTML strings come from a `WeakMap` keyed by item reference.\n * The immutable-update style (\"replace the row object\" instead of \"mutate\n * it\") makes the cache work automatically.\n *\n * 2. Structural handoff. `mount()` recognizes the list segment and bypasses\n * the parse-the-whole-table round trip: only fresh items get parsed (one\n * at a time, into the smallest detached element), and only changed rows\n * get patched in the live DOM. Unchanged rows are physically the same\n * nodes they were before — never visited.\n *\n * `cacheKey` is a passive comparator — it covers the case where external\n * state, not the item itself, drives what the row should render (e.g. a\n * \"currently selected\" id flips a CSS class on one row). Same item identity\n * but a different `cacheKey` return value means \"the cached HTML is stale —\n * re-render this row.\" Not a reactive subscription: it's evaluated once per\n * mount-effect run and compared against the previous run's return value. If\n * you don't pass `cacheKey`, only object-identity changes invalidate the\n * cache. (Renamed from `key` for clarity — it shared a name with React's\n * `key` prop but has different semantics; the new name says what the\n * parameter actually does. Positional callers — the canonical form — are\n * unaffected.)\n *\n * Items must be objects (cache is a `WeakMap`); wrap primitives if you need\n * to iterate them. Each item's render output must produce exactly one\n * top-level element — the list reconciler binds one live DOM node per item.\n */\n\nimport type { ArraySignal } from './array-signal.js';\nimport { maybeWarnDuplicateCacheKeys } from './dev-each-warn.js';\nimport type { SafeHtml } from './jsx-runtime.js';\nimport { granularListSafeHtml, isSafeHtml, listSafeHtml } from './jsx-runtime.js';\nimport type { ArrayPatchInternal } from './segment.js';\n\n/**\n * Cross-bundle brand check for `ArraySignal` instances (KF-95). The\n * `arraySignal` factory + class live in their own subpath\n * (`kerfjs/array-signal`); this module knows nothing about that\n * subpath at runtime — it identifies instances by the brand symbol\n * stamped on them. Apps that never import `arraySignal` shed the\n * ~1 KB of class code without breaking the structural contract here.\n */\nconst ARRAY_SIGNAL_BRAND = Symbol.for('kerfjs.ArraySignal');\n\nfunction isArraySignal<T extends object>(value: unknown): value is ArraySignal<T> {\n return typeof value === 'object'\n && value !== null\n && (value as Record<symbol, unknown>)[ARRAY_SIGNAL_BRAND] === true;\n}\n\ninterface CacheEntry {\n cacheKey: unknown;\n html: string;\n}\n\n/**\n * Per-render context passed in by `mount()` for the duration of one render\n * pass. Carries (a) a counter that assigns a stable list id to the n-th\n * `each()` call across renders within a mount, and (b) a per-mount cache map\n * keyed on those list ids.\n *\n * Why per-(mount, listId) keying for the cache:\n * - Same `each()` callsite across renders within a mount → same id → same\n * cache → cache hits work, even when the JSX render fn is an inline arrow\n * that's a fresh function reference on every closure run (the typical\n * pattern; KF-87 fixed the regression where this broke).\n * - Different `each()` callsites within the same mount → different ids →\n * separate caches → no cross-callsite collision (the case KF-73 fixed,\n * preserved here).\n * - Different mounts → different `RenderContext` instances (the cache map\n * lives on `mount()`'s closure) → separate caches.\n *\n * Outside a `mount()` render (e.g. `each(...).toString()` for SSR string\n * production) `context` is null and items are rendered every call —\n * caching is a `mount()` feature, not a global one.\n */\nexport interface RenderContext {\n counter: number;\n caches: Map<string, WeakMap<object, CacheEntry>>;\n /**\n * Per-list-id record of the binding's `items.length` after the most recent\n * successful reconcile. Maintained by `mount()` via `_setBindingCount`. The\n * granular path consults this to detect drift between the live binding and\n * the arraySignal — drift means a previous render threw mid-reconcile (or\n * a granular path was bypassed externally), so the next render forces a\n * snapshot rebuild rather than applying patches against a stale binding.\n */\n bindingCounts: Map<string, number>;\n}\n\nlet context: RenderContext | null = null;\n\nexport function _setRenderContext(c: RenderContext | null): void {\n context = c;\n}\n\nexport function each<T extends object>(\n items: readonly T[] | ArraySignal<T>,\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey?: (item: T, index: number) => unknown,\n): SafeHtml {\n // KF-92 fast path: when items is an ArraySignal AND we're inside a mount\n // render context AND patches have queued since the last drain, emit a\n // granular list segment that the list reconciler applies in O(patches)\n // instead of O(N). Detection via the brand symbol (KF-95) — the\n // `arraySignal` class lives in the `kerfjs/array-signal` subpath and is\n // not imported here at runtime.\n if (isArraySignal<T>(items) && context !== null) {\n return eachGranular(items, render, cacheKey);\n }\n const snapshotItems: readonly T[] = isArraySignal<T>(items)\n ? items.value as readonly T[]\n : items;\n return eachSnapshot(snapshotItems, render, cacheKey);\n}\n\nfunction eachSnapshot<T extends object>(\n items: readonly T[],\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey: ((item: T, index: number) => unknown) | undefined,\n): SafeHtml {\n let id: string;\n if (context !== null) {\n id = String(context.counter++);\n } else {\n id = 'orphan';\n }\n return eachSnapshotById(items, render, cacheKey, id);\n}\n\n/**\n * Granular path for `arraySignal`-backed lists. Drains queued patches and\n * emits a list segment that the reconciler applies to the existing binding\n * directly — no full iteration of the snapshot, no O(N) classify pass.\n *\n * On the very first render of a list, the binding doesn't exist yet, so\n * the reconciler falls through to the snapshot path. Subsequent renders\n * of the same list (where the binding now exists) take the granular path\n * whenever there are patches to apply.\n */\nfunction eachGranular<T extends object>(\n sig: ArraySignal<T>,\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey: ((item: T, index: number) => unknown) | undefined,\n): SafeHtml {\n // We're inside a mount context (caller-checked).\n const ctx = context as RenderContext;\n const id = String(ctx.counter++);\n // KF-98: a tracked binding count means a prior render of this mount has\n // successfully reconciled this list. On the very first render (no count\n // recorded yet) the granular reconciler has no binding to apply patches\n // to, so any pre-mount mutations would silently produce an empty list.\n // Drain the queue (the snapshot already reflects those mutations) and\n // take the snapshot path; the count will be recorded for the next render.\n const previousBindingCount = ctx.bindingCounts.get(id);\n const patches = sig._consumePatches();\n const snapshot = sig.value as readonly T[];\n\n // First render of this list, no patches, or any 'replace' patch → snapshot.\n // No patches: typical re-render triggered by a non-arraySignal signal change.\n // 'replace': wholesale reset — granular can't help; the snapshot already\n // reflects the post-replace state (and any subsequent granular ops).\n if (previousBindingCount === undefined || patches.length === 0) {\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n // KF-99: detect drift between the live binding and the arraySignal. After\n // a clean prior reconcile, `previousBindingCount + (#inserts - #removes)`\n // must equal `snapshot.length`. If it doesn't, a previous render threw\n // mid-reconcile and left the binding inconsistent with the signal — fall\n // back to the snapshot path, which classifies fresh against `snapshot`\n // and rebuilds the binding to match.\n let netDelta = 0;\n for (const p of patches) {\n if (p.type === 'insert') netDelta += 1;\n else if (p.type === 'remove') netDelta -= 1;\n else if (p.type === 'replace') {\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n }\n // Defensive: triggered only when an external party drains `_consumePatches()`\n // or mutates `_items` behind arraySignal's back, OR when a previous reconcile\n // threw mid-DOM-op (rare; not naturally reachable in tests since apply* ops\n // don't throw on well-formed row HTML).\n /* c8 ignore next 3 */\n if (previousBindingCount + netDelta !== snapshot.length) {\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n\n // Granular path: pre-render every insert/update HTML at JSX-eval time so\n // a throwing render is caught here and we can fall back to the snapshot\n // path (KF-99). Without this, a throw mid-batch would leave patches drained\n // (already done above), the signal mutated, and the live DOM unchanged —\n // permanent divergence with no recovery.\n const renderFnInternal = (item: object, index: number): string => {\n const out = render(item as T, index);\n return isSafeHtml(out) ? out.toString() : out;\n };\n const internalPatches = new Array<ArrayPatchInternal>(patches.length);\n try {\n for (let i = 0; i < patches.length; i++) {\n const p = patches[i];\n if (p.type === 'insert' || p.type === 'update') {\n internalPatches[i] = {\n type: p.type, index: p.index, item: p.item as object,\n html: renderFnInternal(p.item as object, p.index),\n };\n } else {\n internalPatches[i] = p as ArrayPatchInternal;\n }\n }\n } catch {\n // Pre-render threw. The snapshot already reflects every mutation\n // (arraySignal mutates _items eagerly at the call site), but the snapshot\n // path is going to throw on the same bad item too — leaving the binding\n // out of sync with the signal. Clear the binding count so the NEXT\n // render (after the user fixes the bad item) doesn't see the previous\n // render's count and falsely conclude there's no drift; instead it'll\n // take the snapshot path and rebuild from scratch.\n ctx.bindingCounts.delete(id);\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n // The `items` field is left empty for the granular case — the reconciler\n // doesn't need it; every insert/update patch carries pre-rendered HTML.\n return granularListSafeHtml(id, [], internalPatches);\n}\n\n/** Like eachSnapshot but uses a pre-allocated id (caller already advanced the counter). */\nfunction eachSnapshotById<T extends object>(\n items: readonly T[],\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey: ((item: T, index: number) => unknown) | undefined,\n id: string,\n): SafeHtml {\n let cache: WeakMap<object, CacheEntry> | null = null;\n if (context !== null) {\n let c = context.caches.get(id);\n if (c === undefined) {\n c = new WeakMap<object, CacheEntry>();\n context.caches.set(id, c);\n }\n cache = c;\n }\n const segItems = new Array<{ ref: object; cacheKey: unknown; html: string }>(items.length);\n const seen = new Set<object>();\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (typeof item !== 'object' || item === null) {\n throw new Error(\n `each(): items must be objects (the per-item HTML cache is a WeakMap), got ${item === null ? 'null' : typeof item} at index ${i}. `\n + 'Wrap primitives if you need to iterate them, e.g. items.map(v => ({ v })).',\n );\n }\n if (seen.has(item)) {\n throw new Error(\n `each(): the same object reference appears at multiple indices in items (first seen earlier, again at index ${i}). `\n + 'The per-item HTML cache is keyed on object identity, so duplicate references break the keyed reconciler and can leak DOM nodes on re-render. '\n + 'Use a fresh object per row (e.g. items.map(o => ({ ...o })) before passing to each()).',\n );\n }\n seen.add(item);\n const k = cacheKey ? cacheKey(item, i) : undefined;\n let html: string;\n const cached = cache !== null ? cache.get(item) : undefined;\n if (cached !== undefined && cached.cacheKey === k) {\n html = cached.html;\n } else {\n const out = render(item, i);\n html = isSafeHtml(out) ? out.toString() : out;\n if (cache !== null) cache.set(item, { cacheKey: k, html });\n }\n segItems[i] = { ref: item, cacheKey: k, html };\n }\n if (cacheKey !== undefined) {\n maybeWarnDuplicateCacheKeys(id, segItems);\n }\n return listSafeHtml(id, segItems);\n}\n","/**\n * `morph(liveRoot, template)` — minimum-mutation DOM reconciliation.\n *\n * Public primitive (KF-150): one-shot reconciliation against an\n * already-populated element. `mount()` first paints by writing\n * `innerHTML`; `morph()` is the \"I have a live tree and a template,\n * reconcile them in place\" sibling. Use it for SSR hydration of static\n * fragments, page-refresh diffs, third-party widget remounts, etc.\n *\n * Replaces our previous dependency on `morphdom`. The algorithm is the\n * classic two-tree walk: match children by key (id, then data-key, then\n * positional same-tag), morph matches in place, insert / remove / clone\n * the rest. Specialized for what kerf needs:\n *\n * - `childrenOnly` is always true; the live root is never replaced.\n * - Per-element short-circuits: `data-morph-skip` (library-owned, leave\n * element AND subtree verbatim), `data-morph-skip-children` (KF-152 —\n * morph attrs on the element, leave its subtree verbatim — for\n * client-hydrated slots whose loading/state classes still need to flow\n * through), and `isEqualNode` (byte-identical, no work needed).\n * - **`data-morph-preserve`** (KF-151) is honored in the trailing-removal\n * pass: an unmatched live element with this attribute is skipped instead\n * of removed. Lets imperatively-injected nodes (autoplay `<video>`s,\n * tour-widget tooltips, analytics pixels) survive across renders without\n * having to `data-morph-skip` the entire parent.\n * - **`ownedItems`** is the set of element nodes owned by an `each()`\n * list reconciler. The morph skips them in every children walk —\n * they're not added to the keyed-lookup map, the from-cursor advances\n * past them, and the trailing-removal pass leaves them in place. This\n * lets each() coexist with non-list siblings inside the same parent\n * (KF-102 round 2): the morph still walks the parent's children to\n * reconcile siblings, but never disturbs list rows. The parameter is an\n * internal coordination channel between `mount()` and the reconciler;\n * public callers should omit it (the default empty set is correct for\n * any tree that isn't being managed by an active `mount()`).\n * - Focused text inputs (`<input>`/`<textarea>`) keep their value +\n * selection across the morph; focused `[contenteditable]` keeps its\n * entire subtree (typed content + caret + multi-range selection).\n *\n * Algorithm credit: based on the design of\n * https://github.com/patrick-steele-idem/morphdom by Patrick Steele-Idem\n * (MIT licensed). Reimplemented here so kerf can specialize the hot paths\n * (segment-aware list dispatch, lighter callback surface) and drop the\n * runtime dependency. Original copyright preserved in `LICENSE`.\n */\n\nimport type { SafeHtml } from './jsx-runtime.js';\n\nconst ID_KEY_PREFIX = 'id:';\nconst DATA_KEY_PREFIX = 'data-key:';\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\nfunction getNodeKey(node: Node): string | undefined {\n if (node.nodeType !== ELEMENT_NODE) return undefined;\n const el = node as HTMLElement;\n if (el.id !== '') return `${ID_KEY_PREFIX}${el.id}`;\n if (el.dataset !== undefined && el.dataset.key !== undefined) {\n return `${DATA_KEY_PREFIX}${el.dataset.key}`;\n }\n return undefined;\n}\n\nconst EMPTY_OWNED: ReadonlySet<Element> = new Set();\n\n/**\n * Reconcile the children of `liveRoot` to match `template`.\n *\n * `template` can be an `Element` (used directly), a `SafeHtml`, or a raw\n * HTML string — the latter two are stringified and parsed into a transient\n * element whose tag matches `liveRoot`. The active text-entry / focused-\n * contenteditable preservation rules apply in all cases.\n *\n * `ownedItems` is an internal coordination channel for `mount()`'s list\n * reconciler; public callers should omit it.\n */\nexport function morph(\n liveRoot: Element,\n template: Element | SafeHtml | string,\n ownedItems: ReadonlySet<Element> = EMPTY_OWNED,\n): void {\n const templateEl: Element = isElementNode(template)\n ? template\n : parseTemplate(liveRoot, template);\n morphChildren(liveRoot, templateEl, ownedItems);\n}\n\n/**\n * Internal: morph `fromEl` to match `toEl` including the element's own\n * attributes (which the public `morph()` does NOT touch — it only morphs\n * children of the live root). Used by `list-reconcile-granular.ts` to apply\n * an `update` patch in place via attribute + child morphing instead of\n * `replaceChild` discarding the whole subtree. Same short-circuits as\n * `morph()`: `data-morph-skip`, `data-morph-skip-children`, `isEqualNode`,\n * focused contenteditable / text-entry preservation. Tag mismatch falls\n * through to the same parent.replaceChild fallback the public API uses.\n *\n * Underscore-prefixed export (not part of the public API surface). Public\n * callers should use `morph(liveRoot, template)`.\n */\nexport function _morphElement(\n fromEl: Element,\n toEl: Element,\n ownedItems: ReadonlySet<Element> = EMPTY_OWNED,\n): void {\n morphElement(fromEl, toEl, ownedItems);\n}\n\nfunction isElementNode(t: Element | SafeHtml | string): t is Element {\n return typeof t === 'object' && t !== null\n && (t as Node).nodeType === ELEMENT_NODE;\n}\n\nfunction parseTemplate(liveRoot: Element, template: SafeHtml | string): Element {\n const el = liveRoot.cloneNode(false) as Element;\n el.innerHTML = String(template);\n return el;\n}\n\n/**\n * Advance past any owned (list-reconciler-managed) element. Owned items\n * stay put across morphs — they're invisible to the morph's child cursor.\n */\nfunction skipOwned(node: Node | null, ownedItems: ReadonlySet<Element>): Node | null {\n while (node !== null && node.nodeType === ELEMENT_NODE\n && ownedItems.has(node as Element)) {\n node = node.nextSibling;\n }\n return node;\n}\n\nfunction morphChildren(\n fromParent: Element,\n toParent: Element,\n ownedItems: ReadonlySet<Element>,\n): void {\n // Build a keyed lookup from the live children so we can match by key\n // even after reorders. Owned items don't participate in keyed matching\n // (they're not visible to the morph).\n const keyed = new Map<string, Element>();\n for (let c = fromParent.firstChild; c !== null; c = c.nextSibling) {\n if (c.nodeType === ELEMENT_NODE && ownedItems.has(c as Element)) continue;\n const k = getNodeKey(c);\n if (k !== undefined) keyed.set(k, c as Element);\n }\n\n let fromChild: Node | null = skipOwned(fromParent.firstChild, ownedItems);\n let toChild: Node | null = toParent.firstChild;\n\n while (toChild !== null) {\n const toNext = toChild.nextSibling;\n let matched: Node | null = null;\n\n // 1. Try key match.\n const toKey = getNodeKey(toChild);\n if (toKey !== undefined && keyed.has(toKey)) {\n matched = keyed.get(toKey) as Element;\n keyed.delete(toKey);\n if (matched !== fromChild) {\n fromParent.insertBefore(matched, fromChild);\n } else {\n fromChild = skipOwned(fromChild.nextSibling, ownedItems);\n }\n }\n\n // 2. Fall back to positional match — same nodeType, same tag (for\n // elements), and the live node has no key (a keyed node only\n // matches by key, never positionally, so reorders work).\n if (matched === null && fromChild !== null\n && fromChild.nodeType === toChild.nodeType\n && (toChild.nodeType !== ELEMENT_NODE\n || ((fromChild as Element).tagName === (toChild as Element).tagName\n && getNodeKey(fromChild) === undefined))) {\n matched = fromChild;\n fromChild = skipOwned(fromChild.nextSibling, ownedItems);\n }\n\n if (matched !== null) {\n morphNode(matched, toChild, ownedItems);\n } else {\n // 3. No match — clone the new node and insert before fromChild\n // (which may be an owned item we deliberately stopped at; that's\n // fine — `insertBefore(node, ownedItem)` slots the new sibling\n // in immediately before the list region).\n const cloned = toChild.cloneNode(true);\n fromParent.insertBefore(cloned, fromChild);\n }\n\n toChild = toNext;\n }\n\n // 4. Anything past the cursor is unmatched — remove, except for owned\n // items (those stay; they belong to a list reconciler) and elements\n // marked `data-morph-preserve` (KF-151 — imperatively-injected nodes\n // whose lifetime the consumer manages outside kerf).\n while (fromChild !== null) {\n const next = fromChild.nextSibling;\n if (fromChild.nodeType === ELEMENT_NODE) {\n const el = fromChild as Element;\n if (!ownedItems.has(el)\n && (el as HTMLElement).dataset.morphPreserve === undefined) {\n fromParent.removeChild(fromChild);\n }\n } else {\n fromParent.removeChild(fromChild);\n }\n fromChild = next;\n }\n}\n\nfunction morphNode(\n fromNode: Node,\n toNode: Node,\n ownedItems: ReadonlySet<Element>,\n): void {\n if (fromNode.nodeType === ELEMENT_NODE) {\n morphElement(fromNode as Element, toNode as Element, ownedItems);\n return;\n }\n if (fromNode.nodeType === TEXT_NODE || fromNode.nodeType === COMMENT_NODE) {\n const fromText = fromNode as CharacterData;\n const toText = toNode as CharacterData;\n if (fromText.data !== toText.data) fromText.data = toText.data;\n }\n}\n\nfunction morphElement(\n fromEl: Element,\n toEl: Element,\n ownedItems: ReadonlySet<Element>,\n): void {\n if (fromEl.tagName !== toEl.tagName) {\n const replacement = toEl.cloneNode(true);\n fromEl.parentNode?.replaceChild(replacement, fromEl);\n return;\n }\n // 1. Library-owned subtree — leave verbatim.\n if ((fromEl as HTMLElement).dataset.morphSkip !== undefined) return;\n // 2. Byte-identical — nothing to do.\n if (fromEl.isEqualNode(toEl)) return;\n // 3. Focused contenteditable — preserve user's in-progress edit.\n if (fromEl === document.activeElement) {\n const ce = fromEl.getAttribute('contenteditable');\n if (ce !== null && ce.toLowerCase() !== 'false') return;\n if (isTextInputOrTextarea(fromEl)) preserveTextEntryState(fromEl, toEl);\n }\n morphAttributes(fromEl, toEl);\n // 4. Subtree-only skip (KF-152) — attributes have already morphed; leave\n // the children alone. Use for client-hydrated slots whose loading /\n // state classes still need to flow through.\n if ((fromEl as HTMLElement).dataset.morphSkipChildren !== undefined) return;\n // 5. Recurse into children. List items inside `fromEl` (if any) are\n // skipped via `ownedItems` inside morphChildren — list reconciler\n // owns them — but non-list siblings are still morphed.\n morphChildren(fromEl, toEl, ownedItems);\n}\n\n/**\n * Attributes the user agent toggles in response to user interaction.\n * `<details>` and `<dialog>` add/remove `open=\"\"` themselves when the user\n * expands or closes the element. If the developer's JSX never mentions\n * `open`, treating that attribute as user-agent-owned and leaving it alone\n * during the morph keeps the user-driven state intact across re-renders.\n *\n * Trade-off (KF-84): controlled-style `<details open={signal.value}>` where\n * the signal flips false won't auto-collapse the element, because the\n * morph's remove pass no longer reaches `open`. Apps that need controlled\n * behavior should drive `open` imperatively (e.g. `el.removeAttribute('open')`\n * inside an action) or wrap with a state-toggle pattern. The uncontrolled\n * case is the common one and the one that was silently broken before.\n */\nfunction isUserAgentOwnedAttr(tagName: string, name: string): boolean {\n return name === 'open' && (tagName === 'DETAILS' || tagName === 'DIALOG');\n}\n\nfunction morphAttributes(fromEl: Element, toEl: Element): void {\n // Set/update every attribute on toEl.\n const toAttrs = toEl.attributes;\n for (let i = 0; i < toAttrs.length; i++) {\n const attr = toAttrs[i];\n const ns = attr.namespaceURI;\n const name = attr.localName;\n const value = attr.value;\n if (ns !== null) {\n if (fromEl.getAttributeNS(ns, name) !== value) {\n fromEl.setAttributeNS(ns, attr.name, value);\n }\n } else if (fromEl.getAttribute(name) !== value) {\n fromEl.setAttribute(name, value);\n }\n }\n // Remove attributes that are no longer present on toEl.\n const fromAttrs = fromEl.attributes;\n const fromTag = fromEl.tagName;\n for (let i = fromAttrs.length - 1; i >= 0; i--) {\n const attr = fromAttrs[i];\n const ns = attr.namespaceURI;\n const name = attr.localName;\n if (ns !== null) {\n if (!toEl.hasAttributeNS(ns, name)) fromEl.removeAttributeNS(ns, name);\n } else if (!toEl.hasAttribute(name) && !isUserAgentOwnedAttr(fromTag, name)) {\n fromEl.removeAttribute(name);\n }\n }\n}\n\nfunction isTextInputOrTextarea(el: Element): boolean {\n if (el.tagName === 'TEXTAREA') return true;\n if (el.tagName === 'INPUT') {\n const type = (el as HTMLInputElement).type;\n return type === 'text' || type === 'search' || type === 'url' || type === 'email'\n || type === 'tel' || type === 'password' || type === '';\n }\n return false;\n}\n\nfunction preserveTextEntryState(fromEl: Element, toEl: Element): void {\n if (fromEl.tagName === 'TEXTAREA' || fromEl.tagName === 'INPUT') {\n const fromInput = fromEl as HTMLInputElement;\n const toInput = toEl as HTMLInputElement;\n toInput.value = fromInput.value;\n try {\n toInput.setSelectionRange(fromInput.selectionStart, fromInput.selectionEnd);\n } catch {\n // Some input types (number, range, color, …) reject selection APIs.\n }\n }\n}\n","/**\n * Dev-mode warning for Rule 4 violations (KF-174). When the opt-in env var\n * `KERF_DEV_WARN_REBUILT_LISTENERS=1` is set in a non-production build,\n * `mount()` calls `installListenerRebuildWarn()` to set up two things:\n *\n * 1. A global one-time monkey-patch on `EventTarget.prototype.addEventListener`\n * that marks the `Element` receiver with a `Symbol.for(\"kerfjs.devListener\")`\n * flag. The patch is idempotent across mounts.\n *\n * 2. A `MutationObserver` on the mount root, scoped to `{ childList: true,\n * subtree: true }`. When a removed Element (or any descendant of a\n * removed subtree) carries the marker, the observer emits a one-shot\n * `console.warn` pointing at `delegate()` and `data-morph-skip` as the\n * canonical fixes.\n *\n * Why opt-in: the heuristic catches every imperative `addEventListener` whose\n * receiver is later removed from the live tree, including some legitimate\n * patterns (custom elements that attach listeners in their constructor,\n * third-party widgets the user forgot to wrap in `data-morph-skip`, library\n * teardown code that detaches a node it owns). The warning is opt-in so\n * existing projects aren't surprised; CI / dev environments that want the\n * diagnostic enable the env var.\n *\n * The MutationObserver delivers mutations asynchronously (microtask after the\n * morph), so the warning fires AFTER the bad re-render rather than at the\n * call to `addEventListener`. That's why the diagnostic-error audit scores\n * Rule 4 at 2 with the opt-in (not 3) — the model sees the warning paired\n * with the broken listener, not at the read site.\n *\n * Production behavior is unchanged for zero runtime cost.\n */\n\nconst LISTENER_MARKER = Symbol.for('kerfjs.devListener');\n\nlet patched = false;\nlet warned = false;\n\nfunction isOptedIn(): boolean {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n if (proc?.env?.NODE_ENV === 'production') return false;\n return proc?.env?.KERF_DEV_WARN_REBUILT_LISTENERS === '1';\n}\n\ntype ElementProto = { addEventListener: (type: string, listener: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean) => void };\n\nfunction findAddEventListenerProto(): ElementProto {\n // Walk a probe Element's prototype chain to find the prototype that\n // actually owns `addEventListener`. In real browsers this is\n // `EventTarget.prototype`; in test environments (happy-dom) the realm's\n // EventTarget can differ from `globalThis.EventTarget`, so we have to\n // resolve via a live DOM node rather than the global symbol. Every Element\n // extends EventTarget which owns `addEventListener`, so the walk always\n // succeeds before falling off the end of the chain.\n const probe = document.createElement('div');\n let proto: object = Object.getPrototypeOf(probe) as object;\n while (!Object.prototype.hasOwnProperty.call(proto, 'addEventListener')) {\n proto = Object.getPrototypeOf(proto) as object;\n }\n return proto as unknown as ElementProto;\n}\n\nfunction patchAddEventListenerOnce(): void {\n if (patched) return;\n patched = true;\n const proto = findAddEventListenerProto();\n const orig = proto.addEventListener;\n proto.addEventListener = function (\n this: EventTarget,\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: AddEventListenerOptions | boolean,\n ): void {\n // Only mark Element receivers — Document, Window, AbortSignal etc. are\n // valid addEventListener receivers but are never in a mount tree.\n if (this instanceof Element) {\n (this as unknown as Record<symbol, boolean>)[LISTENER_MARKER] = true;\n }\n return orig.call(this, type, listener, options);\n };\n}\n\nfunction hasMarkedListener(el: Element): boolean {\n if ((el as unknown as Record<symbol, boolean>)[LISTENER_MARKER] === true) return true;\n // Walk descendants — when the morph removes a whole subtree, only the root\n // appears in the MutationRecord's removedNodes; an imperative listener on a\n // grandchild would otherwise be invisible.\n const stack: Element[] = [];\n for (let i = 0; i < el.children.length; i++) stack.push(el.children[i]);\n while (stack.length > 0) {\n const cur = stack.pop() as Element;\n if ((cur as unknown as Record<symbol, boolean>)[LISTENER_MARKER] === true) return true;\n for (let i = 0; i < cur.children.length; i++) stack.push(cur.children[i]);\n }\n return false;\n}\n\nfunction emitWarning(): void {\n /* c8 ignore next — paired with the observer's own one-shot check; doubly-guards against re-entry under engines that batch mutations across microtasks */\n if (warned) return;\n warned = true;\n console.warn(\n 'kerf: a node inside a mount()-managed tree was removed/rebuilt while carrying an imperative addEventListener listener. '\n + 'The listener is gone with the old node. Use `delegate(rootEl, \\'click\\', \\'[data-action=\"...\"]\\', handler)` '\n + 'so the listener lives on a stable ancestor and survives re-renders, or wrap the host in `data-morph-skip` if '\n + 'the subtree is library-owned (Monaco, xterm, D3 charts). '\n + 'Set KERF_DEV_WARN_REBUILT_LISTENERS=0 (or unset it) to silence this warning.',\n );\n}\n\nexport function installListenerRebuildWarn(rootEl: Element): MutationObserver | null {\n if (!isOptedIn()) return null;\n patchAddEventListenerOnce();\n const observer = new MutationObserver((mutations) => {\n if (warned) return;\n for (const m of mutations) {\n for (let i = 0; i < m.removedNodes.length; i++) {\n const removed = m.removedNodes[i];\n /* c8 ignore next — text/comment-node removals from morph; never carry the addEventListener marker but we filter to keep the Element-only contract explicit */\n if (!(removed instanceof Element)) continue;\n if (hasMarkedListener(removed)) {\n emitWarning();\n return;\n }\n }\n }\n });\n observer.observe(rootEl, { childList: true, subtree: true });\n return observer;\n}\n\n/**\n * Test helper — resets the one-shot `warned` flag so a subsequent test in the\n * same module can re-exercise the first-warning path. Not exported from the\n * public barrel; the unit-test file imports it directly via the relative path.\n */\nexport function _resetWarnedForTests(): void {\n warned = false;\n}\n","/**\n * Per-list binding shape kept by `mount()` and consumed by both reconcile\n * paths in `list-reconcile-snapshot.ts` and `list-reconcile-granular.ts`.\n *\n * Living in its own file (not re-exported through `list-reconcile.ts`) so\n * the snapshot + granular paths can import it without creating a circular\n * dependency on `list-reconcile.ts` itself. ESM handles cycles via function\n * hoisting, but a cycle involving a non-function helper would be a temporal\n * dead zone — extracting the binding shape + `endAnchor` here keeps the\n * dependency graph acyclic.\n */\n\nexport interface BoundItem {\n ref: object;\n cacheKey: unknown;\n html: string;\n node: Element;\n}\n\nexport interface ListBinding {\n liveParent: Element;\n /**\n * One entry per item currently mounted under `liveParent`, in order.\n * Mirrors the segment's `items` length after each reconcile.\n */\n items: BoundItem[];\n /**\n * The list's `<!--kf-list:N-->` start marker, kept in the live DOM as\n * a permanent anchor (KF-102 round 2). The marker stays put across\n * static-surrounds diffs (it morphs as a comment node), so it gives\n * the list reconciler a stable \"begin\" position even when surrounding\n * siblings get inserted, removed, or reordered around the list.\n *\n * `endAnchor(binding)` derives the \"insert at end of list\" anchor from\n * `marker.nextElementSibling` (empty list) or\n * `items[last].node.nextElementSibling` (non-empty list) — picking up\n * any non-list element the diff inserted between the list and the\n * parent's tail.\n */\n marker: Comment;\n /**\n * KF-173: once we've emitted the missing-key dev warning for this list,\n * we suppress further warnings for the same binding. The flag is set\n * inside `maybeWarnMissingRowKey()` and never cleared — the list is\n * considered \"decided\" after the first row check.\n */\n warnedMissingKey?: boolean;\n}\n\n/**\n * Compute the live-DOM anchor that comes after the list's last item, used\n * by the apply* functions when inserting at the tail of the list.\n *\n * - Empty list: `marker.nextElementSibling` — the next non-list element\n * after the marker, or `null` if the list is the last thing in `liveParent`.\n * - Non-empty list: `items[last].node.nextElementSibling` — derived\n * dynamically so that non-list siblings the diff inserted between the\n * list's last item and the parent's tail still anchor correctly.\n */\nexport function endAnchor(binding: ListBinding): Element | null {\n if (binding.items.length > 0) {\n return binding.items[binding.items.length - 1].node.nextElementSibling;\n }\n return binding.marker.nextElementSibling;\n}\n","/**\n * Fast paths for the granular update reconciler (KF-198 + KF-206).\n *\n * Two heuristics that catch common arraySignal-update shapes before the\n * standard parse + morph path runs and apply the change directly to the\n * live row:\n *\n * - **Attribute-only (KF-198)**: when the only diff between old and new\n * row HTML is in the top-level element's attribute values, call\n * setAttribute / removeAttribute on the live node. Targets the krausest\n * select-row scenario where 2 updates flip `class=\"\"` ↔ `class=\"danger\"`\n * on a `<tr>` with otherwise identical 4-child subtree. Skips parse +\n * morph entirely.\n *\n * - **Text-content-only (KF-206)**: when the only diff is inside one text\n * node's content (no entity touching, no structural or attribute\n * change), patch that text node's nodeValue. Targets the krausest\n * partial-update scenario where 100 updates each rewrite one label\n * text node deep inside the row.\n *\n * Both fast paths bail conservatively on anything that could go wrong —\n * namespaced attributes (`xmlns:*` etc.), `data-morph-skip` anywhere in the\n * row, user-agent-owned attributes (`<details open>`), entity-touching\n * diffs — and the granular path falls back to `_morphElement` or\n * `replaceChild`. The sanity check at the end of the text-content path\n * (live text node's nodeValue must equal what we extracted from oldHtml)\n * is the final safety net: if anything has drifted, we bail.\n *\n * Internal to kerf.\n */\n\nconst LT = 0x3C; // <\nconst GT = 0x3E; // >\nconst DQUOTE = 0x22; // \"\nconst SQUOTE = 0x27; // '\nconst AMP = 0x26; // &\nconst EQ = 0x3D; // =\nconst SLASH = 0x2F; // /\nconst TEXT_NODE = 3;\nconst ELEMENT_NODE = 1;\n\nfunction isWhitespace(cc: number): boolean {\n return cc === 0x20 || cc === 0x09 || cc === 0x0A || cc === 0x0D;\n}\n\ninterface ParsedTag {\n tagName: string;\n attrs: Map<string, string>;\n}\n\n/**\n * KF-198. Returns true if the diff between `oldHtml` and `newHtml` was an\n * attribute-only change on the top-level element AND was applied to\n * `liveNode` directly. Caller should NOT also run the parse + morph path.\n */\nexport function tryAttributeOnlyFastPath(\n liveNode: Element,\n oldHtml: string,\n newHtml: string,\n): boolean {\n // Kerf's JSX runtime escapes '>' to '&gt;' in attribute values and text\n // content, so the first '>' in the row HTML is always the close of the\n // top-level opening tag.\n const oldGt = oldHtml.indexOf('>');\n const newGt = newHtml.indexOf('>');\n if (oldGt === -1 || newGt === -1) return false;\n\n // Everything from '>' onward (children + closing tag) must be byte-equal.\n // If not, the diff is structural or includes text-content changes — defer\n // to the morph path (or the text-content fast path).\n if (oldHtml.length - oldGt !== newHtml.length - newGt) return false;\n if (oldHtml.slice(oldGt) !== newHtml.slice(newGt)) return false;\n\n if (containsDataMorphSkip(oldHtml) || containsDataMorphSkip(newHtml)) return false;\n\n const oldTag = parseOpeningTag(oldHtml, oldGt);\n const newTag = parseOpeningTag(newHtml, newGt);\n if (oldTag === null || newTag === null) return false;\n if (oldTag.tagName !== newTag.tagName) return false;\n\n // Pre-validate: no namespaced attribute names on either side. Setting via\n // plain setAttribute on a namespaced attribute would land it in the null\n // namespace and not match the original; bail and let morph handle it.\n for (const name of oldTag.attrs.keys()) {\n if (name.indexOf(':') !== -1) return false;\n }\n for (const name of newTag.attrs.keys()) {\n if (name.indexOf(':') !== -1) return false;\n }\n\n // Apply the diff.\n const liveTagUpper = liveNode.tagName;\n for (const [name, rawValue] of newTag.attrs) {\n const oldValue = oldTag.attrs.get(name);\n if (oldValue === rawValue) continue;\n liveNode.setAttribute(name, unescapeAttrValue(rawValue));\n }\n for (const name of oldTag.attrs.keys()) {\n if (newTag.attrs.has(name)) continue;\n if (isUserAgentOwnedAttr(liveTagUpper, name)) continue;\n liveNode.removeAttribute(name);\n }\n return true;\n}\n\n/**\n * KF-206. Returns true if the diff between `oldHtml` and `newHtml` was a\n * single-text-node content change AND was applied to `liveNode`'s\n * corresponding live text node directly. Caller should NOT also run the\n * parse + morph path.\n */\nexport function tryTextContentFastPath(\n liveNode: Element,\n oldHtml: string,\n newHtml: string,\n): boolean {\n if (containsDataMorphSkip(oldHtml) || containsDataMorphSkip(newHtml)) return false;\n\n let p = 0;\n const minLen = Math.min(oldHtml.length, newHtml.length);\n while (p < minLen && oldHtml.charCodeAt(p) === newHtml.charCodeAt(p)) p++;\n let s = 0;\n const maxS = minLen - p;\n while (s < maxS\n && oldHtml.charCodeAt(oldHtml.length - 1 - s) === newHtml.charCodeAt(newHtml.length - 1 - s)) {\n s++;\n }\n\n const oldWinEnd = oldHtml.length - s;\n const newWinEnd = newHtml.length - s;\n\n // Diff windows must contain only text-content characters — no tag\n // delimiters, no quotes, no entities, no '=' (which would put us inside\n // an attribute). Either window having an unsafe char means this is not a\n // clean text-only change.\n if (!isPureTextWindow(oldHtml, p, oldWinEnd)) return false;\n if (!isPureTextWindow(newHtml, p, newWinEnd)) return false;\n\n // The char just before the equal-prefix boundary must be either '>'\n // (text node starts here) or another text-content char (we're mid-text).\n // '<' / '\"' / \"'\" / '=' / '&' would mean we're inside a tag or entity.\n if (p === 0) return false;\n const boundaryCc = oldHtml.charCodeAt(p - 1);\n if (boundaryCc === LT || boundaryCc === DQUOTE || boundaryCc === SQUOTE\n || boundaryCc === EQ || boundaryCc === AMP) return false;\n\n // Find the text node's HTML-string boundaries. Text node containing\n // position p starts after the most recent '>' before p in oldHtml; ends\n // at the next '<' at or after p.\n const textStart = lastIndexOfChar(oldHtml, GT, p - 1);\n if (textStart === -1) return false;\n const textEnd = oldHtml.indexOf('<', p);\n if (textEnd === -1) return false;\n // The diff window in oldHtml must lie entirely within this text node.\n if (textEnd < oldWinEnd) return false;\n // newHtml's corresponding `<` position is shifted by the length delta\n // (the diff window is entirely inside this text node, so everything after\n // it is in the equal-suffix region).\n const newTextEnd = textEnd + (newHtml.length - oldHtml.length);\n const oldText = oldHtml.slice(textStart + 1, textEnd);\n const newText = newHtml.slice(textStart + 1, newTextEnd);\n\n // Find the text-node-index in document order.\n const textIdx = countTextNodesBefore(oldHtml, textStart + 1);\n const targetNode = nthTextNodeDescendant(liveNode, textIdx);\n if (targetNode === null) return false;\n\n // Final safety net: the live text node's nodeValue must equal the text\n // we extracted from oldHtml. If it differs (HTML-string vs live drift,\n // browser whitespace normalization, imperative mutation, etc.), bail\n // so the morph path can do its safe thing.\n if (targetNode.nodeValue !== oldText) return false;\n\n targetNode.nodeValue = newText;\n return true;\n}\n\nfunction containsDataMorphSkip(html: string): boolean {\n return html.indexOf('data-morph-skip') !== -1;\n}\n\nfunction isPureTextWindow(html: string, start: number, end: number): boolean {\n for (let i = start; i < end; i++) {\n const cc = html.charCodeAt(i);\n if (cc === LT || cc === GT || cc === DQUOTE || cc === SQUOTE\n || cc === AMP || cc === EQ) return false;\n }\n return true;\n}\n\nfunction lastIndexOfChar(html: string, target: number, beforeInclusive: number): number {\n for (let i = beforeInclusive; i >= 0; i--) {\n if (html.charCodeAt(i) === target) return i;\n }\n return -1;\n}\n\n/**\n * Count text-content runs (non-empty stretches between `>` and `<`) that\n * START before `beforePos` in `html`. Used to convert an HTML-string\n * position to the corresponding text-node-index in document order. Relies\n * on kerf-emitted HTML's invariant that `<` / `>` outside attribute values\n * always denote tag boundaries (entities escape them everywhere else).\n */\nfunction countTextNodesBefore(html: string, beforePos: number): number {\n let count = 0;\n let i = 0;\n while (i < beforePos) {\n if (html.charCodeAt(i) === LT) {\n while (i < beforePos && html.charCodeAt(i) !== GT) i++;\n i++;\n } else {\n const start = i;\n while (i < beforePos && html.charCodeAt(i) !== LT) i++;\n if (i > start) count++;\n }\n }\n return count;\n}\n\nfunction nthTextNodeDescendant(root: Element, n: number): Text | null {\n let count = 0;\n let result: Text | null = null;\n function walk(node: Node): void {\n for (let c = node.firstChild; c !== null; c = c.nextSibling) {\n if (result !== null) return;\n if (c.nodeType === TEXT_NODE) {\n if (count === n) {\n result = c as Text;\n return;\n }\n count++;\n } else if (c.nodeType === ELEMENT_NODE) {\n walk(c);\n }\n }\n }\n walk(root);\n return result;\n}\n\n/**\n * Parse the top-level opening tag of `html` whose closing `>` is at\n * `gtPos`. Returns null on any malformed shape (missing tag name,\n * unquoted attribute values, unterminated attribute, etc.) so the caller\n * bails to the morph path. Kerf's JSX runtime emits well-formed,\n * double-quoted attribute values, so the success path is the common one.\n */\nfunction parseOpeningTag(html: string, gtPos: number): ParsedTag | null {\n if (html.charCodeAt(0) !== LT) return null;\n let i = 1;\n let end = gtPos;\n // Self-closing slash (e.g. `<br/>`) — drop it from the parse range.\n if (i < end && html.charCodeAt(end - 1) === SLASH) end -= 1;\n\n const nameStart = i;\n while (i < end) {\n const cc = html.charCodeAt(i);\n if (isWhitespace(cc)) break;\n i++;\n }\n const tagName = html.slice(nameStart, i);\n if (tagName.length === 0) return null;\n\n const attrs = new Map<string, string>();\n while (i < end) {\n while (i < end && isWhitespace(html.charCodeAt(i))) i++;\n if (i >= end) break;\n const aNameStart = i;\n while (i < end) {\n const cc = html.charCodeAt(i);\n if (cc === EQ || isWhitespace(cc)) break;\n i++;\n }\n const aName = html.slice(aNameStart, i);\n if (aName.length === 0) return null;\n while (i < end && isWhitespace(html.charCodeAt(i))) i++;\n if (i < end && html.charCodeAt(i) === EQ) {\n i++;\n while (i < end && isWhitespace(html.charCodeAt(i))) i++;\n if (i >= end) return null;\n const q = html.charCodeAt(i);\n if (q !== DQUOTE && q !== SQUOTE) return null;\n i++;\n const vStart = i;\n while (i < end && html.charCodeAt(i) !== q) i++;\n if (i >= end) return null;\n attrs.set(aName, html.slice(vStart, i));\n i++;\n } else {\n attrs.set(aName, '');\n }\n }\n return { tagName, attrs };\n}\n\n/**\n * Reverse the five entities kerf's `escapeAttr` produces. Replace in safe\n * order (named entities first; `&amp;` last so its decode doesn't pick up\n * the `&` we just emitted from a different decode).\n */\nfunction unescapeAttrValue(s: string): string {\n if (s.indexOf('&') === -1) return s;\n return s\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&amp;/g, '&');\n}\n\n/**\n * `<details>` and `<dialog>` toggle `open` themselves in response to user\n * interaction. Mirror `morphAttributes`' rule: never remove `open` on them\n * during the fast path — the user-driven state would be wiped.\n */\nfunction isUserAgentOwnedAttr(tagNameUpper: string, name: string): boolean {\n return name === 'open' && (tagNameUpper === 'DETAILS' || tagNameUpper === 'DIALOG');\n}\n","/**\n * Focus snapshot/restore for the keyed list reconciler.\n *\n * Some engines (older Safari, happy-dom) drop focus state on `insertBefore`\n * even when the focused element survives the move connected to the document.\n * The reconciler snapshots the active element + selection range before its\n * move pass, then re-applies them afterwards. Engines that already preserve\n * focus across DOM moves see a no-op; engines that don't get a transparent\n * fix.\n *\n * Lives in its own file (rather than inside `list-reconcile.ts`) to keep that\n * file under the 200-LOC project guideline and to isolate the engine-quirk\n * handling described in `docs/4-render.md` §4.4.\n */\n\nexport interface FocusSnapshot {\n el: HTMLElement;\n selStart: number | null;\n selEnd: number | null;\n}\n\n/**\n * Capture focus + selection on a focused descendant of `liveParent`.\n *\n * Returns null when the active element is outside the list (the diff path\n * handles those cases) or when there's no useful focus state to capture.\n */\nexport function captureFocus(liveParent: Element): FocusSnapshot | null {\n const active = document.activeElement;\n if (active === null || active === document.body) return null;\n if (!liveParent.contains(active)) return null;\n const el = active as HTMLElement;\n let selStart: number | null = null;\n let selEnd: number | null = null;\n if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {\n try {\n selStart = (el as HTMLInputElement).selectionStart;\n selEnd = (el as HTMLInputElement).selectionEnd;\n } catch {\n // Some input types (number, range, color, …) reject selection APIs.\n }\n }\n return { el, selStart, selEnd };\n}\n\nexport function restoreFocus(snap: FocusSnapshot): void {\n if (document.activeElement === snap.el) return;\n if (!snap.el.isConnected) return;\n snap.el.focus();\n if (snap.selStart !== null && snap.selEnd !== null) {\n try {\n (snap.el as HTMLInputElement).setSelectionRange(snap.selStart, snap.selEnd);\n } catch {\n // Selection may have been clobbered by .focus(); not fatal.\n }\n }\n}\n","/**\n * Shared \"exactly one top-level element per row\" contract helpers (KF-103).\n *\n * The keyed-list reconciler in `list-reconcile.ts` and the first-render\n * binding path in `mount.ts` both enforce the same contract on `each()`\n * row HTML. Centralizing the constants and helpers here keeps the three\n * call sites that build error snippets and the eight call sites that\n * parse a row's HTML into a template element from drifting (KF-111 +\n * KF-115).\n */\n\n/**\n * Truncation limit applied to row HTML when including it in a contract-\n * violation error message. Keeps the error readable when a row produced\n * megabytes of HTML by accident.\n */\nexport const ROW_HTML_SNIPPET_MAX = 120;\n\n/**\n * Truncate a row's HTML for inclusion in an error message. Returns the\n * raw string if it's short enough; otherwise the first\n * `ROW_HTML_SNIPPET_MAX` characters with a trailing ellipsis.\n */\nexport function truncateRowHtml(html: string): string {\n return html.length > ROW_HTML_SNIPPET_MAX\n ? html.slice(0, ROW_HTML_SNIPPET_MAX) + '…'\n : html;\n}\n\n/**\n * Parse a row's HTML into a `<template>` and report how many top-level\n * elements it produced. The reconciler uses the count to detect contract\n * violations (count !== 1) on both single-row and bulk-row paths.\n */\nexport function parseRowTemplate(html: string): { tpl: HTMLTemplateElement; count: number } {\n const tpl = document.createElement('template');\n tpl.innerHTML = html;\n return { tpl, count: tpl.content.children.length };\n}\n\n/**\n * Build a precise contract-violation `Error` for the row at `index` whose\n * render produced the given `html`. The thrown message mentions the row\n * index, the actual element count, and the (truncated) HTML so the author\n * can locate and fix the offending row quickly.\n */\nexport function rowContractError(index: number, html: string): Error {\n const { count } = parseRowTemplate(html);\n const reason = count === 0\n ? 'produced no top-level element'\n : `produced ${count} top-level elements; exactly one is required`;\n return new Error(\n `each(): row render at index ${index} ${reason}. `\n + 'Each item\\'s render must return exactly one element — '\n + 'wrap multiple roots in a single parent (e.g. <li>...</li>). '\n + `Got HTML: ${JSON.stringify(truncateRowHtml(html))}`,\n );\n}\n\nfunction isDevMode(): boolean {\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process;\n return proc?.env?.NODE_ENV !== 'production';\n}\n\n/**\n * KF-173: emit a one-shot dev-mode `console.warn` when the first row of an\n * `each()` list lacks both `id` and `data-key` attributes. The reconciler\n * falls back to positional matching in that case, which silently shifts row\n * state (focused inputs, mid-edit textareas) on insert/delete. The warning\n * names the row index, points at the canonical fix, and quotes the HTML\n * snippet so the author can locate the call site.\n *\n * Called per-binding; the caller passes a mutable flag holder so the warning\n * fires at most once per `mount()`-lifetime per `each()` callsite. Set the\n * holder's flag after the call regardless of whether the warning fired.\n * Production builds emit nothing — the gate is `NODE_ENV !== 'production'`.\n */\nexport function maybeWarnMissingRowKey(\n rowEl: Element,\n rowIndex: number,\n rowHtml: string,\n binding: { warnedMissingKey?: boolean },\n): void {\n if (!isDevMode()) return;\n if (binding.warnedMissingKey === true) return;\n binding.warnedMissingKey = true;\n if (rowEl.id !== '' || rowEl.hasAttribute('data-key')) return;\n console.warn(\n `kerf each(): row at index ${rowIndex} has no \\`id\\` or \\`data-key\\` attribute. `\n + 'Without one, rows match positionally — an insert/remove at the head shifts every row\\'s '\n + 'identity, so focused inputs jump to the wrong row, mid-edit textareas swap content with their neighbor, '\n + 'and any per-row state silently follows the wrong item. '\n + 'Add `data-key={item.id}` (or set `id`) to the top-level element returned by the row render. '\n + `Row HTML: ${JSON.stringify(truncateRowHtml(rowHtml))}`,\n );\n}\n","/**\n * Granular reconcile path for `each(...)` bound to an `arraySignal` (KF-92).\n *\n * Applies the patch events emitted by `arraySignal` mutators directly to\n * the live DOM and to `binding.items`, without iterating the full snapshot\n * or doing a classify pass. Cost is O(patches), not O(N).\n *\n * Two perf optimizations:\n * - **KF-93**: contiguous insert runs (patches at index N, N+1, N+2, …) are\n * bulk-parsed in one `template.innerHTML` call and inserted as a single\n * fragment. Saves ~50 ms on append-1k.\n * - **KF-94**: consecutive update runs (any indices — `replaceChild`\n * operates on each row's existing live node independently) are bulk-\n * parsed in one `template.innerHTML` call. Saves the per-patch parse\n * cost on the krausest partial-update scenario.\n *\n * Patches with `type: 'replace'` are filtered out by `each()` upstream and\n * never reach this function (the runtime contract guarantees absence even\n * though the TypeScript type allows them).\n *\n * Internal to kerf — re-exported via `list-reconcile.ts`'s `reconcileList`.\n */\n\nimport { type BoundItem, endAnchor, type ListBinding } from './list-binding.js';\nimport { tryAttributeOnlyFastPath, tryTextContentFastPath } from './list-reconcile-fast-paths.js';\nimport { captureFocus, restoreFocus } from './list-reconcile-focus.js';\nimport { _morphElement } from './morph.js';\nimport type { ListSegment } from './segment.js';\nimport { maybeWarnMissingRowKey,parseRowTemplate, rowContractError, truncateRowHtml } from './utils/rowContract.js';\n\nexport function reconcileGranular(\n binding: ListBinding,\n patches: NonNullable<ListSegment['patches']>,\n): void {\n const { liveParent } = binding;\n const items = binding.items;\n\n // Capture/restore focus around the whole batch (mirrors the snapshot\n // path's KF-65 fix). Some engines (older Safari, happy-dom) blur a\n // focused descendant on `insertBefore` / `replaceChild` even when the\n // ancestor stays connected — covers the move patch (which moves an\n // existing row's <li>), and is a no-op on engines that already\n // preserve focus across DOM ops.\n const focusSnap = captureFocus(liveParent);\n\n let i = 0;\n while (i < patches.length) {\n const patch = patches[i];\n /* c8 ignore next 5 — replace is filtered upstream by each(); this branch\n is defensive type-completeness only. */\n if (patch.type === 'replace') {\n i += 1;\n continue;\n }\n if (patch.type === 'update') {\n // KF-94: detect a run of consecutive update patches (any indices —\n // replaceChild operates on each row's existing live node independently,\n // so contiguity isn't required) and bulk-parse all their HTML in a\n // single `template.innerHTML` call. Saves the per-patch parse overhead\n // on krausest's partial-update scenario (100 update patches at\n // indices 0, 10, 20, … — non-contiguous, so KF-93's run detector\n // doesn't kick in).\n let runEnd = i + 1;\n while (runEnd < patches.length && patches[runEnd].type === 'update') {\n runEnd += 1;\n }\n const runLen = runEnd - i;\n if (runLen === 1) {\n applySingleUpdate(liveParent, items, patch);\n } else {\n applyBulkUpdate(liveParent, items, patches, i, runEnd);\n }\n i = runEnd;\n continue;\n }\n if (patch.type === 'insert') {\n // KF-93: detect a contiguous run of inserts at adjacent indices (each\n // next insert at the previous one's index + 1) and bulk-parse all\n // their HTML in a single `template.innerHTML` call, followed by a\n // single `insertBefore(fragment, anchor)`.\n let runEnd = i + 1;\n while (runEnd < patches.length\n && patches[runEnd].type === 'insert'\n && (patches[runEnd] as { index: number }).index\n === (patches[runEnd - 1] as { index: number }).index + 1) {\n runEnd += 1;\n }\n const runLen = runEnd - i;\n if (runLen === 1) {\n applySingleInsert(liveParent, items, patch, endAnchor(binding));\n } else {\n applyBulkInsert(liveParent, items, patches, i, runEnd, endAnchor(binding));\n }\n i = runEnd;\n continue;\n }\n if (patch.type === 'remove') {\n const entry = items[patch.index];\n liveParent.removeChild(entry.node);\n items.splice(patch.index, 1);\n i += 1;\n continue;\n }\n if (patch.type === 'move') {\n const moved = items[patch.from];\n // Compute the anchor BEFORE we splice, so the index references the\n // pre-move state.\n let anchorIdx = patch.to;\n if (patch.from < patch.to) anchorIdx += 1; // account for upcoming splice removal\n const anchor = anchorIdx < items.length ? items[anchorIdx].node : endAnchor(binding);\n liveParent.insertBefore(moved.node, anchor);\n items.splice(patch.from, 1);\n items.splice(patch.to, 0, moved);\n i += 1;\n continue;\n }\n }\n\n if (focusSnap !== null) restoreFocus(focusSnap);\n // KF-173: warn once per binding if rows lack id / data-key.\n if (items.length > 0) {\n maybeWarnMissingRowKey(items[0].node, 0, items[0].html, binding);\n }\n}\n\nfunction applySingleInsert(\n liveParent: Element,\n items: BoundItem[],\n patch: { type: 'insert'; index: number; item: object; html: string },\n tailAnchor: Element | null,\n): void {\n const { html } = patch;\n const newNode = parseSingleRow(html);\n const anchor = patch.index < items.length ? items[patch.index].node : tailAnchor;\n liveParent.insertBefore(newNode, anchor);\n items.splice(patch.index, 0, {\n ref: patch.item, cacheKey: undefined, html, node: newNode,\n });\n}\n\nfunction applySingleUpdate(\n liveParent: Element,\n items: BoundItem[],\n patch: { type: 'update'; index: number; item: object; html: string },\n): void {\n const { html } = patch;\n const oldEntry = items[patch.index];\n if (html === oldEntry.html) return; // no-op (defensive: caller may emit redundant patches)\n // KF-198 + KF-206: surgical fast paths for the common arraySignal update\n // shapes — top-level attribute flip (krausest select-row) and one-text-\n // node content change (krausest partial-update). Both apply the change\n // directly to the live row, skipping the parse + morph entirely. They\n // bail conservatively on anything that could be unsafe and fall through\n // to the existing _morphElement / replaceChild routes below.\n if (tryAttributeOnlyFastPath(oldEntry.node, oldEntry.html, html)\n || tryTextContentFastPath(oldEntry.node, oldEntry.html, html)) {\n items[patch.index] = { ref: patch.item, cacheKey: undefined, html, node: oldEntry.node };\n return;\n }\n const newNode = parseSingleRow(html);\n // KF-201: morph the existing live node in place when tags match, so\n // structure-preserving updates (text-node change, attribute flip) apply\n // surgically — preserving DOM identity, focus, scroll, IME state, and\n // skipping the layout cost of a full subtree discard-and-reinsert. For\n // the rare tag-mismatch case (consumer's render fn returns a different\n // top-level tag for the same item), fall back to explicit replaceChild\n // so we keep a reference to the new live node.\n if (oldEntry.node.tagName === newNode.tagName) {\n _morphElement(oldEntry.node, newNode);\n items[patch.index] = { ref: patch.item, cacheKey: undefined, html, node: oldEntry.node };\n } else {\n liveParent.replaceChild(newNode, oldEntry.node);\n items[patch.index] = { ref: patch.item, cacheKey: undefined, html, node: newNode };\n }\n}\n\n/**\n * Bulk-parse a run of consecutive update patches (KF-94). Indices may be\n * scattered (non-contiguous). Renders all HTMLs first, filters out no-ops\n * where the new HTML matches the old, then bulk-parses the remaining HTMLs\n * in one `template.innerHTML` call. The replaceChild loop afterwards is\n * unavoidable (one DOM op per row), but we save the per-patch parse cost.\n */\nfunction applyBulkUpdate(\n liveParent: Element,\n items: BoundItem[],\n patches: NonNullable<ListSegment['patches']>,\n start: number,\n end: number,\n): void {\n // Patches already carry pre-rendered HTML (KF-99). One pass over the run:\n // skip no-ops, try the KF-198 / KF-206 fast paths (apply in place when\n // they fire), and collect everything else for one bulk parse + morph.\n interface Change { patchIdx: number; html: string }\n const morphChanges: Change[] = [];\n for (let k = start; k < end; k++) {\n const p = patches[k] as { type: 'update'; index: number; item: object; html: string };\n const oldEntry = items[p.index];\n if (p.html === oldEntry.html) continue;\n if (tryAttributeOnlyFastPath(oldEntry.node, oldEntry.html, p.html)\n || tryTextContentFastPath(oldEntry.node, oldEntry.html, p.html)) {\n items[p.index] = { ref: p.item, cacheKey: undefined, html: p.html, node: oldEntry.node };\n continue;\n }\n morphChanges.push({ patchIdx: k, html: p.html });\n }\n if (morphChanges.length === 0) return;\n\n // Bulk-parse only the rows the fast paths couldn't handle.\n const { tpl, count } = parseRowTemplate(morphChanges.map((c) => c.html).join(''));\n if (count !== morphChanges.length) {\n throw findOffendingChange(patches, morphChanges);\n }\n const newNodes = new Array<Element>(morphChanges.length);\n let child = tpl.content.firstElementChild;\n for (let k = 0; k < newNodes.length; k++) {\n newNodes[k] = child as Element;\n child = (child as Element).nextElementSibling;\n }\n\n // KF-201: morph each row in place when tags match (the common case), so\n // structure-preserving updates skip the discard-and-reinsert layout cost.\n // Tag-mismatch falls back to explicit replaceChild so we keep a reference\n // to the new live node.\n for (let k = 0; k < morphChanges.length; k++) {\n const c = morphChanges[k];\n const p = patches[c.patchIdx] as { type: 'update'; index: number; item: object; html: string };\n const oldEntry = items[p.index];\n if (oldEntry.node.tagName === newNodes[k].tagName) {\n _morphElement(oldEntry.node, newNodes[k]);\n items[p.index] = { ref: p.item, cacheKey: undefined, html: c.html, node: oldEntry.node };\n } else {\n liveParent.replaceChild(newNodes[k], oldEntry.node);\n items[p.index] = { ref: p.item, cacheKey: undefined, html: c.html, node: newNodes[k] };\n }\n }\n}\n\n/**\n * Bulk-parse a contiguous run of insert patches (KF-93). The run starts at\n * `start` (inclusive) and ends at `end` (exclusive); every patch in that\n * range is type `insert` with index === previous.index + 1. We render each\n * row's HTML, concatenate, parse the lot in one `template.innerHTML`, and\n * insert the resulting fragment in a single DOM op.\n */\nfunction applyBulkInsert(\n liveParent: Element,\n items: BoundItem[],\n patches: NonNullable<ListSegment['patches']>,\n start: number,\n end: number,\n tailAnchor: Element | null,\n): void {\n const startIdx = (patches[start] as { index: number }).index;\n const htmls = new Array<string>(end - start);\n for (let k = start; k < end; k++) {\n const p = patches[k] as { type: 'insert'; index: number; item: object; html: string };\n htmls[k - start] = p.html;\n }\n const { tpl, count } = parseRowTemplate(htmls.join(''));\n if (count !== htmls.length) {\n throw findOffendingInsert(patches, start, htmls);\n }\n // Count matches; capture child refs BEFORE the fragment-insert empties\n // tpl.content. Walk unconditionally — count check above guarantees\n // `firstElementChild` is non-null and there are exactly `end - start`\n // children.\n const newNodes = new Array<Element>(end - start);\n let child = tpl.content.firstElementChild;\n for (let k = 0; k < newNodes.length; k++) {\n newNodes[k] = child as Element;\n child = (child as Element).nextElementSibling;\n }\n const anchor = startIdx < items.length ? items[startIdx].node : tailAnchor;\n liveParent.insertBefore(tpl.content, anchor);\n // Splice all new entries into binding.items at the run's start index.\n const newEntries = new Array<BoundItem>(end - start);\n for (let k = 0; k < newEntries.length; k++) {\n const p = patches[start + k] as { type: 'insert'; index: number; item: object; html: string };\n newEntries[k] = {\n ref: p.item, cacheKey: undefined, html: htmls[k], node: newNodes[k],\n };\n }\n items.splice(startIdx, 0, ...newEntries);\n}\n\n/**\n * Parse a single row's HTML string into one Element. Used by the granular\n * reconciler's single-row paths (`applySingleInsert`, `applySingleUpdate`).\n * Each row is expected to render exactly one top-level element (the same\n * contract `each()` enforces in the snapshot path).\n */\nfunction parseSingleRow(html: string): Element {\n const { tpl, count } = parseRowTemplate(html);\n if (count !== 1) {\n const reason = count === 0\n ? 'produced no top-level element'\n : `produced ${count} top-level elements; exactly one is required`;\n throw new Error(\n `each() granular reconcile: row render ${reason}. `\n + 'Each item\\'s render must return exactly one element. '\n + `Got HTML: ${JSON.stringify(truncateRowHtml(html))}`,\n );\n }\n return tpl.content.firstElementChild as Element;\n}\n\n/**\n * Slow-path helper for `applyBulkInsert`. Walks each pre-rendered insert\n * patch's html in isolation to find the offending row.\n */\nfunction findOffendingInsert(\n patches: NonNullable<ListSegment['patches']>,\n start: number,\n htmls: string[],\n): Error {\n for (let i = 0; i < htmls.length; i++) {\n if (parseRowTemplate(htmls[i]).count !== 1) {\n const p = patches[start + i] as { type: 'insert'; index: number };\n return rowContractError(p.index, htmls[i]);\n }\n }\n /* c8 ignore start */\n return new Error('each(): bulk-insert mismatch with no per-row offender (kerf bug).');\n}\n/* c8 ignore stop */\n\n/**\n * Slow-path helper for `applyBulkUpdate`. Walks each non-no-op change to\n * find the offending row.\n */\nfunction findOffendingChange(\n patches: NonNullable<ListSegment['patches']>,\n changes: { patchIdx: number; html: string }[],\n): Error {\n for (const c of changes) {\n if (parseRowTemplate(c.html).count !== 1) {\n const p = patches[c.patchIdx] as { type: 'update'; index: number };\n return rowContractError(p.index, c.html);\n }\n }\n /* c8 ignore start */\n return new Error('each(): bulk-update mismatch with no per-row offender (kerf bug).');\n}\n/* c8 ignore stop */\n","/**\n * Snapshot reconcile path for `each(...)` — the original (non-granular)\n * keyed-list algorithm. Used when:\n * - The list is rendered with a plain array (not an `arraySignal`).\n * - The list is rendered with an `arraySignal` but no patch queue is\n * present (first render, post-`replace()`, or post-drift recovery).\n *\n * Algorithm:\n * 1. Classify each new item as `stable` (cache hit on identity + html),\n * `replaced` (same ref, html changed), or `new` (never seen before).\n * 2. Bulk-parse every fresh row's HTML in ONE `innerHTML` call — for an\n * initial population of 10k rows that's 1 parse instead of 10k.\n * 3. Remove orphan refs (gone from the new list) + replaced rows' old nodes.\n * 4. Compute a longest-increasing-subsequence over old positions; items in\n * the LIS are already in the right relative order, so they don't move.\n * 5. Reverse-pass over the new record, `insertBefore` only the items that\n * didn't anchor the LIS.\n *\n * The KF-89 fast path short-circuits when nothing structural changed —\n * the live tree already matches the new segment, so we can return after\n * step 1 with just the binding update.\n *\n * Internal to kerf — re-exported via `list-reconcile.ts`'s `reconcileList`.\n */\n\nimport { type BoundItem, endAnchor, type ListBinding } from './list-binding.js';\nimport { captureFocus, restoreFocus } from './list-reconcile-focus.js';\nimport type { ListSegment } from './segment.js';\nimport { maybeWarnMissingRowKey,parseRowTemplate, rowContractError } from './utils/rowContract.js';\n\ninterface Classification {\n newRecord: BoundItem[];\n prevIdx: number[];\n replacedNodes: Element[];\n freshIndices: number[];\n freshHtmls: string[];\n}\n\n/**\n * Reconcile via the snapshot algorithm. Mutates `binding.items` to mirror\n * the new segment when done.\n *\n * Focus capture/restore lives in `list-reconcile-focus.ts` — `insertBefore`\n * of a focused descendant's ancestor blurs the element in some engines\n * (happy-dom, older Safari) even when it stays connected; the snapshot fixes\n * those engines and is a no-op on engines that already preserve focus.\n */\nexport function reconcileSnapshot(binding: ListBinding, listSeg: ListSegment): void {\n const { liveParent } = binding;\n const { newRecord, prevIdx, replacedNodes, freshIndices, freshHtmls }\n = classifyItems(binding.items, listSeg);\n\n // KF-89 fast path: if no items were replaced, none are fresh, and every\n // surviving item kept its original position, the live tree already matches\n // the new segment. Skip buildFreshNodes (nothing to build), removeOldNodes\n // (nothing to remove), the LIS pass (no reorder possible), and applyMoves'\n // reverse walk (no moves). For a 1k-row list whose only change is a signal\n // re-read with no item-array delta, this collapses ~10–15 ms of per-render\n // bookkeeping into a single classification pass + the binding update.\n if (replacedNodes.length === 0 && freshIndices.length === 0\n && isInOrder(prevIdx)) {\n binding.items = newRecord;\n if (newRecord.length > 0) {\n maybeWarnMissingRowKey(newRecord[0].node, 0, newRecord[0].html, binding);\n }\n return;\n }\n\n // Compute tail anchor BEFORE removing old nodes: once an item is\n // detached, its `.nextElementSibling` is null and we lose the\n // boundary. Capturing here uses the binding's current (pre-mutation)\n // items[last].node which is still attached.\n const tailAnchor = endAnchor(binding);\n buildFreshNodes(newRecord, freshIndices, freshHtmls);\n const focusSnap = captureFocus(liveParent);\n removeOldNodes(liveParent, replacedNodes);\n applyMoves(liveParent, newRecord, prevIdx, lis(prevIdx), tailAnchor);\n if (focusSnap !== null) restoreFocus(focusSnap);\n binding.items = newRecord;\n if (newRecord.length > 0) {\n maybeWarnMissingRowKey(newRecord[0].node, 0, newRecord[0].html, binding);\n }\n}\n\n/**\n * Classify each item in the new segment against the old binding. Items with\n * a cache-hit (same ref + same html) are reused; replaced/new items get a\n * placeholder `BoundItem` whose `node` is filled in by the bulk parse below.\n */\nfunction classifyItems(oldItems: BoundItem[], listSeg: ListSegment): Classification {\n // Single Map<ref, [item, index]> instead of two Maps over the same key set\n // (KF-90). Halves the .set() calls during the build, halves the lookup\n // probe count during classification. ~1-2 ms saved per render on 1k-row\n // lists.\n const oldByRef = new Map<object, [BoundItem, number]>();\n for (let i = 0; i < oldItems.length; i++) {\n oldByRef.set(oldItems[i].ref, [oldItems[i], i]);\n }\n\n const newRecord: BoundItem[] = new Array(listSeg.items.length);\n const prevIdx = new Array<number>(listSeg.items.length);\n const replacedNodes: Element[] = [];\n const freshIndices: number[] = [];\n const freshHtmls: string[] = [];\n\n for (let i = 0; i < listSeg.items.length; i++) {\n const ni = listSeg.items[i];\n const oi = oldByRef.get(ni.ref);\n if (oi !== undefined) {\n oldByRef.delete(ni.ref);\n if (oi[0].html === ni.html) {\n newRecord[i] = oi[0];\n prevIdx[i] = oi[1];\n continue;\n }\n replacedNodes.push(oi[0].node);\n }\n newRecord[i] = {\n ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: null as unknown as Element,\n };\n prevIdx[i] = -1;\n freshIndices.push(i);\n freshHtmls.push(ni.html);\n }\n\n // Whatever's left in oldByRef is an orphan ref that disappeared from the\n // new list. The caller removes those nodes alongside the replaced ones.\n for (const [, orphan] of oldByRef) replacedNodes.push(orphan[0].node);\n\n return { newRecord, prevIdx, replacedNodes, freshIndices, freshHtmls };\n}\n\n/**\n * Bulk-parse every fresh row's HTML in one `innerHTML` call, then walk the\n * parsed children in order and fill in each placeholder's `node` field.\n *\n * Enforces the \"exactly one top-level element per row\" contract (KF-103):\n * if the bulk parse produces a different number of top-level elements\n * than fresh rows, fall back to per-row parsing to identify the offending\n * row and throw a precise error. The success path stays a single parse.\n */\nfunction buildFreshNodes(\n newRecord: BoundItem[],\n freshIndices: number[],\n freshHtmls: string[],\n): void {\n if (freshHtmls.length === 0) return;\n const { tpl, count } = parseRowTemplate(freshHtmls.join(''));\n if (count !== freshHtmls.length) {\n throw findOffendingRow(newRecord, freshIndices, freshHtmls);\n }\n // After the count check above, we know `tpl.content.children.length`\n // equals `freshIndices.length`, so the walk below always finds an element\n // for every index. No defensive null-guard needed.\n let node = tpl.content.firstElementChild;\n for (const idx of freshIndices) {\n const next = (node as Element).nextElementSibling;\n newRecord[idx].node = node as Element;\n node = next;\n }\n}\n\n/**\n * Walk per-row to find the offending row that violated the contract,\n * returning a precise error to throw. Only invoked when the bulk parse\n * detected a count mismatch — the success path is one parse with no\n * per-row work.\n */\nfunction findOffendingRow(\n newRecord: BoundItem[],\n freshIndices: number[],\n freshHtmls: string[],\n): Error {\n for (let i = 0; i < freshHtmls.length; i++) {\n if (parseRowTemplate(freshHtmls[i]).count !== 1) {\n return rowContractError(freshIndices[i], newRecord[freshIndices[i]].html);\n }\n }\n /* c8 ignore next 2 — unreachable: bulk mismatch ⇒ at least one row violates. */\n return new Error('each(): bulk-parse mismatch with no per-row offender (kerf bug).');\n}\n\n/**\n * Remove every replaced/orphan node still attached to the live parent.\n */\nfunction removeOldNodes(liveParent: Element, replacedNodes: Element[]): void {\n for (const node of replacedNodes) {\n if (node.parentElement === liveParent) liveParent.removeChild(node);\n }\n}\n\n/**\n * `insertBefore` everything that's not in the LIS. Walks the new record in\n * reverse so each move's anchor (`nextSibling`) is already in its final\n * position by the time we reach earlier items.\n *\n * `tailAnchor` is the element that comes AFTER the list inside `liveParent`\n * (or `null` if the list is at the end). The reconciler computes it via\n * `endAnchor(binding)` so it picks up non-list siblings the diff may have\n * inserted between the list and the parent's tail (KF-102).\n */\nfunction applyMoves(\n liveParent: Element,\n newRecord: BoundItem[],\n prevIdx: number[],\n stable: ReadonlySet<number>,\n tailAnchor: Element | null,\n): void {\n let nextSibling: Element | null = tailAnchor;\n for (let i = newRecord.length - 1; i >= 0; i--) {\n const node = newRecord[i].node;\n if (prevIdx[i] === -1 || !stable.has(i)) {\n liveParent.insertBefore(node, nextSibling);\n }\n nextSibling = node;\n }\n}\n\n/**\n * Patience-sort LIS: returns the *set of indices* in `arr` that participate\n * in a longest strictly-increasing subsequence. `-1` entries (representing\n * brand-new items in the new list) are ignored — they can't anchor the\n * subsequence and shouldn't count as stable.\n */\nfunction lis(arr: ReadonlyArray<number>): ReadonlySet<number> {\n const tails: number[] = [];\n const tailIdx: number[] = [];\n const prev = new Array<number>(arr.length);\n for (let i = 0; i < arr.length; i++) {\n const v = arr[i];\n if (v === -1) {\n prev[i] = -1;\n continue;\n }\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (tails[mid] < v) lo = mid + 1;\n else hi = mid;\n }\n prev[i] = lo > 0 ? tailIdx[lo - 1] : -1;\n tails[lo] = v;\n tailIdx[lo] = i;\n }\n const out = new Set<number>();\n let k = tailIdx.length > 0 ? tailIdx[tailIdx.length - 1] : -1;\n while (k !== -1) {\n out.add(k);\n k = prev[k];\n }\n return out;\n}\n\n/**\n * True iff `prevIdx` is `[0, 1, 2, …, n-1]` — every item kept the position it\n * had in the previous render. Used by `reconcileSnapshot` to short-circuit\n * the LIS + move pass when nothing structural changed.\n */\nfunction isInOrder(prevIdx: number[]): boolean {\n for (let i = 0; i < prevIdx.length; i++) {\n if (prevIdx[i] !== i) return false;\n }\n return true;\n}\n","/**\n * Keyed list reconciler — the engine behind `each(...)` inside `mount()`.\n *\n * Public surface (re-exported via the rest of the runtime):\n * - `BoundItem` / `ListBinding`: the binding shape `mount()` keeps\n * per-list, mapping `each()` items to their live DOM nodes.\n * Defined in `list-binding.ts` and re-exported here.\n * - `endAnchor(binding)`: dynamic \"insert at end of list\" anchor.\n * Also defined in `list-binding.ts` and re-exported here.\n * - `reconcileList(binding, listSeg)`: top-level dispatch.\n *\n * Implementation lives in two sibling files:\n * - `list-reconcile-snapshot.ts` — the original keyed algorithm\n * (classify / bulk-parse / LIS / move). Used for plain-array `each()`\n * and for arraySignal-backed `each()` when the patch path can't apply\n * (first render, post-`replace()`, post-drift recovery).\n * - `list-reconcile-granular.ts` — the KF-92 patch-driven path used\n * when an `arraySignal`'s queued patches can be applied directly to\n * the existing binding without iterating the snapshot.\n *\n * The split mirrors the two-axis nature of the reconciler: snapshot-vs-\n * granular path × shared bookkeeping (binding shape, end-of-list anchor,\n * focus capture/restore). The binding shape is in its own `list-binding.ts`\n * file so the two sibling reconcilers can import it without creating a\n * circular dependency back to `list-reconcile.ts`. Internal to kerf — not\n * part of the public API.\n */\n\nexport { type BoundItem, endAnchor, type ListBinding } from './list-binding.js';\nimport type { ListBinding } from './list-binding.js';\nimport { reconcileGranular } from './list-reconcile-granular.js';\nimport { reconcileSnapshot } from './list-reconcile-snapshot.js';\nimport type { ListSegment } from './segment.js';\n\n/**\n * Reconcile `binding`'s live parent against `listSeg`. Mutates `binding.items`\n * to mirror the new segment when done.\n *\n * Dispatch:\n * - **Granular (KF-92)**: an `arraySignal`-backed `each()` whose patch\n * queue is non-empty AND the binding has at least one row. Applies\n * patches directly. `each()` filters `replace` patches upstream so the\n * patches reaching here are guaranteed to be update/insert/remove/move\n * only.\n * - **Snapshot**: every other case — first render of a list, plain-array\n * `each()`, post-`replace()`, post-drift recovery. Runs the keyed\n * classify/build/move algorithm.\n */\nexport function reconcileList(binding: ListBinding, listSeg: ListSegment): void {\n if (listSeg.patches !== undefined && binding.items.length > 0) {\n reconcileGranular(binding, listSeg.patches);\n return;\n }\n reconcileSnapshot(binding, listSeg);\n}\n","/**\n * `mount(rootEl, render)` — kerf's render primitive.\n *\n * Wraps `effect()` so that whenever any signal read inside `render()`\n * changes, we re-run `render()` and apply the minimum DOM mutations against\n * the live tree. Element identity (and thus focus, selection, in-flight\n * pointer interactions, and event listeners on preserved nodes) is preserved\n * wherever the keyed/positional diff matches.\n *\n * Two phases per render:\n *\n * - Static surrounds (everything outside `each()` lists): kerf's native\n * `morph()` reconciler walks a freshly-built template against the live\n * tree. Conventions: id/data-key matching, `data-morph-skip`, focus\n * preservation.\n *\n * - List interiors (children of every `each()` parent): native keyed\n * reconciler operates directly on the live parent's children. No\n * re-parse, no morph walk for cache-hit rows. Cost is O(changes), not\n * O(rows).\n *\n * Compared to a `replaceChildren(...rows.map(toElement))` rebuild pattern,\n * the user-visible win is that an `<input>` the user is typing into\n * survives an unrelated re-render — its DOM node, focus state, and cursor\n * position are not destroyed and recreated on each tick.\n */\n\nimport { maybeWarnEachInMorphSkip } from './dev-each-warn.js';\nimport { installListenerRebuildWarn } from './dev-listener-warn.js';\nimport { _setRenderContext, type RenderContext } from './each.js';\nimport type { SafeHtml } from './jsx-runtime.js';\nimport { isSafeHtml } from './jsx-runtime.js';\nimport {\n type BoundItem,\n type ListBinding,\n reconcileList,\n} from './list-reconcile.js';\nimport { morph } from './morph.js';\nimport { effect } from './reactive.js';\nimport {\n collectLists,\n flatten,\n flattenWithoutListItems,\n type ListSegment,\n type Segment,\n} from './segment.js';\nimport { maybeWarnMissingRowKey,parseRowTemplate, rowContractError } from './utils/rowContract.js';\n\nconst LIST_MARKER_PREFIX = 'kf-list:';\n\n/**\n * Bind `render()` to the children of `rootEl`. Re-runs whenever any signal\n * read inside `render()` changes. Returns a disposer that tears down the\n * effect; call it when the host element is removed from the DOM.\n *\n * Conventions:\n *\n * - Diff keys: `id` and `data-key` are matched across the morph by key\n * rather than positionally, so list reorders move existing nodes instead\n * of churning unrelated siblings.\n * - `data-morph-skip`: any element with this attribute is left untouched\n * inside on subsequent renders. Used for library-owned subtrees (xterm-\n * style widgets, charts, third-party editors) where the library's own\n * lifecycle manages the children.\n * - Focused text-entry inputs (`<input>` of typing kinds, `<textarea>`)\n * keep their current value + selection range across morphs while focused.\n * The user never sees their cursor jump mid-keystroke.\n * - Focused `[contenteditable]` elements have their entire subtree\n * skipped (same mechanism as `data-morph-skip`). The user's in-progress\n * edit — typed content, caret position, multi-range selections, anything\n * else they did to the DOM — survives verbatim. The next render after\n * blur catches up.\n */\nexport type MountResult = SafeHtml | string | number | boolean | null | undefined;\n\n// KF-175 — non-enumerable marker placed on `mount()`'s rootEl so that a\n// second `mount()` call on a descendant, ancestor, or the same element can be\n// detected and rejected. `Symbol.for(...)` so the marker survives multiple\n// kerfjs imports in the same realm (e.g. the dist-full test suite running a\n// rebuilt bundle against the src test infrastructure).\nconst MOUNTED_MARKER = Symbol.for('kerfjs.mounted');\n\nfunction describeEl(el: HTMLElement): string {\n const tag = el.tagName.toLowerCase();\n const id = el.id ? `#${el.id}` : '';\n return `<${tag}${id}>`;\n}\n\nfunction assertNotInsideMountedTree(rootEl: HTMLElement): void {\n // The element itself — same element mounted twice.\n if ((rootEl as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] === true) {\n throw new Error(\n `mount: ${describeEl(rootEl)} is already mounted. `\n + 'Call the disposer returned by the first mount() before mounting again. '\n + 'kerf supports one mount per element — compose with plain functions that return JSX instead of nesting mounts.',\n );\n }\n // Ancestors — walk up.\n let ancestor: Element | null = rootEl.parentElement;\n while (ancestor !== null) {\n if ((ancestor as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] === true) {\n throw new Error(\n 'mount: rootEl is already inside (or contains) a mounted tree. '\n + 'kerf supports one mount per tree — compose with plain functions that return JSX instead of nesting mounts.',\n );\n }\n ancestor = ancestor.parentElement;\n }\n // Descendants — DFS.\n const stack: Element[] = [];\n for (let i = 0; i < rootEl.children.length; i++) stack.push(rootEl.children[i]);\n while (stack.length > 0) {\n const cur = stack.pop() as Element;\n if ((cur as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] === true) {\n throw new Error(\n 'mount: rootEl is already inside (or contains) a mounted tree. '\n + 'kerf supports one mount per tree — compose with plain functions that return JSX instead of nesting mounts.',\n );\n }\n for (let i = 0; i < cur.children.length; i++) stack.push(cur.children[i]);\n }\n}\n\nexport function mount(rootEl: HTMLElement, render: () => MountResult): () => void {\n if (rootEl == null) {\n throw new Error(\n 'mount: rootEl is null/undefined — pass the live element, e.g. mount(document.getElementById(\"app\")!, render). '\n + 'A common cause is a typo in the id or selector that returns null at runtime even though the TypeScript types say HTMLElement.',\n );\n }\n assertNotInsideMountedTree(rootEl);\n (rootEl as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] = true;\n // KF-174: opt-in dev MutationObserver that warns when a node carrying an\n // imperative addEventListener listener is removed/rebuilt by the morph.\n const listenerWarnObserver = installListenerRebuildWarn(rootEl);\n const bindings = new Map<string, ListBinding>();\n // Per-mount render context: the list-id counter is reset at the start of\n // each render (so the n-th `each()` call gets the same id every render);\n // the `caches` map persists across renders so unchanged items skip the\n // JSX work via cache hits even when the JSX render function is an inline\n // arrow that's a fresh function reference on every closure run (KF-87).\n const renderCtx: RenderContext = {\n counter: 0,\n caches: new Map(),\n bindingCounts: new Map(),\n };\n let isFirst = true;\n // KF-88: the static-surrounds HTML string from the previous render. If a\n // re-render produces the same string (the common case when a signal flips\n // a class on one row but the page chrome is unchanged), we skip the\n // template clone, the innerHTML re-parse, and the morph() walk entirely\n // and go straight to the per-list reconcilers. Saves ~8 ms per update-\n // path render against the krausest harness.\n let prevStaticHtml = '';\n\n const disposeEffect = effect(() => {\n renderCtx.counter = 0;\n _setRenderContext(renderCtx);\n let result: MountResult;\n try {\n result = render();\n } finally {\n _setRenderContext(null);\n }\n\n // The `MountResult` union covers `null`, `undefined`, `false`, `true`,\n // and `number` so consumers can write `() => cond ? <jsx/> : null` and\n // `() => cond && <jsx/>` without a cast. `coerceRenderResult` collapses\n // nullish + boolean to `''` (render nothing) and stringifies numbers.\n const segment: Segment = isSafeHtml(result)\n ? (result.__segment ?? { kind: 'static', html: result.__html })\n : { kind: 'static', html: coerceRenderResult(result) };\n\n if (isFirst) {\n runFirstRender(rootEl, segment, bindings);\n prevStaticHtml = flattenWithoutListItems(segment);\n isFirst = false;\n } else {\n prevStaticHtml = runSubsequentRender(rootEl, segment, bindings, renderCtx, prevStaticHtml);\n }\n\n for (const listSeg of collectLists(segment).values()) {\n const binding = bindings.get(listSeg.id) as ListBinding;\n reconcileList(binding, listSeg);\n // KF-99: record the post-reconcile binding length so the next render's\n // granular path can detect drift (a prior render that threw mid-batch\n // leaves the binding shorter than the signal expects).\n renderCtx.bindingCounts.set(listSeg.id, binding.items.length);\n }\n });\n\n return () => {\n disposeEffect();\n listenerWarnObserver?.disconnect();\n // Clear the mounted marker so `mount(sameEl, ...)` after dispose works.\n delete (rootEl as unknown as Record<symbol, unknown>)[MOUNTED_MARKER];\n };\n}\n\n/**\n * First render of a mount: bulk-flatten the segment (items inlined, markers\n * around each list) into `rootEl.innerHTML`, then walk the markers to\n * register a `ListBinding` per list. The subsequent `reconcileList` pass is\n * a no-op (every row's a cache hit on the just-bound items).\n */\nfunction runFirstRender(\n rootEl: HTMLElement,\n segment: Segment,\n bindings: Map<string, ListBinding>,\n): void {\n rootEl.innerHTML = flatten(segment, true);\n bindListsFromMarkers(rootEl, segment, bindings, true);\n}\n\n/**\n * Subsequent render of a mount. Returns the new `prevStaticHtml` so the\n * caller can carry it forward.\n *\n * Two paths:\n *\n * - **KF-88 fast path**: when the static-surrounds string didn't change\n * byte-for-byte, `bindListsFromMarkers` has nothing to discover and the\n * diff would short-circuit on `isEqualNode` for every element it visited —\n * but the visit itself isn't free. Skip both to save ~8 ms per partial-\n * update / select-row / swap-rows render against the krausest harness.\n *\n * Trade-off (KF-117, documented in `docs/4-render.md` §4.4.2): any\n * attribute or child set imperatively on a kerf-managed element (e.g.\n * `el.setAttribute(...)`) survives across no-op re-renders because the\n * diff doesn't run to wipe it. When the surrounds DO change, the diff\n * runs and `morphAttributes` removes anything the JSX didn't authorise.\n * This matches the framework's \"smallest cut\" model: don't touch what\n * JSX didn't change.\n *\n * - **Surrounds-changed path**: clean up orphan bindings (lists that\n * disappeared from this render's segment), build a template from the\n * static-only HTML, run `morph()` over the surrounds with the\n * list-owned items as `ownedItems` (KF-102 round 2 — the morph skips\n * owned items individually but still walks every parent so non-list\n * siblings around an each() reconcile correctly), then bind any\n * newly-appearing lists.\n */\nfunction runSubsequentRender(\n rootEl: HTMLElement,\n segment: Segment,\n bindings: Map<string, ListBinding>,\n renderCtx: RenderContext,\n prevStaticHtml: string,\n): string {\n const currentStaticHtml = flattenWithoutListItems(segment);\n if (currentStaticHtml === prevStaticHtml) {\n return prevStaticHtml;\n }\n cleanupOrphanBindings(segment, bindings, renderCtx);\n const template = rootEl.cloneNode(false) as HTMLElement;\n template.innerHTML = currentStaticHtml;\n morph(rootEl, template, collectOwnedItems(bindings));\n bindListsFromMarkers(rootEl, segment, bindings, false);\n return currentStaticHtml;\n}\n\n/**\n * Coerce a non-`SafeHtml` render result to a safe HTML string. Nullish\n * values and booleans become `''` (render nothing) — matches the React /\n * Solid convention so `{cond ? <jsx/> : null}` and `{cond && <jsx/>}`\n * patterns work without each consumer adding a sentinel. Everything else\n * is stringified (numbers → `\"42\"`, strings pass through).\n */\nfunction coerceRenderResult(result: unknown): string {\n if (result === null || result === undefined) return '';\n if (result === false || result === true) return '';\n return String(result);\n}\n\n/**\n * Walk the live tree's comment nodes; every `<!--kf-list:{id}-->` marker\n * is the start anchor of a list inside `liveParent`. Bind the list (parent +\n * already-rendered item nodes between the marker and the tail). The marker\n * stays in the live DOM (KF-102 round 2): keeping it as a permanent\n * comment-node anchor lets the static-surrounds diff insert/remove/morph\n * non-list siblings around the list without needing to re-establish the\n * list's begin position.\n *\n * `inlinedItems` distinguishes the first-render path (where `flatten(seg,\n * true)` inlines item HTML right after the marker, so the marker's element\n * siblings *are* the list rows) from subsequent renders that newly\n * introduce a list (where `flattenWithoutListItems` emits only the marker\n * and the list reconciler populates items afterwards).\n *\n * Existing bindings whose marker is still in the DOM are left intact —\n * `bindings.has(id)` skips re-binding so the prior render's item nodes\n * survive across static-surrounds diffs.\n */\nfunction bindListsFromMarkers(\n rootEl: Element,\n segment: Segment,\n bindings: Map<string, ListBinding>,\n inlinedItems: boolean,\n): void {\n const lists = collectLists(segment);\n const found: Comment[] = [];\n collectComments(rootEl, found);\n for (const marker of found) {\n if (!marker.data.startsWith(LIST_MARKER_PREFIX)) continue;\n const id = marker.data.slice(LIST_MARKER_PREFIX.length);\n if (bindings.has(id)) continue; // existing binding survives the diff\n const listSeg = lists.get(id) as ListSegment;\n const liveParent = marker.parentElement as Element;\n const items: BoundItem[] = [];\n if (inlinedItems) {\n // KF-103: enforce the \"exactly one top-level element per row\" contract\n // on first render too. Without this check, a multi-root row inlined\n // via `flatten(seg, true)` would silently misalign the binding (each\n // bound item.node points at only the first of a row's 2+ elements,\n // and the leftover elements are picked up as \"next\" rows). The check\n // is per-row so we can pinpoint the offender by index.\n let next: Element | null = marker.nextElementSibling;\n for (let i = 0; i < listSeg.items.length && next !== null; i++) {\n validateInlinedRowMatch(listSeg.items[i].html, i, next);\n items.push({\n ref: listSeg.items[i].ref,\n cacheKey: listSeg.items[i].cacheKey,\n html: listSeg.items[i].html,\n node: next,\n });\n next = next.nextElementSibling;\n }\n }\n const binding: ListBinding = { liveParent, items, marker };\n // KF-173: dev-only one-shot warning if the first row has no id/data-key.\n if (items.length > 0) {\n maybeWarnMissingRowKey(items[0].node, 0, items[0].html, binding);\n }\n // Dev-mode: warn when an each() list is inside a data-morph-skip subtree\n // (list rows still update; static reactive siblings are frozen).\n maybeWarnEachInMorphSkip(id, liveParent, rootEl);\n bindings.set(id, binding);\n }\n}\n\n/**\n * KF-103: validate that `expectedHtml` (one row's render output) matches\n * the live `boundEl`'s `outerHTML` — confirming the row produced exactly\n * one top-level element. If they differ, parse the row in isolation and\n * throw a precise error mentioning the row index and the actual count.\n *\n * Fast path: outerHTML compare is a string equality check (zero allocs in\n * happy-dom; one alloc in V8). Only when they DON'T match (multi-root or\n * subtle browser-normalized single-root case) do we fall back to a full\n * per-row parse for the precise count.\n */\nfunction validateInlinedRowMatch(\n expectedHtml: string,\n index: number,\n boundEl: Element,\n): void {\n if (boundEl.outerHTML === expectedHtml) return;\n // The bound element's outerHTML differs from what we emitted. Parse the\n // expected html in isolation; if it's still single-root the difference\n // is whitespace / browser-normalization (e.g. `<br/>` → `<br>`) and\n // we proceed silently. Otherwise build the precise contract-violation\n // error from the shared helper.\n const { count } = parseRowTemplate(expectedHtml);\n if (count === 1) return;\n throw rowContractError(index, expectedHtml);\n}\n\n/**\n * Build the set of element nodes owned by `each()` list reconcilers, the\n * union of every binding's `items[].node`. The static-surrounds diff\n * skips these so list rows are invisible to the parent walk while\n * sibling reconciliation continues normally (KF-102 round 2).\n */\nfunction collectOwnedItems(bindings: Map<string, ListBinding>): Set<Element> {\n const owned = new Set<Element>();\n for (const b of bindings.values()) {\n for (const item of b.items) owned.add(item.node);\n }\n return owned;\n}\n\n/**\n * Remove items + binding entries for any list that's no longer present in\n * the new segment. The diff's trailing-removal pass would have removed the\n * marker (since the new template no longer emits one for this id), but\n * items are owned and stay protected from removal — so we drop them\n * explicitly here before the diff runs.\n */\nfunction cleanupOrphanBindings(\n segment: Segment,\n bindings: Map<string, ListBinding>,\n renderCtx: RenderContext,\n): void {\n const liveIds = collectLists(segment);\n for (const [id, binding] of bindings) {\n if (liveIds.has(id)) continue;\n for (const item of binding.items) {\n if (item.node.parentElement !== null) {\n item.node.parentElement.removeChild(item.node);\n }\n }\n if (binding.marker.parentElement !== null) {\n binding.marker.parentElement.removeChild(binding.marker);\n }\n bindings.delete(id);\n renderCtx.bindingCounts.delete(id);\n renderCtx.caches.delete(id);\n }\n}\n\n/**\n * Recursive collector for comment nodes — happy-dom's `TreeWalker` doesn't\n * surface `Node.COMMENT_NODE` despite accepting `NodeFilter.SHOW_COMMENT`,\n * so we walk children directly. Cheap (O(elements)) and portable.\n */\nfunction collectComments(node: Node, out: Comment[]): void {\n for (let c: Node | null = node.firstChild; c !== null; c = c.nextSibling) {\n if (c.nodeType === Node.COMMENT_NODE) out.push(c as Comment);\n else if (c.nodeType === Node.ELEMENT_NODE) collectComments(c, out);\n }\n}\n\n\n","/**\n * `toElement(jsx)` — JSX → DOM, with SVG-aware namespace handling.\n *\n * Single-root inputs return an `Element`. Multi-root inputs (text + element,\n * `<><svg/> label</>`, two icons side by side, …) return a `DocumentFragment`\n * containing every top-level node. The DOM insertion APIs (`appendChild`,\n * `replaceChildren`, `append`) inline a `DocumentFragment`'s children on\n * insert, so `parent.replaceChildren(toElement(<>{ICON} label</>))` does the\n * obvious thing — parent gets the svg AND the text, no silent loss.\n *\n * SVG namespacing: the HTML5 parser handles `<svg>` as foreign content\n * correctly even when wrapped in a fragment, so multi-root inputs containing\n * SVGs come out namespaced correctly via the `<template>.innerHTML` path. For\n * single-root SVG inputs the XML parser is preferred (stricter — catches\n * malformed markup the HTML5 parser would silently auto-correct). For orphan\n * SVG-namespace fragments without an `<svg>` wrapper (`<path/>`, `<g>`, …)\n * the input is wrapped in `<svg xmlns=...>` and XML-parsed.\n */\n\nimport type { SafeHtml } from './jsx-runtime.js';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\nconst SVG_FRAGMENT_TAGS = new Set([\n 'g', 'path', 'circle', 'rect', 'line', 'polygon', 'polyline', 'ellipse',\n 'text', 'tspan', 'defs', 'use', 'symbol', 'clipPath', 'mask', 'pattern',\n 'filter', 'marker', 'linearGradient', 'radialGradient', 'stop', 'image',\n 'foreignObject',\n]);\n\nconst EXCERPT_MAX_LEN = 100;\n\nfunction excerpt(html: string): string {\n const trimmed = html.trim();\n return trimmed.length > EXCERPT_MAX_LEN ? `${trimmed.slice(0, EXCERPT_MAX_LEN)}…` : trimmed;\n}\n\nfunction parseSvgOrThrow(html: string, label: string, originalHtml: string): Document {\n const doc = new DOMParser().parseFromString(html, 'image/svg+xml');\n const err = doc.querySelector('parsererror');\n if (err !== null) {\n throw new Error(`toElement: ${label} parse error — ${err.textContent}\\n input: ${excerpt(originalHtml)}`);\n }\n return doc;\n}\n\n// True when the fragment is effectively a single root — exactly one element\n// child, all sibling nodes whitespace-only text. Returns that element, else\n// null. The whitespace tolerance matches the pre-KF-232 behavior for inputs\n// like ` <svg/>\\n` (which were treated as a single SVG root).\nfunction singleRootElement(content: DocumentFragment): Element | null {\n if (content.children.length !== 1) return null;\n const onlyElement = content.firstElementChild;\n /* c8 ignore next — guarded by children.length === 1 above. */\n if (onlyElement === null) return null;\n for (const node of content.childNodes) {\n if (node === onlyElement) continue;\n if (node.nodeType !== Node.TEXT_NODE) return null;\n /* c8 ignore next — `textContent` on a TEXT_NODE is always a string; the `??` is a TypeScript-only guard. */\n if ((node.textContent ?? '').trim() !== '') return null;\n }\n return onlyElement;\n}\n\nexport function toElement(jsx: SafeHtml | string): Element | DocumentFragment {\n const html = typeof jsx === 'string' ? jsx : jsx.toString();\n\n // First pass: HTML <template> parse. This gives us correct namespacing for\n // `<svg>` (foreign content), reveals the multi-root vs single-root shape,\n // and is the universal fallback path. Orphan SVG fragments without an\n // `<svg>` wrapper are the one case that needs a different parser — handled\n // below.\n const t = document.createElement('template');\n t.innerHTML = html;\n const content = t.content;\n\n const single = singleRootElement(content);\n\n if (single !== null) {\n const tag = single.tagName.toLowerCase();\n\n // Single SVG root → re-parse via XML for strict validation. The HTML5\n // parser silently auto-corrects malformed SVG (`<svg><unclosed</svg>`),\n // which is worse than throwing. Trim so trailing whitespace in the input\n // doesn't trip up the XML parser.\n if (tag === 'svg') {\n return parseSvgOrThrow(html.trim(), 'SVG', html).documentElement;\n }\n\n // Single orphan SVG-namespace fragment (`<path/>`, `<g>`, …) — the HTML5\n // parser puts these in the XHTML namespace, so wrap in `<svg>` and\n // XML-parse to get the right namespace on the returned element.\n if (SVG_FRAGMENT_TAGS.has(tag)) {\n const wrapped = `<svg xmlns=\"${SVG_NS}\">${html}</svg>`;\n const doc = parseSvgOrThrow(wrapped, 'SVG fragment', html);\n const first = doc.documentElement.firstElementChild;\n /* c8 ignore next 2 — defensive: a successful XML parse of a wrapped svg always yields ≥1 child. */\n if (first === null) throw new Error(`toElement: SVG fragment produced no element\\n input: ${excerpt(html)}`);\n return first;\n }\n\n return single;\n }\n\n // Multi-root (or no roots): return the parsed DocumentFragment so the caller\n // can splat all the top-level nodes into their container via appendChild /\n // replaceChildren / append. If the input produced nothing at all, throw —\n // there's no useful Node to hand back.\n if (content.childNodes.length === 0) {\n throw new Error(`toElement: produced no element\\n input: ${excerpt(html)}`);\n }\n if (content.children.length === 0) {\n // No element children at all — only text or comments. Same \"no element\"\n // failure as the empty case; toElement's name implies at least one\n // element somewhere.\n throw new Error(`toElement: produced no element\\n input: ${excerpt(html)}`);\n }\n return content;\n}\n"]}
1
+ {"version":3,"sources":["../src/attrSelector.ts","../src/delegate.ts","../src/dev-each-warn.ts","../src/each.ts","../src/morph.ts","../src/dev-listener-warn.ts","../src/list-binding.ts","../src/list-reconcile-fast-paths.ts","../src/list-reconcile-focus.ts","../src/utils/rowContract.ts","../src/list-reconcile-granular.ts","../src/list-reconcile-inplace.ts","../src/list-reconcile-snapshot.ts","../src/list-reconcile.ts","../src/mount.ts","../src/toElement.ts"],"names":["attr","isOptedIn","TEXT_NODE","ELEMENT_NODE","isUserAgentOwnedAttr","parseSingleRow"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `attr(name, value)` — create a pre-computed attribute descriptor (static form).\n * `attr(name)` — create a per-render factory for dynamic attribute values (dynamic form).\n *\n * **Static form** — best for fixed action names, filter keys, role values, etc.\n * Escapes once at module-load time; produces a full {@link AttrSpec} with\n * `.name`, `.value`, `.selector`, and `.attrs`.\n *\n * const ACTIONS = {\n * toggle: attr('data-action', 'toggle'),\n * remove: attr('data-action', 'remove'),\n * } as const satisfies Record<string, AttrSpec<'data-action'>>;\n *\n * // In JSX — spread .attrs (rename-safe; no hardcoded attribute name):\n * <button {...ACTIONS.toggle.attrs}>Toggle</button>\n *\n * // In delegate — use the pre-computed selector:\n * delegate(root, 'click', ACTIONS.toggle.selector, handler);\n *\n * **Dynamic form** — best for per-row data like `data-id`, where the value\n * changes per item but the attribute name is constant.\n * The name is validated and pre-escaped at definition time; calling the\n * returned factory is cheap (just escape the value and freeze the object).\n *\n * const ITEM = { id: attr('data-id') } as const;\n *\n * // In JSX — call the factory inline:\n * <li {...ITEM.id(String(item.id))}>…</li>\n *\n * For ad-hoc compound selectors, concatenate `.selector` strings:\n *\n * delegate(root, 'click',\n * ACTIONS.toggle.selector + attr('data-id', id).selector,\n * handler);\n *\n * Escaping:\n * - Attribute name: escaped as a CSS identifier via `cssEscapeIdent`, which is\n * an SSR-safe (no `CSS.escape`) adaptation of the Mathias Bynens polyfill\n * (https://github.com/nicktindall/cyclon.p2p-common, MIT licensed). Handles\n * control chars, leading digits, non-ASCII, and CSS metacharacters.\n * - Attribute value: embedded in double quotes as a CSS string. Backslashes and\n * double-quote characters are backslash-escaped; control characters are\n * hex-escaped per CSS Syntax Level 3 §3.4.\n *\n * Throws on an empty attribute name (not a valid CSS identifier).\n */\n\n/** Descriptor created by the static {@link attr} overload. */\nexport interface AttrSpec<N extends string = string, V extends string = string> {\n /** The raw attribute name passed to `attr()`. */\n readonly name: N;\n /** The raw attribute value passed to `attr()`. */\n readonly value: V;\n /** Pre-computed `[name=\"value\"]` CSS selector string, safe to pass to `delegate()`. */\n readonly selector: string;\n /** Spreadable JSX object — `{ [name]: value }` — keeps the attribute name out of JSX literals. */\n readonly attrs: { readonly [K in N]: V };\n}\n\n/**\n * Escape `value` as a CSS identifier (for attribute names, id fragments, etc.).\n * Adapted from the CSS.escape polyfill by Mathias Bynens (MIT).\n */\nfunction cssEscapeIdent(value: string): string {\n if (value === '') {\n throw new Error('attr: attribute name must not be empty');\n }\n const str = String(value);\n let result = '';\n for (let i = 0; i < str.length; i++) {\n const cp = str.charCodeAt(i);\n const ch = str.charAt(i);\n\n // U+0000 NULL → replacement character\n if (cp === 0x0000) {\n result += '�';\n continue;\n }\n // Control characters and DEL: hex-escape\n if ((cp >= 0x0001 && cp <= 0x001F) || cp === 0x007F) {\n result += '\\\\' + cp.toString(16) + ' ';\n continue;\n }\n // Leading digit: hex-escape to avoid \"-NN\" / \"3px\"-style ambiguity\n if (i === 0 && cp >= 0x0030 && cp <= 0x0039) {\n result += '\\\\' + cp.toString(16) + ' ';\n continue;\n }\n // Second char is a digit when first is '-' (e.g. \"-3foo\"): hex-escape digit\n if (\n i === 1 &&\n cp >= 0x0030 && cp <= 0x0039 &&\n str.charCodeAt(0) === 0x002D\n ) {\n result += '\\\\' + cp.toString(16) + ' ';\n continue;\n }\n // Non-ASCII, safe identifier chars (letters, digits, underscore, hyphen)\n if (\n cp >= 0x0080 ||\n cp === 0x002D || // `-`\n cp === 0x005F || // `_`\n (cp >= 0x0030 && cp <= 0x0039) || // 0-9\n (cp >= 0x0041 && cp <= 0x005A) || // A-Z\n (cp >= 0x0061 && cp <= 0x007A) // a-z\n ) {\n result += ch;\n continue;\n }\n // Everything else: backslash-escape\n result += '\\\\' + ch;\n }\n return result;\n}\n\n/**\n * Escape `value` as a CSS double-quoted string (for attribute values in\n * `[attr=\"value\"]` selectors).\n */\nfunction escapeCSSString(value: string): string {\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const cp = value.charCodeAt(i);\n const ch = value.charAt(i);\n if (cp === 0x0000) {\n result += '�';\n } else if ((cp >= 0x0001 && cp <= 0x001F) || cp === 0x007F) {\n // Control chars: hex-escape\n result += '\\\\' + cp.toString(16) + ' ';\n } else if (cp === 0x005C) {\n // Backslash\n result += '\\\\\\\\';\n } else if (cp === 0x0022) {\n // Double quote (the string delimiter we use)\n result += '\\\\\"';\n } else {\n result += ch;\n }\n }\n return result;\n}\n\n/**\n * Static overload — pre-computes the full descriptor at definition time.\n * Returns an {@link AttrSpec} with `.name`, `.value`, `.selector`, and `.attrs`.\n */\nexport function attr<N extends string, V extends string>(name: N, value: V): AttrSpec<N, V>;\n\n/**\n * Dynamic overload — pre-validates and pre-escapes the attribute name, returns a\n * factory that accepts a per-render value and produces a frozen spreadable object.\n * Use for per-row attributes like `data-id` where the value changes per item.\n * The optional `V` generic constrains which values the factory accepts:\n * `attr<'data-id', 'a'|'b'>('data-id')` → `(value: 'a'|'b') => { 'data-id': 'a'|'b' }`.\n * Leaving both generics off infers `N` from the argument and defaults `V` to `string`.\n */\nexport function attr<N extends string, V extends string = string>(name: N): (value: V) => { readonly [K in N]: V };\n\nexport function attr<N extends string, V extends string>(\n name: N,\n value?: V,\n): AttrSpec<N, V> | ((value: string) => { readonly [K in N]: string }) {\n const escapedName = cssEscapeIdent(name); // validates + pre-escapes name in both paths\n if (value !== undefined) {\n const selector = `[${escapedName}=\"${escapeCSSString(value)}\"]`;\n return Object.freeze({\n name,\n value,\n selector,\n attrs: Object.freeze({ [name]: value }) as { readonly [K in N]: V },\n }) as AttrSpec<N, V>;\n }\n return (v: string): { readonly [K in N]: string } =>\n Object.freeze({ [name]: v }) as { readonly [K in N]: string };\n}\n","/**\n * Tiny event-delegation helpers. Replace per-element `addEventListener` calls\n * (which don't survive morph re-renders for nodes the diff creates) with one\n * listener at the morph-root that dispatches via `closest()`.\n *\n * Three-tier listener model:\n *\n * - Tier 1 (bubbling events) — use `delegate()`.\n * click, input, change, submit, mousedown/up, keydown/up, pointerdown/up/move,\n * drag*, drop, contextmenu, wheel, copy/paste/cut, focusin/focusout.\n *\n * `delegate()` also auto-promotes the well-known non-bubbling event\n * types (`focus`, `blur`, `scroll`, `load`, `error`, `mouseenter`,\n * `mouseleave`) to the capture phase under the hood, so the call site\n * looks identical for \"interactive thing happens on a descendant\"\n * regardless of whether that event bubbles. Selector matching stays\n * `closest()`-style — the same as for bubbling events — so a wrapper\n * selector like `'.field-row'` still matches when the event fires on\n * a descendant `<input>`.\n *\n * - Tier 2 (explicit capture) — use `delegateCapture()`.\n * The escape hatch for cases the auto-promotion list doesn't cover, or\n * when you want capture-phase semantics and direct `matches()`-style\n * selector matching (no walk-up).\n *\n * - Tier 3 (per-element instances / library-owned subtrees) — mark the\n * host element with `data-morph-skip` and manage the library's\n * lifecycle directly. No delegation helper applies.\n */\n\nimport { warnIfInsideEffect } from './dev-delegate-warn.js';\n\n/**\n * Event types that don't bubble and so wouldn't reach a root-level\n * bubble-phase listener. `delegate()` flips to capture for these; the\n * caller doesn't need to know or care.\n *\n * Membership is conservative — it covers the cases that \"should obviously\n * work\" with delegate() but otherwise don't. For exotic non-bubbling events\n * (custom events, less-common DOM events) the explicit `delegateCapture()`\n * remains the escape hatch.\n */\nconst NON_BUBBLING = new Set<string>([\n 'focus',\n 'blur',\n 'scroll',\n 'load',\n 'error',\n 'mouseenter',\n 'mouseleave',\n]);\n\n/**\n * Validate a CSS selector at registration time, so a typo throws immediately\n * with the bad selector quoted instead of producing a cryptic DOMException\n * the first time a matching event fires.\n */\nfunction assertValidSelector(selector: string, fn: string): void {\n try {\n document.createElement('div').matches(selector);\n } catch {\n throw new Error(\n `${fn}: invalid selector \"${selector}\". `\n + 'Pass a valid CSS selector (e.g. \\'[data-action=\"add\"]\\', \\'.btn\\', \\'input\\').',\n );\n }\n}\n\n/**\n * Delegation that \"just works\" for both bubbling and the common non-bubbling\n * events. Installs ONE listener on `rootEl`; for known non-bubblers (see\n * `NON_BUBBLING` above) the listener is registered on the capture phase so\n * it actually reaches the target, otherwise on the bubble phase. Either way,\n * matching walks up from `event.target` via `closest(selector)` and fires\n * `handler(event, matched)` if the match is inside `rootEl`.\n *\n * The generic `T` narrows the second handler argument to the expected element\n * type — `delegate<HTMLButtonElement>(root, 'click', 'button', (e, btn) => btn.value)`\n * — so consumers can avoid casts. Defaults to `Element` for untyped calls.\n *\n * Returns a disposer that removes the listener.\n *\n * Usage (pseudo-code — see examples for live ones):\n * delegate(rootEl, 'click', '[data-action=\"add\"]', handlerFn);\n * delegate(rootEl, 'focus', 'input', handlerFn); // auto-capture\n */\nexport function delegate<T extends Element = Element>(\n rootEl: HTMLElement,\n type: string,\n selector: string,\n handler: (event: Event, target: T) => void,\n): () => void {\n assertValidSelector(selector, 'delegate');\n warnIfInsideEffect('delegate');\n const listener = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const matched = target.closest(selector);\n if (matched !== null && rootEl.contains(matched)) {\n handler(event, matched as T);\n }\n };\n const capture = NON_BUBBLING.has(type);\n rootEl.addEventListener(type, listener, capture);\n return () => {\n rootEl.removeEventListener(type, listener, capture);\n };\n}\n\n/**\n * Capture-phase delegation — for non-bubbling events (`focus`, `blur`,\n * `scroll`, `load`, `error`). Reaches descendants of `rootEl` that match\n * `selector` regardless of how many times the diff has rebuilt them.\n *\n * The generic `T` narrows the second handler argument to the expected element\n * type, mirroring `delegate<T>()`. Defaults to `Element` for untyped calls.\n *\n * Usage (pseudo-code — see examples for live ones):\n * delegateCapture(rootEl, 'focus', 'input, textarea', handlerFn);\n */\nexport function delegateCapture<T extends Element = Element>(\n rootEl: HTMLElement,\n type: string,\n selector: string,\n handler: (event: Event, target: T) => void,\n): () => void {\n assertValidSelector(selector, 'delegateCapture');\n warnIfInsideEffect('delegateCapture');\n const listener = (event: Event): void => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n if (target.matches(selector) && rootEl.contains(target)) {\n handler(event, target as T);\n }\n };\n rootEl.addEventListener(type, listener, true);\n return () => {\n rootEl.removeEventListener(type, listener, true);\n };\n}\n","/**\n * Dev-mode warning for `each()` inside `data-morph-skip` subtrees\n * (KERF_DEV_WARN_EACH_IN_MORPH_SKIP=1).\n *\n * When the opt-in env var is set, `mount()` calls `maybeWarnEachInMorphSkip()`\n * after establishing a list binding. The function walks from `liveParent` up to\n * `rootEl`; if any ancestor has `data-morph-skip`, it fires a one-shot warning.\n *\n * Why the pattern matters: `data-morph-skip` makes the morph short-circuit\n * before visiting the element's children, so any static JSX reading signals\n * inside the skipped subtree is silently frozen. `each()` rows are NOT frozen —\n * the keyed reconciler runs independently and still updates them. This asymmetry\n * (rows update, signal-reactive siblings don't) is surprising enough to warrant a\n * dev-time callout.\n *\n * Why opt-in: wrapping a library-owned subtree in `data-morph-skip` and\n * legitimately placing an `each()` inside is uncommon but possible (e.g., the\n * library expects to own the host while kerf manages the list). The opt-in keeps\n * the diagnostic available for projects that want it without penalising projects\n * that intentionally use this pattern.\n */\n\nconst warnedIds = new Set<string>();\n\nfunction isOptedIn(): boolean {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n if (proc?.env?.NODE_ENV === 'production') return false;\n return proc?.env?.KERF_DEV_WARN_EACH_IN_MORPH_SKIP === '1';\n}\n\nfunction hasMorphSkipAncestor(el: Element, root: Element): boolean {\n let ancestor: Element | null = el.parentElement;\n while (ancestor !== null && ancestor !== root) {\n if ((ancestor as HTMLElement).dataset.morphSkip !== undefined) return true;\n ancestor = ancestor.parentElement;\n }\n return false;\n}\n\nexport function maybeWarnEachInMorphSkip(\n id: string,\n liveParent: Element,\n rootEl: Element,\n): void {\n if (!isOptedIn()) return;\n /* c8 ignore next — mount() gates on bindings.has(id) before calling this; doubly-guards direct callers */\n if (warnedIds.has(id)) return;\n if (!hasMorphSkipAncestor(liveParent, rootEl)) return;\n warnedIds.add(id);\n console.warn(\n `kerf: each() list '${id}' is inside a data-morph-skip subtree. `\n + 'The keyed reconciler still updates the list rows, but any static signal-reactive JSX '\n + 'inside the same skipped ancestor (e.g. <p>{count.value}</p>) is frozen — '\n + 'the morph never visits it. Remove data-morph-skip from any element that contains '\n + 'reactive JSX content and reserve it for truly library-owned hosts. '\n + 'Set KERF_DEV_WARN_EACH_IN_MORPH_SKIP=0 (or unset it) to silence this warning.',\n );\n}\n\n/** Test helper — resets the one-shot dedup set for unit tests. */\nexport function _resetWarnedForTests(): void {\n warnedIds.clear();\n}\n\n// ---------------------------------------------------------------------------\n// KERF_DEV_WARN_DUPLICATE_EACH_KEYS — duplicate cacheKey values warning\n// ---------------------------------------------------------------------------\n\nconst warnedDupIds = new Set<string>();\n\nfunction isOptedInDupKeys(): boolean {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n if (proc?.env?.NODE_ENV === 'production') return false;\n return proc?.env?.KERF_DEV_WARN_DUPLICATE_EACH_KEYS === '1';\n}\n\n/**\n * Warn when two or more items in the same `each()` list produce the same\n * `cacheKey` value. Duplicate cacheKey values don't cause incorrect DOM\n * behavior (the per-item HTML cache is keyed by object identity, not cacheKey),\n * but they're a reliable signal that the cacheKey function doesn't uniquely\n * identify rows — which means kerf can't tell apart the affected rows for\n * memoization purposes, and external-state-driven re-renders may return stale\n * cached HTML for some items.\n *\n * Called from `eachSnapshotById` only when a `cacheKey` function was provided.\n * `segItems` carries the already-computed cacheKey value per item, so this\n * function never calls `cacheKey(item, i)` a second time.\n */\nexport function maybeWarnDuplicateCacheKeys(\n id: string,\n segItems: readonly { cacheKey: unknown }[],\n): void {\n if (!isOptedInDupKeys()) return;\n if (warnedDupIds.has(id)) return;\n const seen = new Set<unknown>();\n for (const si of segItems) {\n if (seen.has(si.cacheKey)) {\n warnedDupIds.add(id);\n console.warn(\n `kerf: each() list '${id}' has duplicate cacheKey values (duplicate: ${String(si.cacheKey)}). `\n + 'The cacheKey function should return a unique value per row so kerf can tell apart items '\n + 'for memoization — duplicate values cause some rows to return stale cached HTML when '\n + 'external state that affects their render changes. '\n + 'Set KERF_DEV_WARN_DUPLICATE_EACH_KEYS=0 (or unset it) to silence this warning.',\n );\n return;\n }\n seen.add(si.cacheKey);\n }\n}\n\n/** Test helper — resets the duplicate-key dedup set for unit tests. */\nexport function _resetDupWarnedForTests(): void {\n warnedDupIds.clear();\n}\n","/**\n * `each(items, render, cacheKey?)` — keyed list iteration with per-item memoization.\n *\n * Drops in as the body of a list-rendering JSX expression inside a `mount()`\n * render function. Returns a `SafeHtml` carrying a structured list segment,\n * so `mount()` can run a native keyed reconciler instead of the general-\n * purpose morph for these children.\n *\n * Two layers of optimization:\n *\n * 1. Per-item memoization. `render(item)` is skipped for items whose object\n * identity (and optional `cacheKey`) are unchanged since the previous\n * call. Their HTML strings come from a `WeakMap` keyed by item reference.\n * The immutable-update style (\"replace the row object\" instead of \"mutate\n * it\") makes the cache work automatically.\n *\n * 2. Structural handoff. `mount()` recognizes the list segment and bypasses\n * the parse-the-whole-table round trip: only fresh items get parsed (one\n * at a time, into the smallest detached element), and only changed rows\n * get patched in the live DOM. Unchanged rows are physically the same\n * nodes they were before — never visited.\n *\n * `cacheKey` is a passive comparator — it covers the case where external\n * state, not the item itself, drives what the row should render (e.g. a\n * \"currently selected\" id flips a CSS class on one row). Same item identity\n * but a different `cacheKey` return value means \"the cached HTML is stale —\n * re-render this row.\" Not a reactive subscription: it's evaluated once per\n * mount-effect run and compared against the previous run's return value. If\n * you don't pass `cacheKey`, only object-identity changes invalidate the\n * cache. (Renamed from `key` for clarity — it shared a name with React's\n * `key` prop but has different semantics; the new name says what the\n * parameter actually does. Positional callers — the canonical form — are\n * unaffected.)\n *\n * Items must be objects (cache is a `WeakMap`); wrap primitives if you need\n * to iterate them. Each item's render output must produce exactly one\n * top-level element — the list reconciler binds one live DOM node per item.\n */\n\nimport type { ArraySignal } from './array-signal.js';\nimport { maybeWarnDuplicateCacheKeys } from './dev-each-warn.js';\nimport type { SafeHtml } from './jsx-runtime.js';\nimport { granularListSafeHtml, isSafeHtml, listSafeHtml } from './jsx-runtime.js';\nimport type { ArrayPatchInternal } from './segment.js';\n\n/**\n * Cross-bundle brand check for `ArraySignal` instances (KF-95). The\n * `arraySignal` factory + class live in their own subpath\n * (`kerfjs/array-signal`); this module knows nothing about that\n * subpath at runtime — it identifies instances by the brand symbol\n * stamped on them. Apps that never import `arraySignal` shed the\n * ~1 KB of class code without breaking the structural contract here.\n */\nconst ARRAY_SIGNAL_BRAND = Symbol.for('kerfjs.ArraySignal');\n\nfunction isArraySignal<T extends object>(value: unknown): value is ArraySignal<T> {\n return typeof value === 'object'\n && value !== null\n && (value as Record<symbol, unknown>)[ARRAY_SIGNAL_BRAND] === true;\n}\n\ninterface CacheEntry {\n cacheKey: unknown;\n html: string;\n}\n\n/**\n * Per-render context passed in by `mount()` for the duration of one render\n * pass. Carries (a) a counter that assigns a stable list id to the n-th\n * `each()` call across renders within a mount, and (b) a per-mount cache map\n * keyed on those list ids.\n *\n * Why per-(mount, listId) keying for the cache:\n * - Same `each()` callsite across renders within a mount → same id → same\n * cache → cache hits work, even when the JSX render fn is an inline arrow\n * that's a fresh function reference on every closure run (the typical\n * pattern; KF-87 fixed the regression where this broke).\n * - Different `each()` callsites within the same mount → different ids →\n * separate caches → no cross-callsite collision (the case KF-73 fixed,\n * preserved here).\n * - Different mounts → different `RenderContext` instances (the cache map\n * lives on `mount()`'s closure) → separate caches.\n *\n * Outside a `mount()` render (e.g. `each(...).toString()` for SSR string\n * production) `context` is null and items are rendered every call —\n * caching is a `mount()` feature, not a global one.\n */\nexport interface RenderContext {\n counter: number;\n caches: Map<string, WeakMap<object, CacheEntry>>;\n /**\n * Per-list-id record of the binding's `items.length` after the most recent\n * successful reconcile. Maintained by `mount()` via `_setBindingCount`. The\n * granular path consults this to detect drift between the live binding and\n * the arraySignal — drift means a previous render threw mid-reconcile (or\n * a granular path was bypassed externally), so the next render forces a\n * snapshot rebuild rather than applying patches against a stale binding.\n */\n bindingCounts: Map<string, number>;\n}\n\nlet context: RenderContext | null = null;\n\nexport function _setRenderContext(c: RenderContext | null): void {\n context = c;\n}\n\nexport function each<T extends object>(\n items: readonly T[] | ArraySignal<T>,\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey?: (item: T, index: number) => unknown,\n): SafeHtml {\n // KF-92 fast path: when items is an ArraySignal AND we're inside a mount\n // render context AND patches have queued since the last drain, emit a\n // granular list segment that the list reconciler applies in O(patches)\n // instead of O(N). Detection via the brand symbol (KF-95) — the\n // `arraySignal` class lives in the `kerfjs/array-signal` subpath and is\n // not imported here at runtime.\n if (isArraySignal<T>(items) && context !== null) {\n return eachGranular(items, render, cacheKey);\n }\n const snapshotItems: readonly T[] = isArraySignal<T>(items)\n ? items.value as readonly T[]\n : items;\n return eachSnapshot(snapshotItems, render, cacheKey);\n}\n\nfunction eachSnapshot<T extends object>(\n items: readonly T[],\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey: ((item: T, index: number) => unknown) | undefined,\n): SafeHtml {\n let id: string;\n if (context !== null) {\n id = String(context.counter++);\n } else {\n id = 'orphan';\n }\n return eachSnapshotById(items, render, cacheKey, id);\n}\n\n/**\n * Granular path for `arraySignal`-backed lists. Drains queued patches and\n * emits a list segment that the reconciler applies to the existing binding\n * directly — no full iteration of the snapshot, no O(N) classify pass.\n *\n * On the very first render of a list, the binding doesn't exist yet, so\n * the reconciler falls through to the snapshot path. Subsequent renders\n * of the same list (where the binding now exists) take the granular path\n * whenever there are patches to apply.\n */\nfunction eachGranular<T extends object>(\n sig: ArraySignal<T>,\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey: ((item: T, index: number) => unknown) | undefined,\n): SafeHtml {\n // We're inside a mount context (caller-checked).\n const ctx = context as RenderContext;\n const id = String(ctx.counter++);\n // KF-98: a tracked binding count means a prior render of this mount has\n // successfully reconciled this list. On the very first render (no count\n // recorded yet) the granular reconciler has no binding to apply patches\n // to, so any pre-mount mutations would silently produce an empty list.\n // Drain the queue (the snapshot already reflects those mutations) and\n // take the snapshot path; the count will be recorded for the next render.\n const previousBindingCount = ctx.bindingCounts.get(id);\n const patches = sig._consumePatches();\n const snapshot = sig.value as readonly T[];\n\n // First render of this list, no patches, or any 'replace' patch → snapshot.\n // No patches: typical re-render triggered by a non-arraySignal signal change.\n // 'replace': wholesale reset — granular can't help; the snapshot already\n // reflects the post-replace state (and any subsequent granular ops).\n if (previousBindingCount === undefined || patches.length === 0) {\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n // KF-99: detect drift between the live binding and the arraySignal. After\n // a clean prior reconcile, `previousBindingCount + (#inserts - #removes)`\n // must equal `snapshot.length`. If it doesn't, a previous render threw\n // mid-reconcile and left the binding inconsistent with the signal — fall\n // back to the snapshot path, which classifies fresh against `snapshot`\n // and rebuilds the binding to match.\n let netDelta = 0;\n for (const p of patches) {\n if (p.type === 'insert') netDelta += 1;\n else if (p.type === 'remove') netDelta -= 1;\n else if (p.type === 'replace') {\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n }\n // Defensive: triggered only when an external party drains `_consumePatches()`\n // or mutates `_items` behind arraySignal's back, OR when a previous reconcile\n // threw mid-DOM-op (rare; not naturally reachable in tests since apply* ops\n // don't throw on well-formed row HTML).\n /* c8 ignore next 3 */\n if (previousBindingCount + netDelta !== snapshot.length) {\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n\n // Granular path: pre-render every insert/update HTML at JSX-eval time so\n // a throwing render is caught here and we can fall back to the snapshot\n // path (KF-99). Without this, a throw mid-batch would leave patches drained\n // (already done above), the signal mutated, and the live DOM unchanged —\n // permanent divergence with no recovery.\n const renderFnInternal = (item: object, index: number): string => {\n const out = render(item as T, index);\n return isSafeHtml(out) ? out.toString() : out;\n };\n const internalPatches = new Array<ArrayPatchInternal>(patches.length);\n try {\n for (let i = 0; i < patches.length; i++) {\n const p = patches[i];\n if (p.type === 'insert' || p.type === 'update') {\n internalPatches[i] = {\n type: p.type, index: p.index, item: p.item as object,\n html: renderFnInternal(p.item as object, p.index),\n };\n } else {\n internalPatches[i] = p as ArrayPatchInternal;\n }\n }\n } catch {\n // Pre-render threw. The snapshot already reflects every mutation\n // (arraySignal mutates _items eagerly at the call site), but the snapshot\n // path is going to throw on the same bad item too — leaving the binding\n // out of sync with the signal. Clear the binding count so the NEXT\n // render (after the user fixes the bad item) doesn't see the previous\n // render's count and falsely conclude there's no drift; instead it'll\n // take the snapshot path and rebuild from scratch.\n ctx.bindingCounts.delete(id);\n return eachSnapshotById(snapshot, render, cacheKey, id);\n }\n // The `items` field is left empty for the granular case — the reconciler\n // doesn't need it; every insert/update patch carries pre-rendered HTML.\n return granularListSafeHtml(id, [], internalPatches);\n}\n\n/** Like eachSnapshot but uses a pre-allocated id (caller already advanced the counter). */\nfunction eachSnapshotById<T extends object>(\n items: readonly T[],\n render: (item: T, index: number) => SafeHtml | string,\n cacheKey: ((item: T, index: number) => unknown) | undefined,\n id: string,\n): SafeHtml {\n let cache: WeakMap<object, CacheEntry> | null = null;\n if (context !== null) {\n let c = context.caches.get(id);\n if (c === undefined) {\n c = new WeakMap<object, CacheEntry>();\n context.caches.set(id, c);\n }\n cache = c;\n }\n const segItems = new Array<{ ref: object; cacheKey: unknown; html: string }>(items.length);\n const seen = new Set<object>();\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (typeof item !== 'object' || item === null) {\n throw new Error(\n `each(): items must be objects (the per-item HTML cache is a WeakMap), got ${item === null ? 'null' : typeof item} at index ${i}. `\n + 'Wrap primitives if you need to iterate them, e.g. items.map(v => ({ v })).',\n );\n }\n if (seen.has(item)) {\n throw new Error(\n `each(): the same object reference appears at multiple indices in items (first seen earlier, again at index ${i}). `\n + 'The per-item HTML cache is keyed on object identity, so duplicate references break the keyed reconciler and can leak DOM nodes on re-render. '\n + 'Use a fresh object per row (e.g. items.map(o => ({ ...o })) before passing to each()).',\n );\n }\n seen.add(item);\n const k = cacheKey ? cacheKey(item, i) : undefined;\n let html: string;\n const cached = cache !== null ? cache.get(item) : undefined;\n if (cached !== undefined && cached.cacheKey === k) {\n html = cached.html;\n } else {\n const out = render(item, i);\n html = isSafeHtml(out) ? out.toString() : out;\n if (cache !== null) cache.set(item, { cacheKey: k, html });\n }\n segItems[i] = { ref: item, cacheKey: k, html };\n }\n if (cacheKey !== undefined) {\n maybeWarnDuplicateCacheKeys(id, segItems);\n }\n return listSafeHtml(id, segItems);\n}\n","/**\n * `morph(liveRoot, template)` — minimum-mutation DOM reconciliation.\n *\n * Public primitive (KF-150): one-shot reconciliation against an\n * already-populated element. `mount()` first paints by writing\n * `innerHTML`; `morph()` is the \"I have a live tree and a template,\n * reconcile them in place\" sibling. Use it for SSR hydration of static\n * fragments, page-refresh diffs, third-party widget remounts, etc.\n *\n * Replaces our previous dependency on `morphdom`. The algorithm is the\n * classic two-tree walk: match children by key (id, then data-key, then\n * positional same-tag), morph matches in place, insert / remove / clone\n * the rest. Specialized for what kerf needs:\n *\n * - `childrenOnly` is always true; the live root is never replaced.\n * - Per-element short-circuits: `data-morph-skip` (library-owned, leave\n * element AND subtree verbatim), `data-morph-skip-children` (KF-152 —\n * morph attrs on the element, leave its subtree verbatim — for\n * client-hydrated slots whose loading/state classes still need to flow\n * through), and `isEqualNode` (byte-identical, no work needed).\n * - **`data-morph-preserve`** (KF-151) is honored in the trailing-removal\n * pass: an unmatched live element with this attribute is skipped instead\n * of removed. Lets imperatively-injected nodes (autoplay `<video>`s,\n * tour-widget tooltips, analytics pixels) survive across renders without\n * having to `data-morph-skip` the entire parent.\n * - **`ownedItems`** is the set of element nodes owned by an `each()`\n * list reconciler. The morph skips them in every children walk —\n * they're not added to the keyed-lookup map, the from-cursor advances\n * past them, and the trailing-removal pass leaves them in place. This\n * lets each() coexist with non-list siblings inside the same parent\n * (KF-102 round 2): the morph still walks the parent's children to\n * reconcile siblings, but never disturbs list rows. The parameter is an\n * internal coordination channel between `mount()` and the reconciler;\n * public callers should omit it (the default empty set is correct for\n * any tree that isn't being managed by an active `mount()`).\n * - Focused text inputs (`<input>`/`<textarea>`) keep their value +\n * selection across the morph; focused `[contenteditable]` keeps its\n * entire subtree (typed content + caret + multi-range selection).\n *\n * Algorithm credit: based on the design of\n * https://github.com/patrick-steele-idem/morphdom by Patrick Steele-Idem\n * (MIT licensed). Reimplemented here so kerf can specialize the hot paths\n * (segment-aware list dispatch, lighter callback surface) and drop the\n * runtime dependency. Original copyright preserved in `LICENSE`.\n */\n\nimport type { SafeHtml } from './jsx-runtime.js';\n\nconst ID_KEY_PREFIX = 'id:';\nconst DATA_KEY_PREFIX = 'data-key:';\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\nfunction getNodeKey(node: Node): string | undefined {\n if (node.nodeType !== ELEMENT_NODE) return undefined;\n const el = node as HTMLElement;\n if (el.id !== '') return `${ID_KEY_PREFIX}${el.id}`;\n if (el.dataset !== undefined && el.dataset.key !== undefined) {\n return `${DATA_KEY_PREFIX}${el.dataset.key}`;\n }\n return undefined;\n}\n\nconst EMPTY_OWNED: ReadonlySet<Element> = new Set();\n\n/**\n * Reconcile the children of `liveRoot` to match `template`.\n *\n * `template` can be an `Element` (used directly), a `SafeHtml`, or a raw\n * HTML string — the latter two are stringified and parsed into a transient\n * element whose tag matches `liveRoot`. The active text-entry / focused-\n * contenteditable preservation rules apply in all cases.\n *\n * `ownedItems` is an internal coordination channel for `mount()`'s list\n * reconciler; public callers should omit it.\n */\nexport function morph(\n liveRoot: Element,\n template: Element | SafeHtml | string,\n ownedItems: ReadonlySet<Element> = EMPTY_OWNED,\n): void {\n const templateEl: Element = isElementNode(template)\n ? template\n : parseTemplate(liveRoot, template);\n morphChildren(liveRoot, templateEl, ownedItems);\n}\n\n/**\n * Internal: morph `fromEl` to match `toEl` including the element's own\n * attributes (which the public `morph()` does NOT touch — it only morphs\n * children of the live root). Used by `list-reconcile-granular.ts` to apply\n * an `update` patch in place via attribute + child morphing instead of\n * `replaceChild` discarding the whole subtree. Same short-circuits as\n * `morph()`: `data-morph-skip`, `data-morph-skip-children`, `isEqualNode`,\n * focused contenteditable / text-entry preservation. Tag mismatch falls\n * through to the same parent.replaceChild fallback the public API uses.\n *\n * Underscore-prefixed export (not part of the public API surface). Public\n * callers should use `morph(liveRoot, template)`.\n */\nexport function _morphElement(\n fromEl: Element,\n toEl: Element,\n ownedItems: ReadonlySet<Element> = EMPTY_OWNED,\n): void {\n morphElement(fromEl, toEl, ownedItems);\n}\n\nfunction isElementNode(t: Element | SafeHtml | string): t is Element {\n return typeof t === 'object' && t !== null\n && (t as Node).nodeType === ELEMENT_NODE;\n}\n\nfunction parseTemplate(liveRoot: Element, template: SafeHtml | string): Element {\n const el = liveRoot.cloneNode(false) as Element;\n el.innerHTML = String(template);\n return el;\n}\n\n/**\n * Advance past any owned (list-reconciler-managed) element. Owned items\n * stay put across morphs — they're invisible to the morph's child cursor.\n */\nfunction skipOwned(node: Node | null, ownedItems: ReadonlySet<Element>): Node | null {\n while (node !== null && node.nodeType === ELEMENT_NODE\n && ownedItems.has(node as Element)) {\n node = node.nextSibling;\n }\n return node;\n}\n\nfunction morphChildren(\n fromParent: Element,\n toParent: Element,\n ownedItems: ReadonlySet<Element>,\n): void {\n // Build a keyed lookup from the live children so we can match by key\n // even after reorders. Owned items don't participate in keyed matching\n // (they're not visible to the morph).\n const keyed = new Map<string, Element>();\n for (let c = fromParent.firstChild; c !== null; c = c.nextSibling) {\n if (c.nodeType === ELEMENT_NODE && ownedItems.has(c as Element)) continue;\n const k = getNodeKey(c);\n if (k !== undefined) keyed.set(k, c as Element);\n }\n\n let fromChild: Node | null = skipOwned(fromParent.firstChild, ownedItems);\n let toChild: Node | null = toParent.firstChild;\n\n while (toChild !== null) {\n const toNext = toChild.nextSibling;\n let matched: Node | null = null;\n\n // 1. Try key match.\n const toKey = getNodeKey(toChild);\n if (toKey !== undefined && keyed.has(toKey)) {\n matched = keyed.get(toKey) as Element;\n keyed.delete(toKey);\n if (matched !== fromChild) {\n fromParent.insertBefore(matched, fromChild);\n } else {\n fromChild = skipOwned(fromChild.nextSibling, ownedItems);\n }\n }\n\n // 2. Fall back to positional match — same nodeType, same tag (for\n // elements), and the live node has no key (a keyed node only\n // matches by key, never positionally, so reorders work).\n if (matched === null && fromChild !== null\n && fromChild.nodeType === toChild.nodeType\n && (toChild.nodeType !== ELEMENT_NODE\n || ((fromChild as Element).tagName === (toChild as Element).tagName\n && getNodeKey(fromChild) === undefined))) {\n matched = fromChild;\n fromChild = skipOwned(fromChild.nextSibling, ownedItems);\n }\n\n if (matched !== null) {\n morphNode(matched, toChild, ownedItems);\n } else {\n // 3. No match — clone the new node and insert before fromChild\n // (which may be an owned item we deliberately stopped at; that's\n // fine — `insertBefore(node, ownedItem)` slots the new sibling\n // in immediately before the list region).\n const cloned = toChild.cloneNode(true);\n fromParent.insertBefore(cloned, fromChild);\n }\n\n toChild = toNext;\n }\n\n // 4. Anything past the cursor is unmatched — remove, except for owned\n // items (those stay; they belong to a list reconciler) and elements\n // marked `data-morph-preserve` (KF-151 — imperatively-injected nodes\n // whose lifetime the consumer manages outside kerf).\n while (fromChild !== null) {\n const next = fromChild.nextSibling;\n if (fromChild.nodeType === ELEMENT_NODE) {\n const el = fromChild as Element;\n if (!ownedItems.has(el)\n && (el as HTMLElement).dataset.morphPreserve === undefined) {\n fromParent.removeChild(fromChild);\n }\n } else {\n fromParent.removeChild(fromChild);\n }\n fromChild = next;\n }\n}\n\nfunction morphNode(\n fromNode: Node,\n toNode: Node,\n ownedItems: ReadonlySet<Element>,\n): void {\n if (fromNode.nodeType === ELEMENT_NODE) {\n morphElement(fromNode as Element, toNode as Element, ownedItems);\n return;\n }\n if (fromNode.nodeType === TEXT_NODE || fromNode.nodeType === COMMENT_NODE) {\n const fromText = fromNode as CharacterData;\n const toText = toNode as CharacterData;\n if (fromText.data !== toText.data) fromText.data = toText.data;\n }\n}\n\nfunction morphElement(\n fromEl: Element,\n toEl: Element,\n ownedItems: ReadonlySet<Element>,\n): void {\n if (fromEl.tagName !== toEl.tagName) {\n const replacement = toEl.cloneNode(true);\n fromEl.parentNode?.replaceChild(replacement, fromEl);\n return;\n }\n // 1. Library-owned subtree — leave verbatim.\n if ((fromEl as HTMLElement).dataset.morphSkip !== undefined) return;\n // 2. Byte-identical — nothing to do.\n if (fromEl.isEqualNode(toEl)) return;\n // 3. Focused contenteditable — preserve user's in-progress edit.\n if (fromEl === document.activeElement) {\n const ce = fromEl.getAttribute('contenteditable');\n if (ce !== null && ce.toLowerCase() !== 'false') return;\n if (isTextInputOrTextarea(fromEl)) preserveTextEntryState(fromEl, toEl);\n }\n morphAttributes(fromEl, toEl);\n // 4. Subtree-only skip (KF-152) — attributes have already morphed; leave\n // the children alone. Use for client-hydrated slots whose loading /\n // state classes still need to flow through.\n if ((fromEl as HTMLElement).dataset.morphSkipChildren !== undefined) return;\n // 5. Recurse into children. List items inside `fromEl` (if any) are\n // skipped via `ownedItems` inside morphChildren — list reconciler\n // owns them — but non-list siblings are still morphed.\n morphChildren(fromEl, toEl, ownedItems);\n}\n\n/**\n * Attributes the user agent toggles in response to user interaction.\n * `<details>` and `<dialog>` add/remove `open=\"\"` themselves when the user\n * expands or closes the element. If the developer's JSX never mentions\n * `open`, treating that attribute as user-agent-owned and leaving it alone\n * during the morph keeps the user-driven state intact across re-renders.\n *\n * Trade-off (KF-84): controlled-style `<details open={signal.value}>` where\n * the signal flips false won't auto-collapse the element, because the\n * morph's remove pass no longer reaches `open`. Apps that need controlled\n * behavior should drive `open` imperatively (e.g. `el.removeAttribute('open')`\n * inside an action) or wrap with a state-toggle pattern. The uncontrolled\n * case is the common one and the one that was silently broken before.\n */\nfunction isUserAgentOwnedAttr(tagName: string, name: string): boolean {\n return name === 'open' && (tagName === 'DETAILS' || tagName === 'DIALOG');\n}\n\nfunction morphAttributes(fromEl: Element, toEl: Element): void {\n // Set/update every attribute on toEl.\n const toAttrs = toEl.attributes;\n for (let i = 0; i < toAttrs.length; i++) {\n const attr = toAttrs[i];\n const ns = attr.namespaceURI;\n const name = attr.localName;\n const value = attr.value;\n if (ns !== null) {\n if (fromEl.getAttributeNS(ns, name) !== value) {\n fromEl.setAttributeNS(ns, attr.name, value);\n }\n } else if (fromEl.getAttribute(name) !== value) {\n fromEl.setAttribute(name, value);\n }\n }\n // Remove attributes that are no longer present on toEl.\n const fromAttrs = fromEl.attributes;\n const fromTag = fromEl.tagName;\n for (let i = fromAttrs.length - 1; i >= 0; i--) {\n const attr = fromAttrs[i];\n const ns = attr.namespaceURI;\n const name = attr.localName;\n if (ns !== null) {\n if (!toEl.hasAttributeNS(ns, name)) fromEl.removeAttributeNS(ns, name);\n } else if (!toEl.hasAttribute(name) && !isUserAgentOwnedAttr(fromTag, name)) {\n fromEl.removeAttribute(name);\n }\n }\n}\n\nfunction isTextInputOrTextarea(el: Element): boolean {\n if (el.tagName === 'TEXTAREA') return true;\n if (el.tagName === 'INPUT') {\n const type = (el as HTMLInputElement).type;\n return type === 'text' || type === 'search' || type === 'url' || type === 'email'\n || type === 'tel' || type === 'password' || type === '';\n }\n return false;\n}\n\nfunction preserveTextEntryState(fromEl: Element, toEl: Element): void {\n if (fromEl.tagName === 'TEXTAREA' || fromEl.tagName === 'INPUT') {\n const fromInput = fromEl as HTMLInputElement;\n const toInput = toEl as HTMLInputElement;\n toInput.value = fromInput.value;\n try {\n toInput.setSelectionRange(fromInput.selectionStart, fromInput.selectionEnd);\n } catch {\n // Some input types (number, range, color, …) reject selection APIs.\n }\n }\n}\n","/**\n * Dev-mode warning for Rule 4 violations (KF-174). When the opt-in env var\n * `KERF_DEV_WARN_REBUILT_LISTENERS=1` is set in a non-production build,\n * `mount()` calls `installListenerRebuildWarn()` to set up two things:\n *\n * 1. A global one-time monkey-patch on `EventTarget.prototype.addEventListener`\n * that marks the `Element` receiver with a `Symbol.for(\"kerfjs.devListener\")`\n * flag. The patch is idempotent across mounts.\n *\n * 2. A `MutationObserver` on the mount root, scoped to `{ childList: true,\n * subtree: true }`. When a removed Element (or any descendant of a\n * removed subtree) carries the marker, the observer emits a one-shot\n * `console.warn` pointing at `delegate()` and `data-morph-skip` as the\n * canonical fixes.\n *\n * Why opt-in: the heuristic catches every imperative `addEventListener` whose\n * receiver is later removed from the live tree, including some legitimate\n * patterns (custom elements that attach listeners in their constructor,\n * third-party widgets the user forgot to wrap in `data-morph-skip`, library\n * teardown code that detaches a node it owns). The warning is opt-in so\n * existing projects aren't surprised; CI / dev environments that want the\n * diagnostic enable the env var.\n *\n * The MutationObserver delivers mutations asynchronously (microtask after the\n * morph), so the warning fires AFTER the bad re-render rather than at the\n * call to `addEventListener`. That's why the diagnostic-error audit scores\n * Rule 4 at 2 with the opt-in (not 3) — the model sees the warning paired\n * with the broken listener, not at the read site.\n *\n * Production behavior is unchanged for zero runtime cost.\n */\n\nconst LISTENER_MARKER = Symbol.for('kerfjs.devListener');\n\nlet patched = false;\nlet warned = false;\n\nfunction isOptedIn(): boolean {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n if (proc?.env?.NODE_ENV === 'production') return false;\n return proc?.env?.KERF_DEV_WARN_REBUILT_LISTENERS === '1';\n}\n\ntype ElementProto = { addEventListener: (type: string, listener: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean) => void };\n\nfunction findAddEventListenerProto(): ElementProto {\n // Walk a probe Element's prototype chain to find the prototype that\n // actually owns `addEventListener`. In real browsers this is\n // `EventTarget.prototype`; in test environments (happy-dom) the realm's\n // EventTarget can differ from `globalThis.EventTarget`, so we have to\n // resolve via a live DOM node rather than the global symbol. Every Element\n // extends EventTarget which owns `addEventListener`, so the walk always\n // succeeds before falling off the end of the chain.\n const probe = document.createElement('div');\n let proto: object = Object.getPrototypeOf(probe) as object;\n while (!Object.prototype.hasOwnProperty.call(proto, 'addEventListener')) {\n proto = Object.getPrototypeOf(proto) as object;\n }\n return proto as unknown as ElementProto;\n}\n\nfunction patchAddEventListenerOnce(): void {\n if (patched) return;\n patched = true;\n const proto = findAddEventListenerProto();\n const orig = proto.addEventListener;\n proto.addEventListener = function (\n this: EventTarget,\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: AddEventListenerOptions | boolean,\n ): void {\n // Only mark Element receivers — Document, Window, AbortSignal etc. are\n // valid addEventListener receivers but are never in a mount tree.\n if (this instanceof Element) {\n (this as unknown as Record<symbol, boolean>)[LISTENER_MARKER] = true;\n }\n return orig.call(this, type, listener, options);\n };\n}\n\nfunction hasMarkedListener(el: Element): boolean {\n if ((el as unknown as Record<symbol, boolean>)[LISTENER_MARKER] === true) return true;\n // Walk descendants — when the morph removes a whole subtree, only the root\n // appears in the MutationRecord's removedNodes; an imperative listener on a\n // grandchild would otherwise be invisible.\n const stack: Element[] = [];\n for (let i = 0; i < el.children.length; i++) stack.push(el.children[i]);\n while (stack.length > 0) {\n const cur = stack.pop() as Element;\n if ((cur as unknown as Record<symbol, boolean>)[LISTENER_MARKER] === true) return true;\n for (let i = 0; i < cur.children.length; i++) stack.push(cur.children[i]);\n }\n return false;\n}\n\nfunction emitWarning(): void {\n /* c8 ignore next — paired with the observer's own one-shot check; doubly-guards against re-entry under engines that batch mutations across microtasks */\n if (warned) return;\n warned = true;\n console.warn(\n 'kerf: a node inside a mount()-managed tree was removed/rebuilt while carrying an imperative addEventListener listener. '\n + 'The listener is gone with the old node. Use `delegate(rootEl, \\'click\\', \\'[data-action=\"...\"]\\', handler)` '\n + 'so the listener lives on a stable ancestor and survives re-renders, or wrap the host in `data-morph-skip` if '\n + 'the subtree is library-owned (Monaco, xterm, D3 charts). '\n + 'Set KERF_DEV_WARN_REBUILT_LISTENERS=0 (or unset it) to silence this warning.',\n );\n}\n\nexport function installListenerRebuildWarn(rootEl: Element): MutationObserver | null {\n if (!isOptedIn()) return null;\n patchAddEventListenerOnce();\n const observer = new MutationObserver((mutations) => {\n if (warned) return;\n for (const m of mutations) {\n for (let i = 0; i < m.removedNodes.length; i++) {\n const removed = m.removedNodes[i];\n /* c8 ignore next — text/comment-node removals from morph; never carry the addEventListener marker but we filter to keep the Element-only contract explicit */\n if (!(removed instanceof Element)) continue;\n if (hasMarkedListener(removed)) {\n emitWarning();\n return;\n }\n }\n }\n });\n observer.observe(rootEl, { childList: true, subtree: true });\n return observer;\n}\n\n/**\n * Test helper — resets the one-shot `warned` flag so a subsequent test in the\n * same module can re-exercise the first-warning path. Not exported from the\n * public barrel; the unit-test file imports it directly via the relative path.\n */\nexport function _resetWarnedForTests(): void {\n warned = false;\n}\n","/**\n * Per-list binding shape kept by `mount()` and consumed by both reconcile\n * paths in `list-reconcile-snapshot.ts` and `list-reconcile-granular.ts`.\n *\n * Living in its own file (not re-exported through `list-reconcile.ts`) so\n * the snapshot + granular paths can import it without creating a circular\n * dependency on `list-reconcile.ts` itself. ESM handles cycles via function\n * hoisting, but a cycle involving a non-function helper would be a temporal\n * dead zone — extracting the binding shape + `endAnchor` here keeps the\n * dependency graph acyclic.\n */\n\nexport interface BoundItem {\n ref: object;\n cacheKey: unknown;\n html: string;\n node: Element;\n}\n\nexport interface ListBinding {\n liveParent: Element;\n /**\n * One entry per item currently mounted under `liveParent`, in order.\n * Mirrors the segment's `items` length after each reconcile.\n */\n items: BoundItem[];\n /**\n * The list's `<!--kf-list:N-->` start marker, kept in the live DOM as\n * a permanent anchor (KF-102 round 2). The marker stays put across\n * static-surrounds diffs (it morphs as a comment node), so it gives\n * the list reconciler a stable \"begin\" position even when surrounding\n * siblings get inserted, removed, or reordered around the list.\n *\n * `endAnchor(binding)` derives the \"insert at end of list\" anchor from\n * `marker.nextElementSibling` (empty list) or\n * `items[last].node.nextElementSibling` (non-empty list) — picking up\n * any non-list element the diff inserted between the list and the\n * parent's tail.\n */\n marker: Comment;\n /**\n * KF-173: once we've emitted the missing-key dev warning for this list,\n * we suppress further warnings for the same binding. The flag is set\n * inside `maybeWarnMissingRowKey()` and never cleared — the list is\n * considered \"decided\" after the first row check.\n */\n warnedMissingKey?: boolean;\n}\n\n/**\n * Compute the live-DOM anchor that comes after the list's last item, used\n * by the apply* functions when inserting at the tail of the list.\n *\n * - Empty list: `marker.nextElementSibling` — the next non-list element\n * after the marker, or `null` if the list is the last thing in `liveParent`.\n * - Non-empty list: `items[last].node.nextElementSibling` — derived\n * dynamically so that non-list siblings the diff inserted between the\n * list's last item and the parent's tail still anchor correctly.\n */\nexport function endAnchor(binding: ListBinding): Element | null {\n if (binding.items.length > 0) {\n return binding.items[binding.items.length - 1].node.nextElementSibling;\n }\n return binding.marker.nextElementSibling;\n}\n","/**\n * Fast paths for the granular update reconciler (KF-198 + KF-206).\n *\n * Two heuristics that catch common arraySignal-update shapes before the\n * standard parse + morph path runs and apply the change directly to the\n * live row:\n *\n * - **Attribute-only (KF-198)**: when the only diff between old and new\n * row HTML is in the top-level element's attribute values, call\n * setAttribute / removeAttribute on the live node. Targets the krausest\n * select-row scenario where 2 updates flip `class=\"\"` ↔ `class=\"danger\"`\n * on a `<tr>` with otherwise identical 4-child subtree. Skips parse +\n * morph entirely.\n *\n * - **Text-content-only (KF-206)**: when the only diff is inside one text\n * node's content (no entity touching, no structural or attribute\n * change), patch that text node's nodeValue. Targets the krausest\n * partial-update scenario where 100 updates each rewrite one label\n * text node deep inside the row.\n *\n * Both fast paths bail conservatively on anything that could go wrong —\n * namespaced attributes (`xmlns:*` etc.), `data-morph-skip` anywhere in the\n * row, user-agent-owned attributes (`<details open>`), entity-touching\n * diffs — and the granular path falls back to `_morphElement` or\n * `replaceChild`. The sanity check at the end of the text-content path\n * (live text node's nodeValue must equal what we extracted from oldHtml)\n * is the final safety net: if anything has drifted, we bail.\n *\n * Internal to kerf.\n */\n\nconst LT = 0x3C; // <\nconst GT = 0x3E; // >\nconst DQUOTE = 0x22; // \"\nconst SQUOTE = 0x27; // '\nconst AMP = 0x26; // &\nconst EQ = 0x3D; // =\nconst SLASH = 0x2F; // /\nconst TEXT_NODE = 3;\nconst ELEMENT_NODE = 1;\n\nfunction isWhitespace(cc: number): boolean {\n return cc === 0x20 || cc === 0x09 || cc === 0x0A || cc === 0x0D;\n}\n\ninterface ParsedTag {\n tagName: string;\n attrs: Map<string, string>;\n}\n\n/**\n * KF-198. Returns true if the diff between `oldHtml` and `newHtml` was an\n * attribute-only change on the top-level element AND was applied to\n * `liveNode` directly. Caller should NOT also run the parse + morph path.\n */\nexport function tryAttributeOnlyFastPath(\n liveNode: Element,\n oldHtml: string,\n newHtml: string,\n): boolean {\n // Kerf's JSX runtime escapes '>' to '&gt;' in attribute values and text\n // content, so the first '>' in the row HTML is always the close of the\n // top-level opening tag.\n const oldGt = oldHtml.indexOf('>');\n const newGt = newHtml.indexOf('>');\n if (oldGt === -1 || newGt === -1) return false;\n\n // Everything from '>' onward (children + closing tag) must be byte-equal.\n // If not, the diff is structural or includes text-content changes — defer\n // to the morph path (or the text-content fast path).\n if (oldHtml.length - oldGt !== newHtml.length - newGt) return false;\n if (oldHtml.slice(oldGt) !== newHtml.slice(newGt)) return false;\n\n if (containsDataMorphSkip(oldHtml) || containsDataMorphSkip(newHtml)) return false;\n\n const oldTag = parseOpeningTag(oldHtml, oldGt);\n const newTag = parseOpeningTag(newHtml, newGt);\n if (oldTag === null || newTag === null) return false;\n if (oldTag.tagName !== newTag.tagName) return false;\n\n // Pre-validate: no namespaced attribute names on either side. Setting via\n // plain setAttribute on a namespaced attribute would land it in the null\n // namespace and not match the original; bail and let morph handle it.\n for (const name of oldTag.attrs.keys()) {\n if (name.indexOf(':') !== -1) return false;\n }\n for (const name of newTag.attrs.keys()) {\n if (name.indexOf(':') !== -1) return false;\n }\n\n // Apply the diff.\n const liveTagUpper = liveNode.tagName;\n for (const [name, rawValue] of newTag.attrs) {\n const oldValue = oldTag.attrs.get(name);\n if (oldValue === rawValue) continue;\n liveNode.setAttribute(name, unescapeAttrValue(rawValue));\n }\n for (const name of oldTag.attrs.keys()) {\n if (newTag.attrs.has(name)) continue;\n if (isUserAgentOwnedAttr(liveTagUpper, name)) continue;\n liveNode.removeAttribute(name);\n }\n return true;\n}\n\n/**\n * KF-206. Returns true if the diff between `oldHtml` and `newHtml` was a\n * single-text-node content change AND was applied to `liveNode`'s\n * corresponding live text node directly. Caller should NOT also run the\n * parse + morph path.\n */\nexport function tryTextContentFastPath(\n liveNode: Element,\n oldHtml: string,\n newHtml: string,\n): boolean {\n if (containsDataMorphSkip(oldHtml) || containsDataMorphSkip(newHtml)) return false;\n\n let p = 0;\n const minLen = Math.min(oldHtml.length, newHtml.length);\n while (p < minLen && oldHtml.charCodeAt(p) === newHtml.charCodeAt(p)) p++;\n let s = 0;\n const maxS = minLen - p;\n while (s < maxS\n && oldHtml.charCodeAt(oldHtml.length - 1 - s) === newHtml.charCodeAt(newHtml.length - 1 - s)) {\n s++;\n }\n\n const oldWinEnd = oldHtml.length - s;\n const newWinEnd = newHtml.length - s;\n\n // Diff windows must contain only text-content characters — no tag\n // delimiters, no quotes, no entities, no '=' (which would put us inside\n // an attribute). Either window having an unsafe char means this is not a\n // clean text-only change.\n if (!isPureTextWindow(oldHtml, p, oldWinEnd)) return false;\n if (!isPureTextWindow(newHtml, p, newWinEnd)) return false;\n\n // The char just before the equal-prefix boundary must be either '>'\n // (text node starts here) or another text-content char (we're mid-text).\n // '<' / '\"' / \"'\" / '=' / '&' would mean we're inside a tag or entity.\n if (p === 0) return false;\n const boundaryCc = oldHtml.charCodeAt(p - 1);\n if (boundaryCc === LT || boundaryCc === DQUOTE || boundaryCc === SQUOTE\n || boundaryCc === EQ || boundaryCc === AMP) return false;\n\n // Find the text node's HTML-string boundaries. Text node containing\n // position p starts after the most recent '>' before p in oldHtml; ends\n // at the next '<' at or after p.\n const textStart = lastIndexOfChar(oldHtml, GT, p - 1);\n if (textStart === -1) return false;\n const textEnd = oldHtml.indexOf('<', p);\n if (textEnd === -1) return false;\n // The diff window in oldHtml must lie entirely within this text node.\n if (textEnd < oldWinEnd) return false;\n // newHtml's corresponding `<` position is shifted by the length delta\n // (the diff window is entirely inside this text node, so everything after\n // it is in the equal-suffix region).\n const newTextEnd = textEnd + (newHtml.length - oldHtml.length);\n const oldText = oldHtml.slice(textStart + 1, textEnd);\n const newText = newHtml.slice(textStart + 1, newTextEnd);\n\n // Find the text-node-index in document order.\n const textIdx = countTextNodesBefore(oldHtml, textStart + 1);\n const targetNode = nthTextNodeDescendant(liveNode, textIdx);\n if (targetNode === null) return false;\n\n // Final safety net: the live text node's nodeValue must equal the text\n // we extracted from oldHtml. If it differs (HTML-string vs live drift,\n // browser whitespace normalization, imperative mutation, etc.), bail\n // so the morph path can do its safe thing.\n if (targetNode.nodeValue !== oldText) return false;\n\n targetNode.nodeValue = newText;\n return true;\n}\n\nfunction containsDataMorphSkip(html: string): boolean {\n return html.indexOf('data-morph-skip') !== -1;\n}\n\nfunction isPureTextWindow(html: string, start: number, end: number): boolean {\n for (let i = start; i < end; i++) {\n const cc = html.charCodeAt(i);\n if (cc === LT || cc === GT || cc === DQUOTE || cc === SQUOTE\n || cc === AMP || cc === EQ) return false;\n }\n return true;\n}\n\nfunction lastIndexOfChar(html: string, target: number, beforeInclusive: number): number {\n for (let i = beforeInclusive; i >= 0; i--) {\n if (html.charCodeAt(i) === target) return i;\n }\n return -1;\n}\n\n/**\n * Count text-content runs (non-empty stretches between `>` and `<`) that\n * START before `beforePos` in `html`. Used to convert an HTML-string\n * position to the corresponding text-node-index in document order. Relies\n * on kerf-emitted HTML's invariant that `<` / `>` outside attribute values\n * always denote tag boundaries (entities escape them everywhere else).\n */\nfunction countTextNodesBefore(html: string, beforePos: number): number {\n let count = 0;\n let i = 0;\n while (i < beforePos) {\n if (html.charCodeAt(i) === LT) {\n while (i < beforePos && html.charCodeAt(i) !== GT) i++;\n i++;\n } else {\n const start = i;\n while (i < beforePos && html.charCodeAt(i) !== LT) i++;\n if (i > start) count++;\n }\n }\n return count;\n}\n\nfunction nthTextNodeDescendant(root: Element, n: number): Text | null {\n let count = 0;\n let result: Text | null = null;\n function walk(node: Node): void {\n for (let c = node.firstChild; c !== null; c = c.nextSibling) {\n if (result !== null) return;\n if (c.nodeType === TEXT_NODE) {\n if (count === n) {\n result = c as Text;\n return;\n }\n count++;\n } else if (c.nodeType === ELEMENT_NODE) {\n walk(c);\n }\n }\n }\n walk(root);\n return result;\n}\n\n/**\n * Parse the top-level opening tag of `html` whose closing `>` is at\n * `gtPos`. Returns null on any malformed shape (missing tag name,\n * unquoted attribute values, unterminated attribute, etc.) so the caller\n * bails to the morph path. Kerf's JSX runtime emits well-formed,\n * double-quoted attribute values, so the success path is the common one.\n */\nfunction parseOpeningTag(html: string, gtPos: number): ParsedTag | null {\n if (html.charCodeAt(0) !== LT) return null;\n let i = 1;\n let end = gtPos;\n // Self-closing slash (e.g. `<br/>`) — drop it from the parse range.\n if (i < end && html.charCodeAt(end - 1) === SLASH) end -= 1;\n\n const nameStart = i;\n while (i < end) {\n const cc = html.charCodeAt(i);\n if (isWhitespace(cc)) break;\n i++;\n }\n const tagName = html.slice(nameStart, i);\n if (tagName.length === 0) return null;\n\n const attrs = new Map<string, string>();\n while (i < end) {\n while (i < end && isWhitespace(html.charCodeAt(i))) i++;\n if (i >= end) break;\n const aNameStart = i;\n while (i < end) {\n const cc = html.charCodeAt(i);\n if (cc === EQ || isWhitespace(cc)) break;\n i++;\n }\n const aName = html.slice(aNameStart, i);\n if (aName.length === 0) return null;\n while (i < end && isWhitespace(html.charCodeAt(i))) i++;\n if (i < end && html.charCodeAt(i) === EQ) {\n i++;\n while (i < end && isWhitespace(html.charCodeAt(i))) i++;\n if (i >= end) return null;\n const q = html.charCodeAt(i);\n if (q !== DQUOTE && q !== SQUOTE) return null;\n i++;\n const vStart = i;\n while (i < end && html.charCodeAt(i) !== q) i++;\n if (i >= end) return null;\n attrs.set(aName, html.slice(vStart, i));\n i++;\n } else {\n attrs.set(aName, '');\n }\n }\n return { tagName, attrs };\n}\n\n/**\n * Reverse the five entities kerf's `escapeAttr` produces. Replace in safe\n * order (named entities first; `&amp;` last so its decode doesn't pick up\n * the `&` we just emitted from a different decode).\n */\nfunction unescapeAttrValue(s: string): string {\n if (s.indexOf('&') === -1) return s;\n return s\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&amp;/g, '&');\n}\n\n/**\n * `<details>` and `<dialog>` toggle `open` themselves in response to user\n * interaction. Mirror `morphAttributes`' rule: never remove `open` on them\n * during the fast path — the user-driven state would be wiped.\n */\nfunction isUserAgentOwnedAttr(tagNameUpper: string, name: string): boolean {\n return name === 'open' && (tagNameUpper === 'DETAILS' || tagNameUpper === 'DIALOG');\n}\n","/**\n * Focus snapshot/restore for the keyed list reconciler.\n *\n * Some engines (older Safari, happy-dom) drop focus state on `insertBefore`\n * even when the focused element survives the move connected to the document.\n * The reconciler snapshots the active element + selection range before its\n * move pass, then re-applies them afterwards. Engines that already preserve\n * focus across DOM moves see a no-op; engines that don't get a transparent\n * fix.\n *\n * Lives in its own file (rather than inside `list-reconcile.ts`) to keep that\n * file under the 200-LOC project guideline and to isolate the engine-quirk\n * handling described in `docs/4-render.md` §4.4.\n */\n\nexport interface FocusSnapshot {\n el: HTMLElement;\n selStart: number | null;\n selEnd: number | null;\n}\n\n/**\n * Capture focus + selection on a focused descendant of `liveParent`.\n *\n * Returns null when the active element is outside the list (the diff path\n * handles those cases) or when there's no useful focus state to capture.\n */\nexport function captureFocus(liveParent: Element): FocusSnapshot | null {\n const active = document.activeElement;\n if (active === null || active === document.body) return null;\n if (!liveParent.contains(active)) return null;\n const el = active as HTMLElement;\n let selStart: number | null = null;\n let selEnd: number | null = null;\n if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {\n try {\n selStart = (el as HTMLInputElement).selectionStart;\n selEnd = (el as HTMLInputElement).selectionEnd;\n } catch {\n // Some input types (number, range, color, …) reject selection APIs.\n }\n }\n return { el, selStart, selEnd };\n}\n\nexport function restoreFocus(snap: FocusSnapshot): void {\n if (document.activeElement === snap.el) return;\n if (!snap.el.isConnected) return;\n snap.el.focus();\n if (snap.selStart !== null && snap.selEnd !== null) {\n try {\n (snap.el as HTMLInputElement).setSelectionRange(snap.selStart, snap.selEnd);\n } catch {\n // Selection may have been clobbered by .focus(); not fatal.\n }\n }\n}\n","/**\n * Shared \"exactly one top-level element per row\" contract helpers (KF-103).\n *\n * The keyed-list reconciler in `list-reconcile.ts` and the first-render\n * binding path in `mount.ts` both enforce the same contract on `each()`\n * row HTML. Centralizing the constants and helpers here keeps the three\n * call sites that build error snippets and the eight call sites that\n * parse a row's HTML into a template element from drifting (KF-111 +\n * KF-115).\n */\n\n/**\n * Truncation limit applied to row HTML when including it in a contract-\n * violation error message. Keeps the error readable when a row produced\n * megabytes of HTML by accident.\n */\nexport const ROW_HTML_SNIPPET_MAX = 120;\n\n/**\n * Truncate a row's HTML for inclusion in an error message. Returns the\n * raw string if it's short enough; otherwise the first\n * `ROW_HTML_SNIPPET_MAX` characters with a trailing ellipsis.\n */\nexport function truncateRowHtml(html: string): string {\n return html.length > ROW_HTML_SNIPPET_MAX\n ? html.slice(0, ROW_HTML_SNIPPET_MAX) + '…'\n : html;\n}\n\n/**\n * Parse a row's HTML into a `<template>` and report how many top-level\n * elements it produced. The reconciler uses the count to detect contract\n * violations (count !== 1) on both single-row and bulk-row paths.\n */\nexport function parseRowTemplate(html: string): { tpl: HTMLTemplateElement; count: number } {\n const tpl = document.createElement('template');\n tpl.innerHTML = html;\n return { tpl, count: tpl.content.children.length };\n}\n\n/**\n * Build a precise contract-violation `Error` for the row at `index` whose\n * render produced the given `html`. The thrown message mentions the row\n * index, the actual element count, and the (truncated) HTML so the author\n * can locate and fix the offending row quickly.\n */\nexport function rowContractError(index: number, html: string): Error {\n const { count } = parseRowTemplate(html);\n const reason = count === 0\n ? 'produced no top-level element'\n : `produced ${count} top-level elements; exactly one is required`;\n return new Error(\n `each(): row render at index ${index} ${reason}. `\n + 'Each item\\'s render must return exactly one element — '\n + 'wrap multiple roots in a single parent (e.g. <li>...</li>). '\n + `Got HTML: ${JSON.stringify(truncateRowHtml(html))}`,\n );\n}\n\nfunction isDevMode(): boolean {\n const proc = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process;\n return proc?.env?.NODE_ENV !== 'production';\n}\n\n/**\n * KF-173: emit a one-shot dev-mode `console.warn` when the first row of an\n * `each()` list lacks both `id` and `data-key` attributes. The reconciler\n * falls back to positional matching in that case, which silently shifts row\n * state (focused inputs, mid-edit textareas) on insert/delete. The warning\n * names the row index, points at the canonical fix, and quotes the HTML\n * snippet so the author can locate the call site.\n *\n * Called per-binding; the caller passes a mutable flag holder so the warning\n * fires at most once per `mount()`-lifetime per `each()` callsite. Set the\n * holder's flag after the call regardless of whether the warning fired.\n * Production builds emit nothing — the gate is `NODE_ENV !== 'production'`.\n */\nexport function maybeWarnMissingRowKey(\n rowEl: Element,\n rowIndex: number,\n rowHtml: string,\n binding: { warnedMissingKey?: boolean },\n): void {\n if (!isDevMode()) return;\n if (binding.warnedMissingKey === true) return;\n binding.warnedMissingKey = true;\n if (rowEl.id !== '' || rowEl.hasAttribute('data-key')) return;\n console.warn(\n `kerf each(): row at index ${rowIndex} has no \\`id\\` or \\`data-key\\` attribute. `\n + 'Without one, rows match positionally — an insert/remove at the head shifts every row\\'s '\n + 'identity, so focused inputs jump to the wrong row, mid-edit textareas swap content with their neighbor, '\n + 'and any per-row state silently follows the wrong item. '\n + 'Add `data-key={item.id}` (or set `id`) to the top-level element returned by the row render. '\n + `Row HTML: ${JSON.stringify(truncateRowHtml(rowHtml))}`,\n );\n}\n","/**\n * Granular reconcile path for `each(...)` bound to an `arraySignal` (KF-92).\n *\n * Applies the patch events emitted by `arraySignal` mutators directly to\n * the live DOM and to `binding.items`, without iterating the full snapshot\n * or doing a classify pass. Cost is O(patches), not O(N).\n *\n * Two perf optimizations:\n * - **KF-93**: contiguous insert runs (patches at index N, N+1, N+2, …) are\n * bulk-parsed in one `template.innerHTML` call and inserted as a single\n * fragment. Saves ~50 ms on append-1k.\n * - **KF-94**: consecutive update runs (any indices — `replaceChild`\n * operates on each row's existing live node independently) are bulk-\n * parsed in one `template.innerHTML` call. Saves the per-patch parse\n * cost on the krausest partial-update scenario.\n *\n * Patches with `type: 'replace'` are filtered out by `each()` upstream and\n * never reach this function (the runtime contract guarantees absence even\n * though the TypeScript type allows them).\n *\n * Internal to kerf — re-exported via `list-reconcile.ts`'s `reconcileList`.\n */\n\nimport { type BoundItem, endAnchor, type ListBinding } from './list-binding.js';\nimport { tryAttributeOnlyFastPath, tryTextContentFastPath } from './list-reconcile-fast-paths.js';\nimport { captureFocus, restoreFocus } from './list-reconcile-focus.js';\nimport { _morphElement } from './morph.js';\nimport type { ListSegment } from './segment.js';\nimport { maybeWarnMissingRowKey,parseRowTemplate, rowContractError, truncateRowHtml } from './utils/rowContract.js';\n\nexport function reconcileGranular(\n binding: ListBinding,\n patches: NonNullable<ListSegment['patches']>,\n): void {\n const { liveParent } = binding;\n const items = binding.items;\n\n // Capture/restore focus around the whole batch (mirrors the snapshot\n // path's KF-65 fix). Some engines (older Safari, happy-dom) blur a\n // focused descendant on `insertBefore` / `replaceChild` even when the\n // ancestor stays connected — covers the move patch (which moves an\n // existing row's <li>), and is a no-op on engines that already\n // preserve focus across DOM ops.\n const focusSnap = captureFocus(liveParent);\n\n let i = 0;\n while (i < patches.length) {\n const patch = patches[i];\n /* c8 ignore next 5 — replace is filtered upstream by each(); this branch\n is defensive type-completeness only. */\n if (patch.type === 'replace') {\n i += 1;\n continue;\n }\n if (patch.type === 'update') {\n // KF-94: detect a run of consecutive update patches (any indices —\n // replaceChild operates on each row's existing live node independently,\n // so contiguity isn't required) and bulk-parse all their HTML in a\n // single `template.innerHTML` call. Saves the per-patch parse overhead\n // on krausest's partial-update scenario (100 update patches at\n // indices 0, 10, 20, … — non-contiguous, so KF-93's run detector\n // doesn't kick in).\n let runEnd = i + 1;\n while (runEnd < patches.length && patches[runEnd].type === 'update') {\n runEnd += 1;\n }\n const runLen = runEnd - i;\n if (runLen === 1) {\n applySingleUpdate(liveParent, items, patch);\n } else {\n applyBulkUpdate(liveParent, items, patches, i, runEnd);\n }\n i = runEnd;\n continue;\n }\n if (patch.type === 'insert') {\n // KF-93: detect a contiguous run of inserts at adjacent indices (each\n // next insert at the previous one's index + 1) and bulk-parse all\n // their HTML in a single `template.innerHTML` call, followed by a\n // single `insertBefore(fragment, anchor)`.\n let runEnd = i + 1;\n while (runEnd < patches.length\n && patches[runEnd].type === 'insert'\n && (patches[runEnd] as { index: number }).index\n === (patches[runEnd - 1] as { index: number }).index + 1) {\n runEnd += 1;\n }\n const runLen = runEnd - i;\n if (runLen === 1) {\n applySingleInsert(liveParent, items, patch, endAnchor(binding));\n } else {\n applyBulkInsert(liveParent, items, patches, i, runEnd, endAnchor(binding));\n }\n i = runEnd;\n continue;\n }\n if (patch.type === 'remove') {\n const entry = items[patch.index];\n liveParent.removeChild(entry.node);\n items.splice(patch.index, 1);\n i += 1;\n continue;\n }\n if (patch.type === 'move') {\n const moved = items[patch.from];\n // Compute the anchor BEFORE we splice, so the index references the\n // pre-move state.\n let anchorIdx = patch.to;\n if (patch.from < patch.to) anchorIdx += 1; // account for upcoming splice removal\n const anchor = anchorIdx < items.length ? items[anchorIdx].node : endAnchor(binding);\n liveParent.insertBefore(moved.node, anchor);\n items.splice(patch.from, 1);\n items.splice(patch.to, 0, moved);\n i += 1;\n continue;\n }\n }\n\n if (focusSnap !== null) restoreFocus(focusSnap);\n // KF-173: warn once per binding if rows lack id / data-key.\n if (items.length > 0) {\n maybeWarnMissingRowKey(items[0].node, 0, items[0].html, binding);\n }\n}\n\nfunction applySingleInsert(\n liveParent: Element,\n items: BoundItem[],\n patch: { type: 'insert'; index: number; item: object; html: string },\n tailAnchor: Element | null,\n): void {\n const { html } = patch;\n const newNode = parseSingleRow(html);\n const anchor = patch.index < items.length ? items[patch.index].node : tailAnchor;\n liveParent.insertBefore(newNode, anchor);\n items.splice(patch.index, 0, {\n ref: patch.item, cacheKey: undefined, html, node: newNode,\n });\n}\n\nfunction applySingleUpdate(\n liveParent: Element,\n items: BoundItem[],\n patch: { type: 'update'; index: number; item: object; html: string },\n): void {\n const { html } = patch;\n const oldEntry = items[patch.index];\n if (html === oldEntry.html) return; // no-op (defensive: caller may emit redundant patches)\n // KF-198 + KF-206: surgical fast paths for the common arraySignal update\n // shapes — top-level attribute flip (krausest select-row) and one-text-\n // node content change (krausest partial-update). Both apply the change\n // directly to the live row, skipping the parse + morph entirely. They\n // bail conservatively on anything that could be unsafe and fall through\n // to the existing _morphElement / replaceChild routes below.\n if (tryAttributeOnlyFastPath(oldEntry.node, oldEntry.html, html)\n || tryTextContentFastPath(oldEntry.node, oldEntry.html, html)) {\n items[patch.index] = { ref: patch.item, cacheKey: undefined, html, node: oldEntry.node };\n return;\n }\n const newNode = parseSingleRow(html);\n // KF-201: morph the existing live node in place when tags match, so\n // structure-preserving updates (text-node change, attribute flip) apply\n // surgically — preserving DOM identity, focus, scroll, IME state, and\n // skipping the layout cost of a full subtree discard-and-reinsert. For\n // the rare tag-mismatch case (consumer's render fn returns a different\n // top-level tag for the same item), fall back to explicit replaceChild\n // so we keep a reference to the new live node.\n if (oldEntry.node.tagName === newNode.tagName) {\n _morphElement(oldEntry.node, newNode);\n items[patch.index] = { ref: patch.item, cacheKey: undefined, html, node: oldEntry.node };\n } else {\n liveParent.replaceChild(newNode, oldEntry.node);\n items[patch.index] = { ref: patch.item, cacheKey: undefined, html, node: newNode };\n }\n}\n\n/**\n * Bulk-parse a run of consecutive update patches (KF-94). Indices may be\n * scattered (non-contiguous). Renders all HTMLs first, filters out no-ops\n * where the new HTML matches the old, then bulk-parses the remaining HTMLs\n * in one `template.innerHTML` call. The replaceChild loop afterwards is\n * unavoidable (one DOM op per row), but we save the per-patch parse cost.\n */\nfunction applyBulkUpdate(\n liveParent: Element,\n items: BoundItem[],\n patches: NonNullable<ListSegment['patches']>,\n start: number,\n end: number,\n): void {\n // Patches already carry pre-rendered HTML (KF-99). One pass over the run:\n // skip no-ops, try the KF-198 / KF-206 fast paths (apply in place when\n // they fire), and collect everything else for one bulk parse + morph.\n interface Change { patchIdx: number; html: string }\n const morphChanges: Change[] = [];\n for (let k = start; k < end; k++) {\n const p = patches[k] as { type: 'update'; index: number; item: object; html: string };\n const oldEntry = items[p.index];\n if (p.html === oldEntry.html) continue;\n if (tryAttributeOnlyFastPath(oldEntry.node, oldEntry.html, p.html)\n || tryTextContentFastPath(oldEntry.node, oldEntry.html, p.html)) {\n items[p.index] = { ref: p.item, cacheKey: undefined, html: p.html, node: oldEntry.node };\n continue;\n }\n morphChanges.push({ patchIdx: k, html: p.html });\n }\n if (morphChanges.length === 0) return;\n\n // Bulk-parse only the rows the fast paths couldn't handle.\n const { tpl, count } = parseRowTemplate(morphChanges.map((c) => c.html).join(''));\n if (count !== morphChanges.length) {\n throw findOffendingChange(patches, morphChanges);\n }\n const newNodes = new Array<Element>(morphChanges.length);\n let child = tpl.content.firstElementChild;\n for (let k = 0; k < newNodes.length; k++) {\n newNodes[k] = child as Element;\n child = (child as Element).nextElementSibling;\n }\n\n // KF-201: morph each row in place when tags match (the common case), so\n // structure-preserving updates skip the discard-and-reinsert layout cost.\n // Tag-mismatch falls back to explicit replaceChild so we keep a reference\n // to the new live node.\n for (let k = 0; k < morphChanges.length; k++) {\n const c = morphChanges[k];\n const p = patches[c.patchIdx] as { type: 'update'; index: number; item: object; html: string };\n const oldEntry = items[p.index];\n if (oldEntry.node.tagName === newNodes[k].tagName) {\n _morphElement(oldEntry.node, newNodes[k]);\n items[p.index] = { ref: p.item, cacheKey: undefined, html: c.html, node: oldEntry.node };\n } else {\n liveParent.replaceChild(newNodes[k], oldEntry.node);\n items[p.index] = { ref: p.item, cacheKey: undefined, html: c.html, node: newNodes[k] };\n }\n }\n}\n\n/**\n * Bulk-parse a contiguous run of insert patches (KF-93). The run starts at\n * `start` (inclusive) and ends at `end` (exclusive); every patch in that\n * range is type `insert` with index === previous.index + 1. We render each\n * row's HTML, concatenate, parse the lot in one `template.innerHTML`, and\n * insert the resulting fragment in a single DOM op.\n */\nfunction applyBulkInsert(\n liveParent: Element,\n items: BoundItem[],\n patches: NonNullable<ListSegment['patches']>,\n start: number,\n end: number,\n tailAnchor: Element | null,\n): void {\n const startIdx = (patches[start] as { index: number }).index;\n const htmls = new Array<string>(end - start);\n for (let k = start; k < end; k++) {\n const p = patches[k] as { type: 'insert'; index: number; item: object; html: string };\n htmls[k - start] = p.html;\n }\n const { tpl, count } = parseRowTemplate(htmls.join(''));\n if (count !== htmls.length) {\n throw findOffendingInsert(patches, start, htmls);\n }\n // Count matches; capture child refs BEFORE the fragment-insert empties\n // tpl.content. Walk unconditionally — count check above guarantees\n // `firstElementChild` is non-null and there are exactly `end - start`\n // children.\n const newNodes = new Array<Element>(end - start);\n let child = tpl.content.firstElementChild;\n for (let k = 0; k < newNodes.length; k++) {\n newNodes[k] = child as Element;\n child = (child as Element).nextElementSibling;\n }\n const anchor = startIdx < items.length ? items[startIdx].node : tailAnchor;\n liveParent.insertBefore(tpl.content, anchor);\n // Splice all new entries into binding.items at the run's start index.\n const newEntries = new Array<BoundItem>(end - start);\n for (let k = 0; k < newEntries.length; k++) {\n const p = patches[start + k] as { type: 'insert'; index: number; item: object; html: string };\n newEntries[k] = {\n ref: p.item, cacheKey: undefined, html: htmls[k], node: newNodes[k],\n };\n }\n items.splice(startIdx, 0, ...newEntries);\n}\n\n/**\n * Parse a single row's HTML string into one Element. Used by the granular\n * reconciler's single-row paths (`applySingleInsert`, `applySingleUpdate`).\n * Each row is expected to render exactly one top-level element (the same\n * contract `each()` enforces in the snapshot path).\n */\nfunction parseSingleRow(html: string): Element {\n const { tpl, count } = parseRowTemplate(html);\n if (count !== 1) {\n const reason = count === 0\n ? 'produced no top-level element'\n : `produced ${count} top-level elements; exactly one is required`;\n throw new Error(\n `each() granular reconcile: row render ${reason}. `\n + 'Each item\\'s render must return exactly one element. '\n + `Got HTML: ${JSON.stringify(truncateRowHtml(html))}`,\n );\n }\n return tpl.content.firstElementChild as Element;\n}\n\n/**\n * Slow-path helper for `applyBulkInsert`. Walks each pre-rendered insert\n * patch's html in isolation to find the offending row.\n */\nfunction findOffendingInsert(\n patches: NonNullable<ListSegment['patches']>,\n start: number,\n htmls: string[],\n): Error {\n for (let i = 0; i < htmls.length; i++) {\n if (parseRowTemplate(htmls[i]).count !== 1) {\n const p = patches[start + i] as { type: 'insert'; index: number };\n return rowContractError(p.index, htmls[i]);\n }\n }\n /* c8 ignore start */\n return new Error('each(): bulk-insert mismatch with no per-row offender (kerf bug).');\n}\n/* c8 ignore stop */\n\n/**\n * Slow-path helper for `applyBulkUpdate`. Walks each non-no-op change to\n * find the offending row.\n */\nfunction findOffendingChange(\n patches: NonNullable<ListSegment['patches']>,\n changes: { patchIdx: number; html: string }[],\n): Error {\n for (const c of changes) {\n if (parseRowTemplate(c.html).count !== 1) {\n const p = patches[c.patchIdx] as { type: 'update'; index: number };\n return rowContractError(p.index, c.html);\n }\n }\n /* c8 ignore start */\n return new Error('each(): bulk-update mismatch with no per-row offender (kerf bug).');\n}\n/* c8 ignore stop */\n","/**\n * In-place content-update fast path for the snapshot reconciler.\n *\n * When a re-render produces a list segment with the **same item refs in the\n * same order** as the current binding — no inserts, removes, or moves — then\n * only row CONTENT can have changed. The general snapshot path would treat a\n * same-ref/changed-html row as \"replaced\": remove the old DOM node and insert\n * a freshly-parsed one. In a large `<table>` that node swap forces a full\n * relayout, which is expensive even when only one attribute (e.g. a selection\n * class) flipped.\n *\n * This path instead updates each changed row **in place** — reusing the same\n * surgical/morph/replace ladder the granular path uses for `arraySignal`\n * updates (`list-reconcile-fast-paths.ts` + `_morphElement`). Preserving the\n * row's DOM node keeps focus/scroll/IME state and avoids the layout cost, so\n * external-state-driven row changes (e.g. a single `selectedId` signal read\n * via `each()`'s `cacheKey`) update as cheaply as every other framework does.\n *\n * Only the \"no structural change\" shape is handled here; anything with an\n * insert, remove, or move falls through to the full snapshot algorithm. The\n * rare \"row moved AND changed content\" case therefore stays on the general\n * (node-replacing) path.\n *\n * Internal to kerf — invoked from `reconcileSnapshot`.\n */\n\nimport { type BoundItem, type ListBinding } from './list-binding.js';\nimport { tryAttributeOnlyFastPath, tryTextContentFastPath } from './list-reconcile-fast-paths.js';\nimport { captureFocus, restoreFocus } from './list-reconcile-focus.js';\nimport { _morphElement } from './morph.js';\nimport type { ListItem, ListSegment } from './segment.js';\nimport { maybeWarnMissingRowKey, parseRowTemplate, rowContractError } from './utils/rowContract.js';\n\n/**\n * If the new segment has the same refs in the same order as `binding.items`,\n * apply each changed row in place and return `true` (handled). Otherwise\n * return `false` so the caller runs the full classify + LIS + move algorithm.\n */\nexport function tryInPlaceContentUpdate(binding: ListBinding, listSeg: ListSegment): boolean {\n const oldItems = binding.items;\n const items = listSeg.items;\n const n = items.length;\n // Empty lists and any length change can't be a pure content update. Empty\n // is left to the main path (which also handles the missing-key warning edge).\n if (n === 0 || n !== oldItems.length) return false;\n for (let i = 0; i < n; i++) {\n if (items[i].ref !== oldItems[i].ref) return false;\n }\n\n const { liveParent } = binding;\n const newRecord: BoundItem[] = new Array(n);\n // Capture focus once: the surgical + morph routes preserve it inherently,\n // but the rare tag-mismatch `replaceChild` fallback would blur a focused\n // descendant. restoreFocus is a no-op when focus never moved.\n const focusSnap = captureFocus(liveParent);\n for (let i = 0; i < n; i++) {\n newRecord[i] = updateRowInPlace(liveParent, oldItems[i], items[i], i);\n }\n if (focusSnap !== null) restoreFocus(focusSnap);\n\n binding.items = newRecord;\n maybeWarnMissingRowKey(newRecord[0].node, 0, newRecord[0].html, binding);\n return true;\n}\n\n/**\n * Apply one row's content change in place. Mirrors the granular path's\n * `applySingleUpdate` ladder: no-op if unchanged → surgical attribute/text\n * fast paths → `_morphElement` when the top-level tag matches → `replaceChild`\n * when it doesn't (consumer's render fn returned a different top-level tag).\n */\nfunction updateRowInPlace(\n liveParent: Element,\n old: BoundItem,\n ni: ListItem,\n index: number,\n): BoundItem {\n if (old.html === ni.html\n || tryAttributeOnlyFastPath(old.node, old.html, ni.html)\n || tryTextContentFastPath(old.node, old.html, ni.html)) {\n return { ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: old.node };\n }\n const newNode = parseSingleRow(ni.html, index);\n if (old.node.tagName === newNode.tagName) {\n _morphElement(old.node, newNode);\n return { ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: old.node };\n }\n liveParent.replaceChild(newNode, old.node);\n return { ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: newNode };\n}\n\n/** Parse one row's HTML to its single top-level element (row contract). */\nfunction parseSingleRow(html: string, index: number): Element {\n const { tpl, count } = parseRowTemplate(html);\n if (count !== 1) throw rowContractError(index, html);\n return tpl.content.firstElementChild as Element;\n}\n","/**\n * Snapshot reconcile path for `each(...)` — the original (non-granular)\n * keyed-list algorithm. Used when:\n * - The list is rendered with a plain array (not an `arraySignal`).\n * - The list is rendered with an `arraySignal` but no patch queue is\n * present (first render, post-`replace()`, or post-drift recovery).\n *\n * Algorithm:\n * 1. Classify each new item as `stable` (cache hit on identity + html),\n * `replaced` (same ref, html changed), or `new` (never seen before).\n * 2. Bulk-parse every fresh row's HTML in ONE `innerHTML` call — for an\n * initial population of 10k rows that's 1 parse instead of 10k.\n * 3. Remove orphan refs (gone from the new list) + replaced rows' old nodes.\n * 4. Compute a longest-increasing-subsequence over old positions; items in\n * the LIS are already in the right relative order, so they don't move.\n * 5. Reverse-pass over the new record, `insertBefore` only the items that\n * didn't anchor the LIS.\n *\n * The KF-89 fast path short-circuits when nothing structural changed —\n * the live tree already matches the new segment, so we can return after\n * step 1 with just the binding update.\n *\n * Internal to kerf — re-exported via `list-reconcile.ts`'s `reconcileList`.\n */\n\nimport { type BoundItem, endAnchor, type ListBinding } from './list-binding.js';\nimport { captureFocus, restoreFocus } from './list-reconcile-focus.js';\nimport { tryInPlaceContentUpdate } from './list-reconcile-inplace.js';\nimport type { ListSegment } from './segment.js';\nimport { maybeWarnMissingRowKey,parseRowTemplate, rowContractError } from './utils/rowContract.js';\n\ninterface Classification {\n newRecord: BoundItem[];\n prevIdx: number[];\n replacedNodes: Element[];\n freshIndices: number[];\n freshHtmls: string[];\n}\n\n/**\n * Reconcile via the snapshot algorithm. Mutates `binding.items` to mirror\n * the new segment when done.\n *\n * Focus capture/restore lives in `list-reconcile-focus.ts` — `insertBefore`\n * of a focused descendant's ancestor blurs the element in some engines\n * (happy-dom, older Safari) even when it stays connected; the snapshot fixes\n * those engines and is a no-op on engines that already preserve focus.\n */\nexport function reconcileSnapshot(binding: ListBinding, listSeg: ListSegment): void {\n // In-place fast path: same refs in the same order (no inserts/removes/moves)\n // → only content changed, so morph changed rows in place instead of swapping\n // their DOM nodes. Avoids the table-relayout cost of node replacement for\n // external-state-driven row changes (e.g. a single selectedId + cacheKey).\n if (tryInPlaceContentUpdate(binding, listSeg)) return;\n\n // Anything reaching here has a structural change (insert, remove, or move);\n // the pure \"same refs in same order\" case — including the no-op re-render\n // where nothing changed — is handled earlier by tryInPlaceContentUpdate,\n // which keeps every surviving node and morphs only changed rows in place.\n const { liveParent } = binding;\n const { newRecord, prevIdx, replacedNodes, freshIndices, freshHtmls }\n = classifyItems(binding.items, listSeg);\n\n // Compute tail anchor BEFORE removing old nodes: once an item is\n // detached, its `.nextElementSibling` is null and we lose the\n // boundary. Capturing here uses the binding's current (pre-mutation)\n // items[last].node which is still attached.\n const tailAnchor = endAnchor(binding);\n buildFreshNodes(newRecord, freshIndices, freshHtmls);\n const focusSnap = captureFocus(liveParent);\n removeOldNodes(liveParent, replacedNodes);\n applyMoves(liveParent, newRecord, prevIdx, lis(prevIdx), tailAnchor);\n if (focusSnap !== null) restoreFocus(focusSnap);\n binding.items = newRecord;\n if (newRecord.length > 0) {\n maybeWarnMissingRowKey(newRecord[0].node, 0, newRecord[0].html, binding);\n }\n}\n\n/**\n * Classify each item in the new segment against the old binding. Items with\n * a cache-hit (same ref + same html) are reused; replaced/new items get a\n * placeholder `BoundItem` whose `node` is filled in by the bulk parse below.\n */\nfunction classifyItems(oldItems: BoundItem[], listSeg: ListSegment): Classification {\n // Single Map<ref, [item, index]> instead of two Maps over the same key set\n // (KF-90). Halves the .set() calls during the build, halves the lookup\n // probe count during classification. ~1-2 ms saved per render on 1k-row\n // lists.\n const oldByRef = new Map<object, [BoundItem, number]>();\n for (let i = 0; i < oldItems.length; i++) {\n oldByRef.set(oldItems[i].ref, [oldItems[i], i]);\n }\n\n const newRecord: BoundItem[] = new Array(listSeg.items.length);\n const prevIdx = new Array<number>(listSeg.items.length);\n const replacedNodes: Element[] = [];\n const freshIndices: number[] = [];\n const freshHtmls: string[] = [];\n\n for (let i = 0; i < listSeg.items.length; i++) {\n const ni = listSeg.items[i];\n const oi = oldByRef.get(ni.ref);\n if (oi !== undefined) {\n oldByRef.delete(ni.ref);\n if (oi[0].html === ni.html) {\n newRecord[i] = oi[0];\n prevIdx[i] = oi[1];\n continue;\n }\n replacedNodes.push(oi[0].node);\n }\n newRecord[i] = {\n ref: ni.ref, cacheKey: ni.cacheKey, html: ni.html, node: null as unknown as Element,\n };\n prevIdx[i] = -1;\n freshIndices.push(i);\n freshHtmls.push(ni.html);\n }\n\n // Whatever's left in oldByRef is an orphan ref that disappeared from the\n // new list. The caller removes those nodes alongside the replaced ones.\n for (const [, orphan] of oldByRef) replacedNodes.push(orphan[0].node);\n\n return { newRecord, prevIdx, replacedNodes, freshIndices, freshHtmls };\n}\n\n/**\n * Bulk-parse every fresh row's HTML in one `innerHTML` call, then walk the\n * parsed children in order and fill in each placeholder's `node` field.\n *\n * Enforces the \"exactly one top-level element per row\" contract (KF-103):\n * if the bulk parse produces a different number of top-level elements\n * than fresh rows, fall back to per-row parsing to identify the offending\n * row and throw a precise error. The success path stays a single parse.\n */\nfunction buildFreshNodes(\n newRecord: BoundItem[],\n freshIndices: number[],\n freshHtmls: string[],\n): void {\n if (freshHtmls.length === 0) return;\n const { tpl, count } = parseRowTemplate(freshHtmls.join(''));\n if (count !== freshHtmls.length) {\n throw findOffendingRow(newRecord, freshIndices, freshHtmls);\n }\n // After the count check above, we know `tpl.content.children.length`\n // equals `freshIndices.length`, so the walk below always finds an element\n // for every index. No defensive null-guard needed.\n let node = tpl.content.firstElementChild;\n for (const idx of freshIndices) {\n const next = (node as Element).nextElementSibling;\n newRecord[idx].node = node as Element;\n node = next;\n }\n}\n\n/**\n * Walk per-row to find the offending row that violated the contract,\n * returning a precise error to throw. Only invoked when the bulk parse\n * detected a count mismatch — the success path is one parse with no\n * per-row work.\n */\nfunction findOffendingRow(\n newRecord: BoundItem[],\n freshIndices: number[],\n freshHtmls: string[],\n): Error {\n for (let i = 0; i < freshHtmls.length; i++) {\n if (parseRowTemplate(freshHtmls[i]).count !== 1) {\n return rowContractError(freshIndices[i], newRecord[freshIndices[i]].html);\n }\n }\n /* c8 ignore next 2 — unreachable: bulk mismatch ⇒ at least one row violates. */\n return new Error('each(): bulk-parse mismatch with no per-row offender (kerf bug).');\n}\n\n/**\n * Remove every replaced/orphan node still attached to the live parent.\n */\nfunction removeOldNodes(liveParent: Element, replacedNodes: Element[]): void {\n for (const node of replacedNodes) {\n if (node.parentElement === liveParent) liveParent.removeChild(node);\n }\n}\n\n/**\n * `insertBefore` everything that's not in the LIS. Walks the new record in\n * reverse so each move's anchor (`nextSibling`) is already in its final\n * position by the time we reach earlier items.\n *\n * `tailAnchor` is the element that comes AFTER the list inside `liveParent`\n * (or `null` if the list is at the end). The reconciler computes it via\n * `endAnchor(binding)` so it picks up non-list siblings the diff may have\n * inserted between the list and the parent's tail (KF-102).\n */\nfunction applyMoves(\n liveParent: Element,\n newRecord: BoundItem[],\n prevIdx: number[],\n stable: ReadonlySet<number>,\n tailAnchor: Element | null,\n): void {\n let nextSibling: Element | null = tailAnchor;\n for (let i = newRecord.length - 1; i >= 0; i--) {\n const node = newRecord[i].node;\n if (prevIdx[i] === -1 || !stable.has(i)) {\n liveParent.insertBefore(node, nextSibling);\n }\n nextSibling = node;\n }\n}\n\n/**\n * Patience-sort LIS: returns the *set of indices* in `arr` that participate\n * in a longest strictly-increasing subsequence. `-1` entries (representing\n * brand-new items in the new list) are ignored — they can't anchor the\n * subsequence and shouldn't count as stable.\n */\nfunction lis(arr: ReadonlyArray<number>): ReadonlySet<number> {\n const tails: number[] = [];\n const tailIdx: number[] = [];\n const prev = new Array<number>(arr.length);\n for (let i = 0; i < arr.length; i++) {\n const v = arr[i];\n if (v === -1) {\n prev[i] = -1;\n continue;\n }\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (tails[mid] < v) lo = mid + 1;\n else hi = mid;\n }\n prev[i] = lo > 0 ? tailIdx[lo - 1] : -1;\n tails[lo] = v;\n tailIdx[lo] = i;\n }\n const out = new Set<number>();\n let k = tailIdx.length > 0 ? tailIdx[tailIdx.length - 1] : -1;\n while (k !== -1) {\n out.add(k);\n k = prev[k];\n }\n return out;\n}\n","/**\n * Keyed list reconciler — the engine behind `each(...)` inside `mount()`.\n *\n * Public surface (re-exported via the rest of the runtime):\n * - `BoundItem` / `ListBinding`: the binding shape `mount()` keeps\n * per-list, mapping `each()` items to their live DOM nodes.\n * Defined in `list-binding.ts` and re-exported here.\n * - `endAnchor(binding)`: dynamic \"insert at end of list\" anchor.\n * Also defined in `list-binding.ts` and re-exported here.\n * - `reconcileList(binding, listSeg)`: top-level dispatch.\n *\n * Implementation lives in two sibling files:\n * - `list-reconcile-snapshot.ts` — the original keyed algorithm\n * (classify / bulk-parse / LIS / move). Used for plain-array `each()`\n * and for arraySignal-backed `each()` when the patch path can't apply\n * (first render, post-`replace()`, post-drift recovery).\n * - `list-reconcile-granular.ts` — the KF-92 patch-driven path used\n * when an `arraySignal`'s queued patches can be applied directly to\n * the existing binding without iterating the snapshot.\n *\n * The split mirrors the two-axis nature of the reconciler: snapshot-vs-\n * granular path × shared bookkeeping (binding shape, end-of-list anchor,\n * focus capture/restore). The binding shape is in its own `list-binding.ts`\n * file so the two sibling reconcilers can import it without creating a\n * circular dependency back to `list-reconcile.ts`. Internal to kerf — not\n * part of the public API.\n */\n\nexport { type BoundItem, endAnchor, type ListBinding } from './list-binding.js';\nimport type { ListBinding } from './list-binding.js';\nimport { reconcileGranular } from './list-reconcile-granular.js';\nimport { reconcileSnapshot } from './list-reconcile-snapshot.js';\nimport type { ListSegment } from './segment.js';\n\n/**\n * Reconcile `binding`'s live parent against `listSeg`. Mutates `binding.items`\n * to mirror the new segment when done.\n *\n * Dispatch:\n * - **Granular (KF-92)**: an `arraySignal`-backed `each()` whose patch\n * queue is non-empty AND the binding has at least one row. Applies\n * patches directly. `each()` filters `replace` patches upstream so the\n * patches reaching here are guaranteed to be update/insert/remove/move\n * only.\n * - **Snapshot**: every other case — first render of a list, plain-array\n * `each()`, post-`replace()`, post-drift recovery. Runs the keyed\n * classify/build/move algorithm.\n */\nexport function reconcileList(binding: ListBinding, listSeg: ListSegment): void {\n if (listSeg.patches !== undefined && binding.items.length > 0) {\n reconcileGranular(binding, listSeg.patches);\n return;\n }\n reconcileSnapshot(binding, listSeg);\n}\n","/**\n * `mount(rootEl, render)` — kerf's render primitive.\n *\n * Wraps `effect()` so that whenever any signal read inside `render()`\n * changes, we re-run `render()` and apply the minimum DOM mutations against\n * the live tree. Element identity (and thus focus, selection, in-flight\n * pointer interactions, and event listeners on preserved nodes) is preserved\n * wherever the keyed/positional diff matches.\n *\n * Two phases per render:\n *\n * - Static surrounds (everything outside `each()` lists): kerf's native\n * `morph()` reconciler walks a freshly-built template against the live\n * tree. Conventions: id/data-key matching, `data-morph-skip`, focus\n * preservation.\n *\n * - List interiors (children of every `each()` parent): native keyed\n * reconciler operates directly on the live parent's children. No\n * re-parse, no morph walk for cache-hit rows. Cost is O(changes), not\n * O(rows).\n *\n * Compared to a `replaceChildren(...rows.map(toElement))` rebuild pattern,\n * the user-visible win is that an `<input>` the user is typing into\n * survives an unrelated re-render — its DOM node, focus state, and cursor\n * position are not destroyed and recreated on each tick.\n */\n\nimport { maybeWarnEachInMorphSkip } from './dev-each-warn.js';\nimport { installListenerRebuildWarn } from './dev-listener-warn.js';\nimport { _setRenderContext, type RenderContext } from './each.js';\nimport type { SafeHtml } from './jsx-runtime.js';\nimport { isSafeHtml } from './jsx-runtime.js';\nimport {\n type BoundItem,\n type ListBinding,\n reconcileList,\n} from './list-reconcile.js';\nimport { morph } from './morph.js';\nimport { effect } from './reactive.js';\nimport {\n collectLists,\n flatten,\n flattenWithoutListItems,\n type ListSegment,\n type Segment,\n} from './segment.js';\nimport { maybeWarnMissingRowKey,parseRowTemplate, rowContractError } from './utils/rowContract.js';\n\nconst LIST_MARKER_PREFIX = 'kf-list:';\n\n/**\n * Bind `render()` to the children of `rootEl`. Re-runs whenever any signal\n * read inside `render()` changes. Returns a disposer that tears down the\n * effect; call it when the host element is removed from the DOM.\n *\n * Conventions:\n *\n * - Diff keys: `id` and `data-key` are matched across the morph by key\n * rather than positionally, so list reorders move existing nodes instead\n * of churning unrelated siblings.\n * - `data-morph-skip`: any element with this attribute is left untouched\n * inside on subsequent renders. Used for library-owned subtrees (xterm-\n * style widgets, charts, third-party editors) where the library's own\n * lifecycle manages the children.\n * - Focused text-entry inputs (`<input>` of typing kinds, `<textarea>`)\n * keep their current value + selection range across morphs while focused.\n * The user never sees their cursor jump mid-keystroke.\n * - Focused `[contenteditable]` elements have their entire subtree\n * skipped (same mechanism as `data-morph-skip`). The user's in-progress\n * edit — typed content, caret position, multi-range selections, anything\n * else they did to the DOM — survives verbatim. The next render after\n * blur catches up.\n */\nexport type MountResult = SafeHtml | string | number | boolean | null | undefined;\n\n// KF-175 — non-enumerable marker placed on `mount()`'s rootEl so that a\n// second `mount()` call on a descendant, ancestor, or the same element can be\n// detected and rejected. `Symbol.for(...)` so the marker survives multiple\n// kerfjs imports in the same realm (e.g. the dist-full test suite running a\n// rebuilt bundle against the src test infrastructure).\nconst MOUNTED_MARKER = Symbol.for('kerfjs.mounted');\n\nfunction describeEl(el: HTMLElement): string {\n const tag = el.tagName.toLowerCase();\n const id = el.id ? `#${el.id}` : '';\n return `<${tag}${id}>`;\n}\n\nfunction assertNotInsideMountedTree(rootEl: HTMLElement): void {\n // The element itself — same element mounted twice.\n if ((rootEl as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] === true) {\n throw new Error(\n `mount: ${describeEl(rootEl)} is already mounted. `\n + 'Call the disposer returned by the first mount() before mounting again. '\n + 'kerf supports one mount per element — compose with plain functions that return JSX instead of nesting mounts.',\n );\n }\n // Ancestors — walk up.\n let ancestor: Element | null = rootEl.parentElement;\n while (ancestor !== null) {\n if ((ancestor as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] === true) {\n throw new Error(\n 'mount: rootEl is already inside (or contains) a mounted tree. '\n + 'kerf supports one mount per tree — compose with plain functions that return JSX instead of nesting mounts.',\n );\n }\n ancestor = ancestor.parentElement;\n }\n // Descendants — DFS.\n const stack: Element[] = [];\n for (let i = 0; i < rootEl.children.length; i++) stack.push(rootEl.children[i]);\n while (stack.length > 0) {\n const cur = stack.pop() as Element;\n if ((cur as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] === true) {\n throw new Error(\n 'mount: rootEl is already inside (or contains) a mounted tree. '\n + 'kerf supports one mount per tree — compose with plain functions that return JSX instead of nesting mounts.',\n );\n }\n for (let i = 0; i < cur.children.length; i++) stack.push(cur.children[i]);\n }\n}\n\nexport function mount(rootEl: HTMLElement, render: () => MountResult): () => void {\n if (rootEl == null) {\n throw new Error(\n 'mount: rootEl is null/undefined — pass the live element, e.g. mount(document.getElementById(\"app\")!, render). '\n + 'A common cause is a typo in the id or selector that returns null at runtime even though the TypeScript types say HTMLElement.',\n );\n }\n // KF-243: defense-in-depth for inert-document roots. `toElement()` already\n // adopts its output into the live document, but a consumer can hand `mount()`\n // an element built some other way — their own `DOMParser`, a detached\n // `<template>.content` child, `document.implementation.createHTMLDocument()`\n // — whose `ownerDocument` has no browsing context. `mount()`'s first-render\n // `rootEl.innerHTML = …` on such an inert-document element trips the WebKit\n // fragment-parsing bug fixed in KF-240, so adopt it into the live document\n // first. Only genuinely inert owners (`defaultView === null`) are adopted; a\n // live element in another realm (e.g. an iframe, `defaultView !== null`) is\n // left in place — `mount()` works on it as-is, and we must never yank a node\n // out of its own window.\n const owner = rootEl.ownerDocument as Document;\n if (owner !== document) {\n /* c8 ignore start -- the defaultView!==null arm needs a second live browsing context (iframe element); not constructible in the unit environment */\n if (owner.defaultView === null) document.adoptNode(rootEl);\n /* c8 ignore stop */\n }\n assertNotInsideMountedTree(rootEl);\n (rootEl as unknown as Record<symbol, unknown>)[MOUNTED_MARKER] = true;\n // KF-174: opt-in dev MutationObserver that warns when a node carrying an\n // imperative addEventListener listener is removed/rebuilt by the morph.\n const listenerWarnObserver = installListenerRebuildWarn(rootEl);\n const bindings = new Map<string, ListBinding>();\n // Per-mount render context: the list-id counter is reset at the start of\n // each render (so the n-th `each()` call gets the same id every render);\n // the `caches` map persists across renders so unchanged items skip the\n // JSX work via cache hits even when the JSX render function is an inline\n // arrow that's a fresh function reference on every closure run (KF-87).\n const renderCtx: RenderContext = {\n counter: 0,\n caches: new Map(),\n bindingCounts: new Map(),\n };\n let isFirst = true;\n // KF-88: the static-surrounds HTML string from the previous render. If a\n // re-render produces the same string (the common case when a signal flips\n // a class on one row but the page chrome is unchanged), we skip the\n // template clone, the innerHTML re-parse, and the morph() walk entirely\n // and go straight to the per-list reconcilers. Saves ~8 ms per update-\n // path render against the krausest harness.\n let prevStaticHtml = '';\n\n const disposeEffect = effect(() => {\n renderCtx.counter = 0;\n _setRenderContext(renderCtx);\n let result: MountResult;\n try {\n result = render();\n } finally {\n _setRenderContext(null);\n }\n\n // The `MountResult` union covers `null`, `undefined`, `false`, `true`,\n // and `number` so consumers can write `() => cond ? <jsx/> : null` and\n // `() => cond && <jsx/>` without a cast. `coerceRenderResult` collapses\n // nullish + boolean to `''` (render nothing) and stringifies numbers.\n const segment: Segment = isSafeHtml(result)\n ? (result.__segment ?? { kind: 'static', html: result.__html })\n : { kind: 'static', html: coerceRenderResult(result) };\n\n if (isFirst) {\n runFirstRender(rootEl, segment, bindings);\n prevStaticHtml = flattenWithoutListItems(segment);\n isFirst = false;\n } else {\n prevStaticHtml = runSubsequentRender(rootEl, segment, bindings, renderCtx, prevStaticHtml);\n }\n\n for (const listSeg of collectLists(segment).values()) {\n const binding = bindings.get(listSeg.id) as ListBinding;\n reconcileList(binding, listSeg);\n // KF-99: record the post-reconcile binding length so the next render's\n // granular path can detect drift (a prior render that threw mid-batch\n // leaves the binding shorter than the signal expects).\n renderCtx.bindingCounts.set(listSeg.id, binding.items.length);\n }\n });\n\n return () => {\n disposeEffect();\n listenerWarnObserver?.disconnect();\n // Clear the mounted marker so `mount(sameEl, ...)` after dispose works.\n delete (rootEl as unknown as Record<symbol, unknown>)[MOUNTED_MARKER];\n };\n}\n\n/**\n * First render of a mount: bulk-flatten the segment (items inlined, markers\n * around each list) into `rootEl.innerHTML`, then walk the markers to\n * register a `ListBinding` per list. The subsequent `reconcileList` pass is\n * a no-op (every row's a cache hit on the just-bound items).\n */\nfunction runFirstRender(\n rootEl: HTMLElement,\n segment: Segment,\n bindings: Map<string, ListBinding>,\n): void {\n rootEl.innerHTML = flatten(segment, true);\n bindListsFromMarkers(rootEl, segment, bindings, true);\n}\n\n/**\n * Subsequent render of a mount. Returns the new `prevStaticHtml` so the\n * caller can carry it forward.\n *\n * Two paths:\n *\n * - **KF-88 fast path**: when the static-surrounds string didn't change\n * byte-for-byte, `bindListsFromMarkers` has nothing to discover and the\n * diff would short-circuit on `isEqualNode` for every element it visited —\n * but the visit itself isn't free. Skip both to save ~8 ms per partial-\n * update / select-row / swap-rows render against the krausest harness.\n *\n * Trade-off (KF-117, documented in `docs/4-render.md` §4.4.2): any\n * attribute or child set imperatively on a kerf-managed element (e.g.\n * `el.setAttribute(...)`) survives across no-op re-renders because the\n * diff doesn't run to wipe it. When the surrounds DO change, the diff\n * runs and `morphAttributes` removes anything the JSX didn't authorise.\n * This matches the framework's \"smallest cut\" model: don't touch what\n * JSX didn't change.\n *\n * - **Surrounds-changed path**: clean up orphan bindings (lists that\n * disappeared from this render's segment), build a template from the\n * static-only HTML, run `morph()` over the surrounds with the\n * list-owned items as `ownedItems` (KF-102 round 2 — the morph skips\n * owned items individually but still walks every parent so non-list\n * siblings around an each() reconcile correctly), then bind any\n * newly-appearing lists.\n */\nfunction runSubsequentRender(\n rootEl: HTMLElement,\n segment: Segment,\n bindings: Map<string, ListBinding>,\n renderCtx: RenderContext,\n prevStaticHtml: string,\n): string {\n const currentStaticHtml = flattenWithoutListItems(segment);\n if (currentStaticHtml === prevStaticHtml) {\n return prevStaticHtml;\n }\n cleanupOrphanBindings(segment, bindings, renderCtx);\n const template = rootEl.cloneNode(false) as HTMLElement;\n template.innerHTML = currentStaticHtml;\n morph(rootEl, template, collectOwnedItems(bindings));\n bindListsFromMarkers(rootEl, segment, bindings, false);\n return currentStaticHtml;\n}\n\n/**\n * Coerce a non-`SafeHtml` render result to a safe HTML string. Nullish\n * values and booleans become `''` (render nothing) — matches the React /\n * Solid convention so `{cond ? <jsx/> : null}` and `{cond && <jsx/>}`\n * patterns work without each consumer adding a sentinel. Everything else\n * is stringified (numbers → `\"42\"`, strings pass through).\n */\nfunction coerceRenderResult(result: unknown): string {\n if (result === null || result === undefined) return '';\n if (result === false || result === true) return '';\n return String(result);\n}\n\n/**\n * Walk the live tree's comment nodes; every `<!--kf-list:{id}-->` marker\n * is the start anchor of a list inside `liveParent`. Bind the list (parent +\n * already-rendered item nodes between the marker and the tail). The marker\n * stays in the live DOM (KF-102 round 2): keeping it as a permanent\n * comment-node anchor lets the static-surrounds diff insert/remove/morph\n * non-list siblings around the list without needing to re-establish the\n * list's begin position.\n *\n * `inlinedItems` distinguishes the first-render path (where `flatten(seg,\n * true)` inlines item HTML right after the marker, so the marker's element\n * siblings *are* the list rows) from subsequent renders that newly\n * introduce a list (where `flattenWithoutListItems` emits only the marker\n * and the list reconciler populates items afterwards).\n *\n * Existing bindings whose marker is still in the DOM are left intact —\n * `bindings.has(id)` skips re-binding so the prior render's item nodes\n * survive across static-surrounds diffs.\n */\nfunction bindListsFromMarkers(\n rootEl: Element,\n segment: Segment,\n bindings: Map<string, ListBinding>,\n inlinedItems: boolean,\n): void {\n const lists = collectLists(segment);\n const found: Comment[] = [];\n collectComments(rootEl, found);\n for (const marker of found) {\n if (!marker.data.startsWith(LIST_MARKER_PREFIX)) continue;\n const id = marker.data.slice(LIST_MARKER_PREFIX.length);\n if (bindings.has(id)) continue; // existing binding survives the diff\n const listSeg = lists.get(id) as ListSegment;\n const liveParent = marker.parentElement as Element;\n const items: BoundItem[] = [];\n if (inlinedItems) {\n // KF-103: enforce the \"exactly one top-level element per row\" contract\n // on first render too. Without this check, a multi-root row inlined\n // via `flatten(seg, true)` would silently misalign the binding (each\n // bound item.node points at only the first of a row's 2+ elements,\n // and the leftover elements are picked up as \"next\" rows). The check\n // is per-row so we can pinpoint the offender by index.\n let next: Element | null = marker.nextElementSibling;\n for (let i = 0; i < listSeg.items.length && next !== null; i++) {\n validateInlinedRowMatch(listSeg.items[i].html, i, next);\n items.push({\n ref: listSeg.items[i].ref,\n cacheKey: listSeg.items[i].cacheKey,\n html: listSeg.items[i].html,\n node: next,\n });\n next = next.nextElementSibling;\n }\n }\n const binding: ListBinding = { liveParent, items, marker };\n // KF-173: dev-only one-shot warning if the first row has no id/data-key.\n if (items.length > 0) {\n maybeWarnMissingRowKey(items[0].node, 0, items[0].html, binding);\n }\n // Dev-mode: warn when an each() list is inside a data-morph-skip subtree\n // (list rows still update; static reactive siblings are frozen).\n maybeWarnEachInMorphSkip(id, liveParent, rootEl);\n bindings.set(id, binding);\n }\n}\n\n/**\n * KF-103: validate that `expectedHtml` (one row's render output) matches\n * the live `boundEl`'s `outerHTML` — confirming the row produced exactly\n * one top-level element. If they differ, parse the row in isolation and\n * throw a precise error mentioning the row index and the actual count.\n *\n * Fast path: outerHTML compare is a string equality check (zero allocs in\n * happy-dom; one alloc in V8). Only when they DON'T match (multi-root or\n * subtle browser-normalized single-root case) do we fall back to a full\n * per-row parse for the precise count.\n */\nfunction validateInlinedRowMatch(\n expectedHtml: string,\n index: number,\n boundEl: Element,\n): void {\n if (boundEl.outerHTML === expectedHtml) return;\n // The bound element's outerHTML differs from what we emitted. Parse the\n // expected html in isolation; if it's still single-root the difference\n // is whitespace / browser-normalization (e.g. `<br/>` → `<br>`) and\n // we proceed silently. Otherwise build the precise contract-violation\n // error from the shared helper.\n const { count } = parseRowTemplate(expectedHtml);\n if (count === 1) return;\n throw rowContractError(index, expectedHtml);\n}\n\n/**\n * Build the set of element nodes owned by `each()` list reconcilers, the\n * union of every binding's `items[].node`. The static-surrounds diff\n * skips these so list rows are invisible to the parent walk while\n * sibling reconciliation continues normally (KF-102 round 2).\n */\nfunction collectOwnedItems(bindings: Map<string, ListBinding>): Set<Element> {\n const owned = new Set<Element>();\n for (const b of bindings.values()) {\n for (const item of b.items) owned.add(item.node);\n }\n return owned;\n}\n\n/**\n * Remove items + binding entries for any list that's no longer present in\n * the new segment. The diff's trailing-removal pass would have removed the\n * marker (since the new template no longer emits one for this id), but\n * items are owned and stay protected from removal — so we drop them\n * explicitly here before the diff runs.\n */\nfunction cleanupOrphanBindings(\n segment: Segment,\n bindings: Map<string, ListBinding>,\n renderCtx: RenderContext,\n): void {\n const liveIds = collectLists(segment);\n for (const [id, binding] of bindings) {\n if (liveIds.has(id)) continue;\n for (const item of binding.items) {\n if (item.node.parentElement !== null) {\n item.node.parentElement.removeChild(item.node);\n }\n }\n if (binding.marker.parentElement !== null) {\n binding.marker.parentElement.removeChild(binding.marker);\n }\n bindings.delete(id);\n renderCtx.bindingCounts.delete(id);\n renderCtx.caches.delete(id);\n }\n}\n\n/**\n * Recursive collector for comment nodes — happy-dom's `TreeWalker` doesn't\n * surface `Node.COMMENT_NODE` despite accepting `NodeFilter.SHOW_COMMENT`,\n * so we walk children directly. Cheap (O(elements)) and portable.\n */\nfunction collectComments(node: Node, out: Comment[]): void {\n for (let c: Node | null = node.firstChild; c !== null; c = c.nextSibling) {\n if (c.nodeType === Node.COMMENT_NODE) out.push(c as Comment);\n else if (c.nodeType === Node.ELEMENT_NODE) collectComments(c, out);\n }\n}\n\n\n","/**\n * `toElement(jsx)` — JSX → DOM, with SVG-aware namespace handling.\n *\n * Single-root inputs return an `Element`. Multi-root inputs (text + element,\n * `<><svg/> label</>`, two icons side by side, …) return a `DocumentFragment`\n * containing every top-level node. The DOM insertion APIs (`appendChild`,\n * `replaceChildren`, `append`) inline a `DocumentFragment`'s children on\n * insert, so `parent.replaceChildren(toElement(<>{ICON} label</>))` does the\n * obvious thing — parent gets the svg AND the text, no silent loss.\n *\n * The returned node is always adopted into the live `document` before it's\n * handed back (see `adopt()` below) — never left owned by the inert\n * `<template>`/`DOMParser` document it was parsed in, which is unsafe to mutate\n * before insertion on some engines.\n *\n * SVG namespacing: the HTML5 parser handles `<svg>` as foreign content\n * correctly even when wrapped in a fragment, so multi-root inputs containing\n * SVGs come out namespaced correctly via the `<template>.innerHTML` path. For\n * single-root SVG inputs the XML parser is preferred (stricter — catches\n * malformed markup the HTML5 parser would silently auto-correct). For orphan\n * SVG-namespace fragments without an `<svg>` wrapper (`<path/>`, `<g>`, …)\n * the input is wrapped in `<svg xmlns=...>` and XML-parsed.\n */\n\nimport type { SafeHtml } from './jsx-runtime.js';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\nconst SVG_FRAGMENT_TAGS = new Set([\n 'g', 'path', 'circle', 'rect', 'line', 'polygon', 'polyline', 'ellipse',\n 'text', 'tspan', 'defs', 'use', 'symbol', 'clipPath', 'mask', 'pattern',\n 'filter', 'marker', 'linearGradient', 'radialGradient', 'stop', 'image',\n 'foreignObject',\n]);\n\nconst EXCERPT_MAX_LEN = 100;\n\nfunction excerpt(html: string): string {\n const trimmed = html.trim();\n return trimmed.length > EXCERPT_MAX_LEN ? `${trimmed.slice(0, EXCERPT_MAX_LEN)}…` : trimmed;\n}\n\n/**\n * Adopt `node` into the live `document` before returning it.\n *\n * Both parse paths produce nodes that belong to an *inert* document, not the\n * one the caller renders into: the `<template>.content` path yields nodes\n * owned by the template-contents owner document, and the `DOMParser` path\n * yields nodes owned by the parser's document. Returning such a node is a\n * footgun — operating on it before it's inserted (most notably `mount()`'s\n * first-render `rootEl.innerHTML = …`) runs against an inert-document element,\n * which on WebKit trips a fragment-parsing bug: under rapid bursts the parser\n * can hand back a *previous* parse's nodes, so a freshly-built element silently\n * inherits unrelated DOM. (Chromium never reproduces it; the originating\n * report was Safari-only — a feed mounting many `toElement(<div/>)` cards in\n * one flush, each painting a stale sibling's state.) `adoptNode` moves the node\n * into the live document (preserving identity and namespaces), so the returned\n * node is always safe to mutate before insertion.\n */\nfunction adopt<T extends Node>(node: T): T {\n document.adoptNode(node);\n return node;\n}\n\nfunction parseSvgOrThrow(html: string, label: string, originalHtml: string): Document {\n const doc = new DOMParser().parseFromString(html, 'image/svg+xml');\n const err = doc.querySelector('parsererror');\n if (err !== null) {\n throw new Error(`toElement: ${label} parse error — ${err.textContent}\\n input: ${excerpt(originalHtml)}`);\n }\n return doc;\n}\n\n// True when the fragment is effectively a single root — exactly one element\n// child, all sibling nodes whitespace-only text. Returns that element, else\n// null. The whitespace tolerance matches the pre-KF-232 behavior for inputs\n// like ` <svg/>\\n` (which were treated as a single SVG root).\nfunction singleRootElement(content: DocumentFragment): Element | null {\n if (content.children.length !== 1) return null;\n const onlyElement = content.firstElementChild;\n /* c8 ignore next — guarded by children.length === 1 above. */\n if (onlyElement === null) return null;\n for (const node of content.childNodes) {\n if (node === onlyElement) continue;\n if (node.nodeType !== Node.TEXT_NODE) return null;\n /* c8 ignore next — `textContent` on a TEXT_NODE is always a string; the `??` is a TypeScript-only guard. */\n if ((node.textContent ?? '').trim() !== '') return null;\n }\n return onlyElement;\n}\n\nexport function toElement(jsx: SafeHtml | string): Element | DocumentFragment {\n const html = typeof jsx === 'string' ? jsx : jsx.toString();\n\n // First pass: HTML <template> parse. This gives us correct namespacing for\n // `<svg>` (foreign content), reveals the multi-root vs single-root shape,\n // and is the universal fallback path. Orphan SVG fragments without an\n // `<svg>` wrapper are the one case that needs a different parser — handled\n // below.\n const t = document.createElement('template');\n t.innerHTML = html;\n const content = t.content;\n\n const single = singleRootElement(content);\n\n if (single !== null) {\n const tag = single.tagName.toLowerCase();\n\n // Single SVG root → re-parse via XML for strict validation. The HTML5\n // parser silently auto-corrects malformed SVG (`<svg><unclosed</svg>`),\n // which is worse than throwing. Trim so trailing whitespace in the input\n // doesn't trip up the XML parser.\n if (tag === 'svg') {\n return adopt(parseSvgOrThrow(html.trim(), 'SVG', html).documentElement);\n }\n\n // Single orphan SVG-namespace fragment (`<path/>`, `<g>`, …) — the HTML5\n // parser puts these in the XHTML namespace, so wrap in `<svg>` and\n // XML-parse to get the right namespace on the returned element.\n if (SVG_FRAGMENT_TAGS.has(tag)) {\n const wrapped = `<svg xmlns=\"${SVG_NS}\">${html}</svg>`;\n const doc = parseSvgOrThrow(wrapped, 'SVG fragment', html);\n const first = doc.documentElement.firstElementChild;\n /* c8 ignore next 2 — defensive: a successful XML parse of a wrapped svg always yields ≥1 child. */\n if (first === null) throw new Error(`toElement: SVG fragment produced no element\\n input: ${excerpt(html)}`);\n return adopt(first);\n }\n\n return adopt(single);\n }\n\n // Multi-root (or no roots): return the parsed DocumentFragment so the caller\n // can splat all the top-level nodes into their container via appendChild /\n // replaceChildren / append. If the input produced nothing at all, throw —\n // there's no useful Node to hand back.\n if (content.childNodes.length === 0) {\n throw new Error(`toElement: produced no element\\n input: ${excerpt(html)}`);\n }\n if (content.children.length === 0) {\n // No element children at all — only text or comments. Same \"no element\"\n // failure as the empty case; toElement's name implies at least one\n // element somewhere.\n throw new Error(`toElement: produced no element\\n input: ${excerpt(html)}`);\n }\n return adopt(content);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kerfjs",
3
- "version": "0.13.0",
3
+ "version": "0.15.0-beta.1",
4
4
  "description": "Tiny reactive UI framework — fine-grained signals + DOM morphing + JSX. Apply the smallest possible cut to update your DOM.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -88,6 +88,7 @@
88
88
  "prepare": "husky",
89
89
  "release": "bash scripts/release.sh",
90
90
  "release:beta": "bash scripts/release.sh --beta",
91
+ "commit:msg": "gitgist --staged --commit-message",
91
92
  "prepublishOnly": "npm run build",
92
93
  "example:reactivity-demo": "cd examples/reactivity-demo && npm install && npm run dev",
93
94
  "example:reactivity-demo:build": "cd examples/reactivity-demo && npm install && npm run build",
@@ -107,6 +108,7 @@
107
108
  "@vitest/coverage-v8": "^3.0.0",
108
109
  "eslint": "^9.16.0",
109
110
  "eslint-plugin-simple-import-sort": "^12.1.1",
111
+ "gitgist": "^1.0.0",
110
112
  "happy-dom": "^20.9.0",
111
113
  "http-server": "^14.1.1",
112
114
  "husky": "^9.1.7",