@barefootjs/jsx 0.26.4 → 0.28.0
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/compiler.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +941 -130
- package/dist/ir-to-client-js/client-only-elision.d.ts +103 -0
- package/dist/ir-to-client-js/client-only-elision.d.ts.map +1 -0
- package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/branch-loop.d.ts +6 -0
- package/dist/ir-to-client-js/control-flow/plan/branch-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-branch-loop.d.ts +2 -1
- package/dist/ir-to-client-js/control-flow/plan/build-branch-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-insert.d.ts +7 -0
- package/dist/ir-to-client-js/control-flow/plan/build-insert.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts +107 -0
- package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/plan/build-loop.d.ts +9 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/lazy-row-eligibility.d.ts +203 -0
- package/dist/ir-to-client-js/control-flow/plan/lazy-row-eligibility.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts +10 -0
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/shared.d.ts +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/branch-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/claim-plan.d.ts +54 -0
- package/dist/ir-to-client-js/control-flow/stringify/claim-plan.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/stringify/inner-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/insert.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/lazy-row.d.ts +98 -0
- package/dist/ir-to-client-js/control-flow/stringify/lazy-row.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/stringify/loop-child-arm.d.ts +5 -0
- package/dist/ir-to-client-js/control-flow/stringify/loop-child-arm.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts +17 -20
- package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts +63 -4
- package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow.d.ts +1 -1
- package/dist/ir-to-client-js/control-flow.d.ts.map +1 -1
- package/dist/ir-to-client-js/element-refs.d.ts +8 -3
- package/dist/ir-to-client-js/element-refs.d.ts.map +1 -1
- package/dist/ir-to-client-js/emit-reactive.d.ts +8 -1
- package/dist/ir-to-client-js/emit-reactive.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts +24 -0
- package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
- package/dist/ir-to-client-js/imports.d.ts +2 -2
- package/dist/ir-to-client-js/imports.d.ts.map +1 -1
- package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
- package/dist/ir-to-client-js/types.d.ts +9 -1
- package/dist/ir-to-client-js/types.d.ts.map +1 -1
- package/dist/ir-to-client-js/utils.d.ts +1 -1
- package/dist/types.d.ts +25 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +542 -689
- package/src/__tests__/child-components-in-map.test.ts +4 -4
- package/src/__tests__/client-js-generation.test.ts +23 -12
- package/src/__tests__/composite-branch-loop.test.ts +14 -5
- package/src/__tests__/conditional-mapArray-key.test.ts +7 -1
- package/src/__tests__/create-selector.test.ts +21 -7
- package/src/__tests__/cross-file-client-signal.test.ts +5 -1
- package/src/__tests__/early-return-scope-var-ref.test.ts +10 -11
- package/src/__tests__/inline-jsx-callback.test.ts +6 -4
- package/src/__tests__/ir-jsx-props.test.ts +6 -5
- package/src/__tests__/lazy-row-eligibility.test.ts +692 -0
- package/src/__tests__/loop-branch-bare-expression-reactive-text.test.ts +98 -0
- package/src/__tests__/loop-fallback-wrap.test.ts +34 -16
- package/src/__tests__/loop-hoisted-template.test.ts +10 -6
- package/src/__tests__/module-level-signal.audit.test.ts +7 -2
- package/src/__tests__/nested-loop-conditional.test.ts +9 -7
- package/src/__tests__/nested-loop-reactive-attrs.test.ts +2 -2
- package/src/__tests__/preamble-region-patch.test.ts +18 -12
- package/src/__tests__/profile-cond-binding-ids.test.ts +3 -2
- package/src/__tests__/profile-loop-binding-ids.test.ts +4 -3
- package/src/__tests__/profile-nested-binding-ids.test.ts +11 -6
- package/src/__tests__/reactive-attrs-in-map.test.ts +6 -4
- package/src/__tests__/static-loop-csr-materialize.test.ts +6 -1
- package/src/__tests__/template-closure.test.ts +1 -1
- package/src/compiler.ts +11 -0
- package/src/index.ts +1 -0
- package/src/ir-to-client-js/client-only-elision.ts +273 -0
- package/src/ir-to-client-js/collect-elements.ts +56 -17
- package/src/ir-to-client-js/control-flow/plan/branch-loop.ts +6 -0
- package/src/ir-to-client-js/control-flow/plan/build-branch-loop.ts +35 -12
- package/src/ir-to-client-js/control-flow/plan/build-insert.ts +9 -2
- package/src/ir-to-client-js/control-flow/plan/build-lazy-row.ts +305 -0
- package/src/ir-to-client-js/control-flow/plan/build-loop.ts +44 -12
- package/src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts +440 -0
- package/src/ir-to-client-js/control-flow/plan/loop.ts +10 -0
- package/src/ir-to-client-js/control-flow/shared.ts +1 -1
- package/src/ir-to-client-js/control-flow/stringify/branch-loop.ts +34 -4
- package/src/ir-to-client-js/control-flow/stringify/claim-plan.ts +68 -0
- package/src/ir-to-client-js/control-flow/stringify/inner-loop.ts +18 -9
- package/src/ir-to-client-js/control-flow/stringify/insert.ts +17 -11
- package/src/ir-to-client-js/control-flow/stringify/lazy-row.ts +478 -0
- package/src/ir-to-client-js/control-flow/stringify/loop-child-arm.ts +41 -17
- package/src/ir-to-client-js/control-flow/stringify/loop.ts +71 -46
- package/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts +241 -31
- package/src/ir-to-client-js/control-flow.ts +8 -3
- package/src/ir-to-client-js/element-refs.ts +9 -11
- package/src/ir-to-client-js/emit-reactive.ts +50 -14
- package/src/ir-to-client-js/html-template.ts +29 -9
- package/src/ir-to-client-js/imports.ts +13 -4
- package/src/ir-to-client-js/reactivity.ts +3 -2
- package/src/ir-to-client-js/types.ts +10 -2
- package/src/ir-to-client-js/utils.ts +1 -1
- package/src/jsx-to-ir.ts +26 -8
- package/src/types.ts +25 -2
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slot unification Step B (`spec/slot-unification.md` §3(b), §5 "Step B —
|
|
3
|
+
* marker elision"): decide, EXACTLY ONCE and BEFORE either `adapter.generate`
|
|
4
|
+
* (SSR) or `generateClientJs` (CSR) run, which `/* @client *\/` text slots
|
|
5
|
+
* can drop their `<!--bf:sN-->…<!--/-->` marker pair entirely from both
|
|
6
|
+
* outputs. Every consumer (all nine SSR adapters' `renderExpression`, and
|
|
7
|
+
* the CSR emitters in `html-template.ts`) reads the single
|
|
8
|
+
* `IRExpression.markerless` flag this pass writes — nobody re-derives the
|
|
9
|
+
* decision, per CLAUDE.md's "Never add compiler options/hooks for
|
|
10
|
+
* tool-specific output rewriting" spirit: one door in, everyone reads it.
|
|
11
|
+
*
|
|
12
|
+
* Scope — deliberately the NARROWEST slice of §3(b)'s elision rule that is
|
|
13
|
+
* fully sound today, not the general case:
|
|
14
|
+
*
|
|
15
|
+
* Only `expr.clientOnly && expr.slotId` expressions OUTSIDE any loop or
|
|
16
|
+
* conditional branch (i.e. reachable from the component's own render tree
|
|
17
|
+
* by walking only `element`/`text`/`expression`/`fragment` nodes).
|
|
18
|
+
*
|
|
19
|
+
* Why THIS slice and not ordinary reactive text slots (loop rows,
|
|
20
|
+
* conditional branches): every other kind of slot's SSR-rendered width is
|
|
21
|
+
* DATA-DEPENDENT — an ordinary `{item.name}` may render empty or non-empty
|
|
22
|
+
* per request, so a LATER sibling's absolute child-index path would only be
|
|
23
|
+
* valid for the specific width THIS request happened to produce, not for
|
|
24
|
+
* every request the compiled function ever serves. `/* @client *\/`
|
|
25
|
+
* expressions are the one case free of that problem: SSR can never evaluate
|
|
26
|
+
* client-only JS (the whole point of the escape valve), so its rendered
|
|
27
|
+
* width is deterministically ZERO on every request, for every adapter, with
|
|
28
|
+
* no data dependence at all. That determinism is what makes computing a
|
|
29
|
+
* real, reusable, hydration-safe path sound here without also solving the
|
|
30
|
+
* general "does an earlier sibling's width vary by request" problem.
|
|
31
|
+
*
|
|
32
|
+
* Path safety within that scope — the part that generalizes A3's
|
|
33
|
+
* `computeSkeletonSlotPaths` (`html-template.ts`) rather than reinventing
|
|
34
|
+
* it: paths are root-relative child-index chains, exactly like that
|
|
35
|
+
* function's, walked in document order with the SAME "once we hit something
|
|
36
|
+
* whose contributed width isn't a compile-time constant, every remaining
|
|
37
|
+
* sibling AND everything nested inside it loses eligibility" rule (nested
|
|
38
|
+
* content reached only through an uncertain-index sibling would resolve an
|
|
39
|
+
* absolute path through that uncertain index — silently wrong, not loud, so
|
|
40
|
+
* it must never be attempted). Concretely, walking a children list left to
|
|
41
|
+
* right:
|
|
42
|
+
* - a static `element` always contributes exactly one node — recurse into
|
|
43
|
+
* its own children as an independent, freshly-indexed scope (its own
|
|
44
|
+
* internal accounting can't leak out, and nothing external can poison
|
|
45
|
+
* it either, since the element itself is a fixed anchor regardless of
|
|
46
|
+
* what's inside it);
|
|
47
|
+
* - static `text` contributes a node per HTML-parser text-run-merging
|
|
48
|
+
* rules (adjacent text/expression children collapse into ONE Text
|
|
49
|
+
* node — mirrors `computeSkeletonSlotPaths`'s `pendingText` tracking);
|
|
50
|
+
* - a `clientOnly` expression with a slotId is the one ELIGIBLE case,
|
|
51
|
+
* PROVIDED it is not itself part of a merged text run (rule (i) — the
|
|
52
|
+
* `/* @client *\/` slot must not be immediately adjacent, once markers
|
|
53
|
+
* are gone, to loose text or another expression, or the HTML parser
|
|
54
|
+
* would merge them into one Text node with no way to tell which
|
|
55
|
+
* content is which). Once one is elided, this level (and everything
|
|
56
|
+
* nested inside any later sibling) is marked ineligible for the
|
|
57
|
+
* remainder of the walk at this level — see the "freeze" note below;
|
|
58
|
+
* - any other `expression` (a real reactive/static text or markup slot),
|
|
59
|
+
* any `conditional`/`loop`/`component`/`async`/`provider`/
|
|
60
|
+
* `if-statement`/`slot` node, is data-dependent or opaque width and
|
|
61
|
+
* FREEZES the rest of this children list (see below) — this is
|
|
62
|
+
* strictly conservative: it also means a `/* @client *\/` expression
|
|
63
|
+
* is never eligible once any of these appears earlier at the same
|
|
64
|
+
* level, even though `/* @client *\/`'s own width is always zero,
|
|
65
|
+
* because SIBLINGS reached only via nested recursion past that point
|
|
66
|
+
* would otherwise resolve an absolute path through the frozen node's
|
|
67
|
+
* uncertain contributed width;
|
|
68
|
+
* - the same hazard-tag / force-close-group / void-element / `<tr>`
|
|
69
|
+
* foster-parenting guards `computeSkeletonSlotPaths` uses (imported,
|
|
70
|
+
* not re-derived) abort the ENTIRE walk (a global bail, exactly like
|
|
71
|
+
* that function's `state.bailed`) — a parser hazard means every index
|
|
72
|
+
* computed anywhere in this tree is suspect, not just the ones near
|
|
73
|
+
* the hazard, so "don't guess" means don't guess about the blast
|
|
74
|
+
* radius either.
|
|
75
|
+
*
|
|
76
|
+
* "Freeze" (the one simplification versus a maximally-precise per-branch
|
|
77
|
+
* eligibility tracker): once ANY `/* @client *\/` slot at a given level is
|
|
78
|
+
* elided — OR once anything data-dependent/opaque is seen at that level —
|
|
79
|
+
* that level's remaining siblings (and anything nested only through them)
|
|
80
|
+
* stop being assigned real paths for the rest of THIS walk, even though a
|
|
81
|
+
* maximally precise analysis could sometimes still find one. This caps
|
|
82
|
+
* elision at (at most) one `/* @client *\/` slot per static subtree —
|
|
83
|
+
* conservative by design, matching the elision rule's own framing, and it
|
|
84
|
+
* guarantees two elided slots can never end up needing an insertion whose
|
|
85
|
+
* reference node depends on the other's still-unresolved width. Freezing is
|
|
86
|
+
* PER CHILDREN-LIST (an element's own children start a fresh, unfrozen
|
|
87
|
+
* scope) — global-bail is reserved for hazard tags alone.
|
|
88
|
+
*
|
|
89
|
+
* Deferred (loudly, not silently): ordinary reactive text slots in loop
|
|
90
|
+
* rows / conditional branches keep their markers — see above for why
|
|
91
|
+
* widening this to data-dependent-width content needs a materially
|
|
92
|
+
* different (and per-adapter-verified) safety argument that this PR does
|
|
93
|
+
* not attempt.
|
|
94
|
+
*/
|
|
95
|
+
import type { IRNode } from '../types.ts';
|
|
96
|
+
/**
|
|
97
|
+
* Entry point: mutates `root`'s `expression` nodes in place, setting
|
|
98
|
+
* `markerless`/`elidedPath` on every eligible `/* @client *\/` slot found.
|
|
99
|
+
* Safe to call on any component's render tree; a tree with none simply
|
|
100
|
+
* mutates nothing.
|
|
101
|
+
*/
|
|
102
|
+
export declare function decideClientOnlyElision(root: IRNode): void;
|
|
103
|
+
//# sourceMappingURL=client-only-elision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-only-elision.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/client-only-elision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6FG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,aAAa,CAAA;AAmBvD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect-elements.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/collect-elements.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAoC,KAAK,MAAM,EAAmC,MAAM,aAAa,CAAA;AACzH,OAAO,KAAK,EAAE,eAAe,EAA+H,iBAAiB,EAA0B,oBAAoB,EAAc,UAAU,EAAE,MAAM,YAAY,CAAA;AAyGvQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CA0C7E;AAyBD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,wBAIpC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,cAAc,CAAC,EAAE,MAAM,EACvB,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,wBAAwB,GACjC,UAAU,EAAE,CAyId;AAqKD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,iBAAiB,UAAQ,GACxB,IAAI,
|
|
1
|
+
{"version":3,"file":"collect-elements.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/collect-elements.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAoC,KAAK,MAAM,EAAmC,MAAM,aAAa,CAAA;AACzH,OAAO,KAAK,EAAE,eAAe,EAA+H,iBAAiB,EAA0B,oBAAoB,EAAc,UAAU,EAAE,MAAM,YAAY,CAAA;AAyGvQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CA0C7E;AAyBD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,wBAIpC,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,cAAc,CAAC,EAAE,MAAM,EACvB,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,wBAAwB,GACjC,UAAU,EAAE,CAyId;AAqKD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,iBAAiB,UAAQ,GACxB,IAAI,CAmSN;AAuYD;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,GAAG,EAAE,eAAe,EACpB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,SAAS,OAAO,aAAa,EAAE,gBAAgB,EAAE,GAAG,SAAS,GAC/E,iBAAiB,CAenB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,SAAS,CAAC,EAAE,MAAM,EAClB,iBAAiB,CAAC,EAAE,SAAS,OAAO,aAAa,EAAE,gBAAgB,EAAE,GACpE,oBAAoB,EAAE,CA4DxB"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import type { CompositeLoopPlan, LoopChildRefBinding, PreambleRegionPlan } from './loop.ts';
|
|
18
18
|
import type { EventDelegationPlan } from './event-delegation.ts';
|
|
19
19
|
import type { ReactiveEffectsPlan } from './reactive-effects.ts';
|
|
20
|
+
import type { LazyRowPlanData } from './build-lazy-row.ts';
|
|
20
21
|
export interface BranchPlainLoopPlan {
|
|
21
22
|
/**
|
|
22
23
|
* flatMap descriptor mode — see `PlainLoopVariant.flatMapLeafItem`
|
|
@@ -87,6 +88,11 @@ export interface BranchPlainLoopPlan {
|
|
|
87
88
|
* renderItem layout, mirroring the top-level plain plan.
|
|
88
89
|
*/
|
|
89
90
|
preambleRegions: readonly PreambleRegionPlan[];
|
|
91
|
+
/**
|
|
92
|
+
* Lazy row graph plan (`spec/slot-unification.md` §9, L3) — see
|
|
93
|
+
* `PlainLoopVariant.lazyRow`. Undefined ⇒ today's eager emission.
|
|
94
|
+
*/
|
|
95
|
+
lazyRow?: LazyRowPlanData;
|
|
90
96
|
}
|
|
91
97
|
export interface BranchCompositeLoopPlan {
|
|
92
98
|
kind: 'composite';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/branch-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"branch-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/branch-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,sEAAsE;IACtE,eAAe,EAAE,iBAAiB,GAAG,SAAS,CAAA;IAC9C;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAA;IACvB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAA;IACpB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAA;IACjB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAA;IACjB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAA;IACnB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;;;;OAQG;IACH,kBAAkB,EAAE,MAAM,CAAA;IAC1B,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,eAAe,EAAE,mBAAmB,GAAG,IAAI,CAAA;IAC3C,+DAA+D;IAC/D,eAAe,EAAE,mBAAmB,CAAA;IACpC;;;;OAIG;IACH,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACzC;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,eAAe,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC9C;;;OAGG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,WAAW,CAAA;IACjB,4DAA4D;IAC5D,SAAS,EAAE,iBAAiB,CAAA;IAC5B,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAA;IACvB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,mBAAmB,GAAG,uBAAuB,CAAA"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* event-delegation plan.
|
|
11
11
|
*/
|
|
12
12
|
import type { BranchLoop } from '../../types.ts';
|
|
13
|
+
import type { LazyRowScopeInfo } from './lazy-row-eligibility.ts';
|
|
13
14
|
import type { BranchLoopPlan } from './branch-loop.ts';
|
|
14
|
-
export declare function buildBranchLoopPlan(loop: BranchLoop, profileComponentName?: string): BranchLoopPlan;
|
|
15
|
+
export declare function buildBranchLoopPlan(loop: BranchLoop, profileComponentName?: string, lazyScope?: LazyRowScopeInfo): BranchLoopPlan;
|
|
15
16
|
//# sourceMappingURL=build-branch-loop.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-branch-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-branch-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"build-branch-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-branch-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAMhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAGjE,OAAO,KAAK,EAEV,cAAc,EAEf,MAAM,kBAAkB,CAAA;AAEzB,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,oBAAoB,CAAC,EAAE,MAAM,EAC7B,SAAS,CAAC,EAAE,gBAAgB,GAC3B,cAAc,CAiFhB"}
|
|
@@ -8,12 +8,19 @@
|
|
|
8
8
|
* data-to-text mapping.
|
|
9
9
|
*/
|
|
10
10
|
import type { ConditionalElement } from '../../types.ts';
|
|
11
|
+
import type { LazyRowScopeInfo } from './lazy-row-eligibility.ts';
|
|
11
12
|
import type { InsertPlan, ScopeRef } from './types.ts';
|
|
12
13
|
export interface BuildInsertOptions {
|
|
13
14
|
scope: ScopeRef;
|
|
14
15
|
eventNameMode: 'dom' | 'raw';
|
|
15
16
|
/** Owning component name in profile mode (#1690, SR3) — else undefined. */
|
|
16
17
|
profileComponentName?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Component-scope name facts for the lazy row graph gate
|
|
20
|
+
* (`spec/slot-unification.md` §9.4). Threaded down to branch-scoped plain
|
|
21
|
+
* loops; omitted → those loops keep today's eager emission.
|
|
22
|
+
*/
|
|
23
|
+
lazyScope?: LazyRowScopeInfo;
|
|
17
24
|
}
|
|
18
25
|
export declare function buildInsertPlan(elem: ConditionalElement, options: BuildInsertOptions): InsertPlan;
|
|
19
26
|
//# sourceMappingURL=build-insert.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-insert.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-insert.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAEnB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,KAAK,EACV,UAAU,EAGV,QAAQ,EACT,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,QAAQ,CAAA;IACf,aAAa,EAAE,KAAK,GAAG,KAAK,CAAA;IAC5B,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"build-insert.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-insert.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAEnB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,KAAK,EACV,UAAU,EAGV,QAAQ,EACT,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,QAAQ,CAAA;IACf,aAAa,EAAE,KAAK,GAAG,KAAK,CAAA;IAC5B,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAA;CAC7B;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,kBAAkB,GAC1B,UAAU,CAaZ"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the compiler-side `LazyRowPlan` payload (`spec/slot-unification.md`
|
|
3
|
+
* §9, L3) for one plain loop row — or `null` when the row is ineligible and
|
|
4
|
+
* must keep today's eager `mapArray` emission.
|
|
5
|
+
*
|
|
6
|
+
* Everything decided here is BUILD-TIME data: per-binding item/outer
|
|
7
|
+
* classification (`classifyLazyBinding`), ref-array and dedup-slot layout,
|
|
8
|
+
* and the outer-signal prime list. The stringifier
|
|
9
|
+
* (`stringify/lazy-row.ts`) is a deterministic walk over this plan — it
|
|
10
|
+
* makes no classification decision of its own.
|
|
11
|
+
*
|
|
12
|
+
* Free identifiers are never obtained by regex (repo rule). Texts carry
|
|
13
|
+
* `LoopChildReactiveText.freeIdentifiers` from the analyzer; attrs have no
|
|
14
|
+
* such field, so their expression is run through `parseExpression` +
|
|
15
|
+
* `freeIdentifiers` (`expression-parser.ts`) — both of which fail SAFE, the
|
|
16
|
+
* latter returning `null` on an `unsupported` node, which
|
|
17
|
+
* `classifyLazyBinding` turns into "reads both, and opaque".
|
|
18
|
+
*/
|
|
19
|
+
import { type AttrMeta } from '../../../types.ts';
|
|
20
|
+
import type { BranchLoop, ClientJsContext, TopLevelLoop } from '../../types.ts';
|
|
21
|
+
import { type LazyRowEligibility, type LazyRowScopeInfo } from './lazy-row-eligibility.ts';
|
|
22
|
+
/** One reactive attribute of a lazy row. */
|
|
23
|
+
export interface LazyRowAttrBinding {
|
|
24
|
+
slotId: string;
|
|
25
|
+
attrName: string;
|
|
26
|
+
/** Already wrapped via `wrapLoopParamAsAccessor` — reads `<param>()`. */
|
|
27
|
+
wrappedExpression: string;
|
|
28
|
+
meta: AttrMeta;
|
|
29
|
+
/** Index into `entry.refs` holding this slot's element. */
|
|
30
|
+
refIndex: number;
|
|
31
|
+
/** Index into `entry.last` holding this binding's dedup value. */
|
|
32
|
+
ordinal: number;
|
|
33
|
+
readsItem: boolean;
|
|
34
|
+
readsOuter: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** One reactive text (content slot) of a lazy row. */
|
|
37
|
+
export interface LazyRowTextBinding {
|
|
38
|
+
slotId: string;
|
|
39
|
+
wrappedExpression: string;
|
|
40
|
+
ordinal: number;
|
|
41
|
+
readsItem: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Reads at least one reactive outer name — emitted into `applyOuter` with
|
|
44
|
+
* §9.3(1) read-compare-write seeding, which needs the RW claim door
|
|
45
|
+
* (`LazyRowPlanData.textNeedsRead`).
|
|
46
|
+
*/
|
|
47
|
+
readsOuter: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface LazyRowPlanData {
|
|
50
|
+
/** Distinct attr slot ids, in declaration order — `entry.refs[0..n-1]`. */
|
|
51
|
+
attrSlotIds: readonly string[];
|
|
52
|
+
attrs: readonly LazyRowAttrBinding[];
|
|
53
|
+
texts: readonly LazyRowTextBinding[];
|
|
54
|
+
/** Index into `entry.refs` holding the claimed-slot door; -1 when no texts. */
|
|
55
|
+
writerIndex: number;
|
|
56
|
+
/**
|
|
57
|
+
* PER-LOOP door selection (§9.3(1) content seeding): true when at least
|
|
58
|
+
* one text binding is outer-involving and therefore needs `read(id)` to
|
|
59
|
+
* seed by comparison. The emitter then claims through `lazyClaimSlots`
|
|
60
|
+
* (the `{ write, read }` door) and every text write becomes
|
|
61
|
+
* `__r[w].write(...)`; false keeps the single-closure `lazySlots` writer
|
|
62
|
+
* and the bare `__r[w](...)` call form. One decision for the whole loop —
|
|
63
|
+
* the door is a per-ROW allocation, so it must not be chosen per binding.
|
|
64
|
+
*/
|
|
65
|
+
textNeedsRead: boolean;
|
|
66
|
+
/** Total `entry.last` slots. */
|
|
67
|
+
lastCount: number;
|
|
68
|
+
/**
|
|
69
|
+
* Signal / memo getters read at the top of `applyOuter` so the ONE
|
|
70
|
+
* loop-level effect subscribes even while the entry list is empty. Empty
|
|
71
|
+
* ⇒ no `applyOuter` is emitted at all (and hydration does literally
|
|
72
|
+
* nothing per row).
|
|
73
|
+
*/
|
|
74
|
+
outerPrimeGetters: readonly string[];
|
|
75
|
+
/** True when at least one binding is outer-involving. */
|
|
76
|
+
hasOuter: boolean;
|
|
77
|
+
}
|
|
78
|
+
export interface BuildLazyRowArgs {
|
|
79
|
+
loop: TopLevelLoop | BranchLoop;
|
|
80
|
+
/** Fully-chained array expression as emitted (`buildChainedArrayExpr`). */
|
|
81
|
+
arrayExpr: string;
|
|
82
|
+
indexParam: string;
|
|
83
|
+
/** `destructureLoopParam(...).unwrap` — non-empty ⇒ ineligible. */
|
|
84
|
+
paramUnwrap: string;
|
|
85
|
+
mapPreambleWrapped: string;
|
|
86
|
+
preambleRegionCount: number;
|
|
87
|
+
callSite: 'plain' | 'branch-plain';
|
|
88
|
+
flatMapLeafItem: boolean;
|
|
89
|
+
anchored: boolean;
|
|
90
|
+
scope: LazyRowScopeInfo | undefined;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns the lazy row plan when eligible, otherwise `null` plus the
|
|
94
|
+
* decision (exposed for tests / diagnostics via {@link decideLazyRow}).
|
|
95
|
+
*/
|
|
96
|
+
export declare function buildLazyRowPlan(args: BuildLazyRowArgs): LazyRowPlanData | null;
|
|
97
|
+
export declare function decideLazyRow(args: BuildLazyRowArgs): {
|
|
98
|
+
plan: LazyRowPlanData | null;
|
|
99
|
+
decision: LazyRowEligibility;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Project a `ClientJsContext` down to the name facts the §9.4 gate resolves
|
|
103
|
+
* against. Built once per component and threaded into every loop plan
|
|
104
|
+
* builder, so the gate never reaches back into the whole context.
|
|
105
|
+
*/
|
|
106
|
+
export declare function buildLazyRowScopeInfo(ctx: ClientJsContext): LazyRowScopeInfo;
|
|
107
|
+
//# sourceMappingURL=build-lazy-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-lazy-row.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-lazy-row.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAG/D,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC/E,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EAEtB,MAAM,2BAA2B,CAAA;AAElC,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAA;IACzB,IAAI,EAAE,QAAQ,CAAA;IACd,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAA;IAChB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACpC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACpC,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;;;OAQG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,GAAG,UAAU,CAAA;IAC/B,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,QAAQ,EAAE,OAAO,GAAG,cAAc,CAAA;IAClC,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAA;CACpC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,GAAG,IAAI,CAE/E;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG;IACrD,IAAI,EAAE,eAAe,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,kBAAkB,CAAA;CAC7B,CAuHA;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,CAyB5E"}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* `TopLevelLoop`, and is reused by the branch-loop wrapper plan.
|
|
20
20
|
*/
|
|
21
21
|
import type { TopLevelLoop } from '../../types.ts';
|
|
22
|
+
import type { LazyRowScopeInfo } from './lazy-row-eligibility.ts';
|
|
22
23
|
import type { LoopPlan, PlainLoopPlan, StaticLoopPlan } from './types.ts';
|
|
23
24
|
/** Inputs only the static-array variant consumes. */
|
|
24
25
|
export interface BuildLoopPlanOptions {
|
|
@@ -26,6 +27,13 @@ export interface BuildLoopPlanOptions {
|
|
|
26
27
|
unsafeLocalNames: Set<string>;
|
|
27
28
|
/** Owning component name when compiling in profile mode (#1690) — else undefined. */
|
|
28
29
|
profileComponentName?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Component-scope name facts for the lazy row graph gate
|
|
32
|
+
* (`spec/slot-unification.md` §9.4, `buildLazyRowScopeInfo`). Omitted →
|
|
33
|
+
* no loop is lazy-eligible, i.e. today's emission everywhere. Optional so
|
|
34
|
+
* hand-built plan fixtures keep type-checking.
|
|
35
|
+
*/
|
|
36
|
+
lazyScope?: LazyRowScopeInfo;
|
|
29
37
|
}
|
|
30
38
|
/**
|
|
31
39
|
* The single public builder. Selects the variant via the decision tree
|
|
@@ -33,7 +41,7 @@ export interface BuildLoopPlanOptions {
|
|
|
33
41
|
*/
|
|
34
42
|
export declare function buildLoopPlan(elem: TopLevelLoop, opts: BuildLoopPlanOptions): LoopPlan;
|
|
35
43
|
/** @internal — prefer `buildLoopPlan`. Exported for the branch-loop wrapper only. */
|
|
36
|
-
export declare function buildPlainLoopPlan(elem: TopLevelLoop, profileComponentName?: string): PlainLoopPlan;
|
|
44
|
+
export declare function buildPlainLoopPlan(elem: TopLevelLoop, profileComponentName?: string, lazyScope?: LazyRowScopeInfo): PlainLoopPlan;
|
|
37
45
|
/** @internal — prefer `buildLoopPlan`. */
|
|
38
46
|
export declare function buildStaticLoopPlan(elem: TopLevelLoop, unsafeLocalNames: Set<string>, profileComponentName?: string): StaticLoopPlan;
|
|
39
47
|
//# sourceMappingURL=build-loop.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"build-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/build-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EACV,YAAY,EAEb,MAAM,gBAAgB,CAAA;AAiBvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAIjE,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EAEb,cAAc,EACf,MAAM,YAAY,CAAA;AAEnB,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACnC,8FAA8F;IAC9F,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,qFAAqF;IACrF,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAA;CAC7B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,oBAAoB,GAAG,QAAQ,CAsBtF;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,YAAY,EAClB,oBAAoB,CAAC,EAAE,MAAM,EAC7B,SAAS,CAAC,EAAE,gBAAgB,GAC3B,aAAa,CAgGf;AAED,0CAA0C;AAC1C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,cAAc,CAmCpI"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy row graph eligibility — `spec/slot-unification.md` §9.4 (L3).
|
|
3
|
+
*
|
|
4
|
+
* ONE explicit decision function (`lazyRowEligibility`) answering a single
|
|
5
|
+
* question: may this plain loop row be emitted through `mapArrayLazy`
|
|
6
|
+
* (a compiler-emitted `LazyRowPlan`, no per-row reactive resources) instead
|
|
7
|
+
* of today's A3b-consolidated eager `mapArray` emission?
|
|
8
|
+
*
|
|
9
|
+
* Sound-or-loud (§9.3): the answer is always either `{ eligible: true }` or
|
|
10
|
+
* `{ eligible: false, reason }`. There is no silent third path — an
|
|
11
|
+
* ineligible loop keeps byte-for-byte today's emission, and `reason` is a
|
|
12
|
+
* human-readable string so a regression is diagnosable from a unit test
|
|
13
|
+
* rather than by diffing generated JS.
|
|
14
|
+
*
|
|
15
|
+
* The gate is deliberately conservative. Every restriction below is a
|
|
16
|
+
* "widen later" decision, never a correctness compromise:
|
|
17
|
+
*
|
|
18
|
+
* 1. **Shape** (§9.4 "plain loop-row shape"): non-anchored, non-flatMap,
|
|
19
|
+
* single-root, keyed, conditional-free, ref-free, no nested components
|
|
20
|
+
* or inner loops.
|
|
21
|
+
* 2. **No preamble.** A `.map()` callback preamble declares row-local
|
|
22
|
+
* bindings (and can declare row-local signals/memos, which need per-row
|
|
23
|
+
* reactivity by definition). Proving "declares no signal/memo" is not
|
|
24
|
+
* cheap here, and every preamble-declared local would land in a
|
|
25
|
+
* binding's free-identifier set as an unresolvable name anyway — so the
|
|
26
|
+
* rule is the cheap conservative one: **any** `mapPreambleWrapped` or
|
|
27
|
+
* any `preambleRegions` entry makes the loop ineligible.
|
|
28
|
+
* 3. **Every reactive outer dependency must be primable.** `mapArrayLazy`
|
|
29
|
+
* creates ONE loop-level effect for `applyOuter`; that effect subscribes
|
|
30
|
+
* only to what its body reads, and its body must read the outer signals
|
|
31
|
+
* even when the entry list is momentarily EMPTY (otherwise the effect
|
|
32
|
+
* never subscribes and the loop goes permanently dead). The emitter
|
|
33
|
+
* primes those reads with `getter()` statements, which is only possible
|
|
34
|
+
* for names it can prove are zero-arg component signal / memo getters.
|
|
35
|
+
* Any other name that could change reactively — a prop accessor (props
|
|
36
|
+
* may be defined as getters over the parent's signals), or a name the
|
|
37
|
+
* compiler cannot classify at all — is `opaque` and makes the loop
|
|
38
|
+
* ineligible. Imports and component-local functions are opaque TOO
|
|
39
|
+
* (`const isSelected = createSelector(selected)` is an ordinary local
|
|
40
|
+
* whose CALL is the reactive read), so they refuse the loop as well —
|
|
41
|
+
* the `inert` set names them only so the refusal can say which one.
|
|
42
|
+
* Genuinely ignorable are the names that cannot carry a reactive read
|
|
43
|
+
* at all: literal-derived local / module constants and pure globals.
|
|
44
|
+
* 4. **Outer-involving TEXT bindings are ACCEPTED** (§9.5, lifted).
|
|
45
|
+
* §9.3(1) requires read-compare-write seeding on `applyOuter`'s first
|
|
46
|
+
* run: compute the value, READ the current DOM, write only on
|
|
47
|
+
* difference. For an attribute that read is `getAttribute` / a DOM
|
|
48
|
+
* property on the held element ref. For a content slot the read door is
|
|
49
|
+
* `lazyClaimSlots`' `read(id)` (`claim-slots.ts`), the read-capable twin
|
|
50
|
+
* of `lazySlots` over the SAME claim. The emitter picks the door per
|
|
51
|
+
* LOOP — a loop with no outer-involving text keeps the single-closure
|
|
52
|
+
* writer — so this widening costs nothing for loops that do not use it
|
|
53
|
+
* (see `refParts` in `stringify/lazy-row.ts`).
|
|
54
|
+
* 5. **Loop-source hydration consistency** (§9.3(2)): item-driven bindings
|
|
55
|
+
* are never evaluated at hydration, so the SSR rows and the first client
|
|
56
|
+
* `items()` read are TRUSTED to agree. That trust is only sound when
|
|
57
|
+
* both derive from the same data — props (identical by construction via
|
|
58
|
+
* the `bf-p` protocol), literals, and derivations thereof. Any name in
|
|
59
|
+
* the loop source that reaches an import, an environment read, or
|
|
60
|
+
* anything the compiler cannot resolve → ineligible.
|
|
61
|
+
* 6. **Profile mode is never lazy** (§9.4, same policy as A3b): a merged
|
|
62
|
+
* loop-level effect would make every binding on every row share one
|
|
63
|
+
* `#binding:<slotId>` id.
|
|
64
|
+
*/
|
|
65
|
+
/** Facts about one component signal needed by the §9.3(2) source gate. */
|
|
66
|
+
export interface LazyRowSignalFacts {
|
|
67
|
+
/**
|
|
68
|
+
* Free identifiers of the signal's initializer, derived from its
|
|
69
|
+
* structured `SignalInfo.parsed` tree. `null` when `parsed` was absent or
|
|
70
|
+
* the tree contained an `unsupported` node — "unprovable", which the gate
|
|
71
|
+
* treats as a hard stop rather than an assumption.
|
|
72
|
+
*/
|
|
73
|
+
initializerFreeIdentifiers: ReadonlySet<string> | null;
|
|
74
|
+
}
|
|
75
|
+
/** Component-scope facts the gate resolves names against. */
|
|
76
|
+
export interface LazyRowScopeInfo {
|
|
77
|
+
/** Signal getter name → initializer facts. */
|
|
78
|
+
signals: ReadonlyMap<string, LazyRowSignalFacts>;
|
|
79
|
+
/** Memo getter names — reactive and primable via `name()`. */
|
|
80
|
+
memos: ReadonlySet<string>;
|
|
81
|
+
/** Props emit name (`_p`), the source props object name, and every destructured prop param. */
|
|
82
|
+
props: ReadonlySet<string>;
|
|
83
|
+
/**
|
|
84
|
+
* Constant name → free identifiers of its value (`ConstantInfo.freeIdentifiers`).
|
|
85
|
+
* An entry with an EMPTY set is literal-derived. Absent free-id data is
|
|
86
|
+
* modelled as `null` → unprovable for the source gate (but still inert for
|
|
87
|
+
* the binding gate — a `const` never changes reactively).
|
|
88
|
+
*/
|
|
89
|
+
constants: ReadonlyMap<string, ReadonlySet<string> | null>;
|
|
90
|
+
/**
|
|
91
|
+
* Import local names and component-local function names. Used ONLY by the
|
|
92
|
+
* §9.3(2) source gate (to name the failure precisely); binding
|
|
93
|
+
* classification treats them as OPAQUE, not inert — see
|
|
94
|
+
* {@link classifyLazyBinding}.
|
|
95
|
+
*/
|
|
96
|
+
inert: ReadonlySet<string>;
|
|
97
|
+
/** Profile mode (#1690) — never lazy. */
|
|
98
|
+
profile: boolean;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Sentinel `opaqueOuterNames` entry for "free-identifier analysis produced
|
|
102
|
+
* nothing". Distinct from a real opaque NAME: a name means the identifier
|
|
103
|
+
* set is known and only its primability is not, which the re-subscribe seam
|
|
104
|
+
* handles; this means the set itself is unknown, which nothing can handle.
|
|
105
|
+
*/
|
|
106
|
+
export declare const UNKNOWN_IDENTIFIERS = "<unknown>";
|
|
107
|
+
/** One reactive binding of the row, already classified at build time. */
|
|
108
|
+
export interface ClassifiedLazyBinding {
|
|
109
|
+
kind: 'attr' | 'text';
|
|
110
|
+
slotId: string;
|
|
111
|
+
/** Reads the loop param / a destructured param binding. */
|
|
112
|
+
readsItem: boolean;
|
|
113
|
+
/** Reads at least one reactive outer name (or is `opaque`). */
|
|
114
|
+
readsOuter: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Reactive outer names this binding depends on — signal / memo getters the
|
|
117
|
+
* emitter primes at the top of `applyOuter` so the loop-level effect
|
|
118
|
+
* subscribes even with zero rows.
|
|
119
|
+
*/
|
|
120
|
+
reactiveOuterNames: readonly string[];
|
|
121
|
+
/**
|
|
122
|
+
* Outer names that are neither primable (signal/memo) nor provably inert
|
|
123
|
+
* — including the FAIL-SAFE case where free identifiers were unavailable
|
|
124
|
+
* (then `readsItem`/`readsOuter` are both forced true and this carries the
|
|
125
|
+
* `'<unknown>'` sentinel). Non-empty ⇒ ineligible.
|
|
126
|
+
*/
|
|
127
|
+
opaqueOuterNames: readonly string[];
|
|
128
|
+
/** References the loop's index parameter — `applyItem`/`applyOuter` have no index. */
|
|
129
|
+
referencesIndex: boolean;
|
|
130
|
+
}
|
|
131
|
+
/** §9.4 shape facts, read off the loop plan / IR by the caller. */
|
|
132
|
+
export interface LazyRowShapeFacts {
|
|
133
|
+
/** Which emission site is asking. Both plain-loop-row sites are in scope. */
|
|
134
|
+
callSite: 'plain' | 'branch-plain';
|
|
135
|
+
flatMapLeafItem: boolean;
|
|
136
|
+
anchored: boolean;
|
|
137
|
+
bodyIsMultiRoot: boolean;
|
|
138
|
+
/** `LoopCore.key != null` — index-keyed loops are ineligible in v1 (§9.4). */
|
|
139
|
+
hasExplicitKey: boolean;
|
|
140
|
+
conditionalCount: number;
|
|
141
|
+
childRefCount: number;
|
|
142
|
+
nestedComponentCount: number;
|
|
143
|
+
innerLoopCount: number;
|
|
144
|
+
hasChildComponent: boolean;
|
|
145
|
+
hasMapPreamble: boolean;
|
|
146
|
+
preambleRegionCount: number;
|
|
147
|
+
/** A destructured loop param with no `paramBindings` (snapshot unwrap). */
|
|
148
|
+
hasParamUnwrap: boolean;
|
|
149
|
+
}
|
|
150
|
+
export interface LazyRowEligibilityArgs {
|
|
151
|
+
shape: LazyRowShapeFacts;
|
|
152
|
+
bindings: readonly ClassifiedLazyBinding[];
|
|
153
|
+
/**
|
|
154
|
+
* Free identifiers of the loop's SOURCE (`LoopCore.arrayFreeIdentifiers`
|
|
155
|
+
* unioned with the free identifiers of the fully-chained array expression,
|
|
156
|
+
* so `.filter(...)`/`.sort(...)` dependencies are covered). `null` when the
|
|
157
|
+
* IR carried none — ineligible, never assumed empty.
|
|
158
|
+
*/
|
|
159
|
+
arraySourceIdentifiers: ReadonlySet<string> | null;
|
|
160
|
+
scope: LazyRowScopeInfo;
|
|
161
|
+
}
|
|
162
|
+
export type LazyRowEligibility = {
|
|
163
|
+
eligible: true;
|
|
164
|
+
} | {
|
|
165
|
+
eligible: false;
|
|
166
|
+
reason: string;
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Decide whether one plain loop row may use the lazy row graph (§9.4).
|
|
170
|
+
* Pure — every input is pre-resolved data, so this is directly unit-testable
|
|
171
|
+
* without building a component.
|
|
172
|
+
*/
|
|
173
|
+
export declare function lazyRowEligibility(args: LazyRowEligibilityArgs): LazyRowEligibility;
|
|
174
|
+
/**
|
|
175
|
+
* Classify one binding's free identifiers into the row-local / reactive-outer
|
|
176
|
+
* / opaque-outer partition {@link lazyRowEligibility} consumes.
|
|
177
|
+
*
|
|
178
|
+
* **FAIL-SAFE (mandatory, §9.2):** when `free` is `null` — the IR carried no
|
|
179
|
+
* pre-computed free identifiers, or `freeIdentifiers()` refused the parsed
|
|
180
|
+
* tree (an `unsupported` node) — BOTH `readsItem` and `readsOuter` are forced
|
|
181
|
+
* true. A binding with `readsItem` is emitted into `applyItem`; a binding with
|
|
182
|
+
* `readsOuter` into `applyOuter`; a binding in both is emitted in BOTH. Double
|
|
183
|
+
* application is idempotent because every emitted write is dedup-guarded
|
|
184
|
+
* against `entry.last`, so "both" is always the safe answer and never a
|
|
185
|
+
* correctness risk.
|
|
186
|
+
*
|
|
187
|
+
* The unknown case ALSO records an `'<unknown>'` opaque name, which makes the
|
|
188
|
+
* loop ineligible: an outer dependency the compiler cannot name is an outer
|
|
189
|
+
* dependency it cannot PRIME, and an unprimed `applyOuter` effect would never
|
|
190
|
+
* subscribe (see module docstring, restriction 3). So the fail-safe direction
|
|
191
|
+
* is preserved (maximally conservative classification) while the emission
|
|
192
|
+
* refuses loudly instead of shipping a dead effect.
|
|
193
|
+
*/
|
|
194
|
+
export declare function classifyLazyBinding(args: {
|
|
195
|
+
kind: 'attr' | 'text';
|
|
196
|
+
slotId: string;
|
|
197
|
+
free: ReadonlySet<string> | null;
|
|
198
|
+
/** Loop param name plus every destructured `paramBindings` name. */
|
|
199
|
+
rowLocalNames: ReadonlySet<string>;
|
|
200
|
+
indexParam: string;
|
|
201
|
+
scope: LazyRowScopeInfo;
|
|
202
|
+
}): ClassifiedLazyBinding;
|
|
203
|
+
//# sourceMappingURL=lazy-row-eligibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lazy-row-eligibility.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,7 @@ import type { IRLoopChildComponent } from '../../../types.ts';
|
|
|
20
20
|
import type { SkeletonSlotPaths } from '../../html-template.ts';
|
|
21
21
|
import type { ReactiveEffectsPlan } from './reactive-effects.ts';
|
|
22
22
|
import type { InnerLoopsPlan } from './inner-loop.ts';
|
|
23
|
+
import type { LazyRowPlanData } from './build-lazy-row.ts';
|
|
23
24
|
/** Fields shared by every `LoopPlan` variant. */
|
|
24
25
|
interface LoopPlanCommon {
|
|
25
26
|
/** Container element variable (e.g. `_s1` for top-level, `__loop_<cv>` for branch). */
|
|
@@ -163,6 +164,15 @@ interface PlainLoopVariant extends DynamicLoopCommon {
|
|
|
163
164
|
* `__el` to query against.
|
|
164
165
|
*/
|
|
165
166
|
preambleRegions: readonly PreambleRegionPlan[];
|
|
167
|
+
/**
|
|
168
|
+
* Lazy row graph plan (`spec/slot-unification.md` §9, L3). Non-null when
|
|
169
|
+
* `lazyRowEligibility` accepted this loop: the stringifier emits
|
|
170
|
+
* `mapArrayLazy(...)` with this row plan instead of `mapArray(...)` +
|
|
171
|
+
* renderItem, and the row carries NO per-row reactive resources.
|
|
172
|
+
* Undefined for every ineligible loop — those keep today's emission
|
|
173
|
+
* byte-for-byte (sound-or-loud, `plan/lazy-row-eligibility.ts`).
|
|
174
|
+
*/
|
|
175
|
+
lazyRow?: LazyRowPlanData;
|
|
166
176
|
}
|
|
167
177
|
/**
|
|
168
178
|
* Loop body is a single child component (with or without nested child
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,EACb,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/plan/loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import type { IRLoopChildComponent, LoopParamBinding } from '../../types.ts';
|
|
|
16
16
|
import type { LoopChildRefBinding, PreambleRegionPlan } from './plan/loop.ts';
|
|
17
17
|
import type { PreambleRegionSource } from '../../types.ts';
|
|
18
18
|
/**
|
|
19
|
-
* Build the `keyFn` argument for mapArray /
|
|
19
|
+
* Build the `keyFn` argument for mapArray / mapArrayAnchored. `null` when
|
|
20
20
|
* the loop has no key expression. Every `CollectedLoop` variant (top-level /
|
|
21
21
|
* branch / nested) carries an `index: string | null` field (#2218 threaded
|
|
22
22
|
* it onto `NestedLoop` too), so the index param — when present — is always
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/stringify/branch-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"branch-loop.d.ts","sourceRoot":"","sources":["../../../../src/ir-to-client-js/control-flow/stringify/branch-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,wBAAwB,CAAA;AAE/B,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAW/E;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,SAAS,cAAc,EAAE,GAC/B,IAAI,CAIN"}
|