@llui/dom 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/el-split.d.ts +1 -1
- package/dist/el-split.d.ts.map +1 -1
- package/dist/el-split.js +22 -3
- package/dist/el-split.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +22 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +21 -0
- package/dist/internal.js.map +1 -0
- package/dist/mount.d.ts +16 -3
- package/dist/mount.d.ts.map +1 -1
- package/dist/mount.js +8 -5
- package/dist/mount.js.map +1 -1
- package/dist/ssr.d.ts +32 -1
- package/dist/ssr.d.ts.map +1 -1
- package/dist/ssr.js +44 -38
- package/dist/ssr.js.map +1 -1
- package/dist/update-loop.d.ts +1 -1
- package/dist/update-loop.d.ts.map +1 -1
- package/dist/update-loop.js +8 -2
- package/dist/update-loop.js.map +1 -1
- package/package.json +5 -1
package/dist/el-split.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BindingKind } from './types.js';
|
|
2
|
-
export declare function elSplit(tag: string, staticFn: ((el: HTMLElement) => void) | null, events: Array<[string, EventListener]> | null, bindings: Array<[number, BindingKind, string, (state: never) => unknown]> | null, children: Array<Node | string
|
|
2
|
+
export declare function elSplit(tag: string, staticFn: ((el: HTMLElement) => void) | null, events: Array<[string, EventListener]> | null, bindings: Array<[number, BindingKind, string, (state: never) => unknown]> | null, children: Array<Node | string | Array<Node | string>> | null): HTMLElement;
|
|
3
3
|
//# sourceMappingURL=el-split.d.ts.map
|
package/dist/el-split.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"el-split.d.ts","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAK7C,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,EAC5C,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,EAC7C,QAAQ,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"el-split.d.ts","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAK7C,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,EAC5C,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,EAC7C,QAAQ,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,EAMhF,QAAQ,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,GAC3D,WAAW,CAsEb"}
|
package/dist/el-split.js
CHANGED
|
@@ -2,9 +2,11 @@ import { getRenderContext } from './render-context.js';
|
|
|
2
2
|
import { createBinding, applyBinding } from './binding.js';
|
|
3
3
|
import { addCheckedItemUpdater } from './scope.js';
|
|
4
4
|
export function elSplit(tag, staticFn, events, bindings,
|
|
5
|
-
// Accepts raw strings too
|
|
6
|
-
// user code like `button([], ['Sign in'])` works without
|
|
7
|
-
//
|
|
5
|
+
// Accepts raw strings too (wrapped in Text nodes at append time so
|
|
6
|
+
// user code like `button([], ['Sign in'])` works without an explicit
|
|
7
|
+
// text() wrapper) and nested arrays (flattened one level to match the
|
|
8
|
+
// raw createElement path — supports patterns like `main([pageSlot()])`
|
|
9
|
+
// where pageSlot() returns Node[]).
|
|
8
10
|
children) {
|
|
9
11
|
const el = document.createElement(tag);
|
|
10
12
|
if (staticFn) {
|
|
@@ -50,6 +52,23 @@ children) {
|
|
|
50
52
|
if (typeof child === 'string') {
|
|
51
53
|
el.appendChild(document.createTextNode(child));
|
|
52
54
|
}
|
|
55
|
+
else if (Array.isArray(child)) {
|
|
56
|
+
// Arrays-in-children are flattened one level. This matches
|
|
57
|
+
// the raw createElement path in elements.ts and makes patterns
|
|
58
|
+
// like `main([pageSlot()])` (where pageSlot() returns Node[])
|
|
59
|
+
// work consistently between raw and compiled call paths.
|
|
60
|
+
// Without this flattening, tests run via vitest pass (raw path
|
|
61
|
+
// flattens) but SSR via the compiler transform crashes with
|
|
62
|
+
// "appendChild parameter is not of type Node".
|
|
63
|
+
for (const node of child) {
|
|
64
|
+
if (typeof node === 'string') {
|
|
65
|
+
el.appendChild(document.createTextNode(node));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
el.appendChild(node);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
53
72
|
else {
|
|
54
73
|
el.appendChild(child);
|
|
55
74
|
}
|
package/dist/el-split.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"el-split.js","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAElD,MAAM,UAAU,OAAO,CACrB,GAAW,EACX,QAA4C,EAC5C,MAA6C,EAC7C,QAAgF;AAChF,
|
|
1
|
+
{"version":3,"file":"el-split.js","sourceRoot":"","sources":["../src/el-split.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BindingKind } from './types.js'\nimport { getRenderContext } from './render-context.js'\nimport { createBinding, applyBinding } from './binding.js'\nimport { addCheckedItemUpdater } from './scope.js'\n\nexport function elSplit(\n tag: string,\n staticFn: ((el: HTMLElement) => void) | null,\n events: Array<[string, EventListener]> | null,\n bindings: Array<[number, BindingKind, string, (state: never) => unknown]> | null,\n // Accepts raw strings too (wrapped in Text nodes at append time so\n // user code like `button([], ['Sign in'])` works without an explicit\n // text() wrapper) and nested arrays (flattened one level to match the\n // raw createElement path — supports patterns like `main([pageSlot()])`\n // where pageSlot() returns Node[]).\n children: Array<Node | string | Array<Node | string>> | null,\n): HTMLElement {\n const el = document.createElement(tag)\n\n if (staticFn) {\n staticFn(el)\n }\n\n if (events) {\n for (const [eventName, handler] of events) {\n el.addEventListener(eventName, handler)\n }\n }\n\n const ctx = getRenderContext()\n\n if (bindings) {\n for (const [mask, kind, key, accessor] of bindings) {\n const perItem = accessor.length === 0\n if (perItem) {\n const get = accessor as unknown as () => unknown\n const target = { kind, node: el, key }\n const initial = addCheckedItemUpdater(ctx.rootScope, get, (v) => applyBinding(target, v))\n applyBinding(target, initial)\n } else {\n const binding = createBinding(ctx.rootScope, {\n mask,\n accessor,\n kind,\n node: el,\n key,\n perItem: false,\n })\n const initialValue = accessor(ctx.state as never)\n binding.lastValue = initialValue\n applyBinding({ kind, node: el, key }, initialValue)\n }\n }\n }\n\n if (children) {\n for (const child of children) {\n // Strings get wrapped in Text nodes — matches createElement's\n // behavior in elements.ts. Without this, user code that passes\n // raw strings as children (e.g. `button([], ['Sign in'])`) crashes\n // in jsdom with \"parameter 1 is not of type 'Node'\" during SSR\n // and throws a TypeError in strict browsers.\n if (typeof child === 'string') {\n el.appendChild(document.createTextNode(child))\n } else if (Array.isArray(child)) {\n // Arrays-in-children are flattened one level. This matches\n // the raw createElement path in elements.ts and makes patterns\n // like `main([pageSlot()])` (where pageSlot() returns Node[])\n // work consistently between raw and compiled call paths.\n // Without this flattening, tests run via vitest pass (raw path\n // flattens) but SSR via the compiler transform crashes with\n // \"appendChild parameter is not of type Node\".\n for (const node of child) {\n if (typeof node === 'string') {\n el.appendChild(document.createTextNode(node))\n } else {\n el.appendChild(node)\n }\n }\n } else {\n el.appendChild(child)\n }\n }\n }\n\n return el\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { mountApp, hydrateApp, type MountOptions } from './mount.js';
|
|
|
5
5
|
export type { LluiDebugAPI } from './devtools.js';
|
|
6
6
|
export { flush } from './runtime.js';
|
|
7
7
|
export { addressOf } from './addressed.js';
|
|
8
|
-
export { renderToString } from './ssr.js';
|
|
8
|
+
export { renderToString, renderNodes, serializeNodes } from './ssr.js';
|
|
9
9
|
export { mergeHandlers } from './merge-handlers.js';
|
|
10
10
|
export { createContext, provide, useContext, type Context } from './primitives/context.js';
|
|
11
11
|
export { sliceHandler } from './slice-handler.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,YAAY,EACZ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,KAAK,EACL,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAA;AAInB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAIzD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAA;AAGpE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAIjD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { mountApp, hydrateApp } from './mount.js';
|
|
|
7
7
|
// ── Runtime ───────────────────────────────────────────────────────
|
|
8
8
|
export { flush } from './runtime.js';
|
|
9
9
|
export { addressOf } from './addressed.js';
|
|
10
|
-
export { renderToString } from './ssr.js';
|
|
10
|
+
export { renderToString, renderNodes, serializeNodes } from './ssr.js';
|
|
11
11
|
export { mergeHandlers } from './merge-handlers.js';
|
|
12
12
|
export { createContext, provide, useContext } from './primitives/context.js';
|
|
13
13
|
export { sliceHandler } from './slice-handler.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAoBrE,qEAAqE;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAA;AAEzD,qEAAqE;AAErE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAqB,MAAM,YAAY,CAAA;AAKpE,qEAAqE;AAErE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// ── Types ─────────────────────────────────────────────────────────\n\nexport type {\n ComponentDef,\n Send,\n Props,\n AppHandle,\n Scope,\n Binding,\n BindingKind,\n TransitionOptions,\n BranchOptions,\n ShowOptions,\n EachOptions,\n ItemAccessor,\n PortalOptions,\n ForeignOptions,\n ChildOptions,\n} from './types.js'\n\n// ── Component ─────────────────────────────────────────────────────\n\nexport { component } from './component.js'\nexport { createView, type View } from './view-helpers.js'\n\n// ── Mount ─────────────────────────────────────────────────────────\n\nexport { mountApp, hydrateApp, type MountOptions } from './mount.js'\n// installDevTools is NOT re-exported here to keep it out of production bundles.\n// Import directly: import { installDevTools } from '@llui/dom/devtools'\nexport type { LluiDebugAPI } from './devtools.js'\n\n// ── Runtime ───────────────────────────────────────────────────────\n\nexport { flush } from './runtime.js'\nexport { addressOf } from './addressed.js'\nexport { renderToString, renderNodes, serializeNodes } from './ssr.js'\nexport { mergeHandlers } from './merge-handlers.js'\nexport { createContext, provide, useContext, type Context } from './primitives/context.js'\nexport { sliceHandler } from './slice-handler.js'\nexport {\n childHandlers,\n type ChildState,\n type ChildMsg,\n type ModuleState,\n type ModuleMsg,\n} from './compose.js'\n\n// ── View Primitives ───────────────────────────────────────────────\n\nexport { text } from './primitives/text.js'\nexport { branch } from './primitives/branch.js'\nexport { each } from './primitives/each.js'\nexport { virtualEach, type VirtualEachOptions } from './primitives/virtual-each.js'\nexport { show } from './primitives/show.js'\nexport { slice } from './primitives/slice.js'\nexport { portal } from './primitives/portal.js'\nexport { foreign } from './primitives/foreign.js'\nexport { child } from './primitives/child.js'\nexport { lazy, type LazyOptions } from './primitives/lazy.js'\nexport type { LazyDef } from './types.js'\nexport { memo } from './primitives/memo.js'\nexport { selector } from './primitives/selector.js'\nexport { onMount } from './primitives/on-mount.js'\nexport { errorBoundary } from './primitives/error-boundary.js'\n\n// ── Element Helpers ───────────────────────────────────────────────\n\nexport {\n a,\n abbr,\n article,\n aside,\n b,\n blockquote,\n br,\n button,\n canvas,\n code,\n dd,\n details,\n dialog,\n div,\n dl,\n dt,\n em,\n fieldset,\n figcaption,\n figure,\n footer,\n form,\n h1,\n h2,\n h3,\n h4,\n h5,\n h6,\n header,\n hr,\n i,\n iframe,\n img,\n input,\n label,\n legend,\n li,\n main,\n mark,\n nav,\n ol,\n optgroup,\n option,\n output,\n p,\n pre,\n progress,\n section,\n select,\n small,\n span,\n strong,\n sub,\n summary,\n sup,\n table,\n tbody,\n td,\n textarea,\n tfoot,\n th,\n thead,\n time,\n tr,\n ul,\n video,\n} from './elements.js'\n\n// ── SVG Elements ─────────────────────────────────────────────────\n\nexport {\n svg,\n g,\n defs,\n symbol,\n use,\n circle,\n ellipse,\n line,\n path,\n polygon,\n polyline,\n rect,\n text as svgText,\n tspan,\n textPath,\n clipPath,\n linearGradient,\n radialGradient,\n stop,\n mask,\n pattern,\n marker,\n filter,\n feBlend,\n feColorMatrix,\n feComponentTransfer,\n feComposite,\n feConvolveMatrix,\n feDiffuseLighting,\n feDisplacementMap,\n feDropShadow,\n feFlood,\n feGaussianBlur,\n feImage,\n feMerge,\n feMergeNode,\n feMorphology,\n feOffset,\n feSpecularLighting,\n feTile,\n feTurbulence,\n fePointLight,\n feSpotLight,\n feDistantLight,\n feFuncR,\n feFuncG,\n feFuncB,\n feFuncA,\n image,\n foreignObject,\n animate,\n animateMotion,\n animateTransform,\n set,\n mpath,\n desc,\n title as svgTitle,\n metadata,\n} from './svg-elements.js'\n\n// ── MathML Elements ──────────────────────────────────────────────\n\nexport {\n math,\n mi,\n mn,\n mo,\n ms,\n mtext,\n mrow,\n mfrac,\n msqrt,\n mroot,\n msup,\n msub,\n msubsup,\n munder,\n mover,\n munderover,\n mmultiscripts,\n mprescripts,\n mnone,\n mtable,\n mtr,\n mtd,\n mspace,\n mpadded,\n mphantom,\n menclose,\n merror,\n maction,\n semantics,\n annotation,\n annotationXml,\n} from './mathml-elements.js'\n\n// ── Form Utilities ────────────────────────────────────────────────\n\nexport { applyField, type FieldMsg } from './form.js'\n\n// ── Compiler Target ───────────────────────────────────────────────\n\nexport { elSplit } from './el-split.js'\nexport { elTemplate } from './el-template.js'\nexport { _runPhase2 as __runPhase2, _handleMsg as __handleMsg } from './update-loop.js'\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal primitives surface — exported for framework-adapter packages
|
|
3
|
+
* (`@llui/vike`, `@llui/router`, `@llui/transitions`) that need to build
|
|
4
|
+
* their own structural primitives on top of LLui's scope + render-context
|
|
5
|
+
* machinery.
|
|
6
|
+
*
|
|
7
|
+
* **Not part of the public API.** App authors should not import from
|
|
8
|
+
* `@llui/dom/internal`. The shapes here are free to change without a
|
|
9
|
+
* major version bump — the stability contract applies only to the public
|
|
10
|
+
* barrel at `@llui/dom`. Reach for this subpath when you're writing a
|
|
11
|
+
* primitive like `pageSlot()` (from `@llui/vike`) that has to participate
|
|
12
|
+
* in the scope tree, not when you're writing application views.
|
|
13
|
+
*
|
|
14
|
+
* Added in 0.0.16 to support `@llui/vike`'s persistent-layout feature.
|
|
15
|
+
* Any future adapter-level primitive that needs render-context / scope
|
|
16
|
+
* access should re-export from this file rather than duplicating the
|
|
17
|
+
* low-level glue.
|
|
18
|
+
*/
|
|
19
|
+
export { getRenderContext, setRenderContext, clearRenderContext } from './render-context.js';
|
|
20
|
+
export type { RenderContext } from './render-context.js';
|
|
21
|
+
export { createScope, disposeScope, addDisposer } from './scope.js';
|
|
22
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC5F,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal primitives surface — exported for framework-adapter packages
|
|
3
|
+
* (`@llui/vike`, `@llui/router`, `@llui/transitions`) that need to build
|
|
4
|
+
* their own structural primitives on top of LLui's scope + render-context
|
|
5
|
+
* machinery.
|
|
6
|
+
*
|
|
7
|
+
* **Not part of the public API.** App authors should not import from
|
|
8
|
+
* `@llui/dom/internal`. The shapes here are free to change without a
|
|
9
|
+
* major version bump — the stability contract applies only to the public
|
|
10
|
+
* barrel at `@llui/dom`. Reach for this subpath when you're writing a
|
|
11
|
+
* primitive like `pageSlot()` (from `@llui/vike`) that has to participate
|
|
12
|
+
* in the scope tree, not when you're writing application views.
|
|
13
|
+
*
|
|
14
|
+
* Added in 0.0.16 to support `@llui/vike`'s persistent-layout feature.
|
|
15
|
+
* Any future adapter-level primitive that needs render-context / scope
|
|
16
|
+
* access should re-export from this file rather than duplicating the
|
|
17
|
+
* low-level glue.
|
|
18
|
+
*/
|
|
19
|
+
export { getRenderContext, setRenderContext, clearRenderContext } from './render-context.js';
|
|
20
|
+
export { createScope, disposeScope, addDisposer } from './scope.js';
|
|
21
|
+
//# sourceMappingURL=internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAE5F,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA","sourcesContent":["/**\n * Internal primitives surface — exported for framework-adapter packages\n * (`@llui/vike`, `@llui/router`, `@llui/transitions`) that need to build\n * their own structural primitives on top of LLui's scope + render-context\n * machinery.\n *\n * **Not part of the public API.** App authors should not import from\n * `@llui/dom/internal`. The shapes here are free to change without a\n * major version bump — the stability contract applies only to the public\n * barrel at `@llui/dom`. Reach for this subpath when you're writing a\n * primitive like `pageSlot()` (from `@llui/vike`) that has to participate\n * in the scope tree, not when you're writing application views.\n *\n * Added in 0.0.16 to support `@llui/vike`'s persistent-layout feature.\n * Any future adapter-level primitive that needs render-context / scope\n * access should re-export from this file rather than duplicating the\n * low-level glue.\n */\n\nexport { getRenderContext, setRenderContext, clearRenderContext } from './render-context.js'\nexport type { RenderContext } from './render-context.js'\nexport { createScope, disposeScope, addDisposer } from './scope.js'\n"]}
|
package/dist/mount.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentDef, AppHandle } from './types.js';
|
|
1
|
+
import type { ComponentDef, AppHandle, Scope } from './types.js';
|
|
2
2
|
declare global {
|
|
3
3
|
interface ImportMeta {
|
|
4
4
|
env?: {
|
|
@@ -8,7 +8,20 @@ declare global {
|
|
|
8
8
|
}
|
|
9
9
|
export interface MountOptions {
|
|
10
10
|
devTools?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Parent scope for the mounted component's rootScope. When provided,
|
|
13
|
+
* the rootScope is created as a child of this scope — context lookups
|
|
14
|
+
* from within the component walk up through the parent's scope tree,
|
|
15
|
+
* and disposing the parent scope cascades into this instance's scope.
|
|
16
|
+
* Used by `@llui/vike`'s persistent-layout machinery to mount a page
|
|
17
|
+
* as a true scope-tree child of its enclosing layout, so layout-
|
|
18
|
+
* provided contexts flow naturally into pages via `useContext`.
|
|
19
|
+
*
|
|
20
|
+
* When omitted (the default), the rootScope is detached — same as
|
|
21
|
+
* every `mountApp` call before persistent layouts existed.
|
|
22
|
+
*/
|
|
23
|
+
parentScope?: Scope;
|
|
11
24
|
}
|
|
12
|
-
export declare function mountApp<S, M, E>(container: HTMLElement, def: ComponentDef<S, M, E>, data?: unknown,
|
|
13
|
-
export declare function hydrateApp<S, M, E>(container: HTMLElement, def: ComponentDef<S, M, E>, serverState: S): AppHandle;
|
|
25
|
+
export declare function mountApp<S, M, E>(container: HTMLElement, def: ComponentDef<S, M, E>, data?: unknown, options?: MountOptions): AppHandle;
|
|
26
|
+
export declare function hydrateApp<S, M, E>(container: HTMLElement, def: ComponentDef<S, M, E>, serverState: S, options?: MountOptions): AppHandle;
|
|
14
27
|
//# sourceMappingURL=mount.d.ts.map
|
package/dist/mount.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAUhE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,GAAG,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KACxB;CACF;AAsBD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,KAAK,CAAA;CACpB;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,OAAO,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAiFX;AA6DD,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAChC,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,WAAW,EAAE,CAAC,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,SAAS,CAyDX"}
|
package/dist/mount.js
CHANGED
|
@@ -19,15 +19,18 @@ let devToolsInstall = null;
|
|
|
19
19
|
export function _setDevToolsInstall(fn) {
|
|
20
20
|
devToolsInstall = fn;
|
|
21
21
|
}
|
|
22
|
-
export function mountApp(container, def, data,
|
|
22
|
+
export function mountApp(container, def, data, options) {
|
|
23
23
|
// HMR: if this component is already mounted (module re-execution
|
|
24
24
|
// during hot update), swap the definition instead of creating a new instance.
|
|
25
|
-
|
|
25
|
+
// HMR swap bypasses parentScope — HMR re-mounts the outermost app handle,
|
|
26
|
+
// which in a layout setup means the layout re-mounts at the root and the
|
|
27
|
+
// rest of the chain is re-established via the normal mount path.
|
|
28
|
+
if (hmrModule && def.name && !options?.parentScope) {
|
|
26
29
|
const swapped = hmrModule.replaceComponent(def.name, def);
|
|
27
30
|
if (swapped)
|
|
28
31
|
return swapped;
|
|
29
32
|
}
|
|
30
|
-
const inst = createComponentInstance(def, data);
|
|
33
|
+
const inst = createComponentInstance(def, data, options?.parentScope ?? null);
|
|
31
34
|
// Dev-only: auto-install devtools if enabled via '@llui/dom/devtools' import
|
|
32
35
|
if (devToolsInstall)
|
|
33
36
|
devToolsInstall(inst);
|
|
@@ -153,7 +156,7 @@ function dispatchInitialEffects(inst) {
|
|
|
153
156
|
}
|
|
154
157
|
inst.initialEffects = [];
|
|
155
158
|
}
|
|
156
|
-
export function hydrateApp(container, def, serverState) {
|
|
159
|
+
export function hydrateApp(container, def, serverState, options) {
|
|
157
160
|
// Run the original init once to capture its effects. The state it
|
|
158
161
|
// returns is discarded — we use `serverState` (what the server
|
|
159
162
|
// rendered with) instead. The effects are preserved and dispatched
|
|
@@ -167,7 +170,7 @@ export function hydrateApp(container, def, serverState) {
|
|
|
167
170
|
...def,
|
|
168
171
|
init: () => [serverState, originalEffects],
|
|
169
172
|
};
|
|
170
|
-
const inst = createComponentInstance(hydrateDef);
|
|
173
|
+
const inst = createComponentInstance(hydrateDef, undefined, options?.parentScope ?? null);
|
|
171
174
|
// Build the component DOM and swap atomically with server HTML.
|
|
172
175
|
// Server HTML remains visible until JS finishes — no flash.
|
|
173
176
|
// onMount callbacks are collected in a queue and flushed synchronously
|
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 } from './types.js'\nimport { createComponentInstance, flushInstance } from './update-loop.js'\nimport { disposeScope } from './scope.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// 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\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: unknown,\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 if (hmrModule && def.name) {\n const swapped = hmrModule.replaceComponent(def.name, def)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data)\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({ ...inst, container, send: inst.send as (msg: unknown) => void })\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 = document.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\n return {\n dispose() {\n if (disposed) return\n disposed = true\n if (hmrModule && def.name) hmrModule.unregisterForHmr(def.name, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n disposeScope(inst.rootScope)\n container.textContent = ''\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\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\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>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n serverState: S,\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(hydrateDef)\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({ ...inst, container, send: inst.send as (msg: unknown) => void })\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\n return {\n dispose() {\n if (disposed) return\n disposed = true\n inst.abortController.abort()\n unregisterInstance(inst)\n disposeScope(inst.rootScope)\n container.textContent = ''\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\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, Scope } from './types.js'\nimport { createComponentInstance, flushInstance } from './update-loop.js'\nimport { disposeScope } from './scope.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// 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 rootScope. When provided,\n * the rootScope 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 rootScope is detached — same as\n * every `mountApp` call before persistent layouts existed.\n */\n parentScope?: Scope\n}\n\nexport function mountApp<S, M, E>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\n data?: unknown,\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 parentScope — 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?.parentScope) {\n const swapped = hmrModule.replaceComponent(def.name, def)\n if (swapped) return swapped\n }\n\n const inst = createComponentInstance(def, data, options?.parentScope ?? null)\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({ ...inst, container, send: inst.send as (msg: unknown) => void })\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 = document.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\n return {\n dispose() {\n if (disposed) return\n disposed = true\n if (hmrModule && def.name) hmrModule.unregisterForHmr(def.name, inst)\n inst.abortController.abort()\n unregisterInstance(inst)\n disposeScope(inst.rootScope)\n container.textContent = ''\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\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\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>(\n container: HTMLElement,\n def: ComponentDef<S, M, E>,\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(hydrateDef, undefined, options?.parentScope ?? null)\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({ ...inst, container, send: inst.send as (msg: unknown) => void })\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\n return {\n dispose() {\n if (disposed) return\n disposed = true\n inst.abortController.abort()\n unregisterInstance(inst)\n disposeScope(inst.rootScope)\n container.textContent = ''\n },\n flush() {\n if (disposed) return\n flushInstance(inst)\n },\n }\n}\n"]}
|
package/dist/ssr.d.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
import type { ComponentDef } from './types.js';
|
|
1
|
+
import type { ComponentDef, Scope, Binding } from './types.js';
|
|
2
|
+
import { type ComponentInstance } from './update-loop.js';
|
|
3
|
+
/**
|
|
4
|
+
* Render a component to DOM nodes for SSR, returning both the produced
|
|
5
|
+
* nodes and the component instance (so callers can compose trees before
|
|
6
|
+
* serializing — e.g. `@llui/vike` stitches layout + page nodes at the
|
|
7
|
+
* `pageSlot()` marker position before one final serialization pass).
|
|
8
|
+
*
|
|
9
|
+
* Accepts an optional `parentScope` so the rendered instance's rootScope
|
|
10
|
+
* becomes a child of an existing scope tree — used by persistent layouts
|
|
11
|
+
* so contexts provided by an outer layout are reachable from an inner
|
|
12
|
+
* page via `useContext`.
|
|
13
|
+
*
|
|
14
|
+
* Call `initSsrDom()` once before using this on the server.
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderNodes<S, M, E>(def: ComponentDef<S, M, E>, initialState?: S, parentScope?: Scope): {
|
|
17
|
+
nodes: Node[];
|
|
18
|
+
inst: ComponentInstance<S, M, E>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Serialize an array of DOM nodes to an HTML string, adding
|
|
22
|
+
* `data-llui-hydrate` markers on elements that own reactive bindings.
|
|
23
|
+
*
|
|
24
|
+
* Accepts a flat binding list so compositions of multiple instances
|
|
25
|
+
* (layout + page, for persistent-layout SSR) produce correct markers
|
|
26
|
+
* across the whole tree. Pass the union of every composed instance's
|
|
27
|
+
* `allBindings`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function serializeNodes(nodes: Node[], bindings: Binding[]): string;
|
|
2
30
|
/**
|
|
3
31
|
* Render a component to an HTML string for SSR.
|
|
4
32
|
* Evaluates view() against the initial state (or provided data),
|
|
@@ -6,6 +34,9 @@ import type { ComponentDef } from './types.js';
|
|
|
6
34
|
* on nodes with reactive bindings.
|
|
7
35
|
*
|
|
8
36
|
* Call initSsrDom() once before using this on the server.
|
|
37
|
+
*
|
|
38
|
+
* For persistent layouts, use `renderNodes` + `serializeNodes` directly
|
|
39
|
+
* so layout and page nodes can be composed before serialization.
|
|
9
40
|
*/
|
|
10
41
|
export declare function renderToString<S, M, E>(def: ComponentDef<S, M, E>, initialState?: S): string;
|
|
11
42
|
//# sourceMappingURL=ssr.d.ts.map
|
package/dist/ssr.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAKlF;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,YAAY,CAAC,EAAE,CAAC,EAChB,WAAW,CAAC,EAAE,KAAK,GAClB;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;CAAE,CAarD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAezE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,MAAM,CAG5F"}
|
package/dist/ssr.js
CHANGED
|
@@ -3,15 +3,20 @@ import { setRenderContext, clearRenderContext } from './render-context.js';
|
|
|
3
3
|
import { setFlatBindings } from './binding.js';
|
|
4
4
|
import { createView } from './view-helpers.js';
|
|
5
5
|
/**
|
|
6
|
-
* Render a component to
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Render a component to DOM nodes for SSR, returning both the produced
|
|
7
|
+
* nodes and the component instance (so callers can compose trees before
|
|
8
|
+
* serializing — e.g. `@llui/vike` stitches layout + page nodes at the
|
|
9
|
+
* `pageSlot()` marker position before one final serialization pass).
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Accepts an optional `parentScope` so the rendered instance's rootScope
|
|
12
|
+
* becomes a child of an existing scope tree — used by persistent layouts
|
|
13
|
+
* so contexts provided by an outer layout are reachable from an inner
|
|
14
|
+
* page via `useContext`.
|
|
15
|
+
*
|
|
16
|
+
* Call `initSsrDom()` once before using this on the server.
|
|
12
17
|
*/
|
|
13
|
-
export function
|
|
14
|
-
const inst = createComponentInstance(def);
|
|
18
|
+
export function renderNodes(def, initialState, parentScope) {
|
|
19
|
+
const inst = createComponentInstance(def, undefined, parentScope ?? null);
|
|
15
20
|
if (initialState !== undefined) {
|
|
16
21
|
inst.state = initialState;
|
|
17
22
|
}
|
|
@@ -20,14 +25,20 @@ export function renderToString(def, initialState) {
|
|
|
20
25
|
const nodes = def.view(createView(inst.send));
|
|
21
26
|
clearRenderContext();
|
|
22
27
|
setFlatBindings(null);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
return { nodes, inst };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Serialize an array of DOM nodes to an HTML string, adding
|
|
32
|
+
* `data-llui-hydrate` markers on elements that own reactive bindings.
|
|
33
|
+
*
|
|
34
|
+
* Accepts a flat binding list so compositions of multiple instances
|
|
35
|
+
* (layout + page, for persistent-layout SSR) produce correct markers
|
|
36
|
+
* across the whole tree. Pass the union of every composed instance's
|
|
37
|
+
* `allBindings`.
|
|
38
|
+
*/
|
|
39
|
+
export function serializeNodes(nodes, bindings) {
|
|
29
40
|
const hydrateElements = new Set();
|
|
30
|
-
for (const binding of
|
|
41
|
+
for (const binding of bindings) {
|
|
31
42
|
const node = binding.node;
|
|
32
43
|
if (node.nodeType === 1) {
|
|
33
44
|
hydrateElements.add(node);
|
|
@@ -36,25 +47,26 @@ export function renderToString(def, initialState) {
|
|
|
36
47
|
hydrateElements.add(node.parentNode);
|
|
37
48
|
}
|
|
38
49
|
}
|
|
39
|
-
|
|
40
|
-
html = '';
|
|
50
|
+
let html = '';
|
|
41
51
|
for (const node of nodes) {
|
|
42
52
|
html += nodeToStringWithMarkers(node, hydrateElements);
|
|
43
53
|
}
|
|
44
54
|
return html;
|
|
45
55
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Render a component to an HTML string for SSR.
|
|
58
|
+
* Evaluates view() against the initial state (or provided data),
|
|
59
|
+
* serializes the DOM to HTML, and adds data-llui-hydrate markers
|
|
60
|
+
* on nodes with reactive bindings.
|
|
61
|
+
*
|
|
62
|
+
* Call initSsrDom() once before using this on the server.
|
|
63
|
+
*
|
|
64
|
+
* For persistent layouts, use `renderNodes` + `serializeNodes` directly
|
|
65
|
+
* so layout and page nodes can be composed before serialization.
|
|
66
|
+
*/
|
|
67
|
+
export function renderToString(def, initialState) {
|
|
68
|
+
const { nodes, inst } = renderNodes(def, initialState);
|
|
69
|
+
return serializeNodes(nodes, inst.allBindings);
|
|
58
70
|
}
|
|
59
71
|
function nodeToStringWithMarkers(node, bindingNodes) {
|
|
60
72
|
if (node.nodeType === 3) {
|
|
@@ -65,11 +77,11 @@ function nodeToStringWithMarkers(node, bindingNodes) {
|
|
|
65
77
|
}
|
|
66
78
|
if (node.nodeType === 1) {
|
|
67
79
|
const el = node;
|
|
68
|
-
return elementToString(el,
|
|
80
|
+
return elementToString(el, bindingNodes);
|
|
69
81
|
}
|
|
70
82
|
return '';
|
|
71
83
|
}
|
|
72
|
-
function elementToString(el,
|
|
84
|
+
function elementToString(el, bindingNodes) {
|
|
73
85
|
const tag = el.tagName.toLowerCase();
|
|
74
86
|
let attrs = '';
|
|
75
87
|
for (let i = 0; i < el.attributes.length; i++) {
|
|
@@ -80,7 +92,7 @@ function elementToString(el, withMarkers, bindingNodes) {
|
|
|
80
92
|
attrs += ` ${attr.name}="${escapeAttr(attr.value)}"`;
|
|
81
93
|
}
|
|
82
94
|
// Add hydrate marker if this element or any of its text children have bindings
|
|
83
|
-
if (
|
|
95
|
+
if (bindingNodes.has(el)) {
|
|
84
96
|
attrs += ' data-llui-hydrate';
|
|
85
97
|
}
|
|
86
98
|
// Void elements
|
|
@@ -89,13 +101,7 @@ function elementToString(el, withMarkers, bindingNodes) {
|
|
|
89
101
|
}
|
|
90
102
|
let children = '';
|
|
91
103
|
for (let i = 0; i < el.childNodes.length; i++) {
|
|
92
|
-
|
|
93
|
-
if (withMarkers) {
|
|
94
|
-
children += nodeToStringWithMarkers(child, bindingNodes);
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
children += nodeToString(child);
|
|
98
|
-
}
|
|
104
|
+
children += nodeToStringWithMarkers(el.childNodes[i], bindingNodes);
|
|
99
105
|
}
|
|
100
106
|
return `<${tag}${attrs}>${children}</${tag}>`;
|
|
101
107
|
}
|
package/dist/ssr.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr.js","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"ssr.js","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, Scope, Binding } from './types.js'\nimport { createComponentInstance, type ComponentInstance } from './update-loop.js'\nimport { setRenderContext, clearRenderContext } from './render-context.js'\nimport { setFlatBindings } from './binding.js'\nimport { createView } from './view-helpers.js'\n\n/**\n * Render a component to DOM nodes for SSR, returning both the produced\n * nodes and the component instance (so callers can compose trees before\n * serializing — e.g. `@llui/vike` stitches layout + page nodes at the\n * `pageSlot()` marker position before one final serialization pass).\n *\n * Accepts an optional `parentScope` so the rendered instance's rootScope\n * becomes a child of an existing scope tree — used by persistent layouts\n * so contexts provided by an outer layout are reachable from an inner\n * page via `useContext`.\n *\n * Call `initSsrDom()` once before using this on the server.\n */\nexport function renderNodes<S, M, E>(\n def: ComponentDef<S, M, E>,\n initialState?: S,\n parentScope?: Scope,\n): { nodes: Node[]; inst: ComponentInstance<S, M, E> } {\n const inst = createComponentInstance(def, undefined, parentScope ?? null)\n if (initialState !== undefined) {\n inst.state = initialState\n }\n\n setFlatBindings(inst.allBindings)\n setRenderContext({ ...inst, send: inst.send as (msg: unknown) => void })\n const nodes = def.view(createView<S, M>(inst.send))\n clearRenderContext()\n setFlatBindings(null)\n\n return { nodes, inst }\n}\n\n/**\n * Serialize an array of DOM nodes to an HTML string, adding\n * `data-llui-hydrate` markers on elements that own reactive bindings.\n *\n * Accepts a flat binding list so compositions of multiple instances\n * (layout + page, for persistent-layout SSR) produce correct markers\n * across the whole tree. Pass the union of every composed instance's\n * `allBindings`.\n */\nexport function serializeNodes(nodes: Node[], bindings: Binding[]): string {\n const hydrateElements = new Set<Node>()\n for (const binding of bindings) {\n const node = binding.node\n if (node.nodeType === 1) {\n hydrateElements.add(node)\n } else if (node.parentNode && node.parentNode.nodeType === 1) {\n hydrateElements.add(node.parentNode)\n }\n }\n let html = ''\n for (const node of nodes) {\n html += nodeToStringWithMarkers(node, hydrateElements)\n }\n return html\n}\n\n/**\n * Render a component to an HTML string for SSR.\n * Evaluates view() against the initial state (or provided data),\n * serializes the DOM to HTML, and adds data-llui-hydrate markers\n * on nodes with reactive bindings.\n *\n * Call initSsrDom() once before using this on the server.\n *\n * For persistent layouts, use `renderNodes` + `serializeNodes` directly\n * so layout and page nodes can be composed before serialization.\n */\nexport function renderToString<S, M, E>(def: ComponentDef<S, M, E>, initialState?: S): string {\n const { nodes, inst } = renderNodes(def, initialState)\n return serializeNodes(nodes, inst.allBindings)\n}\n\nfunction nodeToStringWithMarkers(node: Node, bindingNodes: Set<Node>): string {\n if (node.nodeType === 3) {\n return escapeHtml(node.textContent ?? '')\n }\n if (node.nodeType === 8) {\n return `<!--${node.textContent ?? ''}-->`\n }\n if (node.nodeType === 1) {\n const el = node as Element\n return elementToString(el, bindingNodes)\n }\n return ''\n}\n\nfunction elementToString(el: Element, bindingNodes: Set<Node>): string {\n const tag = el.tagName.toLowerCase()\n let attrs = ''\n\n for (let i = 0; i < el.attributes.length; i++) {\n const attr = el.attributes[i]!\n // Skip event handler attributes\n if (attr.name.startsWith('on')) continue\n attrs += ` ${attr.name}=\"${escapeAttr(attr.value)}\"`\n }\n\n // Add hydrate marker if this element or any of its text children have bindings\n if (bindingNodes.has(el)) {\n attrs += ' data-llui-hydrate'\n }\n\n // Void elements\n if (isVoidElement(tag)) {\n return `<${tag}${attrs} />`\n }\n\n let children = ''\n for (let i = 0; i < el.childNodes.length; i++) {\n children += nodeToStringWithMarkers(el.childNodes[i]!, bindingNodes)\n }\n\n return `<${tag}${attrs}>${children}</${tag}>`\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')\n}\n\nfunction escapeAttr(s: string): string {\n return s.replace(/&/g, '&').replace(/\"/g, '"')\n}\n\nconst VOID_ELEMENTS = new Set([\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n])\n\nfunction isVoidElement(tag: string): boolean {\n return VOID_ELEMENTS.has(tag)\n}\n"]}
|
package/dist/update-loop.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface ComponentInstance<S = unknown, M = unknown, E = unknown> {
|
|
|
20
20
|
signal: AbortSignal;
|
|
21
21
|
abortController: AbortController;
|
|
22
22
|
}
|
|
23
|
-
export declare function createComponentInstance<S, M, E>(def: ComponentDef<S, M, E>, data?: unknown): ComponentInstance<S, M, E>;
|
|
23
|
+
export declare function createComponentInstance<S, M, E>(def: ComponentDef<S, M, E>, data?: unknown, parentScope?: Scope | null): ComponentInstance<S, M, E>;
|
|
24
24
|
export declare function flushInstance<S, M, E>(inst: ComponentInstance<S, M, E>): void;
|
|
25
25
|
/**
|
|
26
26
|
* Dev-only: overwrite instance state and re-run both phases with FULL_MASK
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-loop.d.ts","sourceRoot":"","sources":["../src/update-loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAKtD,eAAO,MAAM,SAAS,QAAiB,CAAA;AAMvC,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,CAAC,GAAG,EAAE;IAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,GAClE,IAAI,CAEN;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACtE,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1B,KAAK,EAAE,CAAC,CAAA;IACR,cAAc,EAAE,CAAC,EAAE,CAAA;IACnB,SAAS,EAAE,KAAK,CAAA;IAChB,WAAW,EAAE,OAAO,EAAE,CAAA;IACtB,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,KAAK,EAAE,CAAC,EAAE,CAAA;IACV,kBAAkB,EAAE,OAAO,CAAA;IAC3B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,CAAC,EAAE,CAAA;IAChB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAA;IACtB,MAAM,EAAE,WAAW,CAAA;IACnB,eAAe,EAAE,eAAe,CAAA;CACjC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC7C,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"update-loop.d.ts","sourceRoot":"","sources":["../src/update-loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAKtD,eAAO,MAAM,SAAS,QAAiB,CAAA;AAMvC,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,CAAC,GAAG,EAAE;IAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,GAClE,IAAI,CAEN;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACtE,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1B,KAAK,EAAE,CAAC,CAAA;IACR,cAAc,EAAE,CAAC,EAAE,CAAA;IACnB,SAAS,EAAE,KAAK,CAAA;IAChB,WAAW,EAAE,OAAO,EAAE,CAAA;IACtB,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,KAAK,EAAE,CAAC,EAAE,CAAA;IACV,kBAAkB,EAAE,OAAO,CAAA;IAC3B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,CAAC,EAAE,CAAA;IAChB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAA;IACtB,MAAM,EAAE,WAAW,CAAA;IACnB,eAAe,EAAE,eAAe,CAAA;CACjC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC7C,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,EAAE,OAAO,EACd,WAAW,GAAE,KAAK,GAAG,IAAW,GAC/B,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAsC5B;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAI7E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAiCxF;AA0GD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,iBAAiB,EACvB,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAoCtB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,EAAE,EACnB,oBAAoB,EAAE,MAAM,EAC5B,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI,CAuCN"}
|
package/dist/update-loop.js
CHANGED
|
@@ -7,14 +7,20 @@ let addressedDispatcher = null;
|
|
|
7
7
|
export function setAddressedDispatcher(fn) {
|
|
8
8
|
addressedDispatcher = fn;
|
|
9
9
|
}
|
|
10
|
-
export function createComponentInstance(def, data) {
|
|
10
|
+
export function createComponentInstance(def, data, parentScope = null) {
|
|
11
11
|
const [initialState, initialEffects] = def.init(data);
|
|
12
12
|
const controller = new AbortController();
|
|
13
13
|
const inst = {
|
|
14
14
|
def,
|
|
15
15
|
state: initialState,
|
|
16
16
|
initialEffects,
|
|
17
|
-
rootScope
|
|
17
|
+
// When `parentScope` is provided the instance's rootScope becomes a
|
|
18
|
+
// child of that scope. This is how persistent layouts wire pages
|
|
19
|
+
// into the layout's scope tree: the page's rootScope is parented at
|
|
20
|
+
// the layout's pageSlot() point so `useContext` lookups flow layout
|
|
21
|
+
// → page, and scope disposal cascades correctly. Mount paths that
|
|
22
|
+
// don't pass parentScope get the classic detached root.
|
|
23
|
+
rootScope: createScope(parentScope),
|
|
18
24
|
allBindings: [],
|
|
19
25
|
structuralBlocks: [],
|
|
20
26
|
queue: [],
|
package/dist/update-loop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-loop.js","sourceRoot":"","sources":["../src/update-loop.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, Scope, Binding } from './types.js'\nimport type { StructuralBlock } from './structural.js'\nimport { createScope } from './scope.js'\nimport { applyBinding } from './binding.js'\nimport { setCurrentDirtyMask } from './primitives/memo.js'\n\nexport const FULL_MASK = 0xffffffff | 0\n\n// Addressed effect dispatcher — set by addressed.ts when imported\nlet addressedDispatcher: ((eff: { __targetKey: string | number; __msg: unknown }) => void) | null =\n null\n\nexport function setAddressedDispatcher(\n fn: (eff: { __targetKey: string | number; __msg: unknown }) => void,\n): void {\n addressedDispatcher = fn\n}\n\nexport interface ComponentInstance<S = unknown, M = unknown, E = unknown> {\n def: ComponentDef<S, M, E>\n state: S\n initialEffects: E[]\n rootScope: Scope\n allBindings: Binding[]\n structuralBlocks: StructuralBlock[]\n queue: M[]\n microtaskScheduled: boolean\n lastDirtyMask: number\n lastEffects: E[]\n send: (msg: M) => void\n signal: AbortSignal\n abortController: AbortController\n}\n\nexport function createComponentInstance<S, M, E>(\n def: ComponentDef<S, M, E>,\n data?: unknown,\n): ComponentInstance<S, M, E> {\n const [initialState, initialEffects] = (def.init as (data: unknown) => [S, E[]])(data)\n\n const controller = new AbortController()\n\n const inst: ComponentInstance<S, M, E> = {\n def,\n state: initialState,\n initialEffects,\n rootScope: createScope(null),\n allBindings: [],\n structuralBlocks: [],\n queue: [],\n microtaskScheduled: false,\n lastDirtyMask: 0,\n lastEffects: [],\n signal: controller.signal,\n abortController: controller,\n\n send(msg: M) {\n inst.queue.push(msg)\n if (!inst.microtaskScheduled) {\n inst.microtaskScheduled = true\n queueMicrotask(() => {\n inst.microtaskScheduled = false\n processMessages(inst)\n })\n }\n },\n }\n\n return inst\n}\n\nexport function flushInstance<S, M, E>(inst: ComponentInstance<S, M, E>): void {\n if (inst.queue.length === 0) return\n inst.microtaskScheduled = false\n processMessages(inst)\n}\n\n/**\n * Dev-only: overwrite instance state and re-run both phases with FULL_MASK\n * so every binding re-evaluates. Bypasses update() — use for devtools\n * snapshot/restore, not in app code.\n */\nexport function _forceState<S, M, E>(inst: ComponentInstance<S, M, E>, newState: S): void {\n inst.state = newState\n inst.lastDirtyMask = FULL_MASK\n\n const bindings = inst.allBindings\n const bindingsBeforePhase1 = bindings.length\n\n setCurrentDirtyMask(FULL_MASK)\n\n const snapshot = inst.structuralBlocks.slice()\n for (const block of snapshot) {\n block.reconcile(newState, FULL_MASK)\n }\n\n let phase2Len = bindingsBeforePhase1\n if (bindings.length > bindingsBeforePhase1 || (phase2Len > 0 && bindings[0]!.dead)) {\n let w = 0\n for (let r = 0; r < bindings.length; r++) {\n if (!bindings[r]!.dead) bindings[w++] = bindings[r]!\n }\n bindings.length = w\n phase2Len = Math.min(w, bindingsBeforePhase1)\n }\n\n const state = inst.state\n for (let i = 0, len = phase2Len; i < len; i++) {\n const binding = bindings[i]!\n if (binding.dead) continue\n const newValue = binding.accessor(state)\n if (Object.is(newValue, binding.lastValue)) continue\n binding.lastValue = newValue\n applyBinding(binding, newValue)\n }\n}\n\nfunction processMessages<S, M, E>(inst: ComponentInstance<S, M, E>): void {\n const queue = inst.queue\n\n // Single-message fast path: dispatch directly to per-message-type handler\n // if available. Skips dirty computation, Phase 1/2 entirely.\n if (queue.length === 1 && inst.def.__handlers) {\n const msg = queue[0]!\n const handler = inst.def.__handlers[(msg as Record<string, unknown>).type as string] as\n | ((inst: ComponentInstance, msg: unknown) => [S, E[]])\n | undefined\n if (handler) {\n queue.length = 0\n const [newState, effects] = handler(inst as ComponentInstance, msg)\n inst.state = newState\n if (import.meta.env?.DEV) {\n inst.lastDirtyMask = FULL_MASK\n inst.lastEffects = effects\n }\n for (let i = 0; i < effects.length; i++) {\n dispatchEffect(inst, effects[i]!)\n }\n return\n }\n }\n\n // Generic pipeline — drain queue, accumulate dirty bits\n let state = inst.state\n let combinedDirty = 0\n const allEffects: E[] = []\n\n const defUpdate = inst.def.update\n const dirtyFn = inst.def.__dirty\n for (let qi = 0; qi < queue.length; qi++) {\n const msg = queue[qi]!\n const [newState, effects] = defUpdate(state, msg)\n const dirty = dirtyFn ? dirtyFn(state, newState) : FULL_MASK\n if (typeof dirty === 'number') {\n combinedDirty |= dirty\n } else {\n combinedDirty |= dirty[0] | dirty[1]\n }\n state = newState\n // Avoid spread — allocates an iterator per call. For typical effect\n // arrays (0-2 elements) this is a minor saving; for bursts it matters.\n for (let ei = 0; ei < effects.length; ei++) allEffects.push(effects[ei]!)\n }\n queue.length = 0\n\n inst.state = state\n // Dev-only bookkeeping — tests read lastDirtyMask/lastEffects, prod\n // doesn't. Gating here keeps two writes out of the prod hot path.\n if (import.meta.env?.DEV) {\n inst.lastDirtyMask = combinedDirty\n inst.lastEffects = allEffects\n }\n\n // Snapshot binding count before Phase 1 — bindings added during\n // Phase 1 already have correct initial values and skip Phase 2.\n const bindings = inst.allBindings\n const bindingsBeforePhase1 = bindings.length\n\n // Set current dirty mask BEFORE Phase 1 so memo() accessors used in\n // structural primitives (e.g. each.items) can use the bitmask fast path.\n setCurrentDirtyMask(combinedDirty)\n\n if (inst.def.__update) {\n // Compiler-generated fast path — replaces generic Phase 1 + Phase 2\n inst.def.__update(state, combinedDirty, bindings, inst.structuralBlocks, bindingsBeforePhase1)\n } else {\n // Generic Phase 1 + Phase 2 fallback (uncompiled components)\n genericUpdate(inst, state, combinedDirty, bindings, bindingsBeforePhase1)\n }\n\n // Dispatch effects after DOM updates\n for (let i = 0; i < allEffects.length; i++) {\n dispatchEffect(inst, allEffects[i]!)\n }\n}\n\nfunction genericUpdate<S, M, E>(\n inst: ComponentInstance<S, M, E>,\n state: S,\n combinedDirty: number,\n bindings: Binding[],\n bindingsBeforePhase1: number,\n): void {\n // Phase 1 — structural reconciliation. Structural primitives register\n // their blocks BEFORE running builders, so parents precede their nested\n // children in this array. That ordering matters: a parent's reconcile\n // may dispose the old arm, whose disposers splice nested child blocks\n // out of this shared array. Because children are always to the right\n // of their parent, the splice shifts entries left — which is safe for\n // a forward iterator that re-reads length each step.\n const blocks = inst.structuralBlocks\n for (let bi = 0; bi < blocks.length; bi++) {\n const block = blocks[bi]\n if (!block || (block.mask & combinedDirty) === 0) continue\n block.reconcile(state, combinedDirty)\n }\n\n // Phase 2 — compact + update bindings\n _runPhase2(state, combinedDirty, bindings, bindingsBeforePhase1, inst.def.name)\n}\n\n/**\n * Run a handler for a single message: call update(), reconcile blocks\n * with the given method, run Phase 2. Used by compiler-generated __handlers\n * to avoid duplicating boilerplate per message type.\n *\n * @param method 0=reconcile, 1=reconcileItems, 2=reconcileClear, 3=reconcileRemove, -1=skip blocks\n * @public — used by compiler-generated `__handlers`\n */\nexport function _handleMsg(\n inst: ComponentInstance,\n msg: unknown,\n dirty: number,\n method: number,\n): [unknown, unknown[]] {\n const [s, e] = (inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]])(\n inst.state,\n msg,\n )\n inst.state = s\n\n if (method >= 0) {\n const bl = inst.structuralBlocks\n for (let i = 0; i < bl.length; i++) {\n const block = bl[i]\n if (!block || !(block.mask & dirty)) continue\n switch (method) {\n case 0:\n block.reconcile(s, dirty)\n break\n case 1:\n block.reconcileItems?.(s)\n break\n case 2:\n block.reconcileClear?.()\n break\n case 3:\n block.reconcileRemove?.(s)\n break\n default:\n // method >= 10: reconcileChanged with stride = method - 10\n if (method >= 10) block.reconcileChanged?.(s, method - 10)\n break\n }\n }\n }\n\n const b = inst.allBindings\n _runPhase2(s, dirty, b, b.length)\n return [s, e]\n}\n\n/**\n * Phase 2: compact dead bindings + update live bindings.\n * Shared between genericUpdate and compiler-generated __update.\n * @public — used by compiler-generated `__update` functions\n */\nexport function _runPhase2(\n state: unknown,\n dirty: number,\n bindings: Binding[],\n bindingsBeforePhase1: number,\n componentName?: string,\n): void {\n let phase2Len = bindingsBeforePhase1\n if (bindings.length > bindingsBeforePhase1 || (phase2Len > 0 && bindings[0]!.dead)) {\n let w = 0\n for (let r = 0; r < bindings.length; r++) {\n if (!bindings[r]!.dead) bindings[w++] = bindings[r]!\n }\n bindings.length = w\n phase2Len = Math.min(w, bindingsBeforePhase1)\n }\n\n if (dirty !== 0) {\n if (import.meta.env?.DEV && componentName) {\n for (let i = 0, len = phase2Len; i < len; i++) {\n const binding = bindings[i]!\n if (binding.dead || (binding.mask & dirty) === 0) continue\n let newValue: unknown\n try {\n newValue = binding.accessor(state)\n } catch (e) {\n throw enhanceBindingError(e, binding, componentName)\n }\n const last = binding.lastValue\n if (newValue === last || (newValue !== newValue && last !== last)) continue\n binding.lastValue = newValue\n applyBinding(binding, newValue)\n }\n } else {\n for (let i = 0, len = phase2Len; i < len; i++) {\n const binding = bindings[i]!\n if (binding.dead || (binding.mask & dirty) === 0) continue\n const newValue = binding.accessor(state)\n const last = binding.lastValue\n if (newValue === last || (newValue !== newValue && last !== last)) continue\n binding.lastValue = newValue\n applyBinding(binding, newValue)\n }\n }\n }\n}\n\nfunction enhanceBindingError(err: unknown, binding: Binding, componentName: string): Error {\n // For text bindings, binding.node is the Text node — use its parent element.\n const node = binding.node\n const target = node.nodeType === 1 ? (node as Element) : (node.parentElement ?? null)\n let nodeDesc = '?'\n if (target) {\n const id = target.id ? `#${target.id}` : ''\n const cls =\n target.className && typeof target.className === 'string'\n ? `.${target.className.split(' ').filter(Boolean).slice(0, 2).join('.')}`\n : ''\n nodeDesc = `<${target.tagName.toLowerCase()}${id}${cls}>`\n if (node.nodeType === 3) nodeDesc += ' text-child'\n else if (node.nodeType === 8) nodeDesc += ' comment-child'\n }\n const keyPart = binding.key ? ` .${binding.key}` : ''\n const errMsg = err instanceof Error ? err.message : String(err)\n\n // Build accessor source hint if available\n let accessorHint = ''\n try {\n const src = binding.accessor.toString().slice(0, 80)\n accessorHint = `\\n accessor: ${src}${binding.accessor.toString().length > 80 ? '...' : ''}`\n } catch {\n // toString() may throw on revoked proxies, etc.\n }\n\n // Detect common undefined/null access pattern and add a helpful hint\n let undefinedHint = ''\n if (err instanceof TypeError && /Cannot read propert(ies|y).*of (undefined|null)/.test(errMsg)) {\n undefinedHint =\n '\\n hint: Check that your accessor handles undefined state fields (e.g., use optional chaining: s.user?.name)'\n }\n\n const wrapped = new Error(\n `[LLui] ${binding.kind}${keyPart} binding on ${nodeDesc} — accessor threw in <${componentName}>\\n` +\n ` ↳ ${errMsg}` +\n undefinedHint +\n accessorHint,\n err instanceof Error ? { cause: err } : undefined,\n )\n wrapped.stack = (err instanceof Error && err.stack) || wrapped.stack\n return wrapped\n}\n\nfunction dispatchEffect<S, M, E>(inst: ComponentInstance<S, M, E>, effect: E): void {\n const eff = effect as Record<string, unknown>\n\n // Addressed effects — dispatch to target component\n if (eff.__addressed === true && typeof eff.__targetKey !== 'undefined') {\n addressedDispatcher?.(eff as { __targetKey: string | number; __msg: unknown })\n return\n }\n\n // Built-in: delay\n if (eff.type === 'delay') {\n const ms = eff.ms as number\n const onDone = eff.onDone as M\n setTimeout(() => inst.send(onDone), ms)\n return\n }\n\n // Built-in: log\n if (eff.type === 'log') {\n console.log(eff.message)\n return\n }\n\n // User onEffect handler\n if (inst.def.onEffect) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"update-loop.js","sourceRoot":"","sources":["../src/update-loop.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentDef, Scope, Binding } from './types.js'\nimport type { StructuralBlock } from './structural.js'\nimport { createScope } from './scope.js'\nimport { applyBinding } from './binding.js'\nimport { setCurrentDirtyMask } from './primitives/memo.js'\n\nexport const FULL_MASK = 0xffffffff | 0\n\n// Addressed effect dispatcher — set by addressed.ts when imported\nlet addressedDispatcher: ((eff: { __targetKey: string | number; __msg: unknown }) => void) | null =\n null\n\nexport function setAddressedDispatcher(\n fn: (eff: { __targetKey: string | number; __msg: unknown }) => void,\n): void {\n addressedDispatcher = fn\n}\n\nexport interface ComponentInstance<S = unknown, M = unknown, E = unknown> {\n def: ComponentDef<S, M, E>\n state: S\n initialEffects: E[]\n rootScope: Scope\n allBindings: Binding[]\n structuralBlocks: StructuralBlock[]\n queue: M[]\n microtaskScheduled: boolean\n lastDirtyMask: number\n lastEffects: E[]\n send: (msg: M) => void\n signal: AbortSignal\n abortController: AbortController\n}\n\nexport function createComponentInstance<S, M, E>(\n def: ComponentDef<S, M, E>,\n data?: unknown,\n parentScope: Scope | null = null,\n): ComponentInstance<S, M, E> {\n const [initialState, initialEffects] = (def.init as (data: unknown) => [S, E[]])(data)\n\n const controller = new AbortController()\n\n const inst: ComponentInstance<S, M, E> = {\n def,\n state: initialState,\n initialEffects,\n // When `parentScope` is provided the instance's rootScope becomes a\n // child of that scope. This is how persistent layouts wire pages\n // into the layout's scope tree: the page's rootScope is parented at\n // the layout's pageSlot() point so `useContext` lookups flow layout\n // → page, and scope disposal cascades correctly. Mount paths that\n // don't pass parentScope get the classic detached root.\n rootScope: createScope(parentScope),\n allBindings: [],\n structuralBlocks: [],\n queue: [],\n microtaskScheduled: false,\n lastDirtyMask: 0,\n lastEffects: [],\n signal: controller.signal,\n abortController: controller,\n\n send(msg: M) {\n inst.queue.push(msg)\n if (!inst.microtaskScheduled) {\n inst.microtaskScheduled = true\n queueMicrotask(() => {\n inst.microtaskScheduled = false\n processMessages(inst)\n })\n }\n },\n }\n\n return inst\n}\n\nexport function flushInstance<S, M, E>(inst: ComponentInstance<S, M, E>): void {\n if (inst.queue.length === 0) return\n inst.microtaskScheduled = false\n processMessages(inst)\n}\n\n/**\n * Dev-only: overwrite instance state and re-run both phases with FULL_MASK\n * so every binding re-evaluates. Bypasses update() — use for devtools\n * snapshot/restore, not in app code.\n */\nexport function _forceState<S, M, E>(inst: ComponentInstance<S, M, E>, newState: S): void {\n inst.state = newState\n inst.lastDirtyMask = FULL_MASK\n\n const bindings = inst.allBindings\n const bindingsBeforePhase1 = bindings.length\n\n setCurrentDirtyMask(FULL_MASK)\n\n const snapshot = inst.structuralBlocks.slice()\n for (const block of snapshot) {\n block.reconcile(newState, FULL_MASK)\n }\n\n let phase2Len = bindingsBeforePhase1\n if (bindings.length > bindingsBeforePhase1 || (phase2Len > 0 && bindings[0]!.dead)) {\n let w = 0\n for (let r = 0; r < bindings.length; r++) {\n if (!bindings[r]!.dead) bindings[w++] = bindings[r]!\n }\n bindings.length = w\n phase2Len = Math.min(w, bindingsBeforePhase1)\n }\n\n const state = inst.state\n for (let i = 0, len = phase2Len; i < len; i++) {\n const binding = bindings[i]!\n if (binding.dead) continue\n const newValue = binding.accessor(state)\n if (Object.is(newValue, binding.lastValue)) continue\n binding.lastValue = newValue\n applyBinding(binding, newValue)\n }\n}\n\nfunction processMessages<S, M, E>(inst: ComponentInstance<S, M, E>): void {\n const queue = inst.queue\n\n // Single-message fast path: dispatch directly to per-message-type handler\n // if available. Skips dirty computation, Phase 1/2 entirely.\n if (queue.length === 1 && inst.def.__handlers) {\n const msg = queue[0]!\n const handler = inst.def.__handlers[(msg as Record<string, unknown>).type as string] as\n | ((inst: ComponentInstance, msg: unknown) => [S, E[]])\n | undefined\n if (handler) {\n queue.length = 0\n const [newState, effects] = handler(inst as ComponentInstance, msg)\n inst.state = newState\n if (import.meta.env?.DEV) {\n inst.lastDirtyMask = FULL_MASK\n inst.lastEffects = effects\n }\n for (let i = 0; i < effects.length; i++) {\n dispatchEffect(inst, effects[i]!)\n }\n return\n }\n }\n\n // Generic pipeline — drain queue, accumulate dirty bits\n let state = inst.state\n let combinedDirty = 0\n const allEffects: E[] = []\n\n const defUpdate = inst.def.update\n const dirtyFn = inst.def.__dirty\n for (let qi = 0; qi < queue.length; qi++) {\n const msg = queue[qi]!\n const [newState, effects] = defUpdate(state, msg)\n const dirty = dirtyFn ? dirtyFn(state, newState) : FULL_MASK\n if (typeof dirty === 'number') {\n combinedDirty |= dirty\n } else {\n combinedDirty |= dirty[0] | dirty[1]\n }\n state = newState\n // Avoid spread — allocates an iterator per call. For typical effect\n // arrays (0-2 elements) this is a minor saving; for bursts it matters.\n for (let ei = 0; ei < effects.length; ei++) allEffects.push(effects[ei]!)\n }\n queue.length = 0\n\n inst.state = state\n // Dev-only bookkeeping — tests read lastDirtyMask/lastEffects, prod\n // doesn't. Gating here keeps two writes out of the prod hot path.\n if (import.meta.env?.DEV) {\n inst.lastDirtyMask = combinedDirty\n inst.lastEffects = allEffects\n }\n\n // Snapshot binding count before Phase 1 — bindings added during\n // Phase 1 already have correct initial values and skip Phase 2.\n const bindings = inst.allBindings\n const bindingsBeforePhase1 = bindings.length\n\n // Set current dirty mask BEFORE Phase 1 so memo() accessors used in\n // structural primitives (e.g. each.items) can use the bitmask fast path.\n setCurrentDirtyMask(combinedDirty)\n\n if (inst.def.__update) {\n // Compiler-generated fast path — replaces generic Phase 1 + Phase 2\n inst.def.__update(state, combinedDirty, bindings, inst.structuralBlocks, bindingsBeforePhase1)\n } else {\n // Generic Phase 1 + Phase 2 fallback (uncompiled components)\n genericUpdate(inst, state, combinedDirty, bindings, bindingsBeforePhase1)\n }\n\n // Dispatch effects after DOM updates\n for (let i = 0; i < allEffects.length; i++) {\n dispatchEffect(inst, allEffects[i]!)\n }\n}\n\nfunction genericUpdate<S, M, E>(\n inst: ComponentInstance<S, M, E>,\n state: S,\n combinedDirty: number,\n bindings: Binding[],\n bindingsBeforePhase1: number,\n): void {\n // Phase 1 — structural reconciliation. Structural primitives register\n // their blocks BEFORE running builders, so parents precede their nested\n // children in this array. That ordering matters: a parent's reconcile\n // may dispose the old arm, whose disposers splice nested child blocks\n // out of this shared array. Because children are always to the right\n // of their parent, the splice shifts entries left — which is safe for\n // a forward iterator that re-reads length each step.\n const blocks = inst.structuralBlocks\n for (let bi = 0; bi < blocks.length; bi++) {\n const block = blocks[bi]\n if (!block || (block.mask & combinedDirty) === 0) continue\n block.reconcile(state, combinedDirty)\n }\n\n // Phase 2 — compact + update bindings\n _runPhase2(state, combinedDirty, bindings, bindingsBeforePhase1, inst.def.name)\n}\n\n/**\n * Run a handler for a single message: call update(), reconcile blocks\n * with the given method, run Phase 2. Used by compiler-generated __handlers\n * to avoid duplicating boilerplate per message type.\n *\n * @param method 0=reconcile, 1=reconcileItems, 2=reconcileClear, 3=reconcileRemove, -1=skip blocks\n * @public — used by compiler-generated `__handlers`\n */\nexport function _handleMsg(\n inst: ComponentInstance,\n msg: unknown,\n dirty: number,\n method: number,\n): [unknown, unknown[]] {\n const [s, e] = (inst.def.update as (s: unknown, m: unknown) => [unknown, unknown[]])(\n inst.state,\n msg,\n )\n inst.state = s\n\n if (method >= 0) {\n const bl = inst.structuralBlocks\n for (let i = 0; i < bl.length; i++) {\n const block = bl[i]\n if (!block || !(block.mask & dirty)) continue\n switch (method) {\n case 0:\n block.reconcile(s, dirty)\n break\n case 1:\n block.reconcileItems?.(s)\n break\n case 2:\n block.reconcileClear?.()\n break\n case 3:\n block.reconcileRemove?.(s)\n break\n default:\n // method >= 10: reconcileChanged with stride = method - 10\n if (method >= 10) block.reconcileChanged?.(s, method - 10)\n break\n }\n }\n }\n\n const b = inst.allBindings\n _runPhase2(s, dirty, b, b.length)\n return [s, e]\n}\n\n/**\n * Phase 2: compact dead bindings + update live bindings.\n * Shared between genericUpdate and compiler-generated __update.\n * @public — used by compiler-generated `__update` functions\n */\nexport function _runPhase2(\n state: unknown,\n dirty: number,\n bindings: Binding[],\n bindingsBeforePhase1: number,\n componentName?: string,\n): void {\n let phase2Len = bindingsBeforePhase1\n if (bindings.length > bindingsBeforePhase1 || (phase2Len > 0 && bindings[0]!.dead)) {\n let w = 0\n for (let r = 0; r < bindings.length; r++) {\n if (!bindings[r]!.dead) bindings[w++] = bindings[r]!\n }\n bindings.length = w\n phase2Len = Math.min(w, bindingsBeforePhase1)\n }\n\n if (dirty !== 0) {\n if (import.meta.env?.DEV && componentName) {\n for (let i = 0, len = phase2Len; i < len; i++) {\n const binding = bindings[i]!\n if (binding.dead || (binding.mask & dirty) === 0) continue\n let newValue: unknown\n try {\n newValue = binding.accessor(state)\n } catch (e) {\n throw enhanceBindingError(e, binding, componentName)\n }\n const last = binding.lastValue\n if (newValue === last || (newValue !== newValue && last !== last)) continue\n binding.lastValue = newValue\n applyBinding(binding, newValue)\n }\n } else {\n for (let i = 0, len = phase2Len; i < len; i++) {\n const binding = bindings[i]!\n if (binding.dead || (binding.mask & dirty) === 0) continue\n const newValue = binding.accessor(state)\n const last = binding.lastValue\n if (newValue === last || (newValue !== newValue && last !== last)) continue\n binding.lastValue = newValue\n applyBinding(binding, newValue)\n }\n }\n }\n}\n\nfunction enhanceBindingError(err: unknown, binding: Binding, componentName: string): Error {\n // For text bindings, binding.node is the Text node — use its parent element.\n const node = binding.node\n const target = node.nodeType === 1 ? (node as Element) : (node.parentElement ?? null)\n let nodeDesc = '?'\n if (target) {\n const id = target.id ? `#${target.id}` : ''\n const cls =\n target.className && typeof target.className === 'string'\n ? `.${target.className.split(' ').filter(Boolean).slice(0, 2).join('.')}`\n : ''\n nodeDesc = `<${target.tagName.toLowerCase()}${id}${cls}>`\n if (node.nodeType === 3) nodeDesc += ' text-child'\n else if (node.nodeType === 8) nodeDesc += ' comment-child'\n }\n const keyPart = binding.key ? ` .${binding.key}` : ''\n const errMsg = err instanceof Error ? err.message : String(err)\n\n // Build accessor source hint if available\n let accessorHint = ''\n try {\n const src = binding.accessor.toString().slice(0, 80)\n accessorHint = `\\n accessor: ${src}${binding.accessor.toString().length > 80 ? '...' : ''}`\n } catch {\n // toString() may throw on revoked proxies, etc.\n }\n\n // Detect common undefined/null access pattern and add a helpful hint\n let undefinedHint = ''\n if (err instanceof TypeError && /Cannot read propert(ies|y).*of (undefined|null)/.test(errMsg)) {\n undefinedHint =\n '\\n hint: Check that your accessor handles undefined state fields (e.g., use optional chaining: s.user?.name)'\n }\n\n const wrapped = new Error(\n `[LLui] ${binding.kind}${keyPart} binding on ${nodeDesc} — accessor threw in <${componentName}>\\n` +\n ` ↳ ${errMsg}` +\n undefinedHint +\n accessorHint,\n err instanceof Error ? { cause: err } : undefined,\n )\n wrapped.stack = (err instanceof Error && err.stack) || wrapped.stack\n return wrapped\n}\n\nfunction dispatchEffect<S, M, E>(inst: ComponentInstance<S, M, E>, effect: E): void {\n const eff = effect as Record<string, unknown>\n\n // Addressed effects — dispatch to target component\n if (eff.__addressed === true && typeof eff.__targetKey !== 'undefined') {\n addressedDispatcher?.(eff as { __targetKey: string | number; __msg: unknown })\n return\n }\n\n // Built-in: delay\n if (eff.type === 'delay') {\n const ms = eff.ms as number\n const onDone = eff.onDone as M\n setTimeout(() => inst.send(onDone), ms)\n return\n }\n\n // Built-in: log\n if (eff.type === 'log') {\n console.log(eff.message)\n return\n }\n\n // User onEffect handler\n if (inst.def.onEffect) {\n inst.def.onEffect({ effect, send: inst.send, signal: inst.signal })\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llui/dom",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"./hmr": {
|
|
20
20
|
"types": "./dist/hmr.d.ts",
|
|
21
21
|
"import": "./dist/hmr.js"
|
|
22
|
+
},
|
|
23
|
+
"./internal": {
|
|
24
|
+
"types": "./dist/internal.d.ts",
|
|
25
|
+
"import": "./dist/internal.js"
|
|
22
26
|
}
|
|
23
27
|
},
|
|
24
28
|
"files": [
|