kerfjs 4.4.0 → 5.0.0-beta.3

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/LICENSE +1 -1
  3. package/README.md +34 -35
  4. package/ai/cursorrules +46 -1
  5. package/ai/manifest.json +62 -5
  6. package/ai/skill.md +53 -2
  7. package/dist/actions.d.ts +1 -1
  8. package/dist/actions.js +4 -4
  9. package/dist/actions.js.map +1 -1
  10. package/dist/array-signal.js +5 -5
  11. package/dist/async.js +17 -10
  12. package/dist/async.js.map +1 -1
  13. package/dist/attach.d.ts +11 -8
  14. package/dist/attach.js +52 -4
  15. package/dist/attach.js.map +1 -1
  16. package/dist/chunk-GY4XV2UV.js +1 -1
  17. package/dist/{chunk-VVDJLWMP.js → chunk-HW7KSM2Y.js} +2 -2
  18. package/dist/chunk-HW7KSM2Y.js.map +1 -0
  19. package/dist/{chunk-KEZTD6H4.js → chunk-KPXIOG2C.js} +3 -3
  20. package/dist/{chunk-KEZTD6H4.js.map → chunk-KPXIOG2C.js.map} +1 -1
  21. package/dist/{chunk-SAYPJ6XR.js → chunk-KZJXHFIB.js} +10 -6
  22. package/dist/chunk-KZJXHFIB.js.map +1 -0
  23. package/dist/{chunk-MRYM3O3V.js → chunk-LVH3GC6B.js} +11 -8
  24. package/dist/chunk-LVH3GC6B.js.map +1 -0
  25. package/dist/chunk-QIP723L4.js +1 -1
  26. package/dist/{chunk-SRWQKB33.js → chunk-SVATPF5R.js} +97 -74
  27. package/dist/chunk-SVATPF5R.js.map +1 -0
  28. package/dist/{chunk-3APBEVHF.js → chunk-U6FK33SG.js} +3 -3
  29. package/dist/{chunk-3APBEVHF.js.map → chunk-U6FK33SG.js.map} +1 -1
  30. package/dist/{chunk-U32TFTGZ.js → chunk-UZJ6I4T6.js} +3 -3
  31. package/dist/chunk-UZJ6I4T6.js.map +1 -0
  32. package/dist/{chunk-YHH7OUFA.js → chunk-V46JKE44.js} +3 -3
  33. package/dist/chunk-V46JKE44.js.map +1 -0
  34. package/dist/{chunk-SUPUPSBE.js → chunk-ZDCJZCNO.js} +9 -8
  35. package/dist/chunk-ZDCJZCNO.js.map +1 -0
  36. package/dist/dev.d.ts +9 -6
  37. package/dist/dev.js +5 -5
  38. package/dist/dev.js.map +1 -1
  39. package/dist/html.d.ts +1 -1
  40. package/dist/html.js +5 -5
  41. package/dist/html.js.map +1 -1
  42. package/dist/index.d.ts +1 -1
  43. package/dist/index.js +11 -11
  44. package/dist/jsx-runtime.js +5 -5
  45. package/dist/list.d.ts +1 -1
  46. package/dist/list.js +273 -211
  47. package/dist/list.js.map +1 -1
  48. package/dist/overlay.d.ts +190 -280
  49. package/dist/overlay.js +401 -361
  50. package/dist/overlay.js.map +1 -1
  51. package/dist/remount.d.ts +5 -3
  52. package/dist/remount.js +29 -10
  53. package/dist/remount.js.map +1 -1
  54. package/dist/router.d.ts +1 -1
  55. package/dist/router.js +44 -22
  56. package/dist/router.js.map +1 -1
  57. package/dist/scope.d.ts +4 -3
  58. package/dist/scope.js +10 -10
  59. package/dist/scope.js.map +1 -1
  60. package/dist/testing.js +4 -4
  61. package/dist/timing.d.ts +3 -2
  62. package/dist/timing.js +5 -5
  63. package/dist/timing.js.map +1 -1
  64. package/llms.txt +7 -4
  65. package/package.json +12 -10
  66. package/dist/chunk-MRYM3O3V.js.map +0 -1
  67. package/dist/chunk-SAYPJ6XR.js.map +0 -1
  68. package/dist/chunk-SRWQKB33.js.map +0 -1
  69. package/dist/chunk-SUPUPSBE.js.map +0 -1
  70. package/dist/chunk-U32TFTGZ.js.map +0 -1
  71. package/dist/chunk-VVDJLWMP.js.map +0 -1
  72. package/dist/chunk-YHH7OUFA.js.map +0 -1
  73. /package/dist/{attrSelector-Cmu2ZoGO.d.ts → attr-Cmu2ZoGO.d.ts} +0 -0
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev-warn-config.ts","../src/dev-binding-warn.ts","../src/dev-delegate-warn.ts","../src/dev-each-warn.ts","../src/dev-invariants.ts","../src/dev-list-index-warn.ts","../src/dev-list-key-warn.ts","../src/dev-list-rebind-warn.ts","../src/dev-listener-warn.ts","../src/dev-parser-repair-warn.ts","../src/dev-rerender-warn.ts","../src/dev-row-key-warn.ts","../src/dev-signal.ts","../src/dev-store-warn.ts","../src/utils/devReadonly.ts","../src/dev.ts"],"names":["isOptedIn","warnedIds","warned","changed","out","coreSignal"],"mappings":"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","file":"dev.js","sourcesContent":["/**\n * The switch layer for the opt-in diagnostics — the second of the two gates\n * (§11.3.1). The first gate is installation: reaching this module at all means\n * the consumer imported `kerfjs/dev`.\n *\n * Two sources feed one lookup, explicit-call-wins:\n *\n * 1. `enableWarnings({...})` — an in-memory map, set by the consumer through\n * the `kerfjs/dev` entry. Explicit wins in BOTH directions, so\n * `{ narrowSet: false }` silences a warning an ambient env var switched on.\n * 2. `globalThis.process?.env?.KERF_DEV_*` — the environment, kept for Node,\n * SSR, and CI, where exporting a variable is the natural way to turn a\n * diagnostic on for one run.\n *\n * ## Why the env var could not be the only switch\n *\n * It is unreachable in the majority case. kerf is a browser framework, and a\n * browser realm has no `process` object at all — so every one of these\n * warnings was permanently off in exactly the environment (a Vite/webpack dev\n * server) where a developer most wants them. A bundler `define` does not fix\n * it either: the read goes through `globalThis.process` into a local binding,\n * so nothing substitutes the `process.env.X` token. That indirection is not\n * incidental — reading the bare token is what made kerf infer DEVELOPMENT\n * inside production browser bundles.\n *\n * The consumer already holds the module at the moment they opt in\n * (`const dev = await import('kerfjs/dev')`), so handing them a typed function\n * there is both the most reachable and the most discoverable switch. The env\n * vars stay because kerf's own suites and any CI run use them.\n */\n\n/**\n * Which diagnostics to switch on. Every key is off unless you name it; passing\n * `false` explicitly forces a warning off even when its env var is set.\n *\n * `invariants` is not a warning but the structural audit of kerf's own list\n * bookkeeping: `true` reports violations with `console.warn`, `'throw'` raises\n * them (what you want in a test suite, where a warning inside a passing test\n * is invisible).\n */\nexport interface DevWarningOptions {\n /** Imperative `addEventListener` on a node the morph later rebuilds. */\n rebuiltListeners?: boolean;\n /** A `.value` write to a signal that never had a subscriber. */\n untrackedSignals?: boolean;\n /** `defineStore` `set()` called with keys missing from the current state. */\n narrowSet?: boolean;\n /** `delegate()` called inside an `effect()` body — listeners stack up. */\n delegateInEffect?: boolean;\n /** An `each()` list under a `data-morph-skip` subtree. */\n eachInMorphSkip?: boolean;\n /** Two rows in one `each()` producing the same `cacheKey`. */\n duplicateEachKeys?: boolean;\n /** A fine-grained binding switching signal instance on the fast path. */\n staleBinding?: boolean;\n /** A re-render whose whole diff was values — candidates for bindings. */\n valueOnlyRerender?: boolean;\n /** An `each()` container rebuilt by the morph and self-healed. */\n listRebind?: boolean;\n /** A memoized row reused at a different index than it rendered at. */\n staleIndex?: boolean;\n /** Markup the HTML parser repaired (a block element inside a `<p>`). */\n parserRepair?: boolean;\n /** Structural audit of kerf's list bookkeeping: warn, or `'throw'`. */\n invariants?: boolean | 'throw';\n}\n\n/** Option key → the environment variable that means the same thing. */\nconst ENV_NAME: Record<keyof DevWarningOptions, string> = {\n rebuiltListeners: 'KERF_DEV_WARN_REBUILT_LISTENERS',\n untrackedSignals: 'KERF_DEV_WARN_UNTRACKED_SIGNALS',\n narrowSet: 'KERF_DEV_WARN_NARROW_SET',\n delegateInEffect: 'KERF_DEV_WARN_DELEGATE_IN_EFFECT',\n eachInMorphSkip: 'KERF_DEV_WARN_EACH_IN_MORPH_SKIP',\n duplicateEachKeys: 'KERF_DEV_WARN_DUPLICATE_EACH_KEYS',\n staleBinding: 'KERF_DEV_WARN_STALE_BINDING',\n valueOnlyRerender: 'KERF_DEV_WARN_VALUE_ONLY_RERENDER',\n listRebind: 'KERF_DEV_WARN_LIST_REBIND',\n staleIndex: 'KERF_DEV_WARN_STALE_INDEX',\n parserRepair: 'KERF_DEV_WARN_PARSER_REPAIR',\n invariants: 'KERF_DEV_INVARIANTS',\n};\n\n/** Env name → the value the call set. `false` means \"explicitly off\". */\nconst overrides = new Map<string, string | false>();\n\n/** Apply a consumer's `enableWarnings()` options to the override map. */\nexport function applyWarningOptions(options: DevWarningOptions): void {\n for (const [key, value] of Object.entries(options)) {\n const envName = ENV_NAME[key as keyof DevWarningOptions];\n // Unknown keys are ignored rather than thrown on: a consumer who upgrades\n // kerf downwards should not have their app die on a key that used to exist.\n if (envName === undefined || value === undefined) continue;\n overrides.set(envName, value === false ? false : value === true ? '1' : value);\n }\n}\n\n/**\n * The value of one diagnostic switch, or `undefined` when it is off.\n * Every warner's opt-in check goes through here.\n */\nexport function devFlag(envName: string): string | undefined {\n const override = overrides.get(envName);\n if (override !== undefined) return override === false ? undefined : override;\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n return proc?.env?.[envName];\n}\n\n/** Test helper — drops every `enableWarnings()` override. */\nexport function _resetWarningOptionsForTests(): void {\n overrides.clear();\n}\n","/**\n * Dev-mode warning for silently-stale fine-grained bindings on the fast path\n * (KERF_DEV_WARN_STALE_BINDING=1).\n *\n * `mount()` has a fast path: when a re-render produces byte-for-byte identical\n * static-surrounds HTML (`nextStaticHtml === prevStaticHtml`), the morph AND the\n * binding re-wiring are both skipped and the existing per-hole binding effects\n * stay live — each bound to the FIRST signal instance registered for its hole.\n *\n * That is correct for the canonical pattern `class={computed(() => sig.value)}`:\n * the fresh computed each render reads the same underlying signal(s), so the\n * original effect keeps firing. A hole goes silently STALE only when a render\n * switches which signal INSTANCE it binds while the surrounds string is\n * unchanged — `class={cond ? sigA : sigB}`. kerf keeps the original effect bound\n * to `sigA` and never re-binds to `sigB`, so the hole freezes with no error: the\n * UI just stops updating. See docs/2-reactivity §2.9.\n *\n * This warner detects that: on a fast-path render `mount()` calls\n * `maybeWarnStaleBinding(prevWired, current)`, comparing — per hole, in\n * registration order — the signal instance this render registered\n * (`bindingCtx.list`) against the signal instance that is actually wired (the\n * previously-wired list retained by `mount()`). A per-hole difference fires a\n * one-shot warning naming the hole (kind / attr / id) and pointing at the \"bind\n * one computed that switches internally\" fix.\n *\n * Why opt-in: the comparison is raw signal identity, so a GLOBAL (static-\n * surround) hole bound with a *fresh inline* `computed(() => …)` — a new\n * instance every render, but reading the same signals, hence safe — also differs\n * on the fast path and would warn. Binding a STABLE signal / computed reference\n * for global holes (the idiomatic shape) avoids that; the opt-in gate keeps the\n * diagnostic available for projects that want it without penalizing ones that\n * pass a fresh inline computed into a global hole. (Row holes inside `each()` are\n * wired per-row-node and disposed on row removal, so they are not subject to\n * this fast-path staleness and never reach this warner.)\n *\n * Production behavior is unchanged for zero runtime cost — the env-var read\n * short-circuits before any per-render comparison work runs, and `mount()` gates\n * the previously-wired-list retention on the same opt-in so the fast path stays\n * allocation-free when the warning is off.\n */\n\nimport type { Binding } from './bindings.js';\nimport { devFlag } from './dev-warn-config.js';\n\n/** Per-hole one-shot dedup — keyed by the stable per-hole binding id. */\nconst warnedHoles = new Set<string>();\n\nexport function isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_STALE_BINDING') === '1';\n}\n\nfunction describeHole(b: Binding): string {\n return b.kind === 'attr'\n ? `attr '${b.attr}' (id '${b.id}')`\n : `text (id '${b.id}')`;\n}\n\n/**\n * Compare this render's registered holes against the previously-wired holes,\n * in registration order, and warn once per hole whose signal instance changed\n * on a fast-path (byte-equal-surrounds) render. On the fast path the two lists\n * describe the same holes in the same order, so a per-index compare suffices;\n * the `Math.min` guard is defensive against a length skew that can't occur when\n * the surrounds are byte-equal.\n */\nexport function maybeWarnStaleBinding(\n prevWired: readonly Binding[],\n current: readonly Binding[],\n): void {\n if (!isOptedIn()) return;\n const n = Math.min(prevWired.length, current.length);\n for (let i = 0; i < n; i++) {\n const cur = current[i];\n if (prevWired[i].signal === cur.signal) continue;\n if (warnedHoles.has(cur.id)) continue;\n warnedHoles.add(cur.id);\n console.warn(\n `kerf: fine-grained binding ${describeHole(cur)} switched to a different signal instance `\n + 'on a render whose static-surrounds HTML was byte-for-byte unchanged. On that fast path kerf '\n + 'keeps the original binding effect and does NOT re-bind, so this hole is now stale — it still '\n + 'tracks the FIRST signal instance and will not reflect the new one. Bind one computed that '\n + 'switches internally (e.g. class={computed(() => cond.value ? sigA.value : sigB.value)}) instead '\n + 'of switching which signal instance you bind (see docs/2-reactivity §2.9). '\n + 'Set KERF_DEV_WARN_STALE_BINDING=0 (or unset it) to silence this warning.',\n );\n }\n}\n\n/**\n * Test helper — resets the one-shot dedup set so a subsequent test in the same\n * module can re-exercise the first-warning path. Not exported from the public\n * barrel; the unit-test file imports it directly via the relative path.\n */\nexport function _resetWarnedForTests(): void {\n warnedHoles.clear();\n}\n","/**\n * Dev-mode warning for `delegate()` / `delegateCapture()` calls that run\n * inside an `effect()` body (KERF_DEV_WARN_DELEGATE_IN_EFFECT=1).\n *\n * Why the pattern matters: every effect re-run executes its body fresh, which\n * means a `delegate()` call inside the body installs a NEW root listener on\n * each re-run. The effect's disposer cleans up the reactive subscription but\n * not the side-effects the body produced — so previous listeners stay\n * attached, the per-listener closure pins `rootEl` / `handler` / everything\n * the handler closes over, and listener count grows linearly with signal\n * churn. Structurally identical to the addEventListener-inside-mount foot-gun\n * (Hard Rule 4) but doesn't *look* like it.\n *\n * Static analysis can't reliably detect \"inside an effect\" without flow\n * information (effect() is just a function call), so the canonical defense\n * is this runtime opt-in warning. When enabled, `reactive.ts`'s `effect()`\n * wrapper increments a module-level counter before invoking the user body\n * and decrements after; `delegate.ts` checks the counter and fires the\n * warning once total.\n *\n * Production behavior is unchanged for zero runtime cost — the env-var check\n * short-circuits before any state is touched, and the wrapper in\n * `reactive.ts` only wraps when the gate is on.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nlet depth = 0;\nlet warned = false;\n\nfunction isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_DELEGATE_IN_EFFECT') === '1';\n}\n\n/** Called by the `effect()` wrapper in `reactive.ts` before running the user body. */\nexport function enterEffect(): void {\n depth++;\n}\n\n/** Called by the `effect()` wrapper in `reactive.ts` after the user body returns or throws. */\nexport function exitEffect(): void {\n depth--;\n}\n\n/** Public re-export of the env-var check so `reactive.ts` can decide whether to wrap. */\nexport function isDevWarnDelegateInEffectEnabled(): boolean {\n return isOptedIn();\n}\n\n/**\n * Called at the top of `delegate()` and `delegateCapture()`. If the call is\n * happening inside an `effect()` body (depth > 0) AND the env var is on, fire\n * a one-shot warning. The `fn` argument is the name of the caller for the\n * message (\"delegate\" vs \"delegateCapture\").\n */\nexport function warnIfInsideEffect(fn: 'delegate' | 'delegateCapture'): void {\n if (!isOptedIn()) return;\n if (depth === 0) return;\n if (warned) return;\n warned = true;\n console.warn(\n `kerf: ${fn}() was called inside an effect() body. `\n + 'Every effect re-run installs a fresh root listener; the effect disposer cleans up the '\n + 'reactive subscription but not the listeners, so listener count grows linearly with signal '\n + 'churn and each listener pins its handler closure. Register the delegate once at module '\n + 'or setup scope and gate behavior on the signal *inside the handler* where the read is free. '\n + 'See docs/5-event-delegation.md §5.3 \"When capturing the disposer still isn\\'t enough\". '\n + 'Set KERF_DEV_WARN_DELEGATE_IN_EFFECT=0 (or unset it) to silence this warning.',\n );\n}\n\n/** Test helper — resets the one-shot dedup flag and depth counter for unit tests. */\nexport function _resetWarnedForTests(): void {\n warned = false;\n depth = 0;\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\nimport { devFlag } from './dev-warn-config.js';\n\nconst warnedIds = new Set<string>();\n\nfunction isOptedIn(): boolean {\n return devFlag('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 return devFlag('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 * Dev-mode structural invariant checks for the list bindings\n * (`KERF_DEV_INVARIANTS=1` to warn, `=throw` to throw).\n *\n * Every reconciler defect found so far shared one property: **kerf kept running\n * happily in a corrupt state.** A binding pointed at rows no longer in the\n * document; a list's rows sat inside a neighbouring list's region; an id\n * referred to a different list than its binding did. Nothing threw. The damage\n * surfaced several operations later as a wrong render, which is precisely what\n * made those bugs expensive to find — the symptom and the cause were nowhere\n * near each other.\n *\n * This module makes the corrupt *state* the error, at the render that created\n * it. Each invariant below is the negation of a defect that actually shipped:\n *\n * - **marker-live / marker-id** — a binding whose marker left the tree, or\n * whose id is carried by a different marker node. The latter is how a\n * call-order id handed to a different list pointed the arriving list at the\n * previous occupant's container.\n * - **row-parent / row-live** — a binding holding rows that are detached, or\n * attached somewhere other than its own parent. This is the shape of every\n * \"stranded rows\" defect.\n * - **row-order** — a binding's rows must follow its marker in document order\n * and be strictly increasing. Rows that jumped their own marker looked\n * correct on screen while leaving the region bookkeeping wrong.\n * - **row-alias** — one row node claimed by two bindings.\n * - **region-overlap** — one list's rows sitting between another list's first\n * and last row. Two sibling lists interleaving their rows is exactly this.\n *\n * Off by default and dev-only, so production is untouched. `throw` mode exists\n * because a warning inside a passing test is invisible: kerf's own suites can\n * turn corruption into a failure rather than a line in the log.\n */\n\nimport { devFlag } from './dev-warn-config.js';\nimport type { ListBinding } from './list-binding.js';\nimport { LIST_MARKER_PREFIX } from './segment.js';\n\ntype Mode = 'off' | 'warn' | 'throw';\n\nfunction mode(): Mode {\n const value = devFlag('KERF_DEV_INVARIANTS');\n if (value === 'throw') return 'throw';\n return value === '1' ? 'warn' : 'off';\n}\n\n/**\n * Whether the list-invariant checks are active. Exported so `mount()` can skip\n * building the per-list expected-count map entirely when they're off — the\n * checks themselves are a no-op then, but the map would still cost an\n * allocation per render, and this family's contract is zero production cost.\n */\nexport function listInvariantsEnabled(): boolean {\n return mode() !== 'off';\n}\n\n/**\n * Child-position lookup for one parent, built once and reused for every node\n * asked about.\n *\n * Scanning `childNodes` per row would make the whole audit O(rows²) — which is\n * not a theoretical concern: it timed out a 1000-row stress test the first time\n * this shipped. A dev check that is quadratic in list length would only be\n * usable on the lists least likely to need it.\n */\nfunction childIndexer(): (parent: Element, node: Node) => number {\n const cache = new Map<Element, Map<Node, number>>();\n return (parent, node) => {\n let index = cache.get(parent);\n if (index === undefined) {\n index = new Map<Node, number>();\n const kids = parent.childNodes;\n for (let i = 0; i < kids.length; i++) index.set(kids[i], i);\n cache.set(parent, index);\n }\n return index.get(node) ?? -1;\n };\n}\n\nfunction describe(id: string, problem: string): string {\n return `kerf invariant violated after reconcile — each() list '${id}': ${problem}`;\n}\n\n/**\n * Check every list binding against the live DOM. Returns the violations found\n * (empty when healthy) so `mount()` can report them; exported separately from\n * the reporting so tests can assert on the findings directly.\n */\nexport function findListInvariantViolations(\n rootEl: Element,\n bindings: ReadonlyMap<string, ListBinding>,\n expectedCounts?: ReadonlyMap<string, number>,\n): string[] {\n const problems: string[] = [];\n const owners = new Map<Node, string>();\n const indexIn = childIndexer();\n // Per binding: [firstRowIndex, lastRowIndex] within its parent, for the\n // region-overlap pass below.\n const spans: { id: string; parent: Element; from: number; to: number }[] = [];\n\n for (const [id, binding] of bindings) {\n const { marker, liveParent, items } = binding;\n\n // Row-count agreement (KF-416): the binding must hold as many rows as the\n // data it just rendered from. Every other check here is INTERNAL — it\n // confirms the binding agrees with the live DOM — so a reconcile that\n // emptied a list still passes them all (zero items, zero live rows, all\n // consistent). Only comparing against the source length catches a list that\n // rendered the wrong NUMBER of rows, which is how KF-411 slipped through:\n // a self-healed empty binding was internally perfect and externally blank.\n // `expectedCounts` is supplied only for lists in the current render.\n const expected = expectedCounts?.get(id);\n if (expected !== undefined && items.length !== expected) {\n problems.push(describe(id, `holds ${items.length} row(s) but its source has ${expected} — `\n + 'the reconcile dropped or duplicated rows'));\n }\n\n if (!rootEl.contains(marker)) {\n problems.push(describe(id, 'its marker comment is no longer inside the mount root, so every '\n + 'future reconcile would mutate a detached tree'));\n continue;\n }\n if (marker.data !== `${LIST_MARKER_PREFIX}${id}`) {\n problems.push(describe(id, `its marker reads '${marker.data}' — the id is carried by a `\n + 'different marker node, so this binding describes another list'));\n }\n\n const markerIndex = indexIn(liveParent, marker);\n if (markerIndex === -1) {\n problems.push(describe(id, 'its marker is not a child of the parent the binding records'));\n continue;\n }\n\n let previousIndex = markerIndex;\n let first = -1;\n for (let i = 0; i < items.length; i++) {\n const node = items[i].node;\n const index = indexIn(liveParent, node);\n if (index === -1) {\n problems.push(describe(id, `bound row ${i} is not a child of the list's parent `\n + `(<${liveParent.tagName.toLowerCase()}>)${node.isConnected ? ' — it is attached elsewhere in the document' : ' — it is detached'}`));\n continue;\n }\n if (index <= previousIndex) {\n problems.push(describe(id, `bound row ${i} appears at child position ${index}, which is not `\n + `after the previous one (${previousIndex}) — the rows are out of order or have crossed the marker`));\n }\n previousIndex = index;\n if (first === -1) first = index;\n\n const owner = owners.get(node);\n if (owner !== undefined) {\n problems.push(describe(id, `bound row ${i} is also claimed by list '${owner}'`));\n } else {\n owners.set(node, id);\n }\n }\n if (first !== -1) spans.push({ id, parent: liveParent, from: first, to: previousIndex });\n }\n\n // Region overlap: two lists sharing a parent must occupy disjoint stretches of\n // it. Interleaved rows render in the wrong order and make each list's extent\n // unknowable.\n for (let a = 0; a < spans.length; a++) {\n for (let b = a + 1; b < spans.length; b++) {\n if (spans[a].parent !== spans[b].parent) continue;\n if (spans[a].from <= spans[b].to && spans[b].from <= spans[a].to) {\n problems.push(describe(spans[a].id, `its rows (child positions ${spans[a].from}-${spans[a].to}) `\n + `overlap those of list '${spans[b].id}' (${spans[b].from}-${spans[b].to}) in the same parent`));\n }\n }\n }\n\n return problems;\n}\n\n/**\n * Run the checks if opted in, and report anything found. No-op — and no DOM\n * walking at all — when the env var is unset.\n */\nexport function maybeCheckListInvariants(\n rootEl: Element,\n bindings: ReadonlyMap<string, ListBinding>,\n expectedCounts?: ReadonlyMap<string, number>,\n): void {\n const level = mode();\n if (level === 'off') return;\n const problems = findListInvariantViolations(rootEl, bindings, expectedCounts);\n if (problems.length === 0) return;\n const report = `${problems.join('\\n')}\\n`\n + 'This is a kerf bug, not an application one — please report it with the markup that produced it. '\n + 'Set KERF_DEV_INVARIANTS=1 to warn instead of throw, or unset it to disable these checks.';\n if (level === 'throw') throw new Error(report);\n console.warn(report);\n}\n","/**\n * Dev-mode warning for a stale `index` argument in an `each()` row render\n * (KERF_DEV_WARN_STALE_INDEX=1).\n *\n * `each(items, (item, index) => …)` passes the row's position as the second\n * argument. But `each()` memoizes a row's HTML by object identity (+ optional\n * `cacheKey` + content version) — the `index` is NOT part of that key. So when a\n * surviving row's position changes without its ref or cacheKey changing — a\n * reorder, or an insert/remove/move ahead of it — kerf serves the row's cached\n * HTML, which was computed at the OLD index. A numbered list (`{index}. …`),\n * zebra striping, or an \"N of M\" label silently shows the wrong number.\n *\n * When the opt-in env var is set, `each()` calls `maybeWarnStaleIndex()` at the\n * two points a shift can strand a memoized row's index:\n * - the snapshot path, when a cache HIT reuses a row at a different index than\n * it rendered at (a plain-array reorder);\n * - the granular path, when the applied `arraySignal` patches shift an existing\n * row's index (a non-tail insert/remove, or any move).\n * Both are gated on the render fn actually declaring an index parameter\n * (`render.length >= 2`), so a list that never reads the index never warns. This\n * is a heuristic in both directions: a fn that declares `index` but never uses it\n * warns spuriously (false positive), and a fn whose index parameter has a DEFAULT\n * value — `(item, i = 0) => …` — has `Function.length` 1, so it escapes the gate\n * and a genuine index use goes unwarned (false negative). A fully precise check\n * would need to parse the fn source; not worth it for a dev diagnostic.\n *\n * Why opt-in: `render.length >= 2` is a heuristic — a render fn may declare the\n * index parameter and not use it in its output, in which case a reorder is\n * harmless and the warning would be a false positive. The fix (`cacheKey: (_, i)\n * => i`, which folds the index into the memo key so a shifted row re-renders) is\n * also not always wanted: a list whose index only labels rows that never reorder\n * pays nothing today. Opt-in keeps the diagnostic available without penalising\n * either shape.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst warnedIds = new Set<string>();\n\n/** True when the env var opt-in is set in a dev build. Checked first for zero prod cost. */\nexport function isOptedInStaleIndex(): boolean {\n return devFlag('KERF_DEV_WARN_STALE_INDEX') === '1';\n}\n\n/**\n * Fire the one-shot (per list id) stale-index warning. Callers gate on\n * `isOptedInStaleIndex()` AND on having detected a genuine index shift for a\n * list whose render fn declares an index parameter.\n */\nexport function maybeWarnStaleIndex(id: string): void {\n if (warnedIds.has(id)) return;\n warnedIds.add(id);\n console.warn(\n `kerf: each() list '${id}' reused a memoized row at a new index this render, but its render function `\n + 'takes an `index` argument. Rows are memoized by object identity, not by position, so a reorder or an '\n + 'insert/remove ahead of a surviving row serves that row\\'s cached HTML — computed at its OLD index. A '\n + 'numbered list, zebra striping, or an \"N of M\" label will silently show the wrong value. If the row '\n + 'output depends on the index, fold it into the memo key: each(items, render, { cacheKey: (_, i) => i }) '\n + '(combine with your own key if you have one). If the index is not used in the output, ignore this. '\n + 'Set KERF_DEV_WARN_STALE_INDEX=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 * Dev-mode warning for `each()` lists whose identity shifted (KF-392).\n *\n * Without an explicit key, a list is identified by its call order — \"the n-th\n * `each()` this render\". Any render that changes how many `each()` calls run\n * before a list reassigns its identity, and the list is then rebuilt from\n * scratch: row nodes, focus, scroll position and in-progress IME composition\n * are discarded, and the work is O(rows) rather than O(changes).\n *\n * That was entirely silent. `KERF_DEV_WARN_LIST_REBIND` cannot see it either —\n * this rebuild routes through the ordinary classify pass, not the self-heal it\n * watches — so an author had no signal at all that state was being thrown away.\n *\n * **Always on in development, like the missing-row-key warning** rather than\n * env-gated like the `KERF_DEV_WARN_*` family. The reasoning is the same as for\n * that one: it fires only when kerf is about to silently discard row state, it\n * names a concrete one-line fix, and it is one-shot per list — so it is a\n * diagnostic an author always wants, not one they opt into. Production emits\n * nothing because the diagnostics are not installed there — reaching this\n * module at all means the consumer imported `kerfjs/dev`.\n *\n * Detection is deliberately conservative (KF-394). A changed data source alone\n * is NOT a shift — the same list swapping which signal it renders (a filter or\n * tab switch) changes source too, and warning there told authors to fix\n * correct code. `mount()` therefore only reports a candidate when the render's\n * `each()` call count ALSO changed, which is what an id shift requires; and\n * keyed lists are excluded entirely, since a key is the identity.\n *\n * Two shapes stay invisible as a result: two `each()` calls over the SAME\n * `arraySignal` (indistinguishable by source), and two unkeyed lists swapping\n * order at a constant call count. Keys close both by construction, which is\n * what the message asks for.\n */\n\n/**\n * Emit the identity-shift warning for the unkeyed list at `id`.\n *\n * Dedup is the CALLER's job and lives on the per-mount render context — ids are\n * per-mount, so a module-level set meant the first mount to warn for id '0'\n * silenced every other mount's genuine shift forever (KF-394).\n */\nexport function maybeWarnListIdShift(id: string): void {\n console.warn(\n `kerf each(): list '${id}' is now a different list than it was last render. `\n + 'Lists without a key are identified by call order, so adding or removing an each() call '\n + 'before this one reassigns its identity — kerf rebuilds the list from scratch and its rows '\n + 'lose DOM identity, focus, scroll position and in-progress IME composition. '\n + 'Give the affected lists a stable key: each(items, render, { key: \\'my-list\\' }). '\n + 'Keying the conditional list is usually enough — a keyed list does not take a call-order '\n + 'slot, so its siblings stop shifting too.',\n );\n}\n\n","/**\n * Dev-mode warning for each() containers rebuilt by the morph\n * (KERF_DEV_WARN_LIST_REBIND=1).\n *\n * When the opt-in env var is set, `mount()` calls `maybeWarnListRebind()` from\n * the self-heal branch of `bindListsFromMarkers` — the point where an existing\n * list binding's marker is discovered to have left the mount root because the\n * morph rebuilt the list's container (an ancestor's tag changed, so\n * `replaceChild` swapped the whole subtree, cloning a fresh marker).\n *\n * Why the pattern matters: the self-heal makes the rebuild *correct* — the\n * stale binding is dropped, the list re-binds against the fresh marker, and\n * the next reconcile repopulates the rows — but the recovery is lossy. The\n * rows are re-created from scratch, so focus, scroll positions, in-progress\n * IME composition, and any imperative listeners on the old row nodes are\n * silently discarded. An author who didn't intend the ancestor tag swap gets\n * no other signal that their rows are being churned.\n *\n * Why opt-in: swapping an ancestor's tag across renders (`<section>` ↔\n * `<article>` around the same list) is occasionally intentional — semantic\n * element changes driven by state — and the rebuild-with-repopulate behavior\n * is then exactly what the author wants. The opt-in keeps the diagnostic\n * available for projects that want it without penalising that pattern.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst warnedIds = new Set<string>();\n\nfunction isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_LIST_REBIND') === '1';\n}\n\n/**\n * Fire the one-shot (per list id) rebuild warning. `liveParent` is the fresh\n * container the cloned marker landed in — named in the message so the author\n * can find the swap site.\n */\nexport function maybeWarnListRebind(id: string, liveParent: Element): void {\n if (!isOptedIn()) return;\n if (warnedIds.has(id)) return;\n warnedIds.add(id);\n console.warn(\n `kerf: each() list '${id}' had its container (<${liveParent.tagName.toLowerCase()}>) rebuilt by the morph this render — `\n + 'an ancestor\\'s tag changed so the subtree was replaced, or a same-tag sibling positionally took the '\n + 'container\\'s place. The list re-binds and repopulates automatically, but its rows were re-created '\n + 'from scratch: focus, scroll positions, in-progress IME composition, and any imperative listeners on '\n + 'the old row nodes are lost. If the rows should survive, give the LIST\\'S OWN container a stable '\n + 'id/data-key (keying the conditional sibling instead only helps when it is removed, not when it '\n + 'reappears) and keep the tags of the list\\'s ancestors stable across renders. '\n + 'Set KERF_DEV_WARN_LIST_REBIND=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 * 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\nimport { devFlag } from './dev-warn-config.js';\n\nconst LISTENER_MARKER = Symbol.for('kerfjs.devListener');\n\nlet patched = false;\nlet warned = false;\n\nfunction isOptedIn(): boolean {\n return devFlag('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 * Dev-mode warning for markup the HTML parser silently restructures\n * (`KERF_DEV_WARN_PARSER_REPAIR=1`).\n *\n * kerf renders JSX to an HTML string and lets the parser build the DOM, so the\n * parser's content-model repairs apply. The one that actually bites is `<p>`:\n * it may contain only phrasing content, and the parser **auto-closes it** before\n * a block-level child. So\n *\n * <p><section>head</section><ul>{each(rows, …)}</ul></p>\n *\n * becomes `<p></p><section>head</section><ul>…</ul>` — an empty `<p>`, and every\n * child hoisted to be its *sibling*.\n *\n * What this does and doesn't cost is worth stating precisely, because it's\n * narrower than it first looks. kerf reconciles the tree the parser actually\n * produced, and does so consistently: updates, list inserts and conditional\n * toggles all behave correctly afterwards. Nothing is corrupted in the ordinary\n * case. What the author loses is the *shape they wrote* — their `<p>` is empty,\n * their children are somewhere else, and any CSS or query that assumed the\n * nesting silently doesn't match.\n *\n * The reason it deserves a warning rather than a line in the docs is distance:\n * the symptom shows up as \"my list isn't inside the element I put it in\", three\n * levels away from the `<p>` that caused it, and nothing in the JSX looks wrong.\n * Naming the tag pair at first render turns a confusing afternoon into a\n * one-line fix.\n *\n * Why opt-in: the detection is a scan of the emitted HTML rather than a real\n * parse, so while a block-level open tag before a `</p>` is an unambiguous\n * repair signal in kerf's own well-formed output, it is not a proof. The rest of\n * the family's opt-in default keeps that judgement with the consumer.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\n/**\n * Elements that close an open `<p>`. Per the HTML spec's \"a p element's end tag\n * can be omitted if the p element is immediately followed by…\" list.\n */\nconst BLOCK_TAGS = [\n 'address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset',\n 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section',\n 'table', 'ul',\n];\n\n/** `<p …>` or a block-level open tag — whichever comes first from a given index. */\nconst SCAN = new RegExp(`<(/?p|${BLOCK_TAGS.join('|')})[\\\\s/>]`, 'gi');\n\nconst warnedPairs = new Set<string>();\n\nfunction isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_PARSER_REPAIR') === '1';\n}\n\n/**\n * Find the first block-level tag that opens while a `<p>` is still open.\n * Returns the offending tag name, or null when the markup is clean.\n *\n * Only kerf's own output is scanned, which is always well-formed (the JSX\n * runtime emits a matching close for every non-void tag), so a simple\n * open/close walk is sufficient — no nesting depth to track beyond \"are we\n * inside a p\".\n */\nexport function findParagraphRepair(html: string): string | null {\n SCAN.lastIndex = 0;\n let inParagraph = false;\n for (let m = SCAN.exec(html); m !== null; m = SCAN.exec(html)) {\n const tag = m[1].toLowerCase();\n if (tag === '/p') { inParagraph = false; continue; }\n if (tag === 'p') {\n // A nested <p> is itself a repair when one is already open.\n if (inParagraph) return 'p';\n inParagraph = true;\n continue;\n }\n if (inParagraph) return tag;\n }\n return null;\n}\n\n/**\n * Scan a first-render HTML string and warn once per offending tag pair.\n * Short-circuits on the env gate before touching the string.\n */\nexport function maybeWarnParserRepair(html: string): void {\n if (!isOptedIn()) return;\n const tag = findParagraphRepair(html);\n if (tag === null) return;\n const pair = `p>${tag}`;\n if (warnedPairs.has(pair)) return;\n warnedPairs.add(pair);\n console.warn(\n `kerf: a <${tag}> inside a <p> will not survive parsing. `\n + '<p> may contain only phrasing content, so the HTML parser closes it before a '\n + `block-level child — your <p> ends up EMPTY and the <${tag}> (plus everything after it) `\n + 'becomes its sibling instead of its child. kerf then reconciles that repaired tree '\n + 'correctly, so updates still work; what you lose is the structure you wrote, along with '\n + 'any CSS or querySelector that assumed it. Use a <div> (or a phrasing element like '\n + '<span>) in place of the <p>, or move the block content outside it. '\n + 'Set KERF_DEV_WARN_PARSER_REPAIR=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 warnedPairs.clear();\n}\n","/**\n * Dev-mode warning for value-only re-renders (KERF_DEV_WARN_VALUE_ONLY_RERENDER=1).\n *\n * Phase 2 of the update-machinery consolidation (\"values bind, structure\n * re-renders\"): when a `mount()` re-render's static-surrounds HTML differs\n * from the previous render ONLY in text content and attribute values — no\n * element added, removed, moved, or retagged — every changed hole could have\n * been a fine-grained binding instead (`{count}`, `class={sig}`), and the\n * whole render + byte-compare + morph pass was avoidable. This warner points\n * that out once per mount.\n *\n * Detection: parse both HTML strings into detached `<template>`s and walk the\n * two trees in lockstep. Text-node data and element attributes (names AND\n * values — a boolean attribute appearing/disappearing is a value change,\n * since `renderAttr` omits false/nullish) are allowed to differ; any change\n * of child count, node type, tag name, or comment data (marker comments are\n * deterministic per structure, so a changed marker implies a structural or\n * binding-shape change) classifies the render as structural and no warning\n * fires. Conservative by construction: false negatives are fine, false\n * positives would erode trust in the guidance.\n *\n * Why opt-in (docs/11 family rules): plenty of legitimate code re-renders on\n * `.value` reads — the warning is a migration aid for adopting the bound-first\n * idiom, not a lint on correctness. Production behavior is unchanged for zero\n * runtime cost: the env-var read short-circuits before any parsing runs, and\n * the parse itself happens only on the already-slow surrounds-changed path.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\n/** Per-mount one-shot context — created by `mount()`, mirrors NarrowSetWarnContext. */\nexport interface ValueOnlyWarnContext {\n warned: boolean;\n}\n\nexport function isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_VALUE_ONLY_RERENDER') === '1';\n}\n\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\n/**\n * Lockstep structural comparison: true when the two fragments have identical\n * element/comment shape, so every difference is confined to text data and\n * attributes (\"value-only\"). Exported for direct unit coverage of the branch\n * matrix; production callers go through `maybeWarnValueOnlyRerender`.\n */\nexport function _isValueOnlyDiff(a: Node, b: Node): boolean {\n const an = a.childNodes;\n const bn = b.childNodes;\n if (an.length !== bn.length) return false;\n for (let i = 0; i < an.length; i++) {\n const x = an[i];\n const y = bn[i];\n if (x.nodeType !== y.nodeType) return false;\n if (x.nodeType === ELEMENT_NODE) {\n if ((x as Element).tagName !== (y as Element).tagName) return false;\n if (!_isValueOnlyDiff(x, y)) return false;\n } else if (x.nodeType === COMMENT_NODE) {\n if ((x as Comment).data !== (y as Comment).data) return false;\n } else if (x.nodeType !== TEXT_NODE) {\n // Defensive: HTML parsing via template.innerHTML only produces\n // element/text/comment children (no CDATA; PIs parse as bogus\n // comments), so this arm is unreachable by construction — kept so an\n // exotic caller-supplied tree bails structural rather than guessing.\n /* c8 ignore next 2 */\n return false;\n }\n // TEXT_NODE: data may differ freely — that's the value change.\n }\n return true;\n}\n\n/**\n * Called by `mount()` on a surrounds-CHANGED re-render (the byte-compare\n * already failed, so the strings are known to differ). Parses + compares only\n * when the opt-in gate is open and this mount hasn't warned yet.\n */\nexport function maybeWarnValueOnlyRerender(\n prevHtml: string,\n nextHtml: string,\n ctx: ValueOnlyWarnContext,\n): void {\n if (ctx.warned || !isOptedIn()) return;\n const a = document.createElement('template');\n const b = document.createElement('template');\n a.innerHTML = prevHtml;\n b.innerHTML = nextHtml;\n if (!_isValueOnlyDiff(a.content, b.content)) return;\n ctx.warned = true;\n console.warn(\n 'kerf: this re-render changed only text content and attribute values — no structural '\n + 'change — so every changed hole could be a fine-grained binding instead. Values bind, '\n + 'structure re-renders: pass the signal/computed itself ({count}, class={sig}) rather than '\n + 'reading .value in the hole, and each change updates just that node with no render re-run '\n + '(a mount whose render reads no .value never re-renders at all). See docs/2-reactivity §2.9. '\n + 'Set KERF_DEV_WARN_VALUE_ONLY_RERENDER=0 (or unset it) to silence this warning.',\n );\n}\n","/**\n * Dev warning for an `each()` list whose rows carry no `id` / `data-key`\n * (KF-173). Always on when `kerfjs/dev` is installed — no env var, because a\n * keyless list is never intentional.\n *\n * The reconciler falls back to positional matching without a key, which\n * silently shifts row state (focused inputs, mid-edit textareas) on insert or\n * delete. The warning names the fix and quotes the row HTML so the author can\n * locate the call site.\n *\n * Called per-binding with the FIRST row only — rows come from one render\n * function, so sampling row 0 is representative; per-row checking would just\n * repeat the same verdict. The caller passes a mutable flag holder so the\n * warning fires at most once per `mount()`-lifetime per `each()` call site.\n *\n * Lives in its own `dev-*` module (rather than beside the row-contract helpers\n * it borrows `truncateRowHtml` from) so it is reachable only from the\n * `kerfjs/dev` entry and drops out of production bundles with the rest of the\n * family.\n */\n\nimport { truncateRowHtml } from './utils/rowContract.js';\n\nexport function maybeWarnMissingRowKey(\n rowEl: Element,\n rowHtml: string,\n binding: { warnedMissingKey?: boolean },\n): void {\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(): the first row 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 * Dev-mode signal subclass with subscriber tracking (KF-176). When the\n * dev-warn opt-in is enabled, `signal()` returns a `DevSignal` that emits a\n * one-shot `console.warn` the first time `.value` is written to an instance\n * that has never had a subscriber attached. This surfaces the canonical\n * Rule 7 violation (read `.value` outside a render fn / effect — the read\n * doesn't subscribe, so subsequent writes silently fail to re-render) at\n * the moment the user makes the wrong write, instead of leaving them to\n * notice that their UI never updates.\n *\n * The gate is `KERF_DEV_WARN_UNTRACKED_SIGNALS === '1'`, on top of the\n * diagnostics being installed at all — importing `kerfjs/dev` is what makes\n * this module reachable. Off by default because the heuristic produces false\n * positives for purely imperative signals (used as mutable cells with no UI\n * consumer); opt-in is the right shape until a sharper heuristic is found.\n * Production behavior is unchanged for zero runtime cost.\n *\n * The subclass uses signals-core's `SignalOptions.watched` callback to set a\n * per-instance `__hasSubscriber` flag — fired by signals-core when the first\n * subscriber attaches. We never clear the flag on `unwatched`, so a signal\n * that *was* subscribed at some point won't warn even if its subscribers\n * later detach.\n */\n\nimport { Signal } from '@preact/signals-core';\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst WARNING_MESSAGE\n = 'kerf: signal was written but has no subscribers. '\n + 'Did you read `.value` outside of a render fn / effect()? '\n + 'Hoisted reads do not subscribe, so subsequent writes will not re-render. '\n + 'Move the read inside mount()\\'s render fn or effect() callback. '\n + 'Set KERF_DEV_WARN_UNTRACKED_SIGNALS=0 (or unset it) to silence this warning.';\n\nexport class DevSignal<T> extends Signal<T> {\n private __hasSubscriber = false;\n private __warned = false;\n private __constructed = false;\n\n constructor(initial?: T) {\n super(initial as T, {\n watched(this: Signal<T>) {\n (this as unknown as { __hasSubscriber: boolean }).__hasSubscriber = true;\n },\n });\n this.__constructed = true;\n }\n\n override get value(): T { return super.value; }\n override set value(v: T) {\n super.value = v;\n if (this.__constructed && !this.__hasSubscriber && !this.__warned) {\n this.__warned = true;\n console.warn(WARNING_MESSAGE);\n }\n }\n}\n\nexport function isDevWarnUntrackedEnabled(): boolean {\n return devFlag('KERF_DEV_WARN_UNTRACKED_SIGNALS') === '1';\n}\n\n/**\n * This warning is the ONE member of the family whose coverage depends on WHEN\n * `kerfjs/dev` was installed, because `signal()` picks its constructor at\n * creation time. Signals created before the install are plain `Signal`s\n * forever and this warning can never see them.\n *\n * That matters in the common layout, because static imports are hoisted above\n * a top-level `await import()`:\n *\n * ```js\n * import { counter } from './store.js'; // created HERE\n * if (import.meta.env.DEV) await import('kerfjs/dev'); // ...installs after\n * ```\n *\n * kerf's state model is module-scope signals, so that ordering can leave the\n * warning covering almost nothing — and failing SILENTLY, which is the worst\n * outcome for a diagnostic: the author sets the env var, sees nothing, and\n * concludes their code is clean.\n *\n * Retro-fitting already-created signals is not possible. `Signal.prototype`'s\n * `value` accessor is **non-configurable**, so it cannot be patched, and\n * reaching existing instances would need kerf to keep a registry of every\n * signal — a per-signal production cost paid to serve an opt-in dev warning,\n * which is exactly the coupling the hook registry removed. So the miss is\n * converted from silent to loud instead: opting in prints the coverage\n * boundary once, with the fix.\n */\nlet coverageNoticeShown = false;\n\nexport function noteUntrackedCoverage(): void {\n if (coverageNoticeShown) return;\n coverageNoticeShown = true;\n console.warn(\n 'kerf: KERF_DEV_WARN_UNTRACKED_SIGNALS only covers signals created AFTER kerfjs/dev is installed. '\n + 'Static imports are hoisted above `await import(\\'kerfjs/dev\\')`, so module-scope signals in the modules '\n + 'you import are created first and this warning cannot see them — you may get no warnings even where the '\n + 'bug exists. To cover them, make `import \\'kerfjs/dev\\'` the FIRST STATIC import of a dev-only entry file '\n + '(static imports evaluate in order), then load the rest of your app. '\n + 'Set KERF_DEV_WARN_UNTRACKED_SIGNALS=0 (or unset it) to silence this warning.',\n );\n}\n\n/** Test helper — re-arms the one-shot coverage notice. */\nexport function _resetCoverageNoticeForTests(): void {\n coverageNoticeShown = false;\n}\n","/**\n * Dev-mode warning for partial-set violations of Hard Rule 8 (KF-212). When\n * the opt-in env var `KERF_DEV_WARN_NARROW_SET=1` is set in a non-production\n * build, `defineStore`'s `set()` calls `maybeWarnNarrowSet(prev, next, ctx)`\n * before assigning. If `next` is a plain object whose own-keys are a strict\n * subset of `prev`'s own-keys, a one-shot `console.warn` fires naming the\n * missing keys and pointing at the canonical `set({ ...get(), ...next })`\n * merge fix.\n *\n * Why opt-in: narrow-set IS legal — sometimes you want to replace state with\n * a smaller shape (a reset() that drops keys, a feature-flag-driven schema\n * change). The warn is the right shape for the canonical bug (\"I wrote\n * `set({filter})` against a replace-semantics store and wiped items+editingId\")\n * but produces false positives for intentional shape changes. Opt-in keeps\n * the warning available to dev/CI environments that want the diagnostic\n * without surprising existing projects.\n *\n * Trigger condition: ANY key in `prev` missing from `next` — strictly broader\n * than \"fewer keys total.\" A `set({a, c})` against `cur = {a, b}` (same count,\n * different keys) also wipes `b`, so it warns. The original partial-set bug\n * shape was always \"at least one key from current is missing in next\"; the\n * key-count check in the original ticket sketch was an early-exit\n * optimization, not the semantic gate.\n *\n * Skips: non-object cur/next (booleans, numbers, strings — no \"keys\" to\n * miss), null/undefined either side, and arrays either side (shrinking-array\n * replacement is normal, not a partial set).\n *\n * Per-store one-shot dedup: each store warns at most once across its\n * lifetime — matches the KF-174 / KF-176 pattern of \"tell the developer\n * about the rule violation once, then trust them to fix it.\" The dedup\n * scope is the store, not the module, so a second store can still warn\n * if it independently hits the same bug.\n *\n * Production behavior is unchanged for zero runtime cost (the env-var read\n * short-circuits before any per-set work runs).\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nexport interface NarrowSetWarnContext {\n /** Set once per store; the warner reads/writes this to enforce the per-store one-shot dedup. */\n warned: boolean;\n}\n\nconst WARNING_PREFIX\n = 'kerf: defineStore.set() called with keys missing from the current state — ';\nconst WARNING_SUFFIX\n = '. set() REPLACES state; the missing keys will be undefined after this call. '\n + 'Use `set({ ...get(), ...next })` to merge instead, or update each call site to pass the full state. '\n + 'Set KERF_DEV_WARN_NARROW_SET=0 (or unset it) to silence this warning.';\n\nexport function isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_NARROW_SET') === '1';\n}\n\nfunction isPlainObjectState(v: unknown): v is Record<string, unknown> {\n if (v === null || typeof v !== 'object') return false;\n if (Array.isArray(v)) return false;\n return true;\n}\n\nexport function maybeWarnNarrowSet(\n prev: unknown,\n next: unknown,\n ctx: NarrowSetWarnContext,\n): void {\n if (ctx.warned) return;\n if (!isOptedIn()) return;\n if (!isPlainObjectState(prev) || !isPlainObjectState(next)) return;\n\n const missing: string[] = [];\n for (const k of Object.keys(prev)) {\n if (!(k in next)) missing.push(k);\n }\n if (missing.length === 0) return;\n\n ctx.warned = true;\n const keysList = missing.map((k) => `\\`${k}\\``).join(', ');\n console.warn(`${WARNING_PREFIX}${keysList}${WARNING_SUFFIX}`);\n}\n\n/**\n * Test helper — resets the per-store `warned` flag on a context so a\n * subsequent test in the same module can re-exercise the first-warning\n * path. Not exported from the public barrel; the unit-test file imports it\n * directly via the relative path.\n */\nexport function _resetWarnContext(ctx: NarrowSetWarnContext): void {\n ctx.warned = false;\n}\n","/**\n * Dev-only deep read-only guard for `defineStore`'s `get()` snapshot.\n *\n * Replaces the older `Object.freeze(get())` guard, which had three problems:\n * it mutated (froze) the LIVE state object as a side effect of a read, so\n * external references that later legitimately mutated it threw in dev but not\n * prod; it was shallow (`get().nested.x = 1` slipped through); and freezing on\n * read is surprising. This module instead wraps the returned reference in a\n * lazy `Proxy` that:\n *\n * - throws a store-rule-specific `TypeError` on any write (`set` /\n * `deleteProperty` / `defineProperty`) — mutating the object returned by\n * `get()` is a Rule 8 violation (all writes go through actions), and now it\n * is a loud throw instead of a silent desync;\n * - lazily wraps plain-object / array property values in the SAME proxy on\n * access (deep coverage, O(1) per access, no clones), so `get().nested.x = 1`\n * also throws;\n * - leaves primitives, functions, and exotic objects (Date, Map, …) as-is, so\n * `instanceof`, `JSON.stringify`, spread, `Object.keys`, and array iteration\n * all behave exactly as on the raw object.\n *\n * The live state object is never frozen or mutated, so an external reference to\n * it stays writable. This guard is DEV-ONLY: production returns the raw\n * reference and never constructs a proxy, so its perf and semantics are\n * byte-identical to a bare object.\n *\n * `toRaw()` reverses the wrapping so a state object DERIVED from `get()` output\n * (e.g. `set({ ...get(), count: 1 })`, whose nested values are proxies handed\n * back by the `get` trap) is stored as a plain object — the internal signal\n * must never hold a Proxy.\n */\n\nconst RULE_MESSAGE\n = 'kerf: store state is read-only — all writes must go through actions '\n + '(build a new state object and pass it to `set()`). Mutating the object '\n + 'returned by `get()` is a Rule 8 violation and never notifies subscribers.';\n\n/** proxy → its raw target. Lets `toRaw()` unwrap a value derived from `get()`. */\nconst proxyToRaw = new WeakMap<object, object>();\n/** raw → its proxy. Stable proxy identity + avoids re-wrapping the same object. */\nconst rawToProxy = new WeakMap<object, object>();\n\n/** Only plain objects and arrays are wrapped; exotic objects pass through untouched. */\nfunction isWrappable(v: unknown): v is object {\n if (v === null || typeof v !== 'object') return false;\n if (Array.isArray(v)) return true;\n const proto = Object.getPrototypeOf(v) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\nconst handler: ProxyHandler<object> = {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver) as unknown;\n return isWrappable(value) ? devReadonlyProxy(value) : value;\n },\n set() {\n throw new TypeError(RULE_MESSAGE);\n },\n deleteProperty() {\n throw new TypeError(RULE_MESSAGE);\n },\n defineProperty() {\n throw new TypeError(RULE_MESSAGE);\n },\n};\n\n/** Wrap `obj` in the dev read-only proxy (idempotent, identity-stable per raw). */\nexport function devReadonlyProxy<T extends object>(obj: T): T {\n if (proxyToRaw.has(obj)) return obj; // already a proxy — don't double-wrap\n const cached = rawToProxy.get(obj);\n if (cached) return cached as T;\n const p = new Proxy(obj, handler) as T;\n rawToProxy.set(obj, p as object);\n proxyToRaw.set(p as object, obj);\n return p;\n}\n\n/**\n * Deep-unwrap any dev read-only proxies out of `value`, preserving structural\n * sharing: returns the SAME reference when nothing was a proxy, and only\n * allocates along the path to a proxy it actually replaces. Raw targets are\n * fully plain (proxies are never stored), so unwrapping one is deep-clean.\n */\nexport function toRaw<T>(value: T): T {\n return unwrap(value) as T;\n}\n\nfunction unwrap(v: unknown): unknown {\n if (v === null || typeof v !== 'object') return v;\n const raw = proxyToRaw.get(v);\n if (raw !== undefined) return raw; // a proxy → its fully-plain raw target\n if (!isWrappable(v)) return v; // exotic object — leave as-is\n\n if (Array.isArray(v)) {\n let changed = false;\n const out = v.map((item) => {\n const u = unwrap(item);\n if (u !== item) changed = true;\n return u;\n });\n return changed ? out : v;\n }\n\n let changed = false;\n const src = v as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(src)) {\n const u = unwrap(src[k]);\n if (u !== src[k]) changed = true;\n out[k] = u;\n }\n return changed ? out : v;\n}\n","/**\n * `kerfjs/dev` — the development diagnostics bundle.\n *\n * Importing this module installs kerf's dev-only behavior: the whole\n * `KERF_DEV_WARN_*` warning family, the structural list invariants, the\n * read-only store snapshot, and the throw-on-dangerous-URL screen. Importing\n * nothing leaves every hook slot `undefined` and kerf runs in production shape.\n *\n * Put the import behind YOUR environment's dev flag, in YOUR code. That\n * condition folds to `false` in your production build, so the whole statement\n * is eliminated and this chunk is never emitted or fetched:\n *\n * ```js\n * if (import.meta.env.DEV) await import('kerfjs/dev'); // Vite\n * if (process.env.NODE_ENV !== 'production') await import('kerfjs/dev'); // webpack / Node\n * ```\n *\n * No-build / CDN consumers import it unconditionally from their dev page and\n * simply leave it out of the production page — there is no bundler to fold the\n * condition, and nothing for kerf to detect.\n *\n * ## Install ordering\n *\n * Every hook except one is read at CALL time (render, reconcile, `set()`,\n * `delegate()`), so installing any time before your first `mount()` is enough.\n *\n * The exception is `signalFactory`: `signal()` picks its constructor when the\n * signal is CREATED. Static imports are hoisted above a top-level\n * `await import()`, so module-scope signals in imported modules are created\n * before this module runs and the untracked-signal warning will not see them.\n * To cover those, make `import 'kerfjs/dev'` the FIRST STATIC import of a\n * dev-only entry file, then load the rest of your app.\n *\n * Opting into that warning prints this boundary once, so the gap is loud\n * rather than silent. It cannot be closed by retro-fitting existing signals:\n * `Signal.prototype`'s `value` accessor is non-configurable, and reaching live\n * instances would require a per-signal registry that production would pay for.\n *\n * Installation decides whether the diagnostics are PRESENT; each individual\n * warner still reads its own `KERF_DEV_WARN_*` env var to decide whether it is\n * switched ON. That keeps the existing opt-in contract intact.\n *\n * @see docs/11-dev-warnings.md\n */\n\nimport { type Signal, signal as coreSignal } from '@preact/signals-core';\n\nimport { isOptedIn as staleBindingOptedIn, maybeWarnStaleBinding } from './dev-binding-warn.js';\nimport {\n enterEffect,\n exitEffect,\n isDevWarnDelegateInEffectEnabled,\n warnIfInsideEffect,\n} from './dev-delegate-warn.js';\nimport { maybeWarnDuplicateCacheKeys, maybeWarnEachInMorphSkip } from './dev-each-warn.js';\nimport { type DevHooks, installDevHooks } from './dev-hooks.js';\nimport { listInvariantsEnabled, maybeCheckListInvariants } from './dev-invariants.js';\nimport { isOptedInStaleIndex, maybeWarnStaleIndex } from './dev-list-index-warn.js';\nimport { maybeWarnListIdShift } from './dev-list-key-warn.js';\nimport { maybeWarnListRebind } from './dev-list-rebind-warn.js';\nimport { installListenerRebuildWarn } from './dev-listener-warn.js';\nimport { maybeWarnParserRepair } from './dev-parser-repair-warn.js';\nimport { maybeWarnValueOnlyRerender } from './dev-rerender-warn.js';\nimport { maybeWarnMissingRowKey } from './dev-row-key-warn.js';\nimport { DevSignal, isDevWarnUntrackedEnabled, noteUntrackedCoverage } from './dev-signal.js';\nimport { maybeWarnNarrowSet } from './dev-store-warn.js';\nimport { applyWarningOptions, type DevWarningOptions } from './dev-warn-config.js';\nimport { devReadonlyProxy, toRaw } from './utils/devReadonly.js';\n\nexport { clearDevHooks, type DevHooks, devHooks, installDevHooks } from './dev-hooks.js';\nexport type { DevWarningOptions } from './dev-warn-config.js';\n\n/**\n * Switch individual diagnostics on:\n *\n * ```js\n * if (import.meta.env.DEV) {\n * const dev = await import('kerfjs/dev');\n * dev.enableWarnings({ staleBinding: true, narrowSet: true });\n * }\n * ```\n *\n * Installing this module makes the diagnostics PRESENT; this decides which are\n * SWITCHED ON, so the console isn't flooded by warnings you didn't ask for. The\n * `KERF_DEV_WARN_*` environment variables do the same thing for Node, SSR, and\n * CI; an explicit call here wins over the environment in both directions, so\n * `{ narrowSet: false }` silences an ambient var.\n *\n * **In a browser this function is the only switch that works.** A browser realm\n * has no `process` object, and a bundler `define` cannot reach the read (it\n * goes through `globalThis.process` into a local binding), so the environment\n * variables are unreachable there.\n *\n * Call it as early as you can. Every diagnostic reads its switch at call time\n * except the untracked-signal warning, which is chosen when a signal is\n * CREATED — enabling that one prints its coverage boundary once.\n */\nexport function enableWarnings(options: DevWarningOptions): void {\n applyWarningOptions(options);\n if (isDevWarnUntrackedEnabled()) noteUntrackedCoverage();\n}\n\n/**\n * The standard bundle of hooks this entry installs. Exported so kerf's own\n * suites can drop back to the production shape (`clearDevHooks()`) and restore\n * afterwards — re-importing this module would not re-run the install, since\n * module evaluation happens once.\n */\nexport const DEV_HOOKS: DevHooks = {\n // --- reactive ---------------------------------------------------------\n signalFactory: <T>(value: T): Signal<T> => (\n isDevWarnUntrackedEnabled() ? new DevSignal<T>(value) : coreSignal<T>(value)\n ),\n wrapEffect: (fn) => {\n // Resolved once per `effect()` call, matching the pre-hook behavior: an\n // effect created while the warning is off is never wrapped.\n if (!isDevWarnDelegateInEffectEnabled()) return fn;\n return () => {\n enterEffect();\n try {\n return fn();\n } finally {\n exitEffect();\n }\n };\n },\n\n // --- delegate ---------------------------------------------------------\n delegateInEffect: warnIfInsideEffect,\n\n // --- store ------------------------------------------------------------\n narrowSet: maybeWarnNarrowSet,\n storeReadonly: devReadonlyProxy,\n storeToRaw: toRaw,\n\n // --- mount ------------------------------------------------------------\n listenerRebuild: installListenerRebuildWarn,\n listIdShift: maybeWarnListIdShift,\n parserRepair: maybeWarnParserRepair,\n staleBindingEnabled: staleBindingOptedIn,\n staleBinding: maybeWarnStaleBinding,\n listInvariantsEnabled,\n listInvariants: maybeCheckListInvariants,\n valueOnlyRerender: maybeWarnValueOnlyRerender,\n listRebind: maybeWarnListRebind,\n eachInMorphSkip: maybeWarnEachInMorphSkip,\n missingRowKey: maybeWarnMissingRowKey,\n\n // --- each -------------------------------------------------------------\n staleIndexEnabled: isOptedInStaleIndex,\n staleIndex: maybeWarnStaleIndex,\n duplicateCacheKeys: maybeWarnDuplicateCacheKeys,\n\n // --- urlScreen --------------------------------------------------------\n urlScreenThrow: (message: string) => {\n throw new Error(message);\n },\n};\n\ninstallDevHooks(DEV_HOOKS);\n\n// `signal()` picks its constructor at CREATION time, so this one warning can\n// only see signals created after this module runs. Say so at install rather\n// than letting an author opt in and silently get nothing (see\n// `noteUntrackedCoverage` for why retro-fitting is impossible).\n//\n// The opted-in arm can't be exercised by the suite: this module evaluates\n// exactly once, at import, before any test can set the env var — and the\n// global test setup imports it. Both `isDevWarnUntrackedEnabled()` and\n// `noteUntrackedCoverage()` are directly unit-tested either side of this line\n// (tests/unit/dev-signal.internal.test.ts); only the one-time wiring between\n// them is unreachable from a test process.\n/* c8 ignore next -- install-time wiring; module evaluates once, before any test can opt in */\nif (isDevWarnUntrackedEnabled()) noteUntrackedCoverage();\n"]}
1
+ {"version":3,"sources":["../src/dev-warn-config.ts","../src/dev-binding-warn.ts","../src/dev-delegate-warn.ts","../src/dev-each-warn.ts","../src/dev-invariants.ts","../src/dev-list-index-warn.ts","../src/dev-list-key-warn.ts","../src/dev-list-rebind-warn.ts","../src/dev-listener-warn.ts","../src/dev-parser-repair-warn.ts","../src/dev-rerender-warn.ts","../src/dev-row-key-warn.ts","../src/dev-signal.ts","../src/dev-store-warn.ts","../src/utils/dev-readonly.ts","../src/dev.ts"],"names":["isOptedIn","warnedIds","warned","changed","out","coreSignal"],"mappings":"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","file":"dev.js","sourcesContent":["/**\n * The switch layer for the opt-in diagnostics — the second of the two gates\n * (§11.3.1). The first gate is installation: reaching this module at all means\n * the consumer imported `kerfjs/dev`.\n *\n * Two sources feed one lookup, explicit-call-wins:\n *\n * 1. `enableWarnings({...})` — an in-memory map, set by the consumer through\n * the `kerfjs/dev` entry. Explicit wins in BOTH directions, so\n * `{ narrowSet: false }` silences a warning an ambient env var switched on.\n * 2. `globalThis.process?.env?.KERF_DEV_*` — the environment, kept for Node,\n * SSR, and CI, where exporting a variable is the natural way to turn a\n * diagnostic on for one run.\n *\n * ## Why the env var could not be the only switch\n *\n * It is unreachable in the majority case. kerf is a browser framework, and a\n * browser realm has no `process` object at all — so every one of these\n * warnings was permanently off in exactly the environment (a Vite/webpack dev\n * server) where a developer most wants them. A bundler `define` does not fix\n * it either: the read goes through `globalThis.process` into a local binding,\n * so nothing substitutes the `process.env.X` token. That indirection is not\n * incidental — reading the bare token is what made kerf infer DEVELOPMENT\n * inside production browser bundles.\n *\n * The consumer already holds the module at the moment they opt in\n * (`const dev = await import('kerfjs/dev')`), so handing them a typed function\n * there is both the most reachable and the most discoverable switch. The env\n * vars stay because kerf's own suites and any CI run use them.\n */\n\n/**\n * Which diagnostics to switch on. Every key is off unless you name it; passing\n * `false` explicitly forces a warning off even when its env var is set.\n *\n * `invariants` is not a warning but the structural audit of kerf's own list\n * bookkeeping: `true` reports violations with `console.warn`, `'throw'` raises\n * them (what you want in a test suite, where a warning inside a passing test\n * is invisible).\n */\nexport interface DevWarningOptions {\n /** Imperative `addEventListener` on a node the morph later rebuilds. */\n rebuiltListeners?: boolean;\n /** A `.value` write to a signal that never had a subscriber. */\n untrackedSignals?: boolean;\n /** `defineStore` `set()` called with keys missing from the current state. */\n narrowSet?: boolean;\n /** `delegate()` called inside an `effect()` body — listeners stack up. */\n delegateInEffect?: boolean;\n /** An `each()` list under a `data-morph-skip` subtree. */\n eachInMorphSkip?: boolean;\n /** Two rows in one `each()` producing the same `cacheKey`. */\n duplicateEachKeys?: boolean;\n /** A fine-grained binding switching signal instance on the fast path. */\n staleBinding?: boolean;\n /** A re-render whose whole diff was values — candidates for bindings. */\n valueOnlyRerender?: boolean;\n /** An `each()` container rebuilt by the morph and self-healed. */\n listRebind?: boolean;\n /** A memoized row reused at a different index than it rendered at. */\n staleIndex?: boolean;\n /** Markup the HTML parser repaired (a block element inside a `<p>`). */\n parserRepair?: boolean;\n /** Structural audit of kerf's list bookkeeping: warn, or `'throw'`. */\n invariants?: boolean | 'throw';\n}\n\n/** Option key → the environment variable that means the same thing. */\nconst ENV_NAME: Record<keyof DevWarningOptions, string> = {\n rebuiltListeners: 'KERF_DEV_WARN_REBUILT_LISTENERS',\n untrackedSignals: 'KERF_DEV_WARN_UNTRACKED_SIGNALS',\n narrowSet: 'KERF_DEV_WARN_NARROW_SET',\n delegateInEffect: 'KERF_DEV_WARN_DELEGATE_IN_EFFECT',\n eachInMorphSkip: 'KERF_DEV_WARN_EACH_IN_MORPH_SKIP',\n duplicateEachKeys: 'KERF_DEV_WARN_DUPLICATE_EACH_KEYS',\n staleBinding: 'KERF_DEV_WARN_STALE_BINDING',\n valueOnlyRerender: 'KERF_DEV_WARN_VALUE_ONLY_RERENDER',\n listRebind: 'KERF_DEV_WARN_LIST_REBIND',\n staleIndex: 'KERF_DEV_WARN_STALE_INDEX',\n parserRepair: 'KERF_DEV_WARN_PARSER_REPAIR',\n invariants: 'KERF_DEV_INVARIANTS',\n};\n\n/** Env name → the value the call set. `false` means \"explicitly off\". */\nconst overrides = new Map<string, string | false>();\n\n/** Apply a consumer's `enableWarnings()` options to the override map. */\nexport function applyWarningOptions(options: DevWarningOptions): void {\n for (const [key, value] of Object.entries(options)) {\n const envName = ENV_NAME[key as keyof DevWarningOptions];\n // Unknown keys are ignored rather than thrown on: a consumer who upgrades\n // kerf downwards should not have their app die on a key that used to exist.\n if (envName === undefined || value === undefined) continue;\n overrides.set(envName, value === false ? false : value === true ? '1' : value);\n }\n}\n\n/**\n * The value of one diagnostic switch, or `undefined` when it is off.\n * Every warner's opt-in check goes through here.\n */\nexport function devFlag(envName: string): string | undefined {\n const override = overrides.get(envName);\n if (override !== undefined) return override === false ? undefined : override;\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n return proc?.env?.[envName];\n}\n\n/** Test helper — drops every `enableWarnings()` override. */\nexport function _resetWarningOptionsForTests(): void {\n overrides.clear();\n}\n","/**\n * Dev-mode warning for silently-stale fine-grained bindings on the fast path\n * (KERF_DEV_WARN_STALE_BINDING=1).\n *\n * `mount()` has a fast path: when a re-render produces byte-for-byte identical\n * static-surrounds HTML (`nextStaticHtml === prevStaticHtml`), the morph AND the\n * binding re-wiring are both skipped and the existing per-hole binding effects\n * stay live — each bound to the FIRST signal instance registered for its hole.\n *\n * That is correct for the canonical pattern `class={computed(() => sig.value)}`:\n * the fresh computed each render reads the same underlying signal(s), so the\n * original effect keeps firing. A hole goes silently STALE only when a render\n * switches which signal INSTANCE it binds while the surrounds string is\n * unchanged — `class={cond ? sigA : sigB}`. kerf keeps the original effect bound\n * to `sigA` and never re-binds to `sigB`, so the hole freezes with no error: the\n * UI just stops updating. See docs/2-reactivity §2.9.\n *\n * This warner detects that: on a fast-path render `mount()` calls\n * `maybeWarnStaleBinding(prevWired, current)`, comparing — per hole, in\n * registration order — the signal instance this render registered\n * (`bindingCtx.list`) against the signal instance that is actually wired (the\n * previously-wired list retained by `mount()`). A per-hole difference fires a\n * one-shot warning naming the hole (kind / attr / id) and pointing at the \"bind\n * one computed that switches internally\" fix.\n *\n * Why opt-in: the comparison is raw signal identity, so a GLOBAL (static-\n * surround) hole bound with a *fresh inline* `computed(() => …)` — a new\n * instance every render, but reading the same signals, hence safe — also differs\n * on the fast path and would warn. Binding a STABLE signal / computed reference\n * for global holes (the idiomatic shape) avoids that; the opt-in gate keeps the\n * diagnostic available for projects that want it without penalizing ones that\n * pass a fresh inline computed into a global hole. (Row holes inside `each()` are\n * wired per-row-node and disposed on row removal, so they are not subject to\n * this fast-path staleness and never reach this warner.)\n *\n * With the dev entry absent, the nullable hook slots make this module\n * unreachable. With diagnostics installed but this warning switched off, the\n * predicate returns before comparison work, and `mount()` gates the\n * previously-wired-list retention on the same switch so the fast path stays\n * allocation-free.\n */\n\nimport type { Binding } from './bindings.js';\nimport { devFlag } from './dev-warn-config.js';\n\n/** Per-hole one-shot dedup — keyed by the stable per-hole binding id. */\nconst warnedHoles = new Set<string>();\n\nexport function isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_STALE_BINDING') === '1';\n}\n\nfunction describeHole(b: Binding): string {\n return b.kind === 'attr'\n ? `attr '${b.attr}' (id '${b.id}')`\n : `text (id '${b.id}')`;\n}\n\n/**\n * Compare this render's registered holes against the previously-wired holes,\n * in registration order, and warn once per hole whose signal instance changed\n * on a fast-path (byte-equal-surrounds) render. On the fast path the two lists\n * describe the same holes in the same order, so a per-index compare suffices;\n * the `Math.min` guard is defensive against a length skew that can't occur when\n * the surrounds are byte-equal.\n */\nexport function maybeWarnStaleBinding(\n prevWired: readonly Binding[],\n current: readonly Binding[],\n): void {\n if (!isOptedIn()) return;\n const n = Math.min(prevWired.length, current.length);\n for (let i = 0; i < n; i++) {\n const cur = current[i];\n if (prevWired[i].signal === cur.signal) continue;\n if (warnedHoles.has(cur.id)) continue;\n warnedHoles.add(cur.id);\n console.warn(\n `kerf: fine-grained binding ${describeHole(cur)} switched to a different signal instance `\n + 'on a render whose static-surrounds HTML was byte-for-byte unchanged. On that fast path kerf '\n + 'keeps the original binding effect and does NOT re-bind, so this hole is now stale — it still '\n + 'tracks the FIRST signal instance and will not reflect the new one. Bind one computed that '\n + 'switches internally (e.g. class={computed(() => cond.value ? sigA.value : sigB.value)}) instead '\n + 'of switching which signal instance you bind (see docs/2-reactivity §2.9). '\n + 'Set KERF_DEV_WARN_STALE_BINDING=0 (or unset it) to silence this warning.',\n );\n }\n}\n\n/**\n * Test helper — resets the one-shot dedup set so a subsequent test in the same\n * module can re-exercise the first-warning path. Not exported from the public\n * barrel; the unit-test file imports it directly via the relative path.\n */\nexport function _resetWarnedForTests(): void {\n warnedHoles.clear();\n}\n","/**\n * Dev-mode warning for `delegate()` / `delegateCapture()` calls that run\n * inside an `effect()` body (KERF_DEV_WARN_DELEGATE_IN_EFFECT=1).\n *\n * Why the pattern matters: every effect re-run executes its body fresh, which\n * means a `delegate()` call inside the body installs a NEW root listener on\n * each re-run. The effect's disposer cleans up the reactive subscription but\n * not the side-effects the body produced — so previous listeners stay\n * attached, the per-listener closure pins `rootEl` / `handler` / everything\n * the handler closes over, and listener count grows linearly with signal\n * churn. Structurally identical to the addEventListener-inside-mount foot-gun\n * (Hard Rule 4) but doesn't *look* like it.\n *\n * Static analysis can't reliably detect \"inside an effect\" without flow\n * information (effect() is just a function call), so the canonical defense\n * is this runtime opt-in warning. When enabled, `reactive.ts`'s `effect()`\n * wrapper increments a module-level counter before invoking the user body\n * and decrements after; `delegate.ts` checks the counter and fires the\n * warning once total.\n *\n * With the dev entry absent, the nullable hook slot makes this module and its\n * wrapper unreachable. With diagnostics installed but this warning switched\n * off, the predicate short-circuits before any depth state is touched.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nlet depth = 0;\nlet warned = false;\n\nfunction isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_DELEGATE_IN_EFFECT') === '1';\n}\n\n/** Called by the `effect()` wrapper in `reactive.ts` before running the user body. */\nexport function enterEffect(): void {\n depth++;\n}\n\n/** Called by the `effect()` wrapper in `reactive.ts` after the user body returns or throws. */\nexport function exitEffect(): void {\n depth--;\n}\n\n/** Expose the warning-switch check so `reactive.ts` can decide whether to wrap. */\nexport function isDevWarnDelegateInEffectEnabled(): boolean {\n return isOptedIn();\n}\n\n/**\n * Called at the top of `delegate()` and `delegateCapture()`. If the call is\n * happening inside an `effect()` body (depth > 0) AND its switch is on, fire\n * a one-shot warning. The `fn` argument is the name of the caller for the\n * message (\"delegate\" vs \"delegateCapture\").\n */\nexport function warnIfInsideEffect(fn: 'delegate' | 'delegateCapture'): void {\n if (!isOptedIn()) return;\n if (depth === 0) return;\n if (warned) return;\n warned = true;\n console.warn(\n `kerf: ${fn}() was called inside an effect() body. `\n + 'Every effect re-run installs a fresh root listener; the effect disposer cleans up the '\n + 'reactive subscription but not the listeners, so listener count grows linearly with signal '\n + 'churn and each listener pins its handler closure. Register the delegate once at module '\n + 'or setup scope and gate behavior on the signal *inside the handler* where the read is free. '\n + 'See docs/5-event-delegation.md §5.3 \"When capturing the disposer still isn\\'t enough\". '\n + 'Set KERF_DEV_WARN_DELEGATE_IN_EFFECT=0 (or unset it) to silence this warning.',\n );\n}\n\n/** Test helper — resets the one-shot dedup flag and depth counter for unit tests. */\nexport function _resetWarnedForTests(): void {\n warned = false;\n depth = 0;\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\nimport { devFlag } from './dev-warn-config.js';\n\nconst warnedIds = new Set<string>();\n\nfunction isOptedIn(): boolean {\n return devFlag('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 return devFlag('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 * Dev-mode structural invariant checks for the list bindings\n * (`KERF_DEV_INVARIANTS=1` to warn, `=throw` to throw).\n *\n * Every reconciler defect found so far shared one property: **kerf kept running\n * happily in a corrupt state.** A binding pointed at rows no longer in the\n * document; a list's rows sat inside a neighbouring list's region; an id\n * referred to a different list than its binding did. Nothing threw. The damage\n * surfaced several operations later as a wrong render, which is precisely what\n * made those bugs expensive to find — the symptom and the cause were nowhere\n * near each other.\n *\n * This module makes the corrupt *state* the error, at the render that created\n * it. Each invariant below is the negation of a defect that actually shipped:\n *\n * - **marker-live / marker-id** — a binding whose marker left the tree, or\n * whose id is carried by a different marker node. The latter is how a\n * call-order id handed to a different list pointed the arriving list at the\n * previous occupant's container.\n * - **row-parent / row-live** — a binding holding rows that are detached, or\n * attached somewhere other than its own parent. This is the shape of every\n * \"stranded rows\" defect.\n * - **row-order** — a binding's rows must follow its marker in document order\n * and be strictly increasing. Rows that jumped their own marker looked\n * correct on screen while leaving the region bookkeeping wrong.\n * - **row-alias** — one row node claimed by two bindings.\n * - **region-overlap** — one list's rows sitting between another list's first\n * and last row. Two sibling lists interleaving their rows is exactly this.\n *\n * Off by default and reachable only after `kerfjs/dev` is installed. Its\n * switch is `enableWarnings({ invariants: true | 'throw' })` or\n * `KERF_DEV_INVARIANTS=1|throw`; omitting the dev entry leaves production\n * untouched. `throw` mode exists because a warning inside a passing test is\n * invisible: kerf's own suites can turn corruption into a failure rather than\n * a line in the log.\n */\n\nimport { devFlag } from './dev-warn-config.js';\nimport type { ListBinding } from './list-binding.js';\nimport { LIST_MARKER_PREFIX } from './segment.js';\n\ntype Mode = 'off' | 'warn' | 'throw';\n\nfunction mode(): Mode {\n const value = devFlag('KERF_DEV_INVARIANTS');\n if (value === 'throw') return 'throw';\n return value === '1' ? 'warn' : 'off';\n}\n\n/**\n * Whether the list-invariant checks are active. Exported so `mount()` can skip\n * building the per-list expected-count map entirely when they're off — the\n * checks themselves are a no-op then, but the map would still cost an\n * allocation per render, and this family's contract is zero production cost.\n */\nexport function listInvariantsEnabled(): boolean {\n return mode() !== 'off';\n}\n\n/**\n * Child-position lookup for one parent, built once and reused for every node\n * asked about.\n *\n * Scanning `childNodes` per row would make the whole audit O(rows²) — which is\n * not a theoretical concern: it timed out a 1000-row stress test the first time\n * this shipped. A dev check that is quadratic in list length would only be\n * usable on the lists least likely to need it.\n */\nfunction childIndexer(): (parent: Element, node: Node) => number {\n const cache = new Map<Element, Map<Node, number>>();\n return (parent, node) => {\n let index = cache.get(parent);\n if (index === undefined) {\n index = new Map<Node, number>();\n const kids = parent.childNodes;\n for (let i = 0; i < kids.length; i++) index.set(kids[i], i);\n cache.set(parent, index);\n }\n return index.get(node) ?? -1;\n };\n}\n\nfunction describe(id: string, problem: string): string {\n return `kerf invariant violated after reconcile — each() list '${id}': ${problem}`;\n}\n\n/**\n * Check every list binding against the live DOM. Returns the violations found\n * (empty when healthy) so `mount()` can report them; exported separately from\n * the reporting so tests can assert on the findings directly.\n */\nexport function findListInvariantViolations(\n rootEl: Element,\n bindings: ReadonlyMap<string, ListBinding>,\n expectedCounts?: ReadonlyMap<string, number>,\n): string[] {\n const problems: string[] = [];\n const owners = new Map<Node, string>();\n const indexIn = childIndexer();\n // Per binding: [firstRowIndex, lastRowIndex] within its parent, for the\n // region-overlap pass below.\n const spans: { id: string; parent: Element; from: number; to: number }[] = [];\n\n for (const [id, binding] of bindings) {\n const { marker, liveParent, items } = binding;\n\n // Row-count agreement (KF-416): the binding must hold as many rows as the\n // data it just rendered from. Every other check here is INTERNAL — it\n // confirms the binding agrees with the live DOM — so a reconcile that\n // emptied a list still passes them all (zero items, zero live rows, all\n // consistent). Only comparing against the source length catches a list that\n // rendered the wrong NUMBER of rows, which is how KF-411 slipped through:\n // a self-healed empty binding was internally perfect and externally blank.\n // `expectedCounts` is supplied only for lists in the current render.\n const expected = expectedCounts?.get(id);\n if (expected !== undefined && items.length !== expected) {\n problems.push(describe(id, `holds ${items.length} row(s) but its source has ${expected} — `\n + 'the reconcile dropped or duplicated rows'));\n }\n\n if (!rootEl.contains(marker)) {\n problems.push(describe(id, 'its marker comment is no longer inside the mount root, so every '\n + 'future reconcile would mutate a detached tree'));\n continue;\n }\n if (marker.data !== `${LIST_MARKER_PREFIX}${id}`) {\n problems.push(describe(id, `its marker reads '${marker.data}' — the id is carried by a `\n + 'different marker node, so this binding describes another list'));\n }\n\n const markerIndex = indexIn(liveParent, marker);\n if (markerIndex === -1) {\n problems.push(describe(id, 'its marker is not a child of the parent the binding records'));\n continue;\n }\n\n let previousIndex = markerIndex;\n let first = -1;\n for (let i = 0; i < items.length; i++) {\n const node = items[i].node;\n const index = indexIn(liveParent, node);\n if (index === -1) {\n problems.push(describe(id, `bound row ${i} is not a child of the list's parent `\n + `(<${liveParent.tagName.toLowerCase()}>)${node.isConnected ? ' — it is attached elsewhere in the document' : ' — it is detached'}`));\n continue;\n }\n if (index <= previousIndex) {\n problems.push(describe(id, `bound row ${i} appears at child position ${index}, which is not `\n + `after the previous one (${previousIndex}) — the rows are out of order or have crossed the marker`));\n }\n previousIndex = index;\n if (first === -1) first = index;\n\n const owner = owners.get(node);\n if (owner !== undefined) {\n problems.push(describe(id, `bound row ${i} is also claimed by list '${owner}'`));\n } else {\n owners.set(node, id);\n }\n }\n if (first !== -1) spans.push({ id, parent: liveParent, from: first, to: previousIndex });\n }\n\n // Region overlap: two lists sharing a parent must occupy disjoint stretches of\n // it. Interleaved rows render in the wrong order and make each list's extent\n // unknowable.\n for (let a = 0; a < spans.length; a++) {\n for (let b = a + 1; b < spans.length; b++) {\n if (spans[a].parent !== spans[b].parent) continue;\n if (spans[a].from <= spans[b].to && spans[b].from <= spans[a].to) {\n problems.push(describe(spans[a].id, `its rows (child positions ${spans[a].from}-${spans[a].to}) `\n + `overlap those of list '${spans[b].id}' (${spans[b].from}-${spans[b].to}) in the same parent`));\n }\n }\n }\n\n return problems;\n}\n\n/**\n * Run the checks if opted in, and report anything found. No-op — and no DOM\n * walking at all — when the env var is unset.\n */\nexport function maybeCheckListInvariants(\n rootEl: Element,\n bindings: ReadonlyMap<string, ListBinding>,\n expectedCounts?: ReadonlyMap<string, number>,\n): void {\n const level = mode();\n if (level === 'off') return;\n const problems = findListInvariantViolations(rootEl, bindings, expectedCounts);\n if (problems.length === 0) return;\n const report = `${problems.join('\\n')}\\n`\n + 'This is a kerf bug, not an application one — please report it with the markup that produced it. '\n + 'Set KERF_DEV_INVARIANTS=1 to warn instead of throw, or unset it to disable these checks.';\n if (level === 'throw') throw new Error(report);\n console.warn(report);\n}\n","/**\n * Dev-mode warning for a stale `index` argument in an `each()` row render\n * (KERF_DEV_WARN_STALE_INDEX=1).\n *\n * `each(items, (item, index) => …)` passes the row's position as the second\n * argument. But `each()` memoizes a row's HTML by object identity (+ optional\n * `cacheKey` + content version) — the `index` is NOT part of that key. So when a\n * surviving row's position changes without its ref or cacheKey changing — a\n * reorder, or an insert/remove/move ahead of it — kerf serves the row's cached\n * HTML, which was computed at the OLD index. A numbered list (`{index}. …`),\n * zebra striping, or an \"N of M\" label silently shows the wrong number.\n *\n * When the opt-in env var is set, `each()` calls `maybeWarnStaleIndex()` at the\n * two points a shift can strand a memoized row's index:\n * - the snapshot path, when a cache HIT reuses a row at a different index than\n * it rendered at (a plain-array reorder);\n * - the granular path, when the applied `arraySignal` patches shift an existing\n * row's index (a non-tail insert/remove, or any move).\n * Both are gated on the render fn actually declaring an index parameter\n * (`render.length >= 2`), so a list that never reads the index never warns. This\n * is a heuristic in both directions: a fn that declares `index` but never uses it\n * warns spuriously (false positive), and a fn whose index parameter has a DEFAULT\n * value — `(item, i = 0) => …` — has `Function.length` 1, so it escapes the gate\n * and a genuine index use goes unwarned (false negative). A fully precise check\n * would need to parse the fn source; not worth it for a dev diagnostic.\n *\n * Why opt-in: `render.length >= 2` is a heuristic — a render fn may declare the\n * index parameter and not use it in its output, in which case a reorder is\n * harmless and the warning would be a false positive. The fix (`cacheKey: (_, i)\n * => i`, which folds the index into the memo key so a shifted row re-renders) is\n * also not always wanted: a list whose index only labels rows that never reorder\n * pays nothing today. Opt-in keeps the diagnostic available without penalising\n * either shape.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst warnedIds = new Set<string>();\n\n/** True when the env var opt-in is set in a dev build. Checked first for zero prod cost. */\nexport function isOptedInStaleIndex(): boolean {\n return devFlag('KERF_DEV_WARN_STALE_INDEX') === '1';\n}\n\n/**\n * Fire the one-shot (per list id) stale-index warning. Callers gate on\n * `isOptedInStaleIndex()` AND on having detected a genuine index shift for a\n * list whose render fn declares an index parameter.\n */\nexport function maybeWarnStaleIndex(id: string): void {\n if (warnedIds.has(id)) return;\n warnedIds.add(id);\n console.warn(\n `kerf: each() list '${id}' reused a memoized row at a new index this render, but its render function `\n + 'takes an `index` argument. Rows are memoized by object identity, not by position, so a reorder or an '\n + 'insert/remove ahead of a surviving row serves that row\\'s cached HTML — computed at its OLD index. A '\n + 'numbered list, zebra striping, or an \"N of M\" label will silently show the wrong value. If the row '\n + 'output depends on the index, fold it into the memo key: each(items, render, { cacheKey: (_, i) => i }) '\n + '(combine with your own key if you have one). If the index is not used in the output, ignore this. '\n + 'Set KERF_DEV_WARN_STALE_INDEX=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 * Dev-mode warning for `each()` lists whose identity shifted (KF-392).\n *\n * Without an explicit key, a list is identified by its call order — \"the n-th\n * `each()` this render\". Any render that changes how many `each()` calls run\n * before a list reassigns its identity, and the list is then rebuilt from\n * scratch: row nodes, focus, scroll position and in-progress IME composition\n * are discarded, and the work is O(rows) rather than O(changes).\n *\n * That was entirely silent. `KERF_DEV_WARN_LIST_REBIND` cannot see it either —\n * this rebuild routes through the ordinary classify pass, not the self-heal it\n * watches — so an author had no signal at all that state was being thrown away.\n *\n * **Always on once diagnostics are installed, like the missing-row-key\n * warning**, rather than individually switched like the `KERF_DEV_WARN_*`\n * family. The reasoning is the same as for that one: it fires only when kerf\n * is about to silently discard row state, it names a concrete one-line fix,\n * and it is one-shot per list — so it is a diagnostic an author always wants,\n * not one they opt into. The production shape emits nothing because the dev\n * entry is absent; kerf does not infer that shape from the environment.\n *\n * Detection is deliberately conservative (KF-394). A changed data source alone\n * is NOT a shift — the same list swapping which signal it renders (a filter or\n * tab switch) changes source too, and warning there told authors to fix\n * correct code. `mount()` therefore only reports a candidate when the render's\n * `each()` call count ALSO changed, which is what an id shift requires; and\n * keyed lists are excluded entirely, since a key is the identity.\n *\n * Two shapes stay invisible as a result: two `each()` calls over the SAME\n * `arraySignal` (indistinguishable by source), and two unkeyed lists swapping\n * order at a constant call count. Keys close both by construction, which is\n * what the message asks for.\n */\n\n/**\n * Emit the identity-shift warning for the unkeyed list at `id`.\n *\n * Dedup is the CALLER's job and lives on the per-mount render context — ids are\n * per-mount, so a module-level set meant the first mount to warn for id '0'\n * silenced every other mount's genuine shift forever (KF-394).\n */\nexport function maybeWarnListIdShift(id: string): void {\n console.warn(\n `kerf each(): list '${id}' is now a different list than it was last render. `\n + 'Lists without a key are identified by call order, so adding or removing an each() call '\n + 'before this one reassigns its identity — kerf rebuilds the list from scratch and its rows '\n + 'lose DOM identity, focus, scroll position and in-progress IME composition. '\n + 'Give the affected lists a stable key: each(items, render, { key: \\'my-list\\' }). '\n + 'Keying the conditional list is usually enough — a keyed list does not take a call-order '\n + 'slot, so its siblings stop shifting too.',\n );\n}\n","/**\n * Dev-mode warning for each() containers rebuilt by the morph\n * (KERF_DEV_WARN_LIST_REBIND=1).\n *\n * When the opt-in env var is set, `mount()` calls `maybeWarnListRebind()` from\n * the self-heal branch of `bindListsFromMarkers` — the point where an existing\n * list binding's marker is discovered to have left the mount root because the\n * morph rebuilt the list's container (an ancestor's tag changed, so\n * `replaceChild` swapped the whole subtree, cloning a fresh marker).\n *\n * Why the pattern matters: the self-heal makes the rebuild *correct* — the\n * stale binding is dropped, the list re-binds against the fresh marker, and\n * the next reconcile repopulates the rows — but the recovery is lossy. The\n * rows are re-created from scratch, so focus, scroll positions, in-progress\n * IME composition, and any imperative listeners on the old row nodes are\n * silently discarded. An author who didn't intend the ancestor tag swap gets\n * no other signal that their rows are being churned.\n *\n * Why opt-in: swapping an ancestor's tag across renders (`<section>` ↔\n * `<article>` around the same list) is occasionally intentional — semantic\n * element changes driven by state — and the rebuild-with-repopulate behavior\n * is then exactly what the author wants. The opt-in keeps the diagnostic\n * available for projects that want it without penalising that pattern.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst warnedIds = new Set<string>();\n\nfunction isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_LIST_REBIND') === '1';\n}\n\n/**\n * Fire the one-shot (per list id) rebuild warning. `liveParent` is the fresh\n * container the cloned marker landed in — named in the message so the author\n * can find the swap site.\n */\nexport function maybeWarnListRebind(id: string, liveParent: Element): void {\n if (!isOptedIn()) return;\n if (warnedIds.has(id)) return;\n warnedIds.add(id);\n console.warn(\n `kerf: each() list '${id}' had its container (<${liveParent.tagName.toLowerCase()}>) rebuilt by the morph this render — `\n + 'an ancestor\\'s tag changed so the subtree was replaced, or a same-tag sibling positionally took the '\n + 'container\\'s place. The list re-binds and repopulates automatically, but its rows were re-created '\n + 'from scratch: focus, scroll positions, in-progress IME composition, and any imperative listeners on '\n + 'the old row nodes are lost. If the rows should survive, give the LIST\\'S OWN container a stable '\n + 'id/data-key (keying the conditional sibling instead only helps when it is removed, not when it '\n + 'reappears) and keep the tags of the list\\'s ancestors stable across renders. '\n + 'Set KERF_DEV_WARN_LIST_REBIND=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 * Dev-mode warning for Rule 4 violations (KF-174). Once the diagnostics are\n * installed, switching on `rebuiltListeners` through `enableWarnings()` or\n * `KERF_DEV_WARN_REBUILT_LISTENERS=1` makes `mount()` call\n * `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; consumers that want the diagnostic\n * enable its switch.\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 * With the dev entry absent, the nullable hook slot makes this module\n * unreachable. With diagnostics installed but this warning switched off, the\n * predicate returns before patching `EventTarget` or creating an observer.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst LISTENER_MARKER = Symbol.for('kerfjs.devListener');\n\nlet patched = false;\nlet warned = false;\n\nfunction isOptedIn(): boolean {\n return devFlag('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 * Dev-mode warning for markup the HTML parser silently restructures\n * (`KERF_DEV_WARN_PARSER_REPAIR=1`).\n *\n * kerf renders JSX to an HTML string and lets the parser build the DOM, so the\n * parser's content-model repairs apply. The one that actually bites is `<p>`:\n * it may contain only phrasing content, and the parser **auto-closes it** before\n * a block-level child. So\n *\n * <p><section>head</section><ul>{each(rows, …)}</ul></p>\n *\n * becomes `<p></p><section>head</section><ul>…</ul>` — an empty `<p>`, and every\n * child hoisted to be its *sibling*.\n *\n * What this does and doesn't cost is worth stating precisely, because it's\n * narrower than it first looks. kerf reconciles the tree the parser actually\n * produced, and does so consistently: updates, list inserts and conditional\n * toggles all behave correctly afterwards. Nothing is corrupted in the ordinary\n * case. What the author loses is the *shape they wrote* — their `<p>` is empty,\n * their children are somewhere else, and any CSS or query that assumed the\n * nesting silently doesn't match.\n *\n * The reason it deserves a warning rather than a line in the docs is distance:\n * the symptom shows up as \"my list isn't inside the element I put it in\", three\n * levels away from the `<p>` that caused it, and nothing in the JSX looks wrong.\n * Naming the tag pair at first render turns a confusing afternoon into a\n * one-line fix.\n *\n * Why opt-in: the detection is a scan of the emitted HTML rather than a real\n * parse, so while a block-level open tag before a `</p>` is an unambiguous\n * repair signal in kerf's own well-formed output, it is not a proof. The rest of\n * the family's opt-in default keeps that judgement with the consumer.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\n/**\n * Elements that close an open `<p>`. Per the HTML spec's \"a p element's end tag\n * can be omitted if the p element is immediately followed by…\" list.\n */\nconst BLOCK_TAGS = [\n 'address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset',\n 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section',\n 'table', 'ul',\n];\n\n/** `<p …>` or a block-level open tag — whichever comes first from a given index. */\nconst SCAN = new RegExp(`<(/?p|${BLOCK_TAGS.join('|')})[\\\\s/>]`, 'gi');\n\nconst warnedPairs = new Set<string>();\n\nfunction isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_PARSER_REPAIR') === '1';\n}\n\n/**\n * Find the first block-level tag that opens while a `<p>` is still open.\n * Returns the offending tag name, or null when the markup is clean.\n *\n * Only kerf's own output is scanned, which is always well-formed (the JSX\n * runtime emits a matching close for every non-void tag), so a simple\n * open/close walk is sufficient — no nesting depth to track beyond \"are we\n * inside a p\".\n */\nexport function findParagraphRepair(html: string): string | null {\n SCAN.lastIndex = 0;\n let inParagraph = false;\n for (let m = SCAN.exec(html); m !== null; m = SCAN.exec(html)) {\n const tag = m[1].toLowerCase();\n if (tag === '/p') { inParagraph = false; continue; }\n if (tag === 'p') {\n // A nested <p> is itself a repair when one is already open.\n if (inParagraph) return 'p';\n inParagraph = true;\n continue;\n }\n if (inParagraph) return tag;\n }\n return null;\n}\n\n/**\n * Scan a first-render HTML string and warn once per offending tag pair.\n * Short-circuits on the env gate before touching the string.\n */\nexport function maybeWarnParserRepair(html: string): void {\n if (!isOptedIn()) return;\n const tag = findParagraphRepair(html);\n if (tag === null) return;\n const pair = `p>${tag}`;\n if (warnedPairs.has(pair)) return;\n warnedPairs.add(pair);\n console.warn(\n `kerf: a <${tag}> inside a <p> will not survive parsing. `\n + '<p> may contain only phrasing content, so the HTML parser closes it before a '\n + `block-level child — your <p> ends up EMPTY and the <${tag}> (plus everything after it) `\n + 'becomes its sibling instead of its child. kerf then reconciles that repaired tree '\n + 'correctly, so updates still work; what you lose is the structure you wrote, along with '\n + 'any CSS or querySelector that assumed it. Use a <div> (or a phrasing element like '\n + '<span>) in place of the <p>, or move the block content outside it. '\n + 'Set KERF_DEV_WARN_PARSER_REPAIR=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 warnedPairs.clear();\n}\n","/**\n * Dev-mode warning for value-only re-renders (KERF_DEV_WARN_VALUE_ONLY_RERENDER=1).\n *\n * Phase 2 of the update-machinery consolidation (\"values bind, structure\n * re-renders\"): when a `mount()` re-render's static-surrounds HTML differs\n * from the previous render ONLY in text content and attribute values — no\n * element added, removed, moved, or retagged — every changed hole could have\n * been a fine-grained binding instead (`{count}`, `class={sig}`), and the\n * whole render + byte-compare + morph pass was avoidable. This warner points\n * that out once per mount.\n *\n * Detection: parse both HTML strings into detached `<template>`s and walk the\n * two trees in lockstep. Text-node data and element attributes (names AND\n * values — a boolean attribute appearing/disappearing is a value change,\n * since `renderAttr` omits false/nullish) are allowed to differ; any change\n * of child count, node type, tag name, or comment data (marker comments are\n * deterministic per structure, so a changed marker implies a structural or\n * binding-shape change) classifies the render as structural and no warning\n * fires. Conservative by construction: false negatives are fine, false\n * positives would erode trust in the guidance.\n *\n * Why opt-in (docs/11 family rules): plenty of legitimate code re-renders on\n * `.value` reads — the warning is a migration aid for adopting the bound-first\n * idiom, not a lint on correctness. With the dev entry absent, the nullable\n * hook slot makes this module unreachable. With diagnostics installed but the\n * warning switched off, its predicate returns before parsing; enabled parsing\n * happens only on the already-slow surrounds-changed path.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\n/** Per-mount one-shot context — created by `mount()`, mirrors NarrowSetWarnContext. */\nexport interface ValueOnlyWarnContext {\n warned: boolean;\n}\n\nexport function isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_VALUE_ONLY_RERENDER') === '1';\n}\n\nconst ELEMENT_NODE = 1;\nconst TEXT_NODE = 3;\nconst COMMENT_NODE = 8;\n\n/**\n * Lockstep structural comparison: true when the two fragments have identical\n * element/comment shape, so every difference is confined to text data and\n * attributes (\"value-only\"). Exported for direct unit coverage of the branch\n * matrix; installed-hook callers go through `maybeWarnValueOnlyRerender`.\n */\nexport function _isValueOnlyDiff(a: Node, b: Node): boolean {\n const an = a.childNodes;\n const bn = b.childNodes;\n if (an.length !== bn.length) return false;\n for (let i = 0; i < an.length; i++) {\n const x = an[i];\n const y = bn[i];\n if (x.nodeType !== y.nodeType) return false;\n if (x.nodeType === ELEMENT_NODE) {\n if ((x as Element).tagName !== (y as Element).tagName) return false;\n if (!_isValueOnlyDiff(x, y)) return false;\n } else if (x.nodeType === COMMENT_NODE) {\n if ((x as Comment).data !== (y as Comment).data) return false;\n } else if (x.nodeType !== TEXT_NODE) {\n // Defensive: HTML parsing via template.innerHTML only produces\n // element/text/comment children (no CDATA; PIs parse as bogus\n // comments), so this arm is unreachable by construction — kept so an\n // exotic caller-supplied tree bails structural rather than guessing.\n /* c8 ignore next 2 */\n return false;\n }\n // TEXT_NODE: data may differ freely — that's the value change.\n }\n return true;\n}\n\n/**\n * Called by `mount()` on a surrounds-CHANGED re-render (the byte-compare\n * already failed, so the strings are known to differ). Parses + compares only\n * when the opt-in gate is open and this mount hasn't warned yet.\n */\nexport function maybeWarnValueOnlyRerender(\n prevHtml: string,\n nextHtml: string,\n ctx: ValueOnlyWarnContext,\n): void {\n if (ctx.warned || !isOptedIn()) return;\n const a = document.createElement('template');\n const b = document.createElement('template');\n a.innerHTML = prevHtml;\n b.innerHTML = nextHtml;\n if (!_isValueOnlyDiff(a.content, b.content)) return;\n ctx.warned = true;\n console.warn(\n 'kerf: this re-render changed only text content and attribute values — no structural '\n + 'change — so every changed hole could be a fine-grained binding instead. Values bind, '\n + 'structure re-renders: pass the signal/computed itself ({count}, class={sig}) rather than '\n + 'reading .value in the hole, and each change updates just that node with no render re-run '\n + '(a mount whose render reads no .value never re-renders at all). See docs/2-reactivity §2.9. '\n + 'Set KERF_DEV_WARN_VALUE_ONLY_RERENDER=0 (or unset it) to silence this warning.',\n );\n}\n","/**\n * Dev warning for an `each()` list whose rows carry no `id` / `data-key`\n * (KF-173). Always on when `kerfjs/dev` is installed — no env var, because a\n * keyless list is never intentional.\n *\n * The reconciler falls back to positional matching without a key, which\n * silently shifts row state (focused inputs, mid-edit textareas) on insert or\n * delete. The warning names the fix and quotes the row HTML so the author can\n * locate the call site.\n *\n * Called per-binding with the FIRST row only — rows come from one render\n * function, so sampling row 0 is representative; per-row checking would just\n * repeat the same verdict. The caller passes a mutable flag holder so the\n * warning fires at most once per `mount()`-lifetime per `each()` call site.\n *\n * Lives in its own `dev-*` module (rather than beside the row-contract helpers\n * it borrows `truncateRowHtml` from) so it is reachable only from the\n * `kerfjs/dev` entry and drops out of production bundles with the rest of the\n * family.\n */\n\nimport { truncateRowHtml } from './utils/row-contract.js';\n\nexport function maybeWarnMissingRowKey(\n rowEl: Element,\n rowHtml: string,\n binding: { warnedMissingKey?: boolean },\n): void {\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(): the first row 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 * Dev-mode signal subclass with subscriber tracking (KF-176). When the\n * dev-warn opt-in is enabled, `signal()` returns a `DevSignal` that emits a\n * one-shot `console.warn` the first time `.value` is written to an instance\n * that has never had a subscriber attached. This surfaces the canonical\n * Rule 7 violation (read `.value` outside a render fn / effect — the read\n * doesn't subscribe, so subsequent writes silently fail to re-render) at\n * the moment the user makes the wrong write, instead of leaving them to\n * notice that their UI never updates.\n *\n * The switch is `enableWarnings({ untrackedSignals: true })` or\n * `KERF_DEV_WARN_UNTRACKED_SIGNALS=1`, on top of the diagnostics being\n * installed at all — importing `kerfjs/dev` is what makes this module\n * reachable. Off by default because the heuristic produces false positives\n * for purely imperative signals (used as mutable cells with no UI consumer);\n * opt-in is the right shape until a sharper heuristic is found. Omitting the\n * dev entry keeps the subclass and its tracking out of the production path.\n *\n * The subclass uses signals-core's `SignalOptions.watched` callback to set a\n * per-instance `__hasSubscriber` flag — fired by signals-core when the first\n * subscriber attaches. We never clear the flag on `unwatched`, so a signal\n * that *was* subscribed at some point won't warn even if its subscribers\n * later detach.\n */\n\nimport { Signal } from '@preact/signals-core';\n\nimport { devFlag } from './dev-warn-config.js';\n\nconst WARNING_MESSAGE\n = 'kerf: signal was written but has no subscribers. '\n + 'Did you read `.value` outside of a render fn / effect()? '\n + 'Hoisted reads do not subscribe, so subsequent writes will not re-render. '\n + 'Move the read inside mount()\\'s render fn or effect() callback. '\n + 'Set KERF_DEV_WARN_UNTRACKED_SIGNALS=0 (or unset it) to silence this warning.';\n\nexport class DevSignal<T> extends Signal<T> {\n private __hasSubscriber = false;\n private __warned = false;\n private __constructed = false;\n\n constructor(initial?: T) {\n super(initial as T, {\n watched(this: Signal<T>) {\n (this as unknown as { __hasSubscriber: boolean }).__hasSubscriber = true;\n },\n });\n this.__constructed = true;\n }\n\n override get value(): T { return super.value; }\n override set value(v: T) {\n super.value = v;\n if (this.__constructed && !this.__hasSubscriber && !this.__warned) {\n this.__warned = true;\n console.warn(WARNING_MESSAGE);\n }\n }\n}\n\nexport function isDevWarnUntrackedEnabled(): boolean {\n return devFlag('KERF_DEV_WARN_UNTRACKED_SIGNALS') === '1';\n}\n\n/**\n * This warning is the ONE member of the family whose coverage depends on WHEN\n * `kerfjs/dev` was installed, because `signal()` picks its constructor at\n * creation time. Signals created before the install are plain `Signal`s\n * forever and this warning can never see them.\n *\n * That matters in the common layout, because static imports are hoisted above\n * a top-level `await import()`:\n *\n * ```js\n * import { counter } from './store.js'; // created HERE\n * if (import.meta.env.DEV) await import('kerfjs/dev'); // ...installs after\n * ```\n *\n * kerf's state model is module-scope signals, so that ordering can leave the\n * warning covering almost nothing — and failing SILENTLY, which is the worst\n * outcome for a diagnostic: the author sets the env var, sees nothing, and\n * concludes their code is clean.\n *\n * Retro-fitting already-created signals is not possible. `Signal.prototype`'s\n * `value` accessor is **non-configurable**, so it cannot be patched, and\n * reaching existing instances would need kerf to keep a registry of every\n * signal — a per-signal production cost paid to serve an opt-in dev warning,\n * which is exactly the coupling the hook registry removed. So the miss is\n * converted from silent to loud instead: opting in prints the coverage\n * boundary once, with the fix.\n */\nlet coverageNoticeShown = false;\n\nexport function noteUntrackedCoverage(): void {\n if (coverageNoticeShown) return;\n coverageNoticeShown = true;\n console.warn(\n 'kerf: KERF_DEV_WARN_UNTRACKED_SIGNALS only covers signals created AFTER kerfjs/dev is installed. '\n + 'Static imports are hoisted above `await import(\\'kerfjs/dev\\')`, so module-scope signals in the modules '\n + 'you import are created first and this warning cannot see them — you may get no warnings even where the '\n + 'bug exists. To cover them, make `import \\'kerfjs/dev\\'` the FIRST STATIC import of a dev-only entry file '\n + '(static imports evaluate in order), then load the rest of your app. '\n + 'Set KERF_DEV_WARN_UNTRACKED_SIGNALS=0 (or unset it) to silence this warning.',\n );\n}\n\n/** Test helper — re-arms the one-shot coverage notice. */\nexport function _resetCoverageNoticeForTests(): void {\n coverageNoticeShown = false;\n}\n","/**\n * Dev-mode warning for partial-set violations of Hard Rule 8 (KF-212). Once\n * the diagnostics are installed, switching on `narrowSet` through\n * `enableWarnings()` or `KERF_DEV_WARN_NARROW_SET=1` makes `defineStore`'s\n * `set()` call `maybeWarnNarrowSet(prev, next, ctx)` before assigning. If\n * `next` is a plain object whose own-keys are a strict subset of `prev`'s\n * own-keys, a one-shot `console.warn` fires naming the missing keys and\n * pointing at the canonical `set({ ...get(), ...next })` merge fix.\n *\n * Why opt-in: narrow-set IS legal — sometimes you want to replace state with\n * a smaller shape (a reset() that drops keys, a feature-flag-driven schema\n * change). The warn is the right shape for the canonical bug (\"I wrote\n * `set({filter})` against a replace-semantics store and wiped items+editingId\")\n * but produces false positives for intentional shape changes. Opt-in keeps\n * the warning available to dev/CI environments that want the diagnostic\n * without surprising existing projects.\n *\n * Trigger condition: ANY key in `prev` missing from `next` — strictly broader\n * than \"fewer keys total.\" A `set({a, c})` against `cur = {a, b}` (same count,\n * different keys) also wipes `b`, so it warns. The original partial-set bug\n * shape was always \"at least one key from current is missing in next\"; the\n * key-count check in the original ticket sketch was an early-exit\n * optimization, not the semantic gate.\n *\n * Skips: non-object cur/next (booleans, numbers, strings — no \"keys\" to\n * miss), null/undefined either side, and arrays either side (shrinking-array\n * replacement is normal, not a partial set).\n *\n * Per-store one-shot dedup: each store warns at most once across its\n * lifetime — matches the KF-174 / KF-176 pattern of \"tell the developer\n * about the rule violation once, then trust them to fix it.\" The dedup\n * scope is the store, not the module, so a second store can still warn\n * if it independently hits the same bug.\n *\n * With the dev entry absent, `set()` sees no warning hook and allocates no\n * warning context. With diagnostics installed but this warning switched off,\n * the predicate returns before the key comparison.\n */\n\nimport { devFlag } from './dev-warn-config.js';\n\nexport interface NarrowSetWarnContext {\n /** Set once per store; the warner reads/writes this to enforce the per-store one-shot dedup. */\n warned: boolean;\n}\n\nconst WARNING_PREFIX\n = 'kerf: defineStore.set() called with keys missing from the current state — ';\nconst WARNING_SUFFIX\n = '. set() REPLACES state; the missing keys will be undefined after this call. '\n + 'Use `set({ ...get(), ...next })` to merge instead, or update each call site to pass the full state. '\n + 'Set KERF_DEV_WARN_NARROW_SET=0 (or unset it) to silence this warning.';\n\nexport function isOptedIn(): boolean {\n return devFlag('KERF_DEV_WARN_NARROW_SET') === '1';\n}\n\nfunction isPlainObjectState(v: unknown): v is Record<string, unknown> {\n if (v === null || typeof v !== 'object') return false;\n if (Array.isArray(v)) return false;\n return true;\n}\n\nexport function maybeWarnNarrowSet(\n prev: unknown,\n next: unknown,\n ctx: NarrowSetWarnContext,\n): void {\n if (ctx.warned) return;\n if (!isOptedIn()) return;\n if (!isPlainObjectState(prev) || !isPlainObjectState(next)) return;\n\n const missing: string[] = [];\n for (const k of Object.keys(prev)) {\n if (!(k in next)) missing.push(k);\n }\n if (missing.length === 0) return;\n\n ctx.warned = true;\n const keysList = missing.map((k) => `\\`${k}\\``).join(', ');\n console.warn(`${WARNING_PREFIX}${keysList}${WARNING_SUFFIX}`);\n}\n\n/**\n * Test helper — resets the per-store `warned` flag on a context so a\n * subsequent test in the same module can re-exercise the first-warning\n * path. Not exported from the public barrel; the unit-test file imports it\n * directly via the relative path.\n */\nexport function _resetWarnContext(ctx: NarrowSetWarnContext): void {\n ctx.warned = false;\n}\n","/**\n * Dev-only deep read-only guard for `defineStore`'s `get()` snapshot.\n *\n * Replaces the older `Object.freeze(get())` guard, which had three problems:\n * it mutated (froze) the LIVE state object as a side effect of a read, so\n * external references that later legitimately mutated it threw in dev but not\n * prod; it was shallow (`get().nested.x = 1` slipped through); and freezing on\n * read is surprising. This module instead wraps the returned reference in a\n * lazy `Proxy` that:\n *\n * - throws a store-rule-specific `TypeError` on any write (`set` /\n * `deleteProperty` / `defineProperty`) — mutating the object returned by\n * `get()` is a Rule 8 violation (all writes go through actions), and now it\n * is a loud throw instead of a silent desync;\n * - lazily wraps plain-object / array property values in the SAME proxy on\n * access (deep coverage, O(1) per access, no clones), so `get().nested.x = 1`\n * also throws;\n * - leaves primitives, functions, and exotic objects (Date, Map, …) as-is, so\n * `instanceof`, `JSON.stringify`, spread, `Object.keys`, and array iteration\n * all behave exactly as on the raw object.\n *\n * The live state object is never frozen or mutated, so an external reference to\n * it stays writable. This guard is DEV-ONLY: production returns the raw\n * reference and never constructs a proxy, so its perf and semantics are\n * byte-identical to a bare object.\n *\n * `toRaw()` reverses the wrapping so a state object DERIVED from `get()` output\n * (e.g. `set({ ...get(), count: 1 })`, whose nested values are proxies handed\n * back by the `get` trap) is stored as a plain object — the internal signal\n * must never hold a Proxy.\n */\n\nconst RULE_MESSAGE\n = 'kerf: store state is read-only — all writes must go through actions '\n + '(build a new state object and pass it to `set()`). Mutating the object '\n + 'returned by `get()` is a Rule 8 violation and never notifies subscribers.';\n\n/** proxy → its raw target. Lets `toRaw()` unwrap a value derived from `get()`. */\nconst proxyToRaw = new WeakMap<object, object>();\n/** raw → its proxy. Stable proxy identity + avoids re-wrapping the same object. */\nconst rawToProxy = new WeakMap<object, object>();\n\n/** Only plain objects and arrays are wrapped; exotic objects pass through untouched. */\nfunction isWrappable(v: unknown): v is object {\n if (v === null || typeof v !== 'object') return false;\n if (Array.isArray(v)) return true;\n const proto = Object.getPrototypeOf(v) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\nconst handler: ProxyHandler<object> = {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver) as unknown;\n return isWrappable(value) ? devReadonlyProxy(value) : value;\n },\n set() {\n throw new TypeError(RULE_MESSAGE);\n },\n deleteProperty() {\n throw new TypeError(RULE_MESSAGE);\n },\n defineProperty() {\n throw new TypeError(RULE_MESSAGE);\n },\n};\n\n/** Wrap `obj` in the dev read-only proxy (idempotent, identity-stable per raw). */\nexport function devReadonlyProxy<T extends object>(obj: T): T {\n if (proxyToRaw.has(obj)) return obj; // already a proxy — don't double-wrap\n const cached = rawToProxy.get(obj);\n if (cached) return cached as T;\n const p = new Proxy(obj, handler) as T;\n rawToProxy.set(obj, p as object);\n proxyToRaw.set(p as object, obj);\n return p;\n}\n\n/**\n * Deep-unwrap any dev read-only proxies out of `value`, preserving structural\n * sharing: returns the SAME reference when nothing was a proxy, and only\n * allocates along the path to a proxy it actually replaces. Raw targets are\n * fully plain (proxies are never stored), so unwrapping one is deep-clean.\n */\nexport function toRaw<T>(value: T): T {\n return unwrap(value) as T;\n}\n\nfunction unwrap(v: unknown): unknown {\n if (v === null || typeof v !== 'object') return v;\n const raw = proxyToRaw.get(v);\n if (raw !== undefined) return raw; // a proxy → its fully-plain raw target\n if (!isWrappable(v)) return v; // exotic object — leave as-is\n\n if (Array.isArray(v)) {\n let changed = false;\n const out = v.map((item) => {\n const u = unwrap(item);\n if (u !== item) changed = true;\n return u;\n });\n return changed ? out : v;\n }\n\n let changed = false;\n const src = v as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(src)) {\n const u = unwrap(src[k]);\n if (u !== src[k]) changed = true;\n out[k] = u;\n }\n return changed ? out : v;\n}\n","/**\n * `kerfjs/dev` — the development diagnostics bundle.\n *\n * Importing this module installs kerf's dev-only behavior: the whole\n * `KERF_DEV_WARN_*` warning family, the structural list invariants, the\n * read-only store snapshot, and the throw-on-dangerous-URL screen. Importing\n * nothing leaves every hook slot `undefined` and kerf runs in production shape.\n *\n * Put the import behind YOUR environment's dev flag, in YOUR code. That\n * condition folds to `false` in your production build, so the whole statement\n * is eliminated and this chunk is never emitted or fetched:\n *\n * ```js\n * if (import.meta.env.DEV) await import('kerfjs/dev'); // Vite\n * if (process.env.NODE_ENV !== 'production') await import('kerfjs/dev'); // webpack / Node\n * ```\n *\n * No-build / CDN consumers import it unconditionally from their dev page and\n * simply leave it out of the production page — there is no bundler to fold the\n * condition, and nothing for kerf to detect.\n *\n * ## Install ordering\n *\n * Every hook except one is read at CALL time (render, reconcile, `set()`,\n * `delegate()`), so installing any time before your first `mount()` is enough.\n *\n * The exception is `signalFactory`: `signal()` picks its constructor when the\n * signal is CREATED. Static imports are hoisted above a top-level\n * `await import()`, so module-scope signals in imported modules are created\n * before this module runs and the untracked-signal warning will not see them.\n * To cover those, make `import 'kerfjs/dev'` the FIRST STATIC import of a\n * dev-only entry file, then load the rest of your app.\n *\n * Opting into that warning prints this boundary once, so the gap is loud\n * rather than silent. It cannot be closed by retro-fitting existing signals:\n * `Signal.prototype`'s `value` accessor is non-configurable, and reaching live\n * instances would require a per-signal registry that production would pay for.\n *\n * Installation decides whether the diagnostics are PRESENT. Each opt-in\n * warner then reads its own switch through `devFlag()`: an `enableWarnings()`\n * override wins over the matching `KERF_DEV_WARN_*` environment variable.\n * The always-on hooks skip that second gate.\n *\n * @see docs/11-dev-warnings.md\n */\n\nimport { type Signal, signal as coreSignal } from '@preact/signals-core';\n\nimport { isOptedIn as staleBindingOptedIn, maybeWarnStaleBinding } from './dev-binding-warn.js';\nimport {\n enterEffect,\n exitEffect,\n isDevWarnDelegateInEffectEnabled,\n warnIfInsideEffect,\n} from './dev-delegate-warn.js';\nimport { maybeWarnDuplicateCacheKeys, maybeWarnEachInMorphSkip } from './dev-each-warn.js';\nimport { type DevHooks, installDevHooks } from './dev-hooks.js';\nimport { listInvariantsEnabled, maybeCheckListInvariants } from './dev-invariants.js';\nimport { isOptedInStaleIndex, maybeWarnStaleIndex } from './dev-list-index-warn.js';\nimport { maybeWarnListIdShift } from './dev-list-key-warn.js';\nimport { maybeWarnListRebind } from './dev-list-rebind-warn.js';\nimport { installListenerRebuildWarn } from './dev-listener-warn.js';\nimport { maybeWarnParserRepair } from './dev-parser-repair-warn.js';\nimport { maybeWarnValueOnlyRerender } from './dev-rerender-warn.js';\nimport { maybeWarnMissingRowKey } from './dev-row-key-warn.js';\nimport { DevSignal, isDevWarnUntrackedEnabled, noteUntrackedCoverage } from './dev-signal.js';\nimport { maybeWarnNarrowSet } from './dev-store-warn.js';\nimport { applyWarningOptions, type DevWarningOptions } from './dev-warn-config.js';\nimport { devReadonlyProxy, toRaw } from './utils/dev-readonly.js';\n\nexport { clearDevHooks, type DevHooks, devHooks, installDevHooks } from './dev-hooks.js';\nexport type { DevWarningOptions } from './dev-warn-config.js';\n\n/**\n * Switch individual diagnostics on:\n *\n * ```js\n * if (import.meta.env.DEV) {\n * const dev = await import('kerfjs/dev');\n * dev.enableWarnings({ staleBinding: true, narrowSet: true });\n * }\n * ```\n *\n * Installing this module makes the diagnostics PRESENT; this decides which are\n * SWITCHED ON, so the console isn't flooded by warnings you didn't ask for. The\n * `KERF_DEV_WARN_*` environment variables do the same thing for Node, SSR, and\n * CI; an explicit call here wins over the environment in both directions, so\n * `{ narrowSet: false }` silences an ambient var.\n *\n * **In a browser this function is the only switch that works.** A browser realm\n * has no `process` object, and a bundler `define` cannot reach the read (it\n * goes through `globalThis.process` into a local binding), so the environment\n * variables are unreachable there.\n *\n * Call it as early as you can. Every diagnostic reads its switch at call time\n * except the untracked-signal warning, which is chosen when a signal is\n * CREATED — enabling that one prints its coverage boundary once.\n */\nexport function enableWarnings(options: DevWarningOptions): void {\n applyWarningOptions(options);\n if (isDevWarnUntrackedEnabled()) noteUntrackedCoverage();\n}\n\n/**\n * The standard bundle of hooks this entry installs. Exported so kerf's own\n * suites can drop back to the production shape (`clearDevHooks()`) and restore\n * afterwards — re-importing this module would not re-run the install, since\n * module evaluation happens once.\n */\nexport const DEV_HOOKS: DevHooks = {\n // --- reactive ---------------------------------------------------------\n signalFactory: <T>(value: T): Signal<T> => (\n isDevWarnUntrackedEnabled() ? new DevSignal<T>(value) : coreSignal<T>(value)\n ),\n wrapEffect: (fn) => {\n // Resolved once per `effect()` call, matching the pre-hook behavior: an\n // effect created while the warning is off is never wrapped.\n if (!isDevWarnDelegateInEffectEnabled()) return fn;\n return () => {\n enterEffect();\n try {\n return fn();\n } finally {\n exitEffect();\n }\n };\n },\n\n // --- delegate ---------------------------------------------------------\n delegateInEffect: warnIfInsideEffect,\n\n // --- store ------------------------------------------------------------\n narrowSet: maybeWarnNarrowSet,\n storeReadonly: devReadonlyProxy,\n storeToRaw: toRaw,\n\n // --- mount ------------------------------------------------------------\n listenerRebuild: installListenerRebuildWarn,\n listIdShift: maybeWarnListIdShift,\n parserRepair: maybeWarnParserRepair,\n staleBindingEnabled: staleBindingOptedIn,\n staleBinding: maybeWarnStaleBinding,\n listInvariantsEnabled,\n listInvariants: maybeCheckListInvariants,\n valueOnlyRerender: maybeWarnValueOnlyRerender,\n listRebind: maybeWarnListRebind,\n eachInMorphSkip: maybeWarnEachInMorphSkip,\n missingRowKey: maybeWarnMissingRowKey,\n\n // --- each -------------------------------------------------------------\n staleIndexEnabled: isOptedInStaleIndex,\n staleIndex: maybeWarnStaleIndex,\n duplicateCacheKeys: maybeWarnDuplicateCacheKeys,\n\n // --- urlScreen --------------------------------------------------------\n urlScreenThrow: (message: string) => {\n throw new Error(message);\n },\n};\n\ninstallDevHooks(DEV_HOOKS);\n\n// `signal()` picks its constructor at CREATION time, so this one warning can\n// only see signals created after this module runs. Say so at install rather\n// than letting an author opt in and silently get nothing (see\n// `noteUntrackedCoverage` for why retro-fitting is impossible).\n//\n// The opted-in arm can't be exercised by the suite: this module evaluates\n// exactly once, at import, before any test can set the env var — and the\n// global test setup imports it. Both `isDevWarnUntrackedEnabled()` and\n// `noteUntrackedCoverage()` are directly unit-tested either side of this line\n// (tests/unit/dev-signal.internal.test.ts); only the one-time wiring between\n// them is unreachable from a test process.\n/* c8 ignore next -- install-time wiring; module evaluates once, before any test can opt in */\nif (isDevWarnUntrackedEnabled()) noteUntrackedCoverage();\n"]}
package/dist/html.d.ts CHANGED
@@ -25,7 +25,7 @@ import './bindings-CYwoJpQb.js';
25
25
  * Unlike JSX, NO camelCase attribute aliasing is applied — template authors
26
26
  * write real HTML attribute names (`class`, not `className`).
27
27
  *
28
- * Hole contract (enforced by the parser in `utils/templateParse.ts`): holes
28
+ * Hole contract (enforced by the parser in `utils/parseTemplate.ts`): holes
29
29
  * are allowed in text/child positions and as a COMPLETE attribute value
30
30
  * (`attr=${v}` or `attr="${v}"`). Tag-name holes, attribute-name holes,
31
31
  * partial attribute values (`class="a ${b}"`), and holes inside comments
package/dist/html.js CHANGED
@@ -1,9 +1,9 @@
1
- import { _toSegment, assertEmittableAttrName, bindAttr, _renderAttrVerbatim, SafeHtml, bindMarkerAttr } from './chunk-SUPUPSBE.js';
2
- import { isSignal } from './chunk-3APBEVHF.js';
1
+ import { _toSegment, assertEmittableAttrName, bindAttr, _renderAttrVerbatim, SafeHtml, bindMarkerAttr } from './chunk-ZDCJZCNO.js';
2
+ import { isSignal } from './chunk-U6FK33SG.js';
3
3
  import { mergeChildSegments } from './chunk-GY4XV2UV.js';
4
- import './chunk-VVDJLWMP.js';
5
4
 
6
- // src/utils/templateParse.ts
5
+
6
+ // src/utils/parseTemplate.ts
7
7
  var TEXT_HOLE = { kind: "text" };
8
8
  var ATTR_TAIL = /(\s*)([^\s"'<>/=]+)=(["'])?$/;
9
9
  function holeError(detail) {
@@ -154,5 +154,5 @@ function html(strings, ...values) {
154
154
  }
155
155
 
156
156
  export { _parseCount, html };
157
- //# sourceMappingURL=html.js.map
157
+
158
158
  //# sourceMappingURL=html.js.map