@llui/dom 0.0.30 → 0.0.33

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 (42) hide show
  1. package/README.md +1 -0
  2. package/dist/binding-descriptors.d.ts +126 -0
  3. package/dist/binding-descriptors.d.ts.map +1 -0
  4. package/dist/binding-descriptors.js +144 -0
  5. package/dist/binding-descriptors.js.map +1 -0
  6. package/dist/devtools.d.ts +7 -3
  7. package/dist/devtools.d.ts.map +1 -1
  8. package/dist/devtools.js +52 -19
  9. package/dist/devtools.js.map +1 -1
  10. package/dist/el-split.d.ts.map +1 -1
  11. package/dist/el-split.js +12 -0
  12. package/dist/el-split.js.map +1 -1
  13. package/dist/elements.d.ts.map +1 -1
  14. package/dist/elements.js +14 -0
  15. package/dist/elements.js.map +1 -1
  16. package/dist/hmr.d.ts.map +1 -1
  17. package/dist/hmr.js +194 -0
  18. package/dist/hmr.js.map +1 -1
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +10 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/mount.d.ts +22 -0
  24. package/dist/mount.d.ts.map +1 -1
  25. package/dist/mount.js +156 -173
  26. package/dist/mount.js.map +1 -1
  27. package/dist/primitives/sample.d.ts +16 -4
  28. package/dist/primitives/sample.d.ts.map +1 -1
  29. package/dist/primitives/sample.js +16 -4
  30. package/dist/primitives/sample.js.map +1 -1
  31. package/dist/primitives/unsafe-html.d.ts +1 -1
  32. package/dist/primitives/unsafe-html.d.ts.map +1 -1
  33. package/dist/primitives/unsafe-html.js.map +1 -1
  34. package/dist/types.d.ts +99 -5
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js.map +1 -1
  37. package/dist/update-loop.d.ts.map +1 -1
  38. package/dist/update-loop.js.map +1 -1
  39. package/dist/view-helpers.d.ts +19 -3
  40. package/dist/view-helpers.d.ts.map +1 -1
  41. package/dist/view-helpers.js.map +1 -1
  42. package/package.json +1 -1
package/dist/mount.js CHANGED
@@ -3,6 +3,7 @@ import { createComponentInstance, flushInstance } from './update-loop.js';
3
3
  import { disposeLifetime } from './lifetime.js';
4
4
  import { setRenderContext, clearRenderContext } from './render-context.js';
5
5
  import { setFlatBindings } from './binding.js';
6
+ import { getBindingDescriptors } from './binding-descriptors.js';
6
7
  import { registerInstance, unregisterInstance } from './runtime.js';
7
8
  import { createView } from './view-helpers.js';
8
9
  import { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js';
@@ -40,10 +41,18 @@ function _findEndSentinel(anchor) {
40
41
  // ── HMR (dev only) ──────────────────────────────────────────────
41
42
  // Set by enableHmr() from '@llui/dom/hmr' — never imported in production.
42
43
  let hmrModule = null;
43
- /** @internal Called by enableHmr in the hmr module */
44
+ /**
45
+ * @internal Called by enableHmr in the hmr module. Tests use this
46
+ * (paired with `_getHmrModule`) to snapshot/restore prior state across
47
+ * suite boundaries — pass `null` to clear.
48
+ */
44
49
  export function _setHmrModule(m) {
45
50
  hmrModule = m;
46
51
  }
52
+ /** @internal Read the currently-installed HMR module (or null). */
53
+ export function _getHmrModule() {
54
+ return hmrModule;
55
+ }
47
56
  // ── DevTools auto-install (dev only) ────────────────────────────
48
57
  // Set by enableDevTools() from '@llui/dom/devtools' — never imported in production.
49
58
  let devToolsInstall = null;
@@ -51,6 +60,10 @@ let devToolsInstall = null;
51
60
  export function _setDevToolsInstall(fn) {
52
61
  devToolsInstall = fn;
53
62
  }
63
+ /** @internal Read the currently-installed devtools-install hook (or null). */
64
+ export function _getDevToolsInstall() {
65
+ return devToolsInstall;
66
+ }
54
67
  export function mountApp(container, def, data, options) {
55
68
  // HMR: if this component is already mounted (module re-execution
56
69
  // during hot update), swap the definition instead of creating a new instance.
@@ -113,60 +126,9 @@ export function mountApp(container, def, data, options) {
113
126
  hmrModule.registerForHmr(def.name, inst, container);
114
127
  }
115
128
  dispatchInitialEffects(inst);
116
- let disposed = false;
117
- const listeners = new Set();
118
- inst._onCommit = (state) => {
119
- for (const l of Array.from(listeners)) {
120
- try {
121
- l(state);
122
- }
123
- catch (err) {
124
- console.error('[llui] listener threw:', err);
125
- }
126
- }
127
- };
128
- return {
129
- dispose() {
130
- if (disposed)
131
- return;
132
- disposed = true;
133
- listeners.clear();
134
- inst._onCommit = undefined;
135
- if (hmrModule && def.name)
136
- hmrModule.unregisterForHmr(def.name, inst);
137
- inst.abortController.abort();
138
- unregisterInstance(inst);
139
- // Tag the root scope so the disposer log reports app-level
140
- // teardown distinct from in-tree component-unmount events.
141
- inst.rootLifetime.disposalCause = 'app-unmount';
142
- disposeLifetime(inst.rootLifetime);
143
- container.textContent = '';
144
- },
145
- flush() {
146
- if (disposed)
147
- return;
148
- flushInstance(inst);
149
- },
150
- send(msg) {
151
- if (disposed)
152
- return;
153
- inst.send(msg);
154
- },
155
- getState() {
156
- if (disposed) {
157
- throw new Error('[LLui] AppHandle.getState() called after dispose — handle is dead. ' +
158
- 'Detach your event listener / cancel your timer when the handle ' +
159
- 'is disposed to avoid stale reads.');
160
- }
161
- return inst.state;
162
- },
163
- subscribe(listener) {
164
- if (disposed)
165
- return () => { };
166
- listeners.add(listener);
167
- return () => listeners.delete(listener);
168
- },
169
- };
129
+ return buildAppHandle(inst, def.name ?? null, () => {
130
+ container.textContent = '';
131
+ });
170
132
  }
171
133
  // Walks an object graph looking for non-JSON-serializable values. Returns the
172
134
  // first offender found (depth-first), or null if everything is fine. Stops at
@@ -282,57 +244,10 @@ export function mountAtAnchor(anchor, def, data, options) {
282
244
  hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel);
283
245
  }
284
246
  dispatchInitialEffects(inst);
285
- let disposed = false;
286
- const listeners = new Set();
287
- inst._onCommit = (state) => {
288
- for (const l of Array.from(listeners)) {
289
- try {
290
- l(state);
291
- }
292
- catch (err) {
293
- console.error('[llui] listener threw:', err);
294
- }
295
- }
296
- };
297
- return {
298
- dispose() {
299
- if (disposed)
300
- return;
301
- disposed = true;
302
- listeners.clear();
303
- inst._onCommit = undefined;
304
- if (hmrModule && def.name)
305
- hmrModule.unregisterForHmr(def.name, inst);
306
- inst.abortController.abort();
307
- unregisterInstance(inst);
308
- inst.rootLifetime.disposalCause = 'app-unmount';
309
- disposeLifetime(inst.rootLifetime);
310
- _removeBetween(anchor, endSentinel);
311
- endSentinel.parentNode?.removeChild(endSentinel);
312
- },
313
- flush() {
314
- if (disposed)
315
- return;
316
- flushInstance(inst);
317
- },
318
- send(msg) {
319
- if (disposed)
320
- return;
321
- inst.send(msg);
322
- },
323
- getState() {
324
- if (disposed) {
325
- throw new Error('[LLui] AppHandle.getState() called after dispose — handle is dead.');
326
- }
327
- return inst.state;
328
- },
329
- subscribe(listener) {
330
- if (disposed)
331
- return () => { };
332
- listeners.add(listener);
333
- return () => listeners.delete(listener);
334
- },
335
- };
247
+ return buildAppHandle(inst, def.name ?? null, () => {
248
+ _removeBetween(anchor, endSentinel);
249
+ endSentinel.parentNode?.removeChild(endSentinel);
250
+ });
336
251
  }
