@llui/dom 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/binding-registry.d.ts +10 -0
  2. package/dist/binding-registry.d.ts.map +1 -0
  3. package/dist/binding-registry.js +96 -0
  4. package/dist/binding-registry.js.map +1 -0
  5. package/dist/binding.d.ts +22 -0
  6. package/dist/binding.d.ts.map +1 -1
  7. package/dist/binding.js +56 -5
  8. package/dist/binding.js.map +1 -1
  9. package/dist/build-flags.d.ts +25 -0
  10. package/dist/build-flags.d.ts.map +1 -0
  11. package/dist/build-flags.js +18 -0
  12. package/dist/build-flags.js.map +1 -0
  13. package/dist/el-split.d.ts.map +1 -1
  14. package/dist/el-split.js +8 -4
  15. package/dist/el-split.js.map +1 -1
  16. package/dist/el-template.d.ts.map +1 -1
  17. package/dist/el-template.js +15 -18
  18. package/dist/el-template.js.map +1 -1
  19. package/dist/elements.d.ts.map +1 -1
  20. package/dist/elements.js +12 -4
  21. package/dist/elements.js.map +1 -1
  22. package/dist/hmr.js +9 -4
  23. package/dist/hmr.js.map +1 -1
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal/test-component-builder.d.ts +21 -0
  29. package/dist/internal/test-component-builder.d.ts.map +1 -0
  30. package/dist/internal/test-component-builder.js +65 -0
  31. package/dist/internal/test-component-builder.js.map +1 -0
  32. package/dist/internal.d.ts +1 -0
  33. package/dist/internal.d.ts.map +1 -1
  34. package/dist/internal.js +1 -0
  35. package/dist/internal.js.map +1 -1
  36. package/dist/lifetime.d.ts.map +1 -1
  37. package/dist/lifetime.js +16 -3
  38. package/dist/lifetime.js.map +1 -1
  39. package/dist/mount.d.ts +1 -0
  40. package/dist/mount.d.ts.map +1 -1
  41. package/dist/mount.js +32 -22
  42. package/dist/mount.js.map +1 -1
  43. package/dist/primitives/branch.d.ts.map +1 -1
  44. package/dist/primitives/branch.js +29 -16
  45. package/dist/primitives/branch.js.map +1 -1
  46. package/dist/primitives/client-only.d.ts +1 -1
  47. package/dist/primitives/client-only.d.ts.map +1 -1
  48. package/dist/primitives/client-only.js +3 -3
  49. package/dist/primitives/client-only.js.map +1 -1
  50. package/dist/primitives/context.d.ts.map +1 -1
  51. package/dist/primitives/context.js +6 -3
  52. package/dist/primitives/context.js.map +1 -1
  53. package/dist/primitives/each.d.ts.map +1 -1
  54. package/dist/primitives/each.js +121 -74
  55. package/dist/primitives/each.js.map +1 -1
  56. package/dist/primitives/foreign.js +2 -1
  57. package/dist/primitives/foreign.js.map +1 -1
  58. package/dist/primitives/lazy.d.ts +1 -1
  59. package/dist/primitives/lazy.d.ts.map +1 -1
  60. package/dist/primitives/lazy.js +11 -5
  61. package/dist/primitives/lazy.js.map +1 -1
  62. package/dist/primitives/portal.js +2 -1
  63. package/dist/primitives/portal.js.map +1 -1
  64. package/dist/primitives/sample.d.ts.map +1 -1
  65. package/dist/primitives/sample.js +22 -16
  66. package/dist/primitives/sample.js.map +1 -1
  67. package/dist/primitives/track.d.ts +54 -0
  68. package/dist/primitives/track.d.ts.map +1 -0
  69. package/dist/primitives/track.js +54 -0
  70. package/dist/primitives/track.js.map +1 -0
  71. package/dist/primitives/virtual-each.js +4 -2
  72. package/dist/primitives/virtual-each.js.map +1 -1
  73. package/dist/render-context.d.ts +27 -1
  74. package/dist/render-context.d.ts.map +1 -1
  75. package/dist/render-context.js +82 -33
  76. package/dist/render-context.js.map +1 -1
  77. package/dist/ssr.d.ts.map +1 -1
  78. package/dist/ssr.js +5 -3
  79. package/dist/ssr.js.map +1 -1
  80. package/dist/types.d.ts +2 -2
  81. package/dist/types.d.ts.map +1 -1
  82. package/dist/types.js.map +1 -1
  83. package/dist/update-loop.d.ts +1 -0
  84. package/dist/update-loop.d.ts.map +1 -1
  85. package/dist/update-loop.js +115 -50
  86. package/dist/update-loop.js.map +1 -1
  87. package/package.json +1 -1
package/dist/lifetime.js CHANGED
@@ -83,7 +83,13 @@ export function disposeLifetime(scope, skipParentRemoval = false) {
83
83
  // is meant to capture every scope the app destroys, not only ones
84
84
  // that had attached work. Outer flag check keeps production (no
85
85
  // devtools ever installed) at true zero cost — no parent-chain walk.
86
- if (anyDisposerLogInstalled) {
86
+ // Dev-only — wrapped in `import.meta.env?.DEV` so the bundler dead-
87
+ // codes the whole block (including `findInstance` and the parent-
88
+ // chain walk) in production. `anyDisposerLogInstalled` is a static
89
+ // module-level flag never set to true in non-dev runs, so the
90
+ // dropped branch was already unreachable; this guard makes the
91
+ // unreachability bundler-visible.
92
+ if (import.meta.env?.DEV && anyDisposerLogInstalled) {
87
93
  const inst = findInstance(scope);
88
94
  if (inst?._disposerLog !== undefined) {
89
95
  inst._disposerLog.push({
@@ -113,7 +119,8 @@ export function disposeLifetime(scope, skipParentRemoval = false) {
113
119
  // Dev-only: emit disposer events into the owning instance's log.
114
120
  // Outer flag check keeps production (no devtools ever installed) at
115
121
  // true zero cost — skips the O(depth) parent-chain walk entirely.
116
- if (anyDisposerLogInstalled) {
122
+ // Dev-only — see disposeLifetime for rationale.
123
+ if (import.meta.env?.DEV && anyDisposerLogInstalled) {
117
124
  const inst = findInstance(scope);
118
125
  if (inst?._disposerLog !== undefined) {
119
126
  inst._disposerLog.push({
@@ -175,7 +182,13 @@ export function disposeLifetimesBulk(scopes) {
175
182
  for (let d = 0; d < disposers.length; d++)
176
183
  disposers[d]();
177
184
  // Dev-only: emit disposer events — same guard as disposeLifetime.
178
- if (anyDisposerLogInstalled) {
185
+ // Dev-only — wrapped in `import.meta.env?.DEV` so the bundler dead-
186
+ // codes the whole block (including `findInstance` and the parent-
187
+ // chain walk) in production. `anyDisposerLogInstalled` is a static
188
+ // module-level flag never set to true in non-dev runs, so the
189
+ // dropped branch was already unreachable; this guard makes the
190
+ // unreachability bundler-visible.
191
+ if (import.meta.env?.DEV && anyDisposerLogInstalled) {
179
192
  const inst = findInstance(scope);
180
193
  if (inst?._disposerLog !== undefined) {
181
194
  inst._disposerLog.push({
@@ -1 +1 @@
1
- {"version":3,"file":"lifetime.js","sourceRoot":"","sources":["../src/lifetime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Lifetime, Binding } from './types.js'\nimport type { ComponentInstance } from './update-loop.js'\n\nlet nextId = 1\n\n/**\n * Walk up the scope chain to find the owning ComponentInstance. The\n * instance is stamped onto the rootLifetime by `installDevTools`, so this\n * returns null in production (no devtools) or for scopes that haven't\n * yet been parented to a tracked root (e.g., during initial creation).\n */\nfunction findInstance(scope: Lifetime): ComponentInstance | null {\n let s: Lifetime | null = scope\n while (s) {\n if (s.instance) return s.instance\n s = s.parent\n }\n return null\n}\n\n// Shared empty arrays — avoid allocating per scope when unused\nconst EMPTY_LIFETIMES: Lifetime[] = []\nconst EMPTY_DISPOSERS: Array<() => void> = []\nconst EMPTY_BINDINGS: Binding[] = []\nconst EMPTY_UPDATERS: Array<() => void> = []\n\n// Lifetime pool — reuse disposed scope objects to reduce GC pressure.\n// Capped to avoid memory leaks in apps that create/destroy thousands of rows.\nconst SCOPE_POOL: Lifetime[] = []\nconst SCOPE_POOL_MAX = 2048\n\n// Dev-mode flag. Flipped to true by installDevTools() once any component\n// instance has a disposer log. In production this stays false forever,\n// and disposeLifetime skips findInstance entirely — zero cost.\nlet anyDisposerLogInstalled = false\n\n/** @internal — called by devtools.ts::installDevTools */\nexport function _markDisposerLogInstalled(): void {\n anyDisposerLogInstalled = true\n}\n\n/** @internal Drain the scope pool — for testing only */\nexport function _drainScopePool(): void {\n SCOPE_POOL.length = 0\n}\n\nexport function createLifetime(parent: Lifetime | null): Lifetime {\n let scope: Lifetime\n if (SCOPE_POOL.length > 0) {\n scope = SCOPE_POOL.pop()!\n scope.id = nextId++\n scope.parent = parent\n // Arrays already reset to empties by dispose. Reset dev-only hints\n // so recycled scopes don't carry stale tagging/back-refs. Cheap\n // (two undefined writes) and keeps production-identical behavior\n // when these fields are never set.\n scope.disposalCause = undefined\n scope.instance = undefined\n scope._kind = undefined\n } else {\n scope = {\n id: nextId++,\n parent,\n children: EMPTY_LIFETIMES,\n disposers: EMPTY_DISPOSERS,\n bindings: EMPTY_BINDINGS,\n itemUpdaters: EMPTY_UPDATERS,\n }\n }\n\n if (parent) {\n if (parent.children === EMPTY_LIFETIMES) parent.children = []\n parent.children.push(scope)\n }\n\n return scope\n}\n\n/**\n * Dispose a scope and all its children. By default, detaches the scope\n * from its parent's `children` array via `indexOf + splice` — O(N) per\n * call, which becomes O(N²) when disposing many sibling scopes in bulk\n * (e.g. `each` clearing 1000 rows).\n *\n * Pass `skipParentRemoval = true` when the caller will batch-remove\n * children afterwards (see `removeOrphanedFromParent`). The scope's\n * `parent` pointer is still set to `null` so the caller can identify\n * orphaned entries.\n */\nexport function disposeLifetime(scope: Lifetime, skipParentRemoval = false): void {\n if (scope.disposers.length === 0 && scope.children.length === 0 && scope.bindings.length === 0) {\n // Dev-only: still emit a DisposerEvent for empty scopes — the log\n // is meant to capture every scope the app destroys, not only ones\n // that had attached work. Outer flag check keeps production (no\n // devtools ever installed) at true zero cost — no parent-chain walk.\n if (anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n if (!skipParentRemoval) removeFromParent(scope)\n scope.parent = null\n // Don't pool empty scopes from the early-return path — they may be\n // disposed idempotently (twice), which would create pool duplicates\n return\n }\n\n // When skipParentRemoval is true, children don't mutate during disposal —\n // iterate directly without allocating a copy. Otherwise, clone to avoid\n // mutation during iteration.\n const children = skipParentRemoval ? scope.children : scope.children.slice()\n for (const child of children) {\n disposeLifetime(child, skipParentRemoval)\n }\n\n for (const disposer of scope.disposers) {\n disposer()\n }\n\n // Dev-only: emit disposer events into the owning instance's log.\n // Outer flag check keeps production (no devtools ever installed) at\n // true zero cost — skips the O(depth) parent-chain walk entirely.\n if (anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n\n // Mark bindings as dead and break closure/DOM retention\n for (const binding of scope.bindings) {\n binding.dead = true\n binding.accessor = null!\n binding.node = null!\n binding.lastValue = undefined\n }\n\n // Reset to shared empties — don't just truncate, so pooled scopes\n // don't hold allocated-but-empty arrays\n scope.disposers = EMPTY_DISPOSERS\n scope.bindings = EMPTY_BINDINGS\n scope.children = EMPTY_LIFETIMES\n scope.itemUpdaters = EMPTY_UPDATERS\n\n if (!skipParentRemoval) removeFromParent(scope)\n scope.parent = null\n\n // Return to pool for reuse\n if (SCOPE_POOL.length < SCOPE_POOL_MAX) SCOPE_POOL.push(scope)\n}\n\n/**\n * Batch-remove children with `parent === null` from `parent.children`.\n * Called after a bulk `disposeLifetime(child, true)` pass to collapse the\n * individual O(N) splice operations into one O(N) scan.\n */\nexport function removeOrphanedChildren(parent: Lifetime): void {\n const children = parent.children\n let w = 0\n for (let r = 0; r < children.length; r++) {\n if (children[r]!.parent !== null) children[w++] = children[r]!\n }\n children.length = w\n}\n\n/**\n * Bulk dispose an array of sibling scopes — avoids per-scope function call\n * overhead. Used by each() clear path where 1000+ scopes are disposed at once.\n * Caller must call removeOrphanedChildren(parent) afterwards.\n */\nexport function disposeLifetimesBulk(scopes: Lifetime[]): void {\n for (let i = 0; i < scopes.length; i++) {\n const scope = scopes[i]!\n // Recursively dispose children\n const children = scope.children\n if (children.length > 0) {\n disposeLifetimesBulk(children)\n }\n // Run disposers\n const disposers = scope.disposers\n for (let d = 0; d < disposers.length; d++) disposers[d]!()\n // Dev-only: emit disposer events — same guard as disposeLifetime.\n if (anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n // Mark bindings dead\n const bindings = scope.bindings\n for (let b = 0; b < bindings.length; b++) {\n const binding = bindings[b]!\n binding.dead = true\n binding.accessor = null!\n binding.node = null!\n binding.lastValue = undefined\n }\n // Reset to shared empties + detach from parent + return to pool\n scope.disposers = EMPTY_DISPOSERS\n scope.bindings = EMPTY_BINDINGS\n scope.children = EMPTY_LIFETIMES\n scope.itemUpdaters = EMPTY_UPDATERS\n scope.parent = null\n if (SCOPE_POOL.length < SCOPE_POOL_MAX) SCOPE_POOL.push(scope)\n }\n}\n\nexport function addBinding(scope: Lifetime, binding: Binding): void {\n binding.ownerLifetime = scope\n if (scope.bindings === EMPTY_BINDINGS) scope.bindings = []\n scope.bindings.push(binding)\n}\n\nexport function addItemUpdater(scope: Lifetime, updater: () => void): void {\n if (scope.itemUpdaters === EMPTY_UPDATERS) scope.itemUpdaters = []\n scope.itemUpdaters.push(updater)\n}\n\n/**\n * Register a per-item updater that compares the new value against the last\n * value before applying. Shared by `text()`, `elSplit()`, and `elTemplate()`\n * so the equality-check logic lives in one place.\n *\n * @param apply - DOM write: receives the new value when it differs\n * @returns the initial value (caller should apply it to the DOM)\n */\nexport function addCheckedItemUpdater<V>(\n scope: Lifetime,\n get: () => V,\n apply: (value: V) => void,\n): V {\n let last: V = get()\n addItemUpdater(scope, () => {\n const v = get()\n if (v === last || (v !== v && last !== last)) return\n last = v\n apply(v)\n })\n return last\n}\n\nexport function addDisposer(scope: Lifetime, disposer: () => void): void {\n if (scope.disposers === EMPTY_DISPOSERS) scope.disposers = []\n scope.disposers.push(disposer)\n}\n\nfunction removeFromParent(scope: Lifetime): void {\n if (scope.parent) {\n const idx = scope.parent.children.indexOf(scope)\n if (idx !== -1) {\n scope.parent.children.splice(idx, 1)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"lifetime.js","sourceRoot":"","sources":["../src/lifetime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Lifetime, Binding } from './types.js'\nimport type { ComponentInstance } from './update-loop.js'\n\nlet nextId = 1\n\n/**\n * Walk up the scope chain to find the owning ComponentInstance. The\n * instance is stamped onto the rootLifetime by `installDevTools`, so this\n * returns null in production (no devtools) or for scopes that haven't\n * yet been parented to a tracked root (e.g., during initial creation).\n */\nfunction findInstance(scope: Lifetime): ComponentInstance | null {\n let s: Lifetime | null = scope\n while (s) {\n if (s.instance) return s.instance\n s = s.parent\n }\n return null\n}\n\n// Shared empty arrays — avoid allocating per scope when unused\nconst EMPTY_LIFETIMES: Lifetime[] = []\nconst EMPTY_DISPOSERS: Array<() => void> = []\nconst EMPTY_BINDINGS: Binding[] = []\nconst EMPTY_UPDATERS: Array<() => void> = []\n\n// Lifetime pool — reuse disposed scope objects to reduce GC pressure.\n// Capped to avoid memory leaks in apps that create/destroy thousands of rows.\nconst SCOPE_POOL: Lifetime[] = []\nconst SCOPE_POOL_MAX = 2048\n\n// Dev-mode flag. Flipped to true by installDevTools() once any component\n// instance has a disposer log. In production this stays false forever,\n// and disposeLifetime skips findInstance entirely — zero cost.\nlet anyDisposerLogInstalled = false\n\n/** @internal — called by devtools.ts::installDevTools */\nexport function _markDisposerLogInstalled(): void {\n anyDisposerLogInstalled = true\n}\n\n/** @internal Drain the scope pool — for testing only */\nexport function _drainScopePool(): void {\n SCOPE_POOL.length = 0\n}\n\nexport function createLifetime(parent: Lifetime | null): Lifetime {\n let scope: Lifetime\n if (SCOPE_POOL.length > 0) {\n scope = SCOPE_POOL.pop()!\n scope.id = nextId++\n scope.parent = parent\n // Arrays already reset to empties by dispose. Reset dev-only hints\n // so recycled scopes don't carry stale tagging/back-refs. Cheap\n // (two undefined writes) and keeps production-identical behavior\n // when these fields are never set.\n scope.disposalCause = undefined\n scope.instance = undefined\n scope._kind = undefined\n } else {\n scope = {\n id: nextId++,\n parent,\n children: EMPTY_LIFETIMES,\n disposers: EMPTY_DISPOSERS,\n bindings: EMPTY_BINDINGS,\n itemUpdaters: EMPTY_UPDATERS,\n }\n }\n\n if (parent) {\n if (parent.children === EMPTY_LIFETIMES) parent.children = []\n parent.children.push(scope)\n }\n\n return scope\n}\n\n/**\n * Dispose a scope and all its children. By default, detaches the scope\n * from its parent's `children` array via `indexOf + splice` — O(N) per\n * call, which becomes O(N²) when disposing many sibling scopes in bulk\n * (e.g. `each` clearing 1000 rows).\n *\n * Pass `skipParentRemoval = true` when the caller will batch-remove\n * children afterwards (see `removeOrphanedFromParent`). The scope's\n * `parent` pointer is still set to `null` so the caller can identify\n * orphaned entries.\n */\nexport function disposeLifetime(scope: Lifetime, skipParentRemoval = false): void {\n if (scope.disposers.length === 0 && scope.children.length === 0 && scope.bindings.length === 0) {\n // Dev-only: still emit a DisposerEvent for empty scopes — the log\n // is meant to capture every scope the app destroys, not only ones\n // that had attached work. Outer flag check keeps production (no\n // devtools ever installed) at true zero cost — no parent-chain walk.\n // Dev-only — wrapped in `import.meta.env?.DEV` so the bundler dead-\n // codes the whole block (including `findInstance` and the parent-\n // chain walk) in production. `anyDisposerLogInstalled` is a static\n // module-level flag never set to true in non-dev runs, so the\n // dropped branch was already unreachable; this guard makes the\n // unreachability bundler-visible.\n if (import.meta.env?.DEV && anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n if (!skipParentRemoval) removeFromParent(scope)\n scope.parent = null\n // Don't pool empty scopes from the early-return path — they may be\n // disposed idempotently (twice), which would create pool duplicates\n return\n }\n\n // When skipParentRemoval is true, children don't mutate during disposal —\n // iterate directly without allocating a copy. Otherwise, clone to avoid\n // mutation during iteration.\n const children = skipParentRemoval ? scope.children : scope.children.slice()\n for (const child of children) {\n disposeLifetime(child, skipParentRemoval)\n }\n\n for (const disposer of scope.disposers) {\n disposer()\n }\n\n // Dev-only: emit disposer events into the owning instance's log.\n // Outer flag check keeps production (no devtools ever installed) at\n // true zero cost — skips the O(depth) parent-chain walk entirely.\n // Dev-only — see disposeLifetime for rationale.\n if (import.meta.env?.DEV && anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n\n // Mark bindings as dead and break closure/DOM retention\n for (const binding of scope.bindings) {\n binding.dead = true\n binding.accessor = null!\n binding.node = null!\n binding.lastValue = undefined\n }\n\n // Reset to shared empties — don't just truncate, so pooled scopes\n // don't hold allocated-but-empty arrays\n scope.disposers = EMPTY_DISPOSERS\n scope.bindings = EMPTY_BINDINGS\n scope.children = EMPTY_LIFETIMES\n scope.itemUpdaters = EMPTY_UPDATERS\n\n if (!skipParentRemoval) removeFromParent(scope)\n scope.parent = null\n\n // Return to pool for reuse\n if (SCOPE_POOL.length < SCOPE_POOL_MAX) SCOPE_POOL.push(scope)\n}\n\n/**\n * Batch-remove children with `parent === null` from `parent.children`.\n * Called after a bulk `disposeLifetime(child, true)` pass to collapse the\n * individual O(N) splice operations into one O(N) scan.\n */\nexport function removeOrphanedChildren(parent: Lifetime): void {\n const children = parent.children\n let w = 0\n for (let r = 0; r < children.length; r++) {\n if (children[r]!.parent !== null) children[w++] = children[r]!\n }\n children.length = w\n}\n\n/**\n * Bulk dispose an array of sibling scopes — avoids per-scope function call\n * overhead. Used by each() clear path where 1000+ scopes are disposed at once.\n * Caller must call removeOrphanedChildren(parent) afterwards.\n */\nexport function disposeLifetimesBulk(scopes: Lifetime[]): void {\n for (let i = 0; i < scopes.length; i++) {\n const scope = scopes[i]!\n // Recursively dispose children\n const children = scope.children\n if (children.length > 0) {\n disposeLifetimesBulk(children)\n }\n // Run disposers\n const disposers = scope.disposers\n for (let d = 0; d < disposers.length; d++) disposers[d]!()\n // Dev-only: emit disposer events — same guard as disposeLifetime.\n // Dev-only — wrapped in `import.meta.env?.DEV` so the bundler dead-\n // codes the whole block (including `findInstance` and the parent-\n // chain walk) in production. `anyDisposerLogInstalled` is a static\n // module-level flag never set to true in non-dev runs, so the\n // dropped branch was already unreachable; this guard makes the\n // unreachability bundler-visible.\n if (import.meta.env?.DEV && anyDisposerLogInstalled) {\n const inst = findInstance(scope)\n if (inst?._disposerLog !== undefined) {\n inst._disposerLog.push({\n scopeId: String(scope.id),\n cause: scope.disposalCause ?? 'component-unmount',\n timestamp: Date.now(),\n })\n }\n }\n // Mark bindings dead\n const bindings = scope.bindings\n for (let b = 0; b < bindings.length; b++) {\n const binding = bindings[b]!\n binding.dead = true\n binding.accessor = null!\n binding.node = null!\n binding.lastValue = undefined\n }\n // Reset to shared empties + detach from parent + return to pool\n scope.disposers = EMPTY_DISPOSERS\n scope.bindings = EMPTY_BINDINGS\n scope.children = EMPTY_LIFETIMES\n scope.itemUpdaters = EMPTY_UPDATERS\n scope.parent = null\n if (SCOPE_POOL.length < SCOPE_POOL_MAX) SCOPE_POOL.push(scope)\n }\n}\n\nexport function addBinding(scope: Lifetime, binding: Binding): void {\n binding.ownerLifetime = scope\n if (scope.bindings === EMPTY_BINDINGS) scope.bindings = []\n scope.bindings.push(binding)\n}\n\nexport function addItemUpdater(scope: Lifetime, updater: () => void): void {\n if (scope.itemUpdaters === EMPTY_UPDATERS) scope.itemUpdaters = []\n scope.itemUpdaters.push(updater)\n}\n\n/**\n * Register a per-item updater that compares the new value against the last\n * value before applying. Shared by `text()`, `elSplit()`, and `elTemplate()`\n * so the equality-check logic lives in one place.\n *\n * @param apply - DOM write: receives the new value when it differs\n * @returns the initial value (caller should apply it to the DOM)\n */\nexport function addCheckedItemUpdater<V>(\n scope: Lifetime,\n get: () => V,\n apply: (value: V) => void,\n): V {\n let last: V = get()\n addItemUpdater(scope, () => {\n const v = get()\n if (v === last || (v !== v && last !== last)) return\n last = v\n apply(v)\n })\n return last\n}\n\nexport function addDisposer(scope: Lifetime, disposer: () => void): void {\n if (scope.disposers === EMPTY_DISPOSERS) scope.disposers = []\n scope.disposers.push(disposer)\n}\n\nfunction removeFromParent(scope: Lifetime): void {\n if (scope.parent) {\n const idx = scope.parent.children.indexOf(scope)\n if (idx !== -1) {\n scope.parent.children.splice(idx, 1)\n }\n }\n}\n"]}
package/dist/mount.d.ts CHANGED
@@ -4,6 +4,7 @@ declare global {
4
4
  interface ImportMeta {
5
5
  env?: {
6
6
  DEV?: boolean;
7
+ MODE?: string;
7
8
  };
8
9
  }
9
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,KAAK,MAAM,EAAc,MAAM,cAAc,CAAA;AA4CtD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KACxB;CACF;AAoCD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAA;IACzB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAClC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAyIZ;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACtC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAmGZ;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC/C,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAkFX;AA2JD,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC1C,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CA2FX"}
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,KAAK,MAAM,EAAc,MAAM,cAAc,CAAA;AA6CtD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,OAAO,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KACvC;CACF;AAoCD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAA;IACzB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAClC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC9B,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AA2IZ;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACnC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AACZ,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACtC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAAA;AAqGZ;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC/C,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAoFX;AAmKD,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAC1C,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC7B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CA6FX"}
package/dist/mount.js CHANGED
@@ -5,7 +5,7 @@ import { setRenderContext, clearRenderContext } from './render-context.js';
5
5
  import { setFlatBindings } from './binding.js';
6
6
  import { getBindingDescriptors } from './binding-descriptors.js';
7
7
  import { registerInstance, unregisterInstance } from './runtime.js';
8
- import { createView } from './view-helpers.js';
8
+ import { getInstanceViewBag } from './render-context.js';
9
9
  import { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js';
10
10
  // ── Sentinel-region helpers (used by anchor-based mount primitives) ─────
11
11
  /**
@@ -78,14 +78,14 @@ export function mountApp(container, def, data, options) {
78
78
  // handle, which in a layout setup means the layout re-mounts at the
79
79
  // root and the rest of the chain is re-established via the normal
80
80
  // mount path.
81
- if (hmrModule && def.name && !options?.parentLifetime) {
81
+ if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {
82
82
  const swapped = hmrModule.replaceComponentForContainer(def.name, def, container);
83
83
  if (swapped)
84
84
  return swapped;
85
85
  }
86
86
  const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env);
87
87
  // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import
88
- if (devToolsInstall)
88
+ if (import.meta.env?.DEV && devToolsInstall)
89
89
  devToolsInstall(inst);
90
90
  // Dev-only: warn if initial state contains non-serializable values.
91
91
  // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.
@@ -109,7 +109,7 @@ export function mountApp(container, def, data, options) {
109
109
  send: inst.send,
110
110
  instance: inst,
111
111
  });
112
- const nodes = def.view(createView(inst.send));
112
+ const nodes = def.view(getInstanceViewBag(inst, inst.send));
113
113
  clearRenderContext();
114
114
  setFlatBindings(null);
115
115
  popMountQueue(prevMountQueue);
@@ -130,7 +130,7 @@ export function mountApp(container, def, data, options) {
130
130
  // against a fully-wired tree.
131
131
  flushMountQueue(onMountQueue);
132
132
  registerInstance(inst);
133
- if (hmrModule && def.name) {
133
+ if (import.meta.env?.DEV && hmrModule && def.name) {
134
134
  hmrModule.registerForHmr(def.name, inst, container);
135
135
  }
136
136
  dispatchInitialEffects(inst);
@@ -202,7 +202,7 @@ export function mountAtAnchor(anchor, def, data, options) {
202
202
  // Without this, the existing end sentinel below would be reused but
203
203
  // the prior instance would be fully orphaned (lifetime not disposed,
204
204
  // HMR entry not unregistered, activeInstances entry not removed).
205
- if (hmrModule && def.name && !options?.parentLifetime) {
205
+ if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {
206
206
  const swapped = hmrModule.replaceComponentForAnchor(def.name, def, anchor);
207
207
  if (swapped)
208
208
  return swapped;
@@ -227,7 +227,7 @@ export function mountAtAnchor(anchor, def, data, options) {
227
227
  anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling);
228
228
  }
229
229
  const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env);
230
- if (devToolsInstall)
230
+ if (import.meta.env?.DEV && devToolsInstall)
231
231
  devToolsInstall(inst);
232
232
  if (import.meta.env?.DEV) {
233
233
  const offender = findNonSerializable(inst.state);
@@ -245,7 +245,7 @@ export function mountAtAnchor(anchor, def, data, options) {
245
245
  send: inst.send,
246
246
  instance: inst,
247
247
  });
248
- const nodes = def.view(createView(inst.send));
248
+ const nodes = def.view(getInstanceViewBag(inst, inst.send));
249
249
  clearRenderContext();
250
250
  setFlatBindings(null);
251
251
  popMountQueue(prevMountQueue);
@@ -261,7 +261,7 @@ export function mountAtAnchor(anchor, def, data, options) {
261
261
  }
262
262
  flushMountQueue(onMountQueue);
263
263
  registerInstance(inst);
264
- if (hmrModule && def.name) {
264
+ if (import.meta.env?.DEV && hmrModule && def.name) {
265
265
  hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel);
266
266
  }
267
267
  dispatchInitialEffects(inst);
@@ -292,7 +292,7 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
292
292
  // (typical of HMR module re-execution) hot-swaps in place. Matches
293
293
  // mountAtAnchor's behavior. Without this, the second call leaks the
294
294
  // first instance and stacks a second HMR entry under the same name.
295
- if (hmrModule && def.name && !options?.parentLifetime) {
295
+ if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {
296
296
  const swapped = hmrModule.replaceComponentForAnchor(def.name, def, anchor);
297
297
  if (swapped)
298
298
  return swapped;
@@ -314,7 +314,7 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
314
314
  init: () => [serverState, originalEffects],
315
315
  };
316
316
  const inst = createComponentInstance(hydrateDef, undefined, options?.parentLifetime ?? null, options?.env);
317
- if (devToolsInstall)
317
+ if (import.meta.env?.DEV && devToolsInstall)
318
318
  devToolsInstall(inst);
319
319
  const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue();
320
320
  setFlatBindings(inst.allBindings);
@@ -324,7 +324,7 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
324
324
  send: inst.send,
325
325
  instance: inst,
326
326
  });
327
- const nodes = hydrateDef.view(createView(inst.send));
327
+ const nodes = hydrateDef.view(getInstanceViewBag(inst, inst.send));
328
328
  clearRenderContext();
329
329
  setFlatBindings(null);
330
330
  popMountQueue(prevMountQueue);
@@ -339,7 +339,7 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
339
339
  }
340
340
  flushMountQueue(onMountQueue);
341
341
  registerInstance(inst);
342
- if (hmrModule && def.name) {
342
+ if (import.meta.env?.DEV && hmrModule && def.name) {
343
343
  hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel);
344
344
  }
345
345
  // Hydration: skip init's effects by default. The SSR pass already ran
@@ -426,13 +426,14 @@ function buildAppHandle(inst, hmrName, domCleanup) {
426
426
  disposed = true;
427
427
  listeners.clear();
428
428
  inst._onCommit = undefined;
429
- if (hmrModule && hmrName)
429
+ if (import.meta.env?.DEV && hmrModule && hmrName)
430
430
  hmrModule.unregisterForHmr(hmrName, inst);
431
431
  inst.abortController.abort();
432
432
  unregisterInstance(inst);
433
433
  // Tag the root scope so the disposer log reports app-level
434
434
  // teardown distinct from in-tree component-unmount events.
435
- inst.rootLifetime.disposalCause = 'app-unmount';
435
+ if (import.meta.env?.DEV)
436
+ inst.rootLifetime.disposalCause = 'app-unmount';
436
437
  disposeLifetime(inst.rootLifetime);
437
438
  domCleanup();
438
439
  },
@@ -448,9 +449,12 @@ function buildAppHandle(inst, hmrName, domCleanup) {
448
449
  },
449
450
  getState() {
450
451
  if (disposed) {
451
- throw new Error('[LLui] AppHandle.getState() called after dispose — handle is dead. ' +
452
- 'Detach your event listener / cancel your timer when the handle ' +
453
- 'is disposed to avoid stale reads.');
452
+ if (import.meta.env?.DEV) {
453
+ throw new Error('[LLui] AppHandle.getState() called after dispose handle is dead. ' +
454
+ 'Detach your event listener / cancel your timer when the handle ' +
455
+ 'is disposed to avoid stale reads.');
456
+ }
457
+ throw new Error('[LLui] AppHandle.getState() after dispose');
454
458
  }
455
459
  return inst.state;
456
460
  },
@@ -461,6 +465,12 @@ function buildAppHandle(inst, hmrName, domCleanup) {
461
465
  return () => listeners.delete(listener);
462
466
  },
463
467
  getBindingDescriptors() {
468
+ // Agent-only — returns an empty array when the build-time flag is
469
+ // off so callers get a consistent shape. The body's `getBindingDescriptors`
470
+ // import becomes dead-code-eliminable along with the rest of
471
+ // `binding-descriptors.ts`.
472
+ if (typeof __LLUI_AGENT__ === 'undefined' || !__LLUI_AGENT__)
473
+ return [];
464
474
  if (disposed)
465
475
  return [];
466
476
  return getBindingDescriptors(inst);
@@ -507,7 +517,7 @@ export function hydrateApp(container, def, serverState, options) {
507
517
  // semantics as mountApp's fast path: the live instance keeps its
508
518
  // current state and the new def's `serverState` argument is
509
519
  // intentionally ignored on the swap (HMR preserves user state).
510
- if (hmrModule && def.name && !options?.parentLifetime) {
520
+ if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {
511
521
  const swapped = hmrModule.replaceComponentForContainer(def.name, def, container);
512
522
  if (swapped)
513
523
  return swapped;
@@ -533,7 +543,7 @@ export function hydrateApp(container, def, serverState, options) {
533
543
  // `window.__lluiDebug`, and is invisible to MCP / agent client /
534
544
  // devtools console — so a vike SSR app's outermost layout silently
535
545
  // drops out of every observability surface.
536
- if (devToolsInstall)
546
+ if (import.meta.env?.DEV && devToolsInstall)
537
547
  devToolsInstall(inst);
538
548
  // Build the component DOM and swap atomically with server HTML.
539
549
  // Server HTML remains visible until JS finishes — no flash.
@@ -547,7 +557,7 @@ export function hydrateApp(container, def, serverState, options) {
547
557
  send: inst.send,
548
558
  instance: inst,
549
559
  });
550
- const nodes = hydrateDef.view(createView(inst.send));
560
+ const nodes = hydrateDef.view(getInstanceViewBag(inst, inst.send));
551
561
  clearRenderContext();
552
562
  setFlatBindings(null);
553
563
  popMountQueue(prevMountQueue);
@@ -572,7 +582,7 @@ export function hydrateApp(container, def, serverState, options) {
572
582
  // hydrateAtAnchor. Without it, replaceComponent(name, newDef)
573
583
  // silently no-ops on the hydrated layout layer because the HMR
574
584
  // registry has no entry for it.
575
- if (hmrModule && hydrateDef.name) {
585
+ if (import.meta.env?.DEV && hmrModule && hydrateDef.name) {
576
586
  hmrModule.registerForHmr(hydrateDef.name, inst, container);
577
587
  }
578
588
  return buildAppHandle(inst, hydrateDef.name ?? null, () => {
package/dist/mount.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,UAAU,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAA0B,MAAM,kBAAkB,CAAA;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAEzF,2EAA2E;AAE3E;;;;GAIG;AACH,SAAS,cAAc,CAAC,MAAe,EAAE,UAAmB;IAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;IAChC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAM;IAC3B,OAAO,MAAM,CAAC,WAAW,KAAK,IAAI,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACxE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,MAAe;IACvC,IAAI,IAAI,GAAgB,MAAM,CAAC,WAAW,CAAA;IAC1C,OAAO,IAAI,KAAK,IAAI,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,IAAK,IAAgB,CAAC,SAAS,KAAK,gBAAgB,EAAE,CAAC;YAC5E,OAAO,IAAe,CAAA;QACxB,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AASD,mEAAmE;AACnE,0EAA0E;AAE1E,IAAI,SAAS,GAAkC,IAAI,CAAA;AAEnD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,CAAgC;IAC5D,SAAS,GAAG,CAAC,CAAA;AACf,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,mEAAmE;AACnE,oFAAoF;AAEpF,IAAI,eAAe,GAAoC,IAAI,CAAA;AAE3D,gEAAgE;AAChE,MAAM,UAAU,mBAAmB,CAAC,EAAmC;IACrE,eAAe,GAAG,EAAE,CAAA;AACtB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,mBAAmB;IACjC,OAAO,eAAe,CAAA;AACxB,CAAC;AA4DD,MAAM,UAAU,QAAQ,CACtB,SAAsB,EACtB,GAA6B,EAC7B,IAAQ,EACR,OAAsB;IAEtB,6DAA6D;IAC7D,oEAAoE;IACpE,qEAAqE;IACrE,oEAAoE;IACpE,+DAA+D;IAC/D,gEAAgE;IAChE,+DAA+D;IAC/D,+CAA+C;IAC/C,EAAE;IACF,qEAAqE;IACrE,oEAAoE;IACpE,kEAAkE;IAClE,cAAc;IACd,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,SAAS,CAAC,4BAA4B,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;QAChF,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;IAC7B,CAAC;IAED,MAAM,IAAI,GAAG,uBAAuB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,IAAI,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAE9F,6EAA6E;IAC7E,IAAI,eAAe;QAAE,eAAe,CAAC,IAAI,CAAC,CAAA;IAE1C,oEAAoE;IACpE,oFAAoF;IACpF,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChD,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CACV,WAAW,GAAG,CAAC,IAAI,yDAAyD,QAAQ,CAAC,IAAI,IAAI,EAC7F,QAAQ,CAAC,KAAK,EACd,yEAAyE;gBACvE,wEAAwE;gBACxE,2FAA2F,CAC9F,CAAA;QACH,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,sEAAsE;IACtE,oEAAoE;IACpE,yDAAyD;IACzD,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAAA;IACtE,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACjC,gBAAgB,CAAC;QACf,GAAG,IAAI;QACP,SAAS;QACT,IAAI,EAAE,IAAI,CAAC,IAA8B;QACzC,QAAQ,EAAE,IAAyB;KACpC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACnD,kBAAkB,EAAE,CAAA;IACpB,eAAe,CAAC,IAAI,CAAC,CAAA;IACrB,aAAa,CAAC,cAAc,CAAC,CAAA;IAE7B,wEAAwE;IACxE,yEAAyE;IACzE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAA;QAC9C,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QAChD,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAA;IAClC,CAAC;IAED,sEAAsE;IACtE,oEAAoE;IACpE,iEAAiE;IACjE,8BAA8B;IAC9B,eAAe,CAAC,YAAY,CAAC,CAAA;IAE7B,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACtB,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;IACrD,CAAC;IACD,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,EAAE;QACjD,SAAS,CAAC,WAAW,GAAG,EAAE,CAAA;IAC5B,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,8EAA8E;AAC9E,8EAA8E;AAC9E,kDAAkD;AAClD,SAAS,mBAAmB,CAC1B,CAAU,EACV,IAAI,GAAG,OAAO,EACd,KAAK,GAAG,CAAC,EACT,OAAO,IAAI,OAAO,EAAU;IAE5B,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAC1B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,CAAA;IAClB,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACpE,IAAI,CAAC,KAAK,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAC/C,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAC/D,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC/B,MAAM,GAAG,GAAG,CAAW,CAAA;IACvB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACb,IAAI,GAAG,YAAY,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IACpE,IAAI,GAAG,YAAY,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAClE,IAAI,GAAG,YAAY,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAClE,IAAI,GAAG,YAAY,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IACxE,IAAI,GAAG,YAAY,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAC1E,gFAAgF;IAChF,8BAA8B;IAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;QAC9E,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,KAAK,KAAK,EAAE,WAAW,EAAE,IAAI,IAAI,gBAAgB,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IACxF,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;YACrE,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAA;QACjB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,mBAAmB,CAC1B,GAA+B,CAAC,CAAC,CAAC,EACnC,GAAG,IAAI,IAAI,CAAC,EAAE,EACd,KAAK,GAAG,CAAC,EACT,IAAI,CACL,CAAA;QACD,IAAI,CAAC;YAAE,OAAO,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AA8BD,MAAM,UAAU,aAAa,CAC3B,MAAe,EACf,GAA6B,EAC7B,IAAQ,EACR,OAAsB;IAEtB,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAA;IACH,CAAC;IAED,gEAAgE;IAChE,mEAAmE;IACnE,mEAAmE;IACnE,mEAAmE;IACnE,kEAAkE;IAClE,oEAAoE;IACpE,qEAAqE;IACrE,kEAAkE;IAClE,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,SAAS,CAAC,yBAAyB,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QAC1E,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;IAC7B,CAAC;IAED,yCAAyC;IACzC,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,WAAoB,CAAA;IACxB,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CACV,gEAAgE;gBAC9D,oFAAoF,CACvF,CAAA;QACH,CAAC;QACD,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;QACnC,WAAW,GAAG,WAAW,CAAA;IAC3B,CAAC;SAAM,CAAC;QACN,qEAAqE;QACrE,kEAAkE;QAClE,mEAAmE;QACnE,4CAA4C;QAC5C,WAAW,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAA;QAC5E,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IACjE,CAAC;IAED,MAAM,IAAI,GAAG,uBAAuB,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,IAAI,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAE9F,IAAI,eAAe;QAAE,eAAe,CAAC,IAAI,CAAC,CAAA;IAE1C,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChD,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CACV,WAAW,GAAG,CAAC,IAAI,yDAAyD,QAAQ,CAAC,IAAI,IAAI,EAC7F,QAAQ,CAAC,KAAK,EACd,yEAAyE;gBACvE,wEAAwE;gBACxE,2FAA2F,CAC9F,CAAA;QACH,CAAC;IACH,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAAA;IACtE,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACjC,gBAAgB,CAAC;QACf,GAAG,IAAI;QACP,SAAS,EAAE,MAAM,CAAC,aAAa,IAAI,SAAS;QAC5C,IAAI,EAAE,IAAI,CAAC,IAA8B;QACzC,QAAQ,EAAE,IAAyB;KACpC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACnD,kBAAkB,EAAE,CAAA;IACpB,eAAe,CAAC,IAAI,CAAC,CAAA;IACrB,aAAa,CAAC,cAAc,CAAC,CAAA;IAE7B,oEAAoE;IACpE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAA;QAC9C,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QAChD,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IACnD,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,WAAW,CAAC,CAAA;IACxD,CAAC;IAED,eAAe,CAAC,YAAY,CAAC,CAAA;IAE7B,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACtB,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;IAClE,CAAC;IACD,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,EAAE;QACjD,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;QACnC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAe,EACf,GAA6B,EAC7B,WAAc,EACd,OAAsB;IAEtB,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,2FAA2F,CAC5F,CAAA;IACH,CAAC;IAED,6DAA6D;IAC7D,mEAAmE;IACnE,oEAAoE;IACpE,oEAAoE;IACpE,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,SAAS,CAAC,yBAAyB,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QAC1E,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;IAC7B,CAAC;IAED,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,WAAoB,CAAA;IACxB,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;QACnC,WAAW,GAAG,WAAW,CAAA;IAC3B,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAA;QAC5E,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IACjE,CAAC;IAED,6EAA6E;IAC7E,MAAM,CAAC,EAAE,eAAe,CAAC,GAAI,GAAG,CAAC,IAAoC,CAAC,SAAS,CAAC,CAAA;IAChF,MAAM,UAAU,GAA0B;QACxC,GAAG,GAAG;QACN,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC;KAC3C,CAAA;IAED,MAAM,IAAI,GAAG,uBAAuB,CAClC,UAAU,EACV,SAAS,EACT,OAAO,EAAE,cAAc,IAAI,IAAI,EAC/B,OAAO,EAAE,GAAG,CACb,CAAA;IAED,IAAI,eAAe;QAAE,eAAe,CAAC,IAAI,CAAC,CAAA;IAE1C,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAAA;IACtE,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACjC,gBAAgB,CAAC;QACf,GAAG,IAAI;QACP,SAAS,EAAE,MAAM,CAAC,aAAa,IAAI,SAAS;QAC5C,IAAI,EAAE,IAAI,CAAC,IAA8B;QACzC,QAAQ,EAAE,IAAyB;KACpC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,kBAAkB,EAAE,CAAA;IACpB,eAAe,CAAC,IAAI,CAAC,CAAA;IACrB,aAAa,CAAC,cAAc,CAAC,CAAA;IAE7B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAA;QAC9C,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QAChD,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IACnD,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,WAAW,CAAC,CAAA;IACxD,CAAC;IAED,eAAe,CAAC,YAAY,CAAC,CAAA;IAE7B,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACtB,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;IAClE,CAAC;IACD,sEAAsE;IACtE,kEAAkE;IAClE,qEAAqE;IACrE,oDAAoD;IACpD,IAAI,OAAO,EAAE,uBAAuB,EAAE,CAAC;QACrC,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;SAAM,CAAC;QACN,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAA;IACjD,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,EAAE;QACjD,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;QACnC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAyD;IAEzD,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAM;IAClE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IACrE,CAAC;IACD,IAAI,CAAC,cAAc,GAAG,EAAE,CAAA;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,sBAAsB,CAC7B,IAAyD,EACzD,GAAqC;IAErC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG;QAAE,OAAM;IACjC,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,aAAa,CAAA;IAC3C,OAAO,CAAC,IAAI,CACV,UAAU,GAAG,aAAa,IAAI,CAAC,cAAc,CAAC,MAAM,wBAAwB,IAAI,KAAK;QACnF,6EAA6E;QAC7E,6FAA6F,CAChG,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAS,cAAc,CACrB,IAAyD,EACzD,OAAsB,EACtB,UAAsB;IAEtB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAA;IAEjD,IAAI,CAAC,SAAS,GAAG,CAAC,KAAc,EAAE,EAAE;QAClC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,CAAC,CAAC,KAAK,CAAC,CAAA;YACV,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAA;YAC9C,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,OAAO;QACL,OAAO;YACL,IAAI,QAAQ;gBAAE,OAAM;YACpB,QAAQ,GAAG,IAAI,CAAA;YACf,SAAS,CAAC,KAAK,EAAE,CAAA;YACjB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;YAC1B,IAAI,SAAS,IAAI,OAAO;gBAAE,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACnE,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAA;YAC5B,kBAAkB,CAAC,IAAI,CAAC,CAAA;YACxB,2DAA2D;YAC3D,2DAA2D;YAC3D,IAAI,CAAC,YAAY,CAAC,aAAa,GAAG,aAAa,CAAA;YAC/C,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YAClC,UAAU,EAAE,CAAA;QACd,CAAC;QACD,KAAK;YACH,IAAI,QAAQ;gBAAE,OAAM;YACpB,aAAa,CAAC,IAAI,CAAC,CAAA;QACrB,CAAC;QACD,IAAI,CAAC,GAAY;YACf,IAAI,QAAQ;gBAAE,OACb;YAAC,IAAI,CAAC,IAA6B,CAAC,GAAG,CAAC,CAAA;QAC3C,CAAC;QACD,QAAQ;YACN,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,qEAAqE;oBACnE,iEAAiE;oBACjE,mCAAmC,CACtC,CAAA;YACH,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAA;QACnB,CAAC;QACD,SAAS,CAAC,QAAkC;YAC1C,IAAI,QAAQ;gBAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;YAC7B,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACvB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACzC,CAAC;QACD,qBAAqB;YACnB,IAAI,QAAQ;gBAAE,OAAO,EAAE,CAAA;YACvB,OAAO,qBAAqB,CAAC,IAAyB,CAAC,CAAA;QACzD,CAAC;QACD,UAAU,CAAC,SAAS,EAAE,WAAW;YAC/B,IAAI,QAAQ;gBAAE,OAAM;YACpB,8DAA8D;YAC9D,+DAA+D;YAC/D,+DAA+D;YAC/D,8DAA8D;YAC9D,2CAA2C;YAC3C,aAAa,CAAC,IAAI,CAAC,CAOlB;YAAC,IAAI,CAAC,GAAoC,CAAC,MAAM,GAAG,SAAS,CAAA;YAC9D,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC9B,CAAC;gBAAC,IAAI,CAAC,GAAyC,CAAC,QAAQ,GAAG,WAAW,CAAA;YACzE,CAAC;QACH,CAAC;QACD,UAAU,CAAC,GAAG;YACZ,IAAI,QAAQ;gBAAE,OAAO,IAAI,CAAA;YACzB,4DAA4D;YAC5D,8DAA8D;YAC9D,6DAA6D;YAC7D,wDAAwD;YACxD,iEAAiE;YACjE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GACpB,IAAI,CAAC,GAAG,CAAC,MACV,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAClB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAoB,EAAE,CAAA;QACjD,CAAC;QACD,iBAAiB,CAAC,IAAI;YACpB,IAAI,QAAQ;gBAAE,OAAM;YACpB,IAAI,CAAC,eAAe,GAAG,IAAI,IAAI,SAAS,CAAA;QAC1C,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,SAAsB,EACtB,GAA6B,EAC7B,WAAc,EACd,OAAsB;IAEtB,6DAA6D;IAC7D,mEAAmE;IACnE,mEAAmE;IACnE,oEAAoE;IACpE,oEAAoE;IACpE,iEAAiE;IACjE,4DAA4D;IAC5D,gEAAgE;IAChE,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;QACtD,MAAM,OAAO,GAAG,SAAS,CAAC,4BAA4B,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;QAChF,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;IAC7B,CAAC;IAED,kEAAkE;IAClE,+DAA+D;IAC/D,mEAAmE;IACnE,mEAAmE;IACnE,oEAAoE;IACpE,iEAAiE;IACjE,oEAAoE;IACpE,mDAAmD;IACnD,MAAM,CAAC,EAAE,eAAe,CAAC,GAAI,GAAG,CAAC,IAAoC,CAAC,SAAS,CAAC,CAAA;IAEhF,MAAM,UAAU,GAA0B;QACxC,GAAG,GAAG;QACN,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC;KAC3C,CAAA;IAED,MAAM,IAAI,GAAG,uBAAuB,CAClC,UAAU,EACV,SAAS,EACT,OAAO,EAAE,cAAc,IAAI,IAAI,EAC/B,OAAO,EAAE,GAAG,CACb,CAAA;IAED,sEAAsE;IACtE,kEAAkE;IAClE,kEAAkE;IAClE,yDAAyD;IACzD,iEAAiE;IACjE,mEAAmE;IACnE,4CAA4C;IAC5C,IAAI,eAAe;QAAE,eAAe,CAAC,IAAI,CAAC,CAAA;IAE1C,gEAAgE;IAChE,4DAA4D;IAC5D,uEAAuE;IACvE,gDAAgD;IAChD,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAAA;IACtE,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACjC,gBAAgB,CAAC;QACf,GAAG,IAAI;QACP,SAAS;QACT,IAAI,EAAE,IAAI,CAAC,IAA8B;QACzC,QAAQ,EAAE,IAAyB;KACpC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,kBAAkB,EAAE,CAAA;IACpB,eAAe,CAAC,IAAI,CAAC,CAAA;IACrB,aAAa,CAAC,cAAc,CAAC,CAAA;IAE7B,sEAAsE;IACtE,SAAS,CAAC,eAAe,CAAC,GAAG,KAAK,CAAC,CAAA;IAEnC,sEAAsE;IACtE,eAAe,CAAC,YAAY,CAAC,CAAA;IAE7B,sEAAsE;IACtE,kEAAkE;IAClE,qEAAqE;IACrE,qEAAqE;IACrE,mEAAmE;IACnE,mDAAmD;IACnD,IAAI,OAAO,EAAE,uBAAuB,EAAE,CAAC;QACrC,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;SAAM,CAAC;QACN,sBAAsB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;IAC5C,CAAC;IAED,gBAAgB,CAAC,IAAI,CAAC,CAAA;IACtB,wDAAwD;IACxD,8DAA8D;IAC9D,+DAA+D;IAC/D,gCAAgC;IAChC,IAAI,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;QACjC,SAAS,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,EAAE;QACxD,SAAS,CAAC,WAAW,GAAG,EAAE,CAAA;IAC5B,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import type { ComponentDef, AppHandle, Lifetime } from './types.js'\nimport { type DomEnv, browserEnv } from './dom-env.js'\nimport { createComponentInstance, flushInstance, type ComponentInstance } from './update-loop.js'\nimport { disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { registerInstance, unregisterInstance } from './runtime.js'\nimport { createView } from './view-helpers.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js'\n\n// ── Sentinel-region helpers (used by anchor-based mount primitives) ─────\n\n/**\n * Remove every sibling from `anchor.nextSibling` up to but not including\n * `stopBefore`. Used by anchor-based mount primitives and their HMR\n * swap path to clear the owned DOM region between the pair.\n */\nfunction _removeBetween(anchor: Comment, stopBefore: Comment): void {\n const parent = anchor.parentNode\n if (parent === null) return\n while (anchor.nextSibling !== null && anchor.nextSibling !== stopBefore) {\n parent.removeChild(anchor.nextSibling)\n }\n}\n\n/**\n * Walk forward from `anchor.nextSibling` looking for an existing\n * `<!-- llui-mount-end -->` sentinel. Used by mount/hydrate at anchor\n * to reuse a server-emitted (or stale) sentinel rather than synthesizing\n * a duplicate. Returns null if no matching comment is found before the\n * end of the parent's children.\n */\nfunction _findEndSentinel(anchor: Comment): Comment | null {\n let node: Node | null = anchor.nextSibling\n while (node !== null) {\n if (node.nodeType === 8 && (node as Comment).nodeValue === 'llui-mount-end') {\n return node as Comment\n }\n node = node.nextSibling\n }\n return null\n}\n\n// Vite injects import.meta.env.DEV — declare the shape for TypeScript\ndeclare global {\n interface ImportMeta {\n env?: { DEV?: boolean }\n }\n}\n\n// ── HMR (dev only) ──────────────────────────────────────────────\n// Set by enableHmr() from '@llui/dom/hmr' — never imported in production.\n\nlet hmrModule: typeof import('./hmr') | null = null\n\n/**\n * @internal Called by enableHmr in the hmr module. Tests use this\n * (paired with `_getHmrModule`) to snapshot/restore prior state across\n * suite boundaries — pass `null` to clear.\n */\nexport function _setHmrModule(m: typeof import('./hmr') | null): void {\n hmrModule = m\n}\n\n/** @internal Read the currently-installed HMR module (or null). */\nexport function _getHmrModule(): typeof import('./hmr') | null {\n return hmrModule\n}\n\n// ── DevTools auto-install (dev only) ────────────────────────────\n// Set by enableDevTools() from '@llui/dom/devtools' — never imported in production.\n\nlet devToolsInstall: ((inst: object) => void) | null = null\n\n/** @internal Called by enableDevTools in the devtools module */\nexport function _setDevToolsInstall(fn: ((inst: object) => void) | null): void {\n devToolsInstall = fn\n}\n\n/** @internal Read the currently-installed devtools-install hook (or null). */\nexport function _getDevToolsInstall(): ((inst: object) => void) | null {\n return devToolsInstall\n}\n\nexport interface MountOptions {\n devTools?: boolean\n /**\n * Parent scope for the mounted component's rootLifetime. When provided,\n * the rootLifetime is created as a child of this scope — context lookups\n * from within the component walk up through the parent's scope tree,\n * and disposing the parent scope cascades into this instance's scope.\n * Used by `@llui/vike`'s persistent-layout machinery to mount a page\n * as a true scope-tree child of its enclosing layout, so layout-\n * provided contexts flow naturally into pages via `useContext`.\n *\n * When omitted (the default), the rootLifetime is detached — same as\n * every `mountApp` call before persistent layouts existed.\n */\n parentLifetime?: Lifetime\n /**\n * DOM env override. Defaults to `browserEnv()` — wraps the browser\n * globals. Specify only when mounting into a non-browser DOM (e.g.\n * a jsdom instance held by a test harness, or isolated DOM per\n * shadow root).\n */\n env?: DomEnv\n /**\n * **`hydrateApp` / `hydrateAtAnchor` only.** When `true`, fire the\n * effects that `init()` returned during hydration the same way\n * `mountApp` does on a fresh mount. Defaults to `false` because the\n * SSR render already ran `init()` on the server, and re-running its\n * effects on the client typically produces duplicate work — an\n * `httpGet` issued from `init()` would fetch on the server *and* on\n * hydration; a subscription would attach twice; etc.\n *\n * Opt in only when:\n * - `init()` returns no effects, OR\n * - all returned effects are idempotent / client-only (e.g.\n * wiring a `window` event listener, opening a `WebSocket`), AND\n * - the SSR path didn't run them (typically when `init()` checks a\n * `loaded` flag in state and returns `[]` on the server).\n *\n * Pre-0.0.31 behavior was to always run init effects on hydrate;\n * the option preserves it on demand for projects that depended on\n * it. The default-off direction matches the safer expectation that\n * \"hydration should be cheap and side-effect-free.\"\n */\n runInitEffectsOnHydrate?: boolean\n}\n\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n // HMR: if this exact container already hosts a mount of this\n // component (module re-execution during hot update re-runs the same\n // mountApp call), swap the definition in place instead of creating a\n // second instance. Match on container: when the same component name\n // is mounted into N distinct containers (e.g. a page's onMount\n // iterating placeholders), each call must produce its own fresh\n // mount — swapping the existing entry would re-render into the\n // wrong container and leave the new one empty.\n //\n // HMR swap bypasses parentLifetime — HMR re-mounts the outermost app\n // handle, which in a layout setup means the layout re-mounts at the\n // root and the rest of the chain is re-established via the normal\n // mount path.\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForContainer(def.name, def, container)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import\n if (devToolsInstall) devToolsInstall(inst)\n\n // Dev-only: warn if initial state contains non-serializable values.\n // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n // Run view() within a render context so primitives can register bindings.\n // Also collect onMount callbacks in a queue we'll flush synchronously\n // after node insertion — prevents the race where a user event fires\n // between mount and the queueMicrotask callback running.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout-invalidating operation\n // instead of N individual appendChild calls on a live container element.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n container.appendChild(frag)\n } else if (nodes.length === 1) {\n container.appendChild(nodes[0]!)\n }\n\n // Flush onMount callbacks SYNCHRONOUSLY now that the DOM is in place.\n // Any listeners they attach are ready before this function returns,\n // so a synchronous dispatchEvent in the caller's next line fires\n // against a fully-wired tree.\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForHmr(def.name, inst, container)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n container.textContent = ''\n })\n}\n\n// Walks an object graph looking for non-JSON-serializable values. Returns the\n// first offender found (depth-first), or null if everything is fine. Stops at\n// depth 6 to bound runtime cost for large states.\nfunction findNonSerializable(\n v: unknown,\n path = 'state',\n depth = 0,\n seen = new WeakSet<object>(),\n): { path: string; value: unknown } | null {\n if (depth > 6) return null\n if (v === null || v === undefined) return null\n const t = typeof v\n if (t === 'string' || t === 'number' || t === 'boolean') return null\n if (t === 'function') return { path, value: v }\n if (t === 'symbol' || t === 'bigint') return { path, value: v }\n if (t !== 'object') return null\n const obj = v as object\n if (seen.has(obj)) return null\n seen.add(obj)\n if (obj instanceof Date) return { path: `${path} (Date)`, value: v }\n if (obj instanceof Map) return { path: `${path} (Map)`, value: v }\n if (obj instanceof Set) return { path: `${path} (Set)`, value: v }\n if (obj instanceof RegExp) return { path: `${path} (RegExp)`, value: v }\n if (obj instanceof Promise) return { path: `${path} (Promise)`, value: v }\n // Plain objects/arrays have Object.prototype / Array.prototype. Class instances\n // have a different prototype.\n const proto = Object.getPrototypeOf(obj)\n if (proto !== null && proto !== Object.prototype && proto !== Array.prototype) {\n return { path: `${path} (${proto?.constructor?.name ?? 'class instance'})`, value: v }\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const r = findNonSerializable(v[i], `${path}[${i}]`, depth + 1, seen)\n if (r) return r\n }\n return null\n }\n for (const k of Object.keys(obj)) {\n const r = findNonSerializable(\n (obj as Record<string, unknown>)[k],\n `${path}.${k}`,\n depth + 1,\n seen,\n )\n if (r) return r\n }\n return null\n}\n\n/**\n * Mount a component relative to a comment anchor rather than inside a\n * container element. Inserts a synthesized end sentinel (`<!-- llui-mount-end -->`)\n * immediately after the anchor and places the component's nodes between\n * the pair. The anchor must already be attached to a live DOM tree.\n *\n * Unlike `mountApp`, the caller's anchor node is preserved across the\n * handle's lifetime — only the content between the pair (and the end\n * sentinel itself) is disposed. Used by `@llui/vike` persistent layouts\n * to mount chain layers without a wrapper element.\n *\n * If a pre-existing `<!-- llui-mount-end -->` is found after the anchor\n * (e.g. stale from an undisposed prior mount), the content between the\n * anchor and that sentinel is swept and the sentinel is reused. Dev mode\n * warns in that case.\n */\nexport function mountAtAnchor<S, M, E>(\n anchor: Comment,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] mountAtAnchor: anchor comment must be attached to a live DOM tree before mount`,\n )\n }\n\n // HMR fast path: a second call into the same anchor (typical of\n // module re-execution that re-runs the user's mountAtAnchor call —\n // e.g. a vike persistent layout layer) hot-swaps in place. Matches\n // on anchor identity so independent mounts at different anchors of\n // the same-named component still each produce their own instance.\n // Without this, the existing end sentinel below would be reused but\n // the prior instance would be fully orphaned (lifetime not disposed,\n // HMR entry not unregistered, activeInstances entry not removed).\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForAnchor(def.name, def, anchor)\n if (swapped) return swapped\n }\n\n // Locate or synthesize the end sentinel.\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n if (import.meta.env?.DEV) {\n console.warn(\n `[LLui] mountAtAnchor: anchor has a pre-existing end sentinel. ` +\n `A prior mount was not disposed — sweeping stale siblings and reusing the sentinel.`,\n )\n }\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n // Use the caller-provided env if any — end-sentinel creation happens\n // before `inst` exists, so we pick the env directly from options.\n // (browserEnv() fallback matches what createComponentInstance will\n // use below when options.env is undefined.)\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n if (devToolsInstall) devToolsInstall(inst)\n\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout pass instead of N.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\n/**\n * Hydrate a component relative to a comment anchor rather than inside a\n * container element. Analogous to `hydrateApp` — uses `serverState` as\n * the initial state (not `init()`'s output) while preserving `init()`'s\n * effects for post-mount dispatch.\n *\n * The DOM-handling path is identical to `mountAtAnchor`: reuses a\n * pre-existing end sentinel when present, synthesizes one otherwise.\n * Atomic-swaps the owned region whether or not server content is there\n * to replace. No error for a missing end sentinel — the vike chain's\n * outer `hydrateApp`'s `replaceChildren` wipes inner layers' sentinels,\n * so inner-layer `hydrateAtAnchor` calls routinely find nothing to\n * reuse, and that's normal.\n */\nexport function hydrateAtAnchor<S, M, E, D = void>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] hydrateAtAnchor: anchor comment must be attached to a live DOM tree before hydrate`,\n )\n }\n\n // HMR fast path: a second hydrateAtAnchor on the same anchor\n // (typical of HMR module re-execution) hot-swaps in place. Matches\n // mountAtAnchor's behavior. Without this, the second call leaks the\n // first instance and stacks a second HMR entry under the same name.\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForAnchor(def.name, def, anchor)\n if (swapped) return swapped\n }\n\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n // Run original init() to capture effects, then override state with server's.\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n if (devToolsInstall) devToolsInstall(inst)\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true`.\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateAtAnchor')\n }\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\nfunction dispatchInitialEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n): void {\n if (inst.initialEffects.length === 0 || !inst.def.onEffect) return\n for (const effect of inst.initialEffects) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n inst.initialEffects = []\n}\n\n/**\n * Dev-only warning when a hydrate path silently drops a non-empty\n * `initialEffects` array. The default-skip behavior is deliberate (the\n * server already ran them), but if `init()` produces effects that\n * weren't run on the server — typically client-only init pipelines —\n * silent drop is a footgun. Surface the count and the opt-in.\n */\nfunction warnDroppedInitEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n via: 'hydrateApp' | 'hydrateAtAnchor',\n): void {\n if (!import.meta.env?.DEV) return\n if (inst.initialEffects.length === 0) return\n const name = inst.def.name ?? '<anonymous>'\n console.warn(\n `[LLui] ${via}: skipped ${inst.initialEffects.length} init effect(s) for \"${name}\". ` +\n `Hydration drops init effects by default since the server already ran them. ` +\n `If these effects only fire on the client, pass \\`runInitEffectsOnHydrate: true\\` to opt in.`,\n )\n}\n\n/**\n * Build the `AppHandle` returned by every mount/hydrate path. Captures\n * the `_onCommit` listener registry, the `disposed` flag, and the\n * standard `flush` / `send` / `getState` / `subscribe` shape — all\n * code that was previously duplicated four times across `mountApp`,\n * `mountAtAnchor`, `hydrateApp`, and `hydrateAtAnchor`.\n *\n * Variation lives in the two parameters:\n * - `hmrName` — the def's name used to call `hmrModule.unregisterForHmr`\n * on dispose. Pass `null` to skip HMR unregistration (no current\n * mount path needs that, but it keeps the helper honest).\n * - `domCleanup` — final teardown step that detaches mounted nodes.\n * Container-rooted paths set `container.textContent = ''`;\n * anchor-rooted paths call `_removeBetween(anchor, endSentinel)`\n * and detach the end sentinel. Runs LAST in the dispose chain to\n * match the historical ordering exactly (lifetime is disposed\n * before nodes are detached, so binding teardown sees attached\n * DOM until the very end).\n *\n * The mount-path-parity test in `mount-path-parity.test.ts` enforces\n * that each public entry point produces structurally identical\n * AppHandle behavior — this helper is the realisation of that\n * promise.\n */\nfunction buildAppHandle<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n hmrName: string | null,\n domCleanup: () => void,\n): AppHandle {\n let disposed = false\n const listeners = new Set<(s: unknown) => void>()\n\n inst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n inst._onCommit = undefined\n if (hmrModule && hmrName) hmrModule.unregisterForHmr(hmrName, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n // Tag the root scope so the disposer log reports app-level\n // teardown distinct from in-tree component-unmount events.\n inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n domCleanup()\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\n },\n send(msg: unknown) {\n if (disposed) return\n ;(inst.send as (m: unknown) => void)(msg)\n },\n getState() {\n if (disposed) {\n throw new Error(\n '[LLui] AppHandle.getState() called after dispose — handle is dead. ' +\n 'Detach your event listener / cancel your timer when the handle ' +\n 'is disposed to avoid stale reads.',\n )\n }\n return inst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n if (disposed) return []\n return getBindingDescriptors(inst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n // Drain pending messages with the OLD update first — anything\n // already in the queue was constructed under the old contract,\n // and re-routing it through a new reducer mid-flight could mix\n // half of one transition with half of another (e.g. a payload\n // shape the new update no longer accepts).\n flushInstance(inst)\n // Mutate the def in place so subsequent `inst.def.update`\n // reads — including the per-message read in `flushInstance`'s\n // generic loop — pick up the new function. We deliberately\n // don't replace `inst.def` itself: existing closures, the\n // `__update` fast path, and `__handlers` all stay valid; only\n // the user-visible reducer function changes.\n ;(inst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(inst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n // Direct invocation against current state. No subscribe, no\n // flush, no effect handler. The reducer's contract per TEA is\n // a pure function — calling it twice with the same args is a\n // no-op other than allocations. Returning the raw tuple\n // shape lets the agent inspect both halves without interpreting.\n const [state, effects] = (\n inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(inst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n setOnBindingError(hook) {\n if (disposed) return\n inst._onBindingError = hook ?? undefined\n },\n }\n}\n\nexport function hydrateApp<S, M, E, D = void>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n // HMR fast path: a second hydrateApp into the same container\n // (typical of HMR module re-execution) hot-swaps in place. Without\n // this, the second call leaks the first instance — its lifetime is\n // never disposed, its HMR entry stays in the registry, its bindings\n // keep running on detached DOM. State preservation follows the same\n // semantics as mountApp's fast path: the live instance keeps its\n // current state and the new def's `serverState` argument is\n // intentionally ignored on the swap (HMR preserves user state).\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForContainer(def.name, def, container)\n if (swapped) return swapped\n }\n\n // Run the original init once to capture its effects. The state it\n // returns is discarded — we use `serverState` (what the server\n // rendered with) instead. The effects are preserved and dispatched\n // after the DOM is in place, so components that rely on \"load data\n // or wire subscriptions on mount\" behave consistently between fresh\n // mount and SSR+hydrate. If the original init has already-loaded\n // data for the hydration case, gate the effect emission inside init\n // itself (e.g. based on a `loaded` flag in state).\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools'\n // import. The other three mount paths (mountApp / mountAtAnchor /\n // hydrateAtAnchor) all call this; without it, the hydrated layout\n // never appears in `window.__lluiComponents`, never sets\n // `window.__lluiDebug`, and is invisible to MCP / agent client /\n // devtools console — so a vike SSR app's outermost layout silently\n // drops out of every observability surface.\n if (devToolsInstall) devToolsInstall(inst)\n\n // Build the component DOM and swap atomically with server HTML.\n // Server HTML remains visible until JS finishes — no flash.\n // onMount callbacks are collected in a queue and flushed synchronously\n // after the swap, matching mountApp's ordering.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Atomic swap — replaces server HTML with client DOM in one operation\n container.replaceChildren(...nodes)\n\n // Flush onMount callbacks synchronously now that the DOM is in place.\n flushMountQueue(onMountQueue)\n\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true` for projects that\n // need the post-swap dispatch (typically when `init()` is gated by\n // a `loaded` flag and returns `[]` on the server).\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateApp')\n }\n\n registerInstance(inst)\n // HMR registration — same as mountApp / mountAtAnchor /\n // hydrateAtAnchor. Without it, replaceComponent(name, newDef)\n // silently no-ops on the hydrated layout layer because the HMR\n // registry has no entry for it.\n if (hmrModule && hydrateDef.name) {\n hmrModule.registerForHmr(hydrateDef.name, inst, container)\n }\n return buildAppHandle(inst, hydrateDef.name ?? null, () => {\n container.textContent = ''\n })\n}\n"]}
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle, Lifetime } from './types.js'\nimport { type DomEnv, browserEnv } from './dom-env.js'\nimport { createComponentInstance, flushInstance, type ComponentInstance } from './update-loop.js'\nimport { disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { registerInstance, unregisterInstance } from './runtime.js'\nimport type { View } from './view-helpers.js'\nimport { getInstanceViewBag } from './render-context.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js'\n\n// ── Sentinel-region helpers (used by anchor-based mount primitives) ─────\n\n/**\n * Remove every sibling from `anchor.nextSibling` up to but not including\n * `stopBefore`. Used by anchor-based mount primitives and their HMR\n * swap path to clear the owned DOM region between the pair.\n */\nfunction _removeBetween(anchor: Comment, stopBefore: Comment): void {\n const parent = anchor.parentNode\n if (parent === null) return\n while (anchor.nextSibling !== null && anchor.nextSibling !== stopBefore) {\n parent.removeChild(anchor.nextSibling)\n }\n}\n\n/**\n * Walk forward from `anchor.nextSibling` looking for an existing\n * `<!-- llui-mount-end -->` sentinel. Used by mount/hydrate at anchor\n * to reuse a server-emitted (or stale) sentinel rather than synthesizing\n * a duplicate. Returns null if no matching comment is found before the\n * end of the parent's children.\n */\nfunction _findEndSentinel(anchor: Comment): Comment | null {\n let node: Node | null = anchor.nextSibling\n while (node !== null) {\n if (node.nodeType === 8 && (node as Comment).nodeValue === 'llui-mount-end') {\n return node as Comment\n }\n node = node.nextSibling\n }\n return null\n}\n\n// Vite injects import.meta.env.DEV — declare the shape for TypeScript\ndeclare global {\n interface ImportMeta {\n env?: { DEV?: boolean; MODE?: string }\n }\n}\n\n// ── HMR (dev only) ──────────────────────────────────────────────\n// Set by enableHmr() from '@llui/dom/hmr' — never imported in production.\n\nlet hmrModule: typeof import('./hmr') | null = null\n\n/**\n * @internal Called by enableHmr in the hmr module. Tests use this\n * (paired with `_getHmrModule`) to snapshot/restore prior state across\n * suite boundaries — pass `null` to clear.\n */\nexport function _setHmrModule(m: typeof import('./hmr') | null): void {\n hmrModule = m\n}\n\n/** @internal Read the currently-installed HMR module (or null). */\nexport function _getHmrModule(): typeof import('./hmr') | null {\n return hmrModule\n}\n\n// ── DevTools auto-install (dev only) ────────────────────────────\n// Set by enableDevTools() from '@llui/dom/devtools' — never imported in production.\n\nlet devToolsInstall: ((inst: object) => void) | null = null\n\n/** @internal Called by enableDevTools in the devtools module */\nexport function _setDevToolsInstall(fn: ((inst: object) => void) | null): void {\n devToolsInstall = fn\n}\n\n/** @internal Read the currently-installed devtools-install hook (or null). */\nexport function _getDevToolsInstall(): ((inst: object) => void) | null {\n return devToolsInstall\n}\n\nexport interface MountOptions {\n devTools?: boolean\n /**\n * Parent scope for the mounted component's rootLifetime. When provided,\n * the rootLifetime is created as a child of this scope — context lookups\n * from within the component walk up through the parent's scope tree,\n * and disposing the parent scope cascades into this instance's scope.\n * Used by `@llui/vike`'s persistent-layout machinery to mount a page\n * as a true scope-tree child of its enclosing layout, so layout-\n * provided contexts flow naturally into pages via `useContext`.\n *\n * When omitted (the default), the rootLifetime is detached — same as\n * every `mountApp` call before persistent layouts existed.\n */\n parentLifetime?: Lifetime\n /**\n * DOM env override. Defaults to `browserEnv()` — wraps the browser\n * globals. Specify only when mounting into a non-browser DOM (e.g.\n * a jsdom instance held by a test harness, or isolated DOM per\n * shadow root).\n */\n env?: DomEnv\n /**\n * **`hydrateApp` / `hydrateAtAnchor` only.** When `true`, fire the\n * effects that `init()` returned during hydration the same way\n * `mountApp` does on a fresh mount. Defaults to `false` because the\n * SSR render already ran `init()` on the server, and re-running its\n * effects on the client typically produces duplicate work — an\n * `httpGet` issued from `init()` would fetch on the server *and* on\n * hydration; a subscription would attach twice; etc.\n *\n * Opt in only when:\n * - `init()` returns no effects, OR\n * - all returned effects are idempotent / client-only (e.g.\n * wiring a `window` event listener, opening a `WebSocket`), AND\n * - the SSR path didn't run them (typically when `init()` checks a\n * `loaded` flag in state and returns `[]` on the server).\n *\n * Pre-0.0.31 behavior was to always run init effects on hydrate;\n * the option preserves it on demand for projects that depended on\n * it. The default-off direction matches the safer expectation that\n * \"hydration should be cheap and side-effect-free.\"\n */\n runInitEffectsOnHydrate?: boolean\n}\n\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n // HMR: if this exact container already hosts a mount of this\n // component (module re-execution during hot update re-runs the same\n // mountApp call), swap the definition in place instead of creating a\n // second instance. Match on container: when the same component name\n // is mounted into N distinct containers (e.g. a page's onMount\n // iterating placeholders), each call must produce its own fresh\n // mount — swapping the existing entry would re-render into the\n // wrong container and leave the new one empty.\n //\n // HMR swap bypasses parentLifetime — HMR re-mounts the outermost app\n // handle, which in a layout setup means the layout re-mounts at the\n // root and the rest of the chain is re-established via the normal\n // mount path.\n if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForContainer(def.name, def, container)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import\n if (import.meta.env?.DEV && devToolsInstall) devToolsInstall(inst)\n\n // Dev-only: warn if initial state contains non-serializable values.\n // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n // Run view() within a render context so primitives can register bindings.\n // Also collect onMount callbacks in a queue we'll flush synchronously\n // after node insertion — prevents the race where a user event fires\n // between mount and the queueMicrotask callback running.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(\n getInstanceViewBag<S, M>(inst as ComponentInstance, inst.send) as View<S, M>,\n )\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout-invalidating operation\n // instead of N individual appendChild calls on a live container element.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n container.appendChild(frag)\n } else if (nodes.length === 1) {\n container.appendChild(nodes[0]!)\n }\n\n // Flush onMount callbacks SYNCHRONOUSLY now that the DOM is in place.\n // Any listeners they attach are ready before this function returns,\n // so a synchronous dispatchEvent in the caller's next line fires\n // against a fully-wired tree.\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (import.meta.env?.DEV && hmrModule && def.name) {\n hmrModule.registerForHmr(def.name, inst, container)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n container.textContent = ''\n })\n}\n\n// Walks an object graph looking for non-JSON-serializable values. Returns the\n// first offender found (depth-first), or null if everything is fine. Stops at\n// depth 6 to bound runtime cost for large states.\nfunction findNonSerializable(\n v: unknown,\n path = 'state',\n depth = 0,\n seen = new WeakSet<object>(),\n): { path: string; value: unknown } | null {\n if (depth > 6) return null\n if (v === null || v === undefined) return null\n const t = typeof v\n if (t === 'string' || t === 'number' || t === 'boolean') return null\n if (t === 'function') return { path, value: v }\n if (t === 'symbol' || t === 'bigint') return { path, value: v }\n if (t !== 'object') return null\n const obj = v as object\n if (seen.has(obj)) return null\n seen.add(obj)\n if (obj instanceof Date) return { path: `${path} (Date)`, value: v }\n if (obj instanceof Map) return { path: `${path} (Map)`, value: v }\n if (obj instanceof Set) return { path: `${path} (Set)`, value: v }\n if (obj instanceof RegExp) return { path: `${path} (RegExp)`, value: v }\n if (obj instanceof Promise) return { path: `${path} (Promise)`, value: v }\n // Plain objects/arrays have Object.prototype / Array.prototype. Class instances\n // have a different prototype.\n const proto = Object.getPrototypeOf(obj)\n if (proto !== null && proto !== Object.prototype && proto !== Array.prototype) {\n return { path: `${path} (${proto?.constructor?.name ?? 'class instance'})`, value: v }\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const r = findNonSerializable(v[i], `${path}[${i}]`, depth + 1, seen)\n if (r) return r\n }\n return null\n }\n for (const k of Object.keys(obj)) {\n const r = findNonSerializable(\n (obj as Record<string, unknown>)[k],\n `${path}.${k}`,\n depth + 1,\n seen,\n )\n if (r) return r\n }\n return null\n}\n\n/**\n * Mount a component relative to a comment anchor rather than inside a\n * container element. Inserts a synthesized end sentinel (`<!-- llui-mount-end -->`)\n * immediately after the anchor and places the component's nodes between\n * the pair. The anchor must already be attached to a live DOM tree.\n *\n * Unlike `mountApp`, the caller's anchor node is preserved across the\n * handle's lifetime — only the content between the pair (and the end\n * sentinel itself) is disposed. Used by `@llui/vike` persistent layouts\n * to mount chain layers without a wrapper element.\n *\n * If a pre-existing `<!-- llui-mount-end -->` is found after the anchor\n * (e.g. stale from an undisposed prior mount), the content between the\n * anchor and that sentinel is swept and the sentinel is reused. Dev mode\n * warns in that case.\n */\nexport function mountAtAnchor<S, M, E>(\n anchor: Comment,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] mountAtAnchor: anchor comment must be attached to a live DOM tree before mount`,\n )\n }\n\n // HMR fast path: a second call into the same anchor (typical of\n // module re-execution that re-runs the user's mountAtAnchor call —\n // e.g. a vike persistent layout layer) hot-swaps in place. Matches\n // on anchor identity so independent mounts at different anchors of\n // the same-named component still each produce their own instance.\n // Without this, the existing end sentinel below would be reused but\n // the prior instance would be fully orphaned (lifetime not disposed,\n // HMR entry not unregistered, activeInstances entry not removed).\n if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForAnchor(def.name, def, anchor)\n if (swapped) return swapped\n }\n\n // Locate or synthesize the end sentinel.\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n if (import.meta.env?.DEV) {\n console.warn(\n `[LLui] mountAtAnchor: anchor has a pre-existing end sentinel. ` +\n `A prior mount was not disposed — sweeping stale siblings and reusing the sentinel.`,\n )\n }\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n // Use the caller-provided env if any — end-sentinel creation happens\n // before `inst` exists, so we pick the env directly from options.\n // (browserEnv() fallback matches what createComponentInstance will\n // use below when options.env is undefined.)\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n if (import.meta.env?.DEV && devToolsInstall) devToolsInstall(inst)\n\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(\n getInstanceViewBag<S, M>(inst as ComponentInstance, inst.send) as View<S, M>,\n )\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout pass instead of N.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (import.meta.env?.DEV && hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\n/**\n * Hydrate a component relative to a comment anchor rather than inside a\n * container element. Analogous to `hydrateApp` — uses `serverState` as\n * the initial state (not `init()`'s output) while preserving `init()`'s\n * effects for post-mount dispatch.\n *\n * The DOM-handling path is identical to `mountAtAnchor`: reuses a\n * pre-existing end sentinel when present, synthesizes one otherwise.\n * Atomic-swaps the owned region whether or not server content is there\n * to replace. No error for a missing end sentinel — the vike chain's\n * outer `hydrateApp`'s `replaceChildren` wipes inner layers' sentinels,\n * so inner-layer `hydrateAtAnchor` calls routinely find nothing to\n * reuse, and that's normal.\n */\nexport function hydrateAtAnchor<S, M, E, D = void>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] hydrateAtAnchor: anchor comment must be attached to a live DOM tree before hydrate`,\n )\n }\n\n // HMR fast path: a second hydrateAtAnchor on the same anchor\n // (typical of HMR module re-execution) hot-swaps in place. Matches\n // mountAtAnchor's behavior. Without this, the second call leaks the\n // first instance and stacks a second HMR entry under the same name.\n if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForAnchor(def.name, def, anchor)\n if (swapped) return swapped\n }\n\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n // Run original init() to capture effects, then override state with server's.\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n if (import.meta.env?.DEV && devToolsInstall) devToolsInstall(inst)\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(\n getInstanceViewBag<S, M>(inst as ComponentInstance, inst.send) as View<S, M>,\n )\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (import.meta.env?.DEV && hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true`.\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateAtAnchor')\n }\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\nfunction dispatchInitialEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n): void {\n if (inst.initialEffects.length === 0 || !inst.def.onEffect) return\n for (const effect of inst.initialEffects) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n inst.initialEffects = []\n}\n\n/**\n * Dev-only warning when a hydrate path silently drops a non-empty\n * `initialEffects` array. The default-skip behavior is deliberate (the\n * server already ran them), but if `init()` produces effects that\n * weren't run on the server — typically client-only init pipelines —\n * silent drop is a footgun. Surface the count and the opt-in.\n */\nfunction warnDroppedInitEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n via: 'hydrateApp' | 'hydrateAtAnchor',\n): void {\n if (!import.meta.env?.DEV) return\n if (inst.initialEffects.length === 0) return\n const name = inst.def.name ?? '<anonymous>'\n console.warn(\n `[LLui] ${via}: skipped ${inst.initialEffects.length} init effect(s) for \"${name}\". ` +\n `Hydration drops init effects by default since the server already ran them. ` +\n `If these effects only fire on the client, pass \\`runInitEffectsOnHydrate: true\\` to opt in.`,\n )\n}\n\n/**\n * Build the `AppHandle` returned by every mount/hydrate path. Captures\n * the `_onCommit` listener registry, the `disposed` flag, and the\n * standard `flush` / `send` / `getState` / `subscribe` shape — all\n * code that was previously duplicated four times across `mountApp`,\n * `mountAtAnchor`, `hydrateApp`, and `hydrateAtAnchor`.\n *\n * Variation lives in the two parameters:\n * - `hmrName` — the def's name used to call `hmrModule.unregisterForHmr`\n * on dispose. Pass `null` to skip HMR unregistration (no current\n * mount path needs that, but it keeps the helper honest).\n * - `domCleanup` — final teardown step that detaches mounted nodes.\n * Container-rooted paths set `container.textContent = ''`;\n * anchor-rooted paths call `_removeBetween(anchor, endSentinel)`\n * and detach the end sentinel. Runs LAST in the dispose chain to\n * match the historical ordering exactly (lifetime is disposed\n * before nodes are detached, so binding teardown sees attached\n * DOM until the very end).\n *\n * The mount-path-parity test in `mount-path-parity.test.ts` enforces\n * that each public entry point produces structurally identical\n * AppHandle behavior — this helper is the realisation of that\n * promise.\n */\nfunction buildAppHandle<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n hmrName: string | null,\n domCleanup: () => void,\n): AppHandle {\n let disposed = false\n const listeners = new Set<(s: unknown) => void>()\n\n inst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n inst._onCommit = undefined\n if (import.meta.env?.DEV && hmrModule && hmrName) hmrModule.unregisterForHmr(hmrName, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n // Tag the root scope so the disposer log reports app-level\n // teardown distinct from in-tree component-unmount events.\n if (import.meta.env?.DEV) inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n domCleanup()\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\n },\n send(msg: unknown) {\n if (disposed) return\n ;(inst.send as (m: unknown) => void)(msg)\n },\n getState() {\n if (disposed) {\n if (import.meta.env?.DEV) {\n throw new Error(\n '[LLui] AppHandle.getState() called after dispose — handle is dead. ' +\n 'Detach your event listener / cancel your timer when the handle ' +\n 'is disposed to avoid stale reads.',\n )\n }\n throw new Error('[LLui] AppHandle.getState() after dispose')\n }\n return inst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n // Agent-only — returns an empty array when the build-time flag is\n // off so callers get a consistent shape. The body's `getBindingDescriptors`\n // import becomes dead-code-eliminable along with the rest of\n // `binding-descriptors.ts`.\n if (typeof __LLUI_AGENT__ === 'undefined' || !__LLUI_AGENT__) return []\n if (disposed) return []\n return getBindingDescriptors(inst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n // Drain pending messages with the OLD update first — anything\n // already in the queue was constructed under the old contract,\n // and re-routing it through a new reducer mid-flight could mix\n // half of one transition with half of another (e.g. a payload\n // shape the new update no longer accepts).\n flushInstance(inst)\n // Mutate the def in place so subsequent `inst.def.update`\n // reads — including the per-message read in `flushInstance`'s\n // generic loop — pick up the new function. We deliberately\n // don't replace `inst.def` itself: existing closures, the\n // `__update` fast path, and `__handlers` all stay valid; only\n // the user-visible reducer function changes.\n ;(inst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(inst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n // Direct invocation against current state. No subscribe, no\n // flush, no effect handler. The reducer's contract per TEA is\n // a pure function — calling it twice with the same args is a\n // no-op other than allocations. Returning the raw tuple\n // shape lets the agent inspect both halves without interpreting.\n const [state, effects] = (\n inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(inst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n setOnBindingError(hook) {\n if (disposed) return\n inst._onBindingError = hook ?? undefined\n },\n }\n}\n\nexport function hydrateApp<S, M, E, D = void>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n // HMR fast path: a second hydrateApp into the same container\n // (typical of HMR module re-execution) hot-swaps in place. Without\n // this, the second call leaks the first instance — its lifetime is\n // never disposed, its HMR entry stays in the registry, its bindings\n // keep running on detached DOM. State preservation follows the same\n // semantics as mountApp's fast path: the live instance keeps its\n // current state and the new def's `serverState` argument is\n // intentionally ignored on the swap (HMR preserves user state).\n if (import.meta.env?.DEV && hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponentForContainer(def.name, def, container)\n if (swapped) return swapped\n }\n\n // Run the original init once to capture its effects. The state it\n // returns is discarded — we use `serverState` (what the server\n // rendered with) instead. The effects are preserved and dispatched\n // after the DOM is in place, so components that rely on \"load data\n // or wire subscriptions on mount\" behave consistently between fresh\n // mount and SSR+hydrate. If the original init has already-loaded\n // data for the hydration case, gate the effect emission inside init\n // itself (e.g. based on a `loaded` flag in state).\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools'\n // import. The other three mount paths (mountApp / mountAtAnchor /\n // hydrateAtAnchor) all call this; without it, the hydrated layout\n // never appears in `window.__lluiComponents`, never sets\n // `window.__lluiDebug`, and is invisible to MCP / agent client /\n // devtools console — so a vike SSR app's outermost layout silently\n // drops out of every observability surface.\n if (import.meta.env?.DEV && devToolsInstall) devToolsInstall(inst)\n\n // Build the component DOM and swap atomically with server HTML.\n // Server HTML remains visible until JS finishes — no flash.\n // onMount callbacks are collected in a queue and flushed synchronously\n // after the swap, matching mountApp's ordering.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(\n getInstanceViewBag<S, M>(inst as ComponentInstance, inst.send) as View<S, M>,\n )\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Atomic swap — replaces server HTML with client DOM in one operation\n container.replaceChildren(...nodes)\n\n // Flush onMount callbacks synchronously now that the DOM is in place.\n flushMountQueue(onMountQueue)\n\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true` for projects that\n // need the post-swap dispatch (typically when `init()` is gated by\n // a `loaded` flag and returns `[]` on the server).\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateApp')\n }\n\n registerInstance(inst)\n // HMR registration — same as mountApp / mountAtAnchor /\n // hydrateAtAnchor. Without it, replaceComponent(name, newDef)\n // silently no-ops on the hydrated layout layer because the HMR\n // registry has no entry for it.\n if (import.meta.env?.DEV && hmrModule && hydrateDef.name) {\n hmrModule.registerForHmr(hydrateDef.name, inst, container)\n }\n return buildAppHandle(inst, hydrateDef.name ?? null, () => {\n container.textContent = ''\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"branch.d.ts","sourceRoot":"","sources":["../../src/primitives/branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,aAAa,CAAA;AAe1D,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC9D,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC3B,IAAI,EAAE,CAwKR"}
1
+ {"version":3,"file":"branch.d.ts","sourceRoot":"","sources":["../../src/primitives/branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,aAAa,CAAA;AA6B1D,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC9D,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC3B,IAAI,EAAE,CA6KR"}