337
252
  /**
338
253
  * Hydrate a component relative to a comment anchor rather than inside a
@@ -397,7 +312,71 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
397
312
  if (hmrModule && def.name) {
398
313
  hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel);
399
314
  }
400
- dispatchInitialEffects(inst);
315
+ // Hydration: skip init's effects by default. The SSR pass already ran
316
+ // them on the server; re-running on the client typically produces
317
+ // duplicate work (double fetches, double subscriptions). Opt back in
318
+ // via `MountOptions.runInitEffectsOnHydrate: true`.
319
+ if (options?.runInitEffectsOnHydrate) {
320
+ dispatchInitialEffects(inst);
321
+ }
322
+ else {
323
+ warnDroppedInitEffects(inst, 'hydrateAtAnchor');
324
+ }
325
+ return buildAppHandle(inst, def.name ?? null, () => {
326
+ _removeBetween(anchor, endSentinel);
327
+ endSentinel.parentNode?.removeChild(endSentinel);
328
+ });
329
+ }
330
+ function dispatchInitialEffects(inst) {
331
+ if (inst.initialEffects.length === 0 || !inst.def.onEffect)
332
+ return;
333
+ for (const effect of inst.initialEffects) {
334
+ inst.def.onEffect({ effect, send: inst.send, signal: inst.signal });
335
+ }
336
+ inst.initialEffects = [];
337
+ }
338
+ /**
339
+ * Dev-only warning when a hydrate path silently drops a non-empty
340
+ * `initialEffects` array. The default-skip behavior is deliberate (the
341
+ * server already ran them), but if `init()` produces effects that
342
+ * weren't run on the server — typically client-only init pipelines —
343
+ * silent drop is a footgun. Surface the count and the opt-in.
344
+ */
345
+ function warnDroppedInitEffects(inst, via) {
346
+ if (!import.meta.env?.DEV)
347
+ return;
348
+ if (inst.initialEffects.length === 0)
349
+ return;
350
+ const name = inst.def.name ?? '<anonymous>';
351
+ console.warn(`[LLui] ${via}: skipped ${inst.initialEffects.length} init effect(s) for "${name}". ` +
352
+ `Hydration drops init effects by default since the server already ran them. ` +
353
+ `If these effects only fire on the client, pass \`runInitEffectsOnHydrate: true\` to opt in.`);
354
+ }
355
+ /**
356
+ * Build the `AppHandle` returned by every mount/hydrate path. Captures
357
+ * the `_onCommit` listener registry, the `disposed` flag, and the
358
+ * standard `flush` / `send` / `getState` / `subscribe` shape — all
359
+ * code that was previously duplicated four times across `mountApp`,
360
+ * `mountAtAnchor`, `hydrateApp`, and `hydrateAtAnchor`.
361
+ *
362
+ * Variation lives in the two parameters:
363
+ * - `hmrName` — the def's name used to call `hmrModule.unregisterForHmr`
364
+ * on dispose. Pass `null` to skip HMR unregistration (no current
365
+ * mount path needs that, but it keeps the helper honest).
366
+ * - `domCleanup` — final teardown step that detaches mounted nodes.
367
+ * Container-rooted paths set `container.textContent = ''`;
368
+ * anchor-rooted paths call `_removeBetween(anchor, endSentinel)`
369
+ * and detach the end sentinel. Runs LAST in the dispose chain to
370
+ * match the historical ordering exactly (lifetime is disposed
371
+ * before nodes are detached, so binding teardown sees attached
372
+ * DOM until the very end).
373
+ *
374
+ * The mount-path-parity test in `mount-path-parity.test.ts` enforces
375
+ * that each public entry point produces structurally identical
376
+ * AppHandle behavior — this helper is the realisation of that
377
+ * promise.
378
+ */
379
+ function buildAppHandle(inst, hmrName, domCleanup) {
401
380
  let disposed = false;
402
381
  const listeners = new Set();
403
382
  inst._onCommit = (state) => {
@@ -417,14 +396,15 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
417
396
  disposed = true;
418
397
  listeners.clear();
419
398
  inst._onCommit = undefined;
420
- if (hmrModule && def.name)
421
- hmrModule.unregisterForHmr(def.name, inst);
399
+ if (hmrModule && hmrName)
400
+ hmrModule.unregisterForHmr(hmrName, inst);
422
401
  inst.abortController.abort();
423
402
  unregisterInstance(inst);
403
+ // Tag the root scope so the disposer log reports app-level
404
+ // teardown distinct from in-tree component-unmount events.
424
405
  inst.rootLifetime.disposalCause = 'app-unmount';
425
406
  disposeLifetime(inst.rootLifetime);
426
- _removeBetween(anchor, endSentinel);
427
- endSentinel.parentNode?.removeChild(endSentinel);
407
+ domCleanup();
428
408
  },
429
409
  flush() {
430
410
  if (disposed)
@@ -438,7 +418,9 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
438
418
  },
439
419
  getState() {
440
420
  if (disposed) {
441
- throw new Error('[LLui] AppHandle.getState() called after dispose — handle is dead.');
421
+ throw new Error('[LLui] AppHandle.getState() called after dispose — handle is dead. ' +
422
+ 'Detach your event listener / cancel your timer when the handle ' +
423
+ 'is disposed to avoid stale reads.');
442
424
  }
443
425
  return inst.state;
444
426
  },
@@ -448,16 +430,39 @@ export function hydrateAtAnchor(anchor, def, serverState, options) {
448
430
  listeners.add(listener);
449
431
  return () => listeners.delete(listener);
450
432
  },
433
+ getBindingDescriptors() {
434
+ if (disposed)
435
+ return [];
436
+ return getBindingDescriptors(inst);
437
+ },
438
+ swapUpdate(newUpdate, newOnEffect) {
439
+ if (disposed)
440
+ return;
441
+ // Drain pending messages with the OLD update first — anything
442
+ // already in the queue was constructed under the old contract,
443
+ // and re-routing it through a new reducer mid-flight could mix
444
+ // half of one transition with half of another (e.g. a payload
445
+ // shape the new update no longer accepts).
446
+ flushInstance(inst);
447
+ inst.def.update = newUpdate;
448
+ if (newOnEffect !== undefined) {
449
+ ;
450
+ inst.def.onEffect = newOnEffect;
451
+ }
452
+ },
453
+ runReducer(msg) {
454
+ if (disposed)
455
+ return null;
456
+ // Direct invocation against current state. No subscribe, no
457
+ // flush, no effect handler. The reducer's contract per TEA is
458
+ // a pure function — calling it twice with the same args is a
459
+ // no-op other than allocations. Returning the raw tuple
460
+ // shape lets the agent inspect both halves without interpreting.
461
+ const [state, effects] = inst.def.update(inst.state, msg);
462
+ return { state, effects: effects };
463
+ },
451
464
  };
452
465
  }
453
- function dispatchInitialEffects(inst) {
454
- if (inst.initialEffects.length === 0 || !inst.def.onEffect)
455
- return;
456
- for (const effect of inst.initialEffects) {
457
- inst.def.onEffect({ effect, send: inst.send, signal: inst.signal });
458
- }
459
- inst.initialEffects = [];
460
- }
461
466
  export function hydrateApp(container, def, serverState, options) {
462
467
  // Run the original init once to capture its effects. The state it
463
468
  // returns is discarded — we use `serverState` (what the server
@@ -473,6 +478,15 @@ export function hydrateApp(container, def, serverState, options) {
473
478
  init: () => [serverState, originalEffects],
474
479
  };
475
480
  const inst = createComponentInstance(hydrateDef, undefined, options?.parentLifetime ?? null, options?.env);
481
+ // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools'
482
+ // import. The other three mount paths (mountApp / mountAtAnchor /
483
+ // hydrateAtAnchor) all call this; without it, the hydrated layout
484
+ // never appears in `window.__lluiComponents`, never sets
485
+ // `window.__lluiDebug`, and is invisible to MCP / agent client /
486
+ // devtools console — so a vike SSR app's outermost layout silently
487
+ // drops out of every observability surface.
488
+ if (devToolsInstall)
489
+ devToolsInstall(inst);
476
490
  // Build the component DOM and swap atomically with server HTML.
477
491
  // Server HTML remains visible until JS finishes — no flash.
478
492
  // onMount callbacks are collected in a queue and flushed synchronously
@@ -493,59 +507,28 @@ export function hydrateApp(container, def, serverState, options) {
493
507
  container.replaceChildren(...nodes);
494
508
  // Flush onMount callbacks synchronously now that the DOM is in place.
495
509
  flushMountQueue(onMountQueue);
496
- // Fire the original init's effects post-swap, matching mountApp's
497
- // lifecycle. Previously these were silently dropped.
498
- dispatchInitialEffects(inst);
510
+ // Hydration: skip init's effects by default. The SSR pass already ran
511
+ // them on the server; re-running on the client typically produces
512
+ // duplicate work (double fetches, double subscriptions). Opt back in
513
+ // via `MountOptions.runInitEffectsOnHydrate: true` for projects that
514
+ // need the post-swap dispatch (typically when `init()` is gated by
515
+ // a `loaded` flag and returns `[]` on the server).
516
+ if (options?.runInitEffectsOnHydrate) {
517
+ dispatchInitialEffects(inst);
518
+ }
519
+ else {
520
+ warnDroppedInitEffects(inst, 'hydrateApp');
521
+ }
499
522
  registerInstance(inst);
500
- let disposed = false;
501
- const listeners = new Set();
502
- inst._onCommit = (state) => {
503
- for (const l of Array.from(listeners)) {
504
- try {
505
- l(state);
506
- }
507
- catch (err) {
508
- console.error('[llui] listener threw:', err);
509
- }
510
- }
511
- };
512
- return {
513
- dispose() {
514
- if (disposed)
515
- return;
516
- disposed = true;
517
- listeners.clear();
518
- inst._onCommit = undefined;
519
- inst.abortController.abort();
520
- unregisterInstance(inst);
521
- // Tag the root scope so the disposer log reports app-level
522
- // teardown distinct from in-tree component-unmount events.
523
- inst.rootLifetime.disposalCause = 'app-unmount';
524
- disposeLifetime(inst.rootLifetime);
525
- container.textContent = '';
526
- },
527
- flush() {
528
- if (disposed)
529
- return;
530
- flushInstance(inst);
531
- },
532
- send(msg) {
533
- if (disposed)
534
- return;
535
- inst.send(msg);
536
- },
537
- getState() {
538
- if (disposed) {
539
- throw new Error('[LLui] AppHandle.getState() called after dispose — handle is dead.');
540
- }
541
- return inst.state;
542
- },
543
- subscribe(listener) {
544
- if (disposed)
545
- return () => { };
546
- listeners.add(listener);
547
- return () => listeners.delete(listener);
548
- },
549
- };
523
+ // HMR registration — same as mountApp / mountAtAnchor /
524
+ // hydrateAtAnchor. Without it, replaceComponent(name, newDef)
525
+ // silently no-ops on the hydrated layout layer because the HMR
526
+ // registry has no entry for it.
527
+ if (hmrModule && hydrateDef.name) {
528
+ hmrModule.registerForHmr(hydrateDef.name, inst, container);
529
+ }
530
+ return buildAppHandle(inst, hydrateDef.name ?? null, () => {
531
+ container.textContent = '';
532
+ });
550
533
  }
551
534
  //# sourceMappingURL=mount.js.map
package/dist/mount.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle, Lifetime } from './types.js'\nimport { type DomEnv, browserEnv } from './dom-env.js'\nimport { createComponentInstance, flushInstance, type ComponentInstance } from './update-loop.js'\nimport { disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { 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/** @internal Called by enableHmr in the hmr module */\nexport function _setHmrModule(m: typeof import('./hmr')): void {\n hmrModule = m\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\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\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n // HMR: if this component is already mounted (module re-execution\n // during hot update), swap the definition instead of creating a new instance.\n // HMR swap bypasses parentLifetime — HMR re-mounts the outermost app handle,\n // which in a layout setup means the layout re-mounts at the root and the\n // rest of the chain is re-established via the normal mount path.\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponent(def.name, def)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import\n if (devToolsInstall) devToolsInstall(inst)\n\n // Dev-only: warn if initial state contains non-serializable values.\n // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n // Run view() within a render context so primitives can register bindings.\n // Also collect onMount callbacks in a queue we'll flush synchronously\n // after node insertion — prevents the race where a user event fires\n // between mount and the queueMicrotask callback running.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout-invalidating operation\n // instead of N individual appendChild calls on a live container element.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n container.appendChild(frag)\n } else if (nodes.length === 1) {\n container.appendChild(nodes[0]!)\n }\n\n // Flush onMount callbacks SYNCHRONOUSLY now that the DOM is in place.\n // Any listeners they attach are ready before this function returns,\n // so a synchronous dispatchEvent in the caller's next line fires\n // against a fully-wired tree.\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForHmr(def.name, inst, container)\n }\n dispatchInitialEffects(inst)\n 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 && def.name) hmrModule.unregisterForHmr(def.name, 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 container.textContent = ''\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 }\n}\n\n// Walks an object graph looking for non-JSON-serializable values. Returns the\n// first offender found (depth-first), or null if everything is fine. Stops at\n// depth 6 to bound runtime cost for large states.\nfunction findNonSerializable(\n v: unknown,\n path = 'state',\n depth = 0,\n seen = new WeakSet<object>(),\n): { path: string; value: unknown } | null {\n if (depth > 6) return null\n if (v === null || v === undefined) return null\n const t = typeof v\n if (t === 'string' || t === 'number' || t === 'boolean') return null\n if (t === 'function') return { path, value: v }\n if (t === 'symbol' || t === 'bigint') return { path, value: v }\n if (t !== 'object') return null\n const obj = v as object\n if (seen.has(obj)) return null\n seen.add(obj)\n if (obj instanceof Date) return { path: `${path} (Date)`, value: v }\n if (obj instanceof Map) return { path: `${path} (Map)`, value: v }\n if (obj instanceof Set) return { path: `${path} (Set)`, value: v }\n if (obj instanceof RegExp) return { path: `${path} (RegExp)`, value: v }\n if (obj instanceof Promise) return { path: `${path} (Promise)`, value: v }\n // Plain objects/arrays have Object.prototype / Array.prototype. Class instances\n // have a different prototype.\n const proto = Object.getPrototypeOf(obj)\n if (proto !== null && proto !== Object.prototype && proto !== Array.prototype) {\n return { path: `${path} (${proto?.constructor?.name ?? 'class instance'})`, value: v }\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const r = findNonSerializable(v[i], `${path}[${i}]`, depth + 1, seen)\n if (r) return r\n }\n return null\n }\n for (const k of Object.keys(obj)) {\n const r = findNonSerializable(\n (obj as Record<string, unknown>)[k],\n `${path}.${k}`,\n depth + 1,\n seen,\n )\n if (r) return r\n }\n return null\n}\n\n/**\n * Mount a component relative to a comment anchor rather than inside a\n * container element. Inserts a synthesized end sentinel (`<!-- llui-mount-end -->`)\n * immediately after the anchor and places the component's nodes between\n * the pair. The anchor must already be attached to a live DOM tree.\n *\n * Unlike `mountApp`, the caller's anchor node is preserved across the\n * handle's lifetime — only the content between the pair (and the end\n * sentinel itself) is disposed. Used by `@llui/vike` persistent layouts\n * to mount chain layers without a wrapper element.\n *\n * If a pre-existing `<!-- llui-mount-end -->` is found after the anchor\n * (e.g. stale from an undisposed prior mount), the content between the\n * anchor and that sentinel is swept and the sentinel is reused. Dev mode\n * warns in that case.\n */\nexport function mountAtAnchor<S, M, E>(\n anchor: Comment,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] mountAtAnchor: anchor comment must be attached to a live DOM tree before mount`,\n )\n }\n\n // Locate or synthesize the end sentinel.\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n if (import.meta.env?.DEV) {\n console.warn(\n `[LLui] mountAtAnchor: anchor has a pre-existing end sentinel. ` +\n `A prior mount was not disposed — sweeping stale siblings and reusing the sentinel.`,\n )\n }\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n // Use the caller-provided env if any — end-sentinel creation happens\n // before `inst` exists, so we pick the env directly from options.\n // (browserEnv() fallback matches what createComponentInstance will\n // use below when options.env is undefined.)\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n if (devToolsInstall) devToolsInstall(inst)\n\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout pass instead of N.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\n 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 && def.name) hmrModule.unregisterForHmr(def.name, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\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('[LLui] AppHandle.getState() called after dispose — handle is dead.')\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 }\n}\n\n/**\n * Hydrate a component relative to a comment anchor rather than inside a\n * container element. Analogous to `hydrateApp` — uses `serverState` as\n * the initial state (not `init()`'s output) while preserving `init()`'s\n * effects for post-mount dispatch.\n *\n * The DOM-handling path is identical to `mountAtAnchor`: reuses a\n * pre-existing end sentinel when present, synthesizes one otherwise.\n * Atomic-swaps the owned region whether or not server content is there\n * to replace. No error for a missing end sentinel — the vike chain's\n * outer `hydrateApp`'s `replaceChildren` wipes inner layers' sentinels,\n * so inner-layer `hydrateAtAnchor` calls routinely find nothing to\n * reuse, and that's normal.\n */\nexport function hydrateAtAnchor<S, M, E, D = void>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] hydrateAtAnchor: anchor comment must be attached to a live DOM tree before hydrate`,\n )\n }\n\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n // Run original init() to capture effects, then override state with server's.\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n if (devToolsInstall) devToolsInstall(inst)\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\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 && def.name) hmrModule.unregisterForHmr(def.name, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\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('[LLui] AppHandle.getState() called after dispose — handle is dead.')\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 }\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\nexport function hydrateApp<S, M, E, D = void>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n // Run the original init once to capture its effects. The state it\n // returns is discarded — we use `serverState` (what the server\n // rendered with) instead. The effects are preserved and dispatched\n // after the DOM is in place, so components that rely on \"load data\n // or wire subscriptions on mount\" behave consistently between fresh\n // mount and SSR+hydrate. If the original init has already-loaded\n // data for the hydration case, gate the effect emission inside init\n // itself (e.g. based on a `loaded` flag in state).\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n // 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 // Fire the original init's effects post-swap, matching mountApp's\n // lifecycle. Previously these were silently dropped.\n dispatchInitialEffects(inst)\n\n registerInstance(inst)\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 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 container.textContent = ''\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('[LLui] AppHandle.getState() called after dispose — handle is dead.')\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 }\n}\n"]}
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, AppHandle, Lifetime } from './types.js'\nimport { type DomEnv, browserEnv } from './dom-env.js'\nimport { createComponentInstance, flushInstance, type ComponentInstance } from './update-loop.js'\nimport { disposeLifetime } from './lifetime.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { getBindingDescriptors } from './binding-descriptors.js'\nimport { registerInstance, unregisterInstance } from './runtime.js'\nimport { createView } from './view-helpers.js'\nimport { pushMountQueue, popMountQueue, flushMountQueue } from './primitives/on-mount.js'\n\n// ── Sentinel-region helpers (used by anchor-based mount primitives) ─────\n\n/**\n * Remove every sibling from `anchor.nextSibling` up to but not including\n * `stopBefore`. Used by anchor-based mount primitives and their HMR\n * swap path to clear the owned DOM region between the pair.\n */\nfunction _removeBetween(anchor: Comment, stopBefore: Comment): void {\n const parent = anchor.parentNode\n if (parent === null) return\n while (anchor.nextSibling !== null && anchor.nextSibling !== stopBefore) {\n parent.removeChild(anchor.nextSibling)\n }\n}\n\n/**\n * Walk forward from `anchor.nextSibling` looking for an existing\n * `<!-- llui-mount-end -->` sentinel. Used by mount/hydrate at anchor\n * to reuse a server-emitted (or stale) sentinel rather than synthesizing\n * a duplicate. Returns null if no matching comment is found before the\n * end of the parent's children.\n */\nfunction _findEndSentinel(anchor: Comment): Comment | null {\n let node: Node | null = anchor.nextSibling\n while (node !== null) {\n if (node.nodeType === 8 && (node as Comment).nodeValue === 'llui-mount-end') {\n return node as Comment\n }\n node = node.nextSibling\n }\n return null\n}\n\n// Vite injects import.meta.env.DEV — declare the shape for TypeScript\ndeclare global {\n interface ImportMeta {\n env?: { DEV?: boolean }\n }\n}\n\n// ── HMR (dev only) ──────────────────────────────────────────────\n// Set by enableHmr() from '@llui/dom/hmr' — never imported in production.\n\nlet hmrModule: typeof import('./hmr') | null = null\n\n/**\n * @internal Called by enableHmr in the hmr module. Tests use this\n * (paired with `_getHmrModule`) to snapshot/restore prior state across\n * suite boundaries — pass `null` to clear.\n */\nexport function _setHmrModule(m: typeof import('./hmr') | null): void {\n hmrModule = m\n}\n\n/** @internal Read the currently-installed HMR module (or null). */\nexport function _getHmrModule(): typeof import('./hmr') | null {\n return hmrModule\n}\n\n// ── DevTools auto-install (dev only) ────────────────────────────\n// Set by enableDevTools() from '@llui/dom/devtools' — never imported in production.\n\nlet devToolsInstall: ((inst: object) => void) | null = null\n\n/** @internal Called by enableDevTools in the devtools module */\nexport function _setDevToolsInstall(fn: ((inst: object) => void) | null): void {\n devToolsInstall = fn\n}\n\n/** @internal Read the currently-installed devtools-install hook (or null). */\nexport function _getDevToolsInstall(): ((inst: object) => void) | null {\n return devToolsInstall\n}\n\nexport interface MountOptions {\n devTools?: boolean\n /**\n * Parent scope for the mounted component's rootLifetime. When provided,\n * the rootLifetime is created as a child of this scope — context lookups\n * from within the component walk up through the parent's scope tree,\n * and disposing the parent scope cascades into this instance's scope.\n * Used by `@llui/vike`'s persistent-layout machinery to mount a page\n * as a true scope-tree child of its enclosing layout, so layout-\n * provided contexts flow naturally into pages via `useContext`.\n *\n * When omitted (the default), the rootLifetime is detached — same as\n * every `mountApp` call before persistent layouts existed.\n */\n parentLifetime?: Lifetime\n /**\n * DOM env override. Defaults to `browserEnv()` — wraps the browser\n * globals. Specify only when mounting into a non-browser DOM (e.g.\n * a jsdom instance held by a test harness, or isolated DOM per\n * shadow root).\n */\n env?: DomEnv\n /**\n * **`hydrateApp` / `hydrateAtAnchor` only.** When `true`, fire the\n * effects that `init()` returned during hydration the same way\n * `mountApp` does on a fresh mount. Defaults to `false` because the\n * SSR render already ran `init()` on the server, and re-running its\n * effects on the client typically produces duplicate work — an\n * `httpGet` issued from `init()` would fetch on the server *and* on\n * hydration; a subscription would attach twice; etc.\n *\n * Opt in only when:\n * - `init()` returns no effects, OR\n * - all returned effects are idempotent / client-only (e.g.\n * wiring a `window` event listener, opening a `WebSocket`), AND\n * - the SSR path didn't run them (typically when `init()` checks a\n * `loaded` flag in state and returns `[]` on the server).\n *\n * Pre-0.0.31 behavior was to always run init effects on hydrate;\n * the option preserves it on demand for projects that depended on\n * it. The default-off direction matches the safer expectation that\n * \"hydration should be cheap and side-effect-free.\"\n */\n runInitEffectsOnHydrate?: boolean\n}\n\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountApp<S, M, E, D>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n // HMR: if this component is already mounted (module re-execution\n // during hot update), swap the definition instead of creating a new instance.\n // HMR swap bypasses parentLifetime — HMR re-mounts the outermost app handle,\n // which in a layout setup means the layout re-mounts at the root and the\n // rest of the chain is re-established via the normal mount path.\n if (hmrModule && def.name && !options?.parentLifetime) {\n const swapped = hmrModule.replaceComponent(def.name, def)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import\n if (devToolsInstall) devToolsInstall(inst)\n\n // Dev-only: warn if initial state contains non-serializable values.\n // Silent bug-bomb: Date/Map/Set/class instances break SSR, hydration, replay tools.\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n // Run view() within a render context so primitives can register bindings.\n // Also collect onMount callbacks in a queue we'll flush synchronously\n // after node insertion — prevents the race where a user event fires\n // between mount and the queueMicrotask callback running.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout-invalidating operation\n // instead of N individual appendChild calls on a live container element.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n container.appendChild(frag)\n } else if (nodes.length === 1) {\n container.appendChild(nodes[0]!)\n }\n\n // Flush onMount callbacks SYNCHRONOUSLY now that the DOM is in place.\n // Any listeners they attach are ready before this function returns,\n // so a synchronous dispatchEvent in the caller's next line fires\n // against a fully-wired tree.\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForHmr(def.name, inst, container)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n container.textContent = ''\n })\n}\n\n// Walks an object graph looking for non-JSON-serializable values. Returns the\n// first offender found (depth-first), or null if everything is fine. Stops at\n// depth 6 to bound runtime cost for large states.\nfunction findNonSerializable(\n v: unknown,\n path = 'state',\n depth = 0,\n seen = new WeakSet<object>(),\n): { path: string; value: unknown } | null {\n if (depth > 6) return null\n if (v === null || v === undefined) return null\n const t = typeof v\n if (t === 'string' || t === 'number' || t === 'boolean') return null\n if (t === 'function') return { path, value: v }\n if (t === 'symbol' || t === 'bigint') return { path, value: v }\n if (t !== 'object') return null\n const obj = v as object\n if (seen.has(obj)) return null\n seen.add(obj)\n if (obj instanceof Date) return { path: `${path} (Date)`, value: v }\n if (obj instanceof Map) return { path: `${path} (Map)`, value: v }\n if (obj instanceof Set) return { path: `${path} (Set)`, value: v }\n if (obj instanceof RegExp) return { path: `${path} (RegExp)`, value: v }\n if (obj instanceof Promise) return { path: `${path} (Promise)`, value: v }\n // Plain objects/arrays have Object.prototype / Array.prototype. Class instances\n // have a different prototype.\n const proto = Object.getPrototypeOf(obj)\n if (proto !== null && proto !== Object.prototype && proto !== Array.prototype) {\n return { path: `${path} (${proto?.constructor?.name ?? 'class instance'})`, value: v }\n }\n if (Array.isArray(v)) {\n for (let i = 0; i < v.length; i++) {\n const r = findNonSerializable(v[i], `${path}[${i}]`, depth + 1, seen)\n if (r) return r\n }\n return null\n }\n for (const k of Object.keys(obj)) {\n const r = findNonSerializable(\n (obj as Record<string, unknown>)[k],\n `${path}.${k}`,\n depth + 1,\n seen,\n )\n if (r) return r\n }\n return null\n}\n\n/**\n * Mount a component relative to a comment anchor rather than inside a\n * container element. Inserts a synthesized end sentinel (`<!-- llui-mount-end -->`)\n * immediately after the anchor and places the component's nodes between\n * the pair. The anchor must already be attached to a live DOM tree.\n *\n * Unlike `mountApp`, the caller's anchor node is preserved across the\n * handle's lifetime — only the content between the pair (and the end\n * sentinel itself) is disposed. Used by `@llui/vike` persistent layouts\n * to mount chain layers without a wrapper element.\n *\n * If a pre-existing `<!-- llui-mount-end -->` is found after the anchor\n * (e.g. stale from an undisposed prior mount), the content between the\n * anchor and that sentinel is swept and the sentinel is reused. Dev mode\n * warns in that case.\n */\nexport function mountAtAnchor<S, M, E>(\n anchor: Comment,\n def: ComponentDef<S, M, E>,\n data?: undefined,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data: D,\n options?: MountOptions,\n): AppHandle\nexport function mountAtAnchor<S, M, E, D>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n data?: D,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] mountAtAnchor: anchor comment must be attached to a live DOM tree before mount`,\n )\n }\n\n // Locate or synthesize the end sentinel.\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n if (import.meta.env?.DEV) {\n console.warn(\n `[LLui] mountAtAnchor: anchor has a pre-existing end sentinel. ` +\n `A prior mount was not disposed — sweeping stale siblings and reusing the sentinel.`,\n )\n }\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n // Use the caller-provided env if any — end-sentinel creation happens\n // before `inst` exists, so we pick the env directly from options.\n // (browserEnv() fallback matches what createComponentInstance will\n // use below when options.env is undefined.)\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n const inst = createComponentInstance(def, data, options?.parentLifetime ?? null, options?.env)\n\n if (devToolsInstall) devToolsInstall(inst)\n\n if (import.meta.env?.DEV) {\n const offender = findNonSerializable(inst.state)\n if (offender) {\n console.warn(\n `[LLui] <${def.name}> initial state contains a non-serializable value at \"${offender.path}\":`,\n offender.value,\n '\\nState must be plain JSON (no Date/Map/Set/class instances/functions).' +\n '\\nThis will break SSR hydration, state replay, and devtools snapshots.' +\n '\\nhint: Convert to a serializable representation (e.g., Date → ISO string, Map → Record).',\n )\n }\n }\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Batch-insert via DocumentFragment — one layout pass instead of N.\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n dispatchInitialEffects(inst)\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\n/**\n * Hydrate a component relative to a comment anchor rather than inside a\n * container element. Analogous to `hydrateApp` — uses `serverState` as\n * the initial state (not `init()`'s output) while preserving `init()`'s\n * effects for post-mount dispatch.\n *\n * The DOM-handling path is identical to `mountAtAnchor`: reuses a\n * pre-existing end sentinel when present, synthesizes one otherwise.\n * Atomic-swaps the owned region whether or not server content is there\n * to replace. No error for a missing end sentinel — the vike chain's\n * outer `hydrateApp`'s `replaceChildren` wipes inner layers' sentinels,\n * so inner-layer `hydrateAtAnchor` calls routinely find nothing to\n * reuse, and that's normal.\n */\nexport function hydrateAtAnchor<S, M, E, D = void>(\n anchor: Comment,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n if (anchor.parentNode === null) {\n throw new Error(\n `[LLui] hydrateAtAnchor: anchor comment must be attached to a live DOM tree before hydrate`,\n )\n }\n\n const existingEnd = _findEndSentinel(anchor)\n let endSentinel: Comment\n if (existingEnd !== null) {\n _removeBetween(anchor, existingEnd)\n endSentinel = existingEnd\n } else {\n endSentinel = (options?.env ?? browserEnv()).createComment('llui-mount-end')\n anchor.parentNode.insertBefore(endSentinel, anchor.nextSibling)\n }\n\n // Run original init() to capture effects, then override state with server's.\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n if (devToolsInstall) devToolsInstall(inst)\n\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container: anchor.parentElement ?? undefined,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n if (nodes.length > 1) {\n const frag = inst.dom.createDocumentFragment()\n for (const node of nodes) frag.appendChild(node)\n anchor.parentNode.insertBefore(frag, endSentinel)\n } else if (nodes.length === 1) {\n anchor.parentNode.insertBefore(nodes[0]!, endSentinel)\n }\n\n flushMountQueue(onMountQueue)\n\n registerInstance(inst)\n if (hmrModule && def.name) {\n hmrModule.registerForAnchor(def.name, inst, anchor, endSentinel)\n }\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true`.\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateAtAnchor')\n }\n return buildAppHandle(inst, def.name ?? null, () => {\n _removeBetween(anchor, endSentinel)\n endSentinel.parentNode?.removeChild(endSentinel)\n })\n}\n\nfunction dispatchInitialEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n): void {\n if (inst.initialEffects.length === 0 || !inst.def.onEffect) return\n for (const effect of inst.initialEffects) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n inst.initialEffects = []\n}\n\n/**\n * Dev-only warning when a hydrate path silently drops a non-empty\n * `initialEffects` array. The default-skip behavior is deliberate (the\n * server already ran them), but if `init()` produces effects that\n * weren't run on the server — typically client-only init pipelines —\n * silent drop is a footgun. Surface the count and the opt-in.\n */\nfunction warnDroppedInitEffects<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n via: 'hydrateApp' | 'hydrateAtAnchor',\n): void {\n if (!import.meta.env?.DEV) return\n if (inst.initialEffects.length === 0) return\n const name = inst.def.name ?? '<anonymous>'\n console.warn(\n `[LLui] ${via}: skipped ${inst.initialEffects.length} init effect(s) for \"${name}\". ` +\n `Hydration drops init effects by default since the server already ran them. ` +\n `If these effects only fire on the client, pass \\`runInitEffectsOnHydrate: true\\` to opt in.`,\n )\n}\n\n/**\n * Build the `AppHandle` returned by every mount/hydrate path. Captures\n * the `_onCommit` listener registry, the `disposed` flag, and the\n * standard `flush` / `send` / `getState` / `subscribe` shape — all\n * code that was previously duplicated four times across `mountApp`,\n * `mountAtAnchor`, `hydrateApp`, and `hydrateAtAnchor`.\n *\n * Variation lives in the two parameters:\n * - `hmrName` — the def's name used to call `hmrModule.unregisterForHmr`\n * on dispose. Pass `null` to skip HMR unregistration (no current\n * mount path needs that, but it keeps the helper honest).\n * - `domCleanup` — final teardown step that detaches mounted nodes.\n * Container-rooted paths set `container.textContent = ''`;\n * anchor-rooted paths call `_removeBetween(anchor, endSentinel)`\n * and detach the end sentinel. Runs LAST in the dispose chain to\n * match the historical ordering exactly (lifetime is disposed\n * before nodes are detached, so binding teardown sees attached\n * DOM until the very end).\n *\n * The mount-path-parity test in `mount-path-parity.test.ts` enforces\n * that each public entry point produces structurally identical\n * AppHandle behavior — this helper is the realisation of that\n * promise.\n */\nfunction buildAppHandle<S, M, E>(\n inst: ReturnType<typeof createComponentInstance<S, M, E>>,\n hmrName: string | null,\n domCleanup: () => void,\n): AppHandle {\n let disposed = false\n const listeners = new Set<(s: unknown) => void>()\n\n inst._onCommit = (state: unknown) => {\n for (const l of Array.from(listeners)) {\n try {\n l(state)\n } catch (err) {\n console.error('[llui] listener threw:', err)\n }\n }\n }\n\n return {\n dispose() {\n if (disposed) return\n disposed = true\n listeners.clear()\n inst._onCommit = undefined\n if (hmrModule && hmrName) hmrModule.unregisterForHmr(hmrName, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n // Tag the root scope so the disposer log reports app-level\n // teardown distinct from in-tree component-unmount events.\n inst.rootLifetime.disposalCause = 'app-unmount'\n disposeLifetime(inst.rootLifetime)\n domCleanup()\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\n },\n send(msg: unknown) {\n if (disposed) return\n ;(inst.send as (m: unknown) => void)(msg)\n },\n getState() {\n if (disposed) {\n throw new Error(\n '[LLui] AppHandle.getState() called after dispose — handle is dead. ' +\n 'Detach your event listener / cancel your timer when the handle ' +\n 'is disposed to avoid stale reads.',\n )\n }\n return inst.state\n },\n subscribe(listener: (state: unknown) => void) {\n if (disposed) return () => {}\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n getBindingDescriptors() {\n if (disposed) return []\n return getBindingDescriptors(inst as ComponentInstance)\n },\n swapUpdate(newUpdate, newOnEffect) {\n if (disposed) return\n // Drain pending messages with the OLD update first — anything\n // already in the queue was constructed under the old contract,\n // and re-routing it through a new reducer mid-flight could mix\n // half of one transition with half of another (e.g. a payload\n // shape the new update no longer accepts).\n flushInstance(inst)\n // Mutate the def in place so subsequent `inst.def.update`\n // reads — including the per-message read in `flushInstance`'s\n // generic loop — pick up the new function. We deliberately\n // don't replace `inst.def` itself: existing closures, the\n // `__update` fast path, and `__handlers` all stay valid; only\n // the user-visible reducer function changes.\n ;(inst.def as { update: typeof newUpdate }).update = newUpdate\n if (newOnEffect !== undefined) {\n ;(inst.def as { onEffect?: typeof newOnEffect }).onEffect = newOnEffect\n }\n },\n runReducer(msg) {\n if (disposed) return null\n // Direct invocation against current state. No subscribe, no\n // flush, no effect handler. The reducer's contract per TEA is\n // a pure function — calling it twice with the same args is a\n // no-op other than allocations. Returning the raw tuple\n // shape lets the agent inspect both halves without interpreting.\n const [state, effects] = (\n inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]]\n )(inst.state, msg)\n return { state, effects: effects as unknown[] }\n },\n }\n}\n\nexport function hydrateApp<S, M, E, D = void>(\n container: HTMLElement,\n def: ComponentDef<S, M, E, D>,\n serverState: S,\n options?: MountOptions,\n): AppHandle {\n // Run the original init once to capture its effects. The state it\n // returns is discarded — we use `serverState` (what the server\n // rendered with) instead. The effects are preserved and dispatched\n // after the DOM is in place, so components that rely on \"load data\n // or wire subscriptions on mount\" behave consistently between fresh\n // mount and SSR+hydrate. If the original init has already-loaded\n // data for the hydration case, gate the effect emission inside init\n // itself (e.g. based on a `loaded` flag in state).\n const [, originalEffects] = (def.init as (data: unknown) => [S, E[]])(undefined)\n\n const hydrateDef: ComponentDef<S, M, E> = {\n ...def,\n init: () => [serverState, originalEffects],\n }\n\n const inst = createComponentInstance(\n hydrateDef,\n undefined,\n options?.parentLifetime ?? null,\n options?.env,\n )\n\n // Dev-only: auto-install devtools if enabled via '@llui/dom/devtools'\n // import. The other three mount paths (mountApp / mountAtAnchor /\n // hydrateAtAnchor) all call this; without it, the hydrated layout\n // never appears in `window.__lluiComponents`, never sets\n // `window.__lluiDebug`, and is invisible to MCP / agent client /\n // devtools console — so a vike SSR app's outermost layout silently\n // drops out of every observability surface.\n if (devToolsInstall) devToolsInstall(inst)\n\n // Build the component DOM and swap atomically with server HTML.\n // Server HTML remains visible until JS finishes — no flash.\n // onMount callbacks are collected in a queue and flushed synchronously\n // after the swap, matching mountApp's ordering.\n const { queue: onMountQueue, prev: prevMountQueue } = pushMountQueue()\n setFlatBindings(inst.allBindings)\n setRenderContext({\n ...inst,\n container,\n send: inst.send as (msg: unknown) => void,\n instance: inst as ComponentInstance,\n })\n const nodes = hydrateDef.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n popMountQueue(prevMountQueue)\n\n // Atomic swap — replaces server HTML with client DOM in one operation\n container.replaceChildren(...nodes)\n\n // Flush onMount callbacks synchronously now that the DOM is in place.\n flushMountQueue(onMountQueue)\n\n // Hydration: skip init's effects by default. The SSR pass already ran\n // them on the server; re-running on the client typically produces\n // duplicate work (double fetches, double subscriptions). Opt back in\n // via `MountOptions.runInitEffectsOnHydrate: true` for projects that\n // need the post-swap dispatch (typically when `init()` is gated by\n // a `loaded` flag and returns `[]` on the server).\n if (options?.runInitEffectsOnHydrate) {\n dispatchInitialEffects(inst)\n } else {\n warnDroppedInitEffects(inst, 'hydrateApp')\n }\n\n registerInstance(inst)\n // HMR registration — same as mountApp / mountAtAnchor /\n // hydrateAtAnchor. Without it, replaceComponent(name, newDef)\n // silently no-ops on the hydrated layout layer because the HMR\n // registry has no entry for it.\n if (hmrModule && hydrateDef.name) {\n hmrModule.registerForHmr(hydrateDef.name, inst, container)\n }\n return buildAppHandle(inst, hydrateDef.name ?? null, () => {\n container.textContent = ''\n })\n}\n"]}
@@ -1,11 +1,23 @@
1
1
  /**
2
2
  * Read current state inside a render context and return the result of
3
3
  * `selector(state)`. No binding is created, no mask is assigned — this
4
- * is a one-shot imperative read.
4
+ * is a one-shot imperative read at view-construction time.
5
5
  *
6
- * Use when a builder needs the current state snapshot (e.g. to pass
7
- * an object to an imperative renderer), and a reactive binding would
8
- * be wrong semantically.
6
+ * **Don't use for variable-length lists.** Wrapping a list-render in
7
+ * `sample` looks idiomatic but silently breaks reactivity: the
8
+ * `.map(...)` runs once at construction, captures the row objects in
9
+ * closure, and never re-runs when state updates in place. The cells
10
+ * inside the captured rows show stale data; only a full structural
11
+ * rebuild (e.g. a parent `branch` swapping arms) will refresh them.
12
+ * Use `each` + `ItemAccessor` instead — see the "List of editable
13
+ * rows" recipe in the cookbook.
14
+ *
15
+ * **Use for** passing a state snapshot to an imperative renderer
16
+ * (foreign libraries, third-party canvas/svg builders), reading a
17
+ * value to compute a static piece of structure that doesn't need to
18
+ * react, or any case where a reactive binding would be semantically
19
+ * wrong (e.g. capturing a value at *this exact moment* for a
20
+ * one-shot side effect).
9
21
  *
10
22
  * Also exposed as `h.sample` on the View bag for destructure-from-`h`
11
23
  * ergonomics. The top-level import form works everywhere a render
@@ -1 +1 @@
1
- {"version":3,"file":"sample.d.ts","sourceRoot":"","sources":["../../src/primitives/sample.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAGrD"}
1
+ {"version":3,"file":"sample.d.ts","sourceRoot":"","sources":["../../src/primitives/sample.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAGrD"}