@barefootjs/jsx 0.34.0 → 0.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer-context.d.ts.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1072 -903
- package/dist/ir-to-client-js/collect-elements.d.ts +22 -2
- package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -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-component-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-composite-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-inner-loop.d.ts +14 -2
- package/dist/ir-to-client-js/control-flow/plan/build-inner-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts +11 -0
- package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop-child-arm.d.ts +6 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop-child-arm.d.ts.map +1 -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/build-plain-row.d.ts +52 -0
- package/dist/ir-to-client-js/control-flow/plan/build-plain-row.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/plan/build-reactive-effects.d.ts +5 -2
- package/dist/ir-to-client-js/control-flow/plan/build-reactive-effects.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/inner-loop.d.ts +24 -44
- package/dist/ir-to-client-js/control-flow/plan/inner-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/lazy-conditional.d.ts +6 -7
- package/dist/ir-to-client-js/control-flow/plan/lazy-conditional.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/lazy-preamble.d.ts +5 -7
- package/dist/ir-to-client-js/control-flow/plan/lazy-preamble.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/lazy-row-eligibility.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/loop-child-arm.d.ts +14 -0
- package/dist/ir-to-client-js/control-flow/plan/loop-child-arm.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts +10 -6
- 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 +11 -9
- package/dist/ir-to-client-js/control-flow/shared.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/composite-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/inner-loop.d.ts +6 -14
- 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/lazy-row.d.ts +1 -3
- package/dist/ir-to-client-js/control-flow/stringify/lazy-row.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/loop-child-arm.d.ts +19 -3
- 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.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts +5 -1
- package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts.map +1 -1
- package/dist/ir-to-client-js/csr-substitute.d.ts +16 -0
- package/dist/ir-to-client-js/csr-substitute.d.ts.map +1 -1
- package/dist/ir-to-client-js/emit-reactive.d.ts +54 -0
- package/dist/ir-to-client-js/emit-reactive.d.ts.map +1 -1
- package/dist/ir-to-client-js/emit-registration.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts +2 -2
- 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/index.d.ts.map +1 -1
- package/dist/ir-to-client-js/markup-slots.d.ts +21 -0
- package/dist/ir-to-client-js/markup-slots.d.ts.map +1 -0
- package/dist/ir-to-client-js/reactivity.d.ts +62 -18
- package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
- package/dist/ir-to-client-js/safe-html.d.ts +158 -0
- package/dist/ir-to-client-js/safe-html.d.ts.map +1 -0
- package/dist/ir-to-client-js/types.d.ts +18 -2
- package/dist/ir-to-client-js/types.d.ts.map +1 -1
- package/dist/ir-to-client-js/utils.d.ts +34 -1
- package/dist/ir-to-client-js/utils.d.ts.map +1 -1
- package/dist/jsx-to-ir.d.ts.map +1 -1
- package/dist/prop-rewrite.d.ts +8 -3
- package/dist/prop-rewrite.d.ts.map +1 -1
- package/dist/props-binding.d.ts +22 -1
- package/dist/props-binding.d.ts.map +1 -1
- package/dist/reactivity-checker.d.ts +18 -0
- package/dist/reactivity-checker.d.ts.map +1 -1
- package/dist/ssr-defaults.d.ts.map +1 -1
- package/dist/types.d.ts +5 -10
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +138 -22
- package/src/__tests__/binding-scope-ratchet.test.ts +25 -2
- package/src/__tests__/build-plain-row-consolidation.test.ts +120 -0
- package/src/__tests__/child-prop-fallback-wrap.test.ts +4 -2
- package/src/__tests__/client-template-escape-soundness.test.ts +538 -0
- package/src/__tests__/compiler-stress-1244.test.ts +8 -8
- package/src/__tests__/csr-template-loop-shadowing.test.ts +4 -2
- package/src/__tests__/flatmap-segments.test.ts +1 -1
- package/src/__tests__/issue-2868-cond-arm-tag-collision.test.ts +185 -0
- package/src/__tests__/issue-2869-attr-dedup-guard.test.ts +141 -0
- package/src/__tests__/lazy-conditional.test.ts +52 -12
- package/src/__tests__/lazy-preamble.test.ts +11 -11
- package/src/__tests__/lazy-row-eligibility.test.ts +8 -3
- package/src/__tests__/loop-child-reactive-attr-const-shadow.test.ts +25 -3
- package/src/__tests__/loop-index-reactivity.test.ts +208 -0
- package/src/__tests__/loop-item-conditional-codegen.test.ts +4 -2
- package/src/__tests__/map-arbitrary-body.test.ts +1 -1
- package/src/__tests__/map-body-brand-checker.test.ts +176 -0
- package/src/__tests__/nested-loop-index-param.test.ts +41 -8
- package/src/__tests__/nested-loop-non-outer-reactivity.test.ts +177 -0
- package/src/__tests__/nested-loop-plain.test.ts +39 -25
- package/src/__tests__/nested-loop-reactive-attrs.test.ts +16 -6
- package/src/__tests__/preamble-branch-arm-rerun.test.ts +135 -0
- package/src/__tests__/reactive-attrs-in-map.test.ts +13 -10
- package/src/__tests__/rewrite-destructured-props.test.ts +37 -0
- package/src/__tests__/safe-html-splice-door.test.ts +61 -0
- package/src/__tests__/ssr-defaults.test.ts +59 -0
- package/src/__tests__/style-css-var-reactive.test.ts +4 -1
- package/src/analyzer-context.ts +12 -10
- package/src/analyzer.ts +4 -0
- package/src/index.ts +8 -2
- package/src/ir-to-client-js/collect-elements.ts +126 -32
- package/src/ir-to-client-js/control-flow/plan/build-branch-loop.ts +20 -28
- package/src/ir-to-client-js/control-flow/plan/build-component-loop.ts +9 -7
- package/src/ir-to-client-js/control-flow/plan/build-composite-loop.ts +12 -6
- package/src/ir-to-client-js/control-flow/plan/build-inner-loop.ts +36 -59
- package/src/ir-to-client-js/control-flow/plan/build-lazy-row.ts +25 -4
- package/src/ir-to-client-js/control-flow/plan/build-loop-child-arm.ts +36 -9
- package/src/ir-to-client-js/control-flow/plan/build-loop.ts +35 -35
- package/src/ir-to-client-js/control-flow/plan/build-plain-row.ts +116 -0
- package/src/ir-to-client-js/control-flow/plan/build-reactive-effects.ts +23 -8
- package/src/ir-to-client-js/control-flow/plan/inner-loop.ts +24 -45
- package/src/ir-to-client-js/control-flow/plan/lazy-conditional.ts +11 -10
- package/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts +11 -13
- package/src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts +13 -3
- package/src/ir-to-client-js/control-flow/plan/loop-child-arm.ts +14 -0
- package/src/ir-to-client-js/control-flow/plan/loop.ts +10 -6
- package/src/ir-to-client-js/control-flow/shared.ts +40 -17
- package/src/ir-to-client-js/control-flow/stringify/composite-loop.ts +2 -1
- package/src/ir-to-client-js/control-flow/stringify/inner-loop.ts +20 -66
- package/src/ir-to-client-js/control-flow/stringify/insert.ts +4 -2
- package/src/ir-to-client-js/control-flow/stringify/lazy-row.ts +22 -15
- package/src/ir-to-client-js/control-flow/stringify/loop-child-arm.ts +53 -11
- package/src/ir-to-client-js/control-flow/stringify/loop.ts +4 -2
- package/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts +29 -18
- package/src/ir-to-client-js/csr-substitute.ts +29 -0
- package/src/ir-to-client-js/emit-reactive.ts +92 -6
- package/src/ir-to-client-js/emit-registration.ts +2 -4
- package/src/ir-to-client-js/html-template.ts +67 -245
- package/src/ir-to-client-js/imports.ts +3 -0
- package/src/ir-to-client-js/index.ts +4 -4
- package/src/ir-to-client-js/markup-slots.ts +25 -0
- package/src/ir-to-client-js/reactivity.ts +73 -27
- package/src/ir-to-client-js/safe-html.ts +243 -0
- package/src/ir-to-client-js/types.ts +19 -3
- package/src/ir-to-client-js/utils.ts +58 -10
- package/src/jsx-to-ir.ts +136 -24
- package/src/prop-rewrite.ts +8 -4
- package/src/props-binding.ts +37 -1
- package/src/reactivity-checker.ts +60 -0
- package/src/ssr-defaults.ts +45 -0
- package/src/types.ts +5 -10
- package/src/__tests__/text-slot-escaping.test.ts +0 -65
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
* from `LoopChildBranchSummary.reactiveAttrs` / `.reactiveTexts` —
|
|
13
13
|
* collected per-branch, recursively, so a doubly-nested conditional's
|
|
14
14
|
* arm carries its own bindings instead of an outer scope reaching in.
|
|
15
|
-
* 4. Apply `addCondAttrToTemplate` to
|
|
16
|
-
*
|
|
15
|
+
* 4. Apply `addCondAttrToTemplate` to each branch's HTML (already
|
|
16
|
+
* loop-param-wrapped at IR render time, #2868) so the stringifier
|
|
17
|
+
* emits a ready-to-interpolate template literal.
|
|
17
18
|
* 5. Recurse into the per-arm sub-plans via `LoopChildArmPlan` —
|
|
18
19
|
* events, child component inits, inner loops, nested conditionals,
|
|
19
20
|
* attrs, texts. No legacy passthrough remains.
|
|
@@ -52,6 +53,8 @@ export interface BuildReactiveEffectsArgs {
|
|
|
52
53
|
conditionals: readonly LoopChildConditional[] | undefined
|
|
53
54
|
loopParam: string
|
|
54
55
|
loopParamBindings?: readonly LoopParamBinding[]
|
|
56
|
+
/** This loop's index param name, when it declares one (#2859). */
|
|
57
|
+
loopIndex?: string | null
|
|
55
58
|
/** Owning component name in profile mode (#1690, SR3) — else undefined. */
|
|
56
59
|
profileComponentName?: string
|
|
57
60
|
}
|
|
@@ -60,8 +63,8 @@ export interface BuildReactiveEffectsArgs {
|
|
|
60
63
|
export function buildReactiveEffectsPlan(
|
|
61
64
|
args: BuildReactiveEffectsArgs,
|
|
62
65
|
): ReactiveEffectsPlan {
|
|
63
|
-
const { attrs, texts, conditionals, loopParam, loopParamBindings, profileComponentName } = args
|
|
64
|
-
const wrap = (expr: string) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings)
|
|
66
|
+
const { attrs, texts, conditionals, loopParam, loopParamBindings, loopIndex, profileComponentName } = args
|
|
67
|
+
const wrap = (expr: string) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings, loopIndex)
|
|
65
68
|
|
|
66
69
|
// 1. Group attrs by slot, preserving declaration order (Map insertion order
|
|
67
70
|
// matches the legacy iteration that produced byte-identical output).
|
|
@@ -108,10 +111,17 @@ export function buildReactiveEffectsPlan(
|
|
|
108
111
|
conditionalPlans.push({
|
|
109
112
|
slotId: cond.slotId,
|
|
110
113
|
wrappedCondition: wrap(cond.condition),
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
// whenTrueHtml/whenFalseHtml are already loop-param-wrapped at IR
|
|
115
|
+
// render time (`irToHtmlTemplate`'s `loopParams`, collect-elements.ts)
|
|
116
|
+
// — do NOT re-wrap the rendered HTML string here. A word-boundary
|
|
117
|
+
// regex over already-assembled markup matches a bare tag name that
|
|
118
|
+
// collides with the param/index identifier (`<i>` -> `<i()>`) just
|
|
119
|
+
// as readily as a real reference, since `<`/`>` are non-word
|
|
120
|
+
// characters (#2868).
|
|
121
|
+
whenTrueTemplateHtml: addCondAttrToTemplate(cond.whenTrueHtml, cond.slotId),
|
|
122
|
+
whenFalseTemplateHtml: addCondAttrToTemplate(cond.whenFalseHtml, cond.slotId),
|
|
123
|
+
whenTrueArm: buildOuterArm(cond.whenTrue, wrap, loopParam, loopParamBindings, loopIndex, cond.slotId, profileComponentName),
|
|
124
|
+
whenFalseArm: buildOuterArm(cond.whenFalse, wrap, loopParam, loopParamBindings, loopIndex, cond.slotId, profileComponentName),
|
|
115
125
|
...(cond.readsPreamble && { readsPreamble: true }),
|
|
116
126
|
})
|
|
117
127
|
}
|
|
@@ -130,6 +140,8 @@ function buildOuterArm(
|
|
|
130
140
|
wrap: (expr: string) => string,
|
|
131
141
|
loopParam: string,
|
|
132
142
|
loopParamBindings: readonly LoopParamBinding[] | undefined,
|
|
143
|
+
/** This loop's index param name, when it declares one (#2861). */
|
|
144
|
+
loopIndex: string | null | undefined,
|
|
133
145
|
/** The conditional's own slot id — threaded to `buildBranchInnerLoopsPlan`'s `condSlotId` (#2705). */
|
|
134
146
|
condSlotId: string,
|
|
135
147
|
profileComponentName?: string,
|
|
@@ -150,6 +162,7 @@ function buildOuterArm(
|
|
|
150
162
|
condSlotId,
|
|
151
163
|
outerLoopParam: loopParam,
|
|
152
164
|
outerLoopParamBindings: loopParamBindings,
|
|
165
|
+
outerLoopIndex: loopIndex,
|
|
153
166
|
wrapOuter: wrap,
|
|
154
167
|
}),
|
|
155
168
|
nestedConditionals: buildLoopChildConditionalsPlan({
|
|
@@ -158,6 +171,7 @@ function buildOuterArm(
|
|
|
158
171
|
wrap,
|
|
159
172
|
loopParam,
|
|
160
173
|
loopParamBindings,
|
|
174
|
+
loopIndex,
|
|
161
175
|
}),
|
|
162
176
|
attrs: buildArmAttrsPlan(branch.reactiveAttrs, wrap),
|
|
163
177
|
texts: buildArmTextsPlan(branch.reactiveTexts, wrap),
|
|
@@ -175,6 +189,7 @@ export function buildLoopReactiveEffectsPlan(elem: TopLevelLoop, profileComponen
|
|
|
175
189
|
conditionals: elem.bindings.conditionals,
|
|
176
190
|
loopParam: elem.param,
|
|
177
191
|
loopParamBindings: elem.paramBindings,
|
|
192
|
+
loopIndex: elem.index,
|
|
178
193
|
profileComponentName,
|
|
179
194
|
})
|
|
180
195
|
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plan types for inner loops emitted inside a composite loop's renderItem
|
|
3
|
-
* body. Each `InnerLoopPlan` is one level (= one `mapArray`
|
|
4
|
-
*
|
|
5
|
-
* deeper nestings.
|
|
3
|
+
* body. Each `InnerLoopPlan` is one level (= one `mapArray`); `childLevels`
|
|
4
|
+
* recurses for deeper nestings.
|
|
6
5
|
*
|
|
7
6
|
* Replaces the legacy `emitInnerLoopSetup` + `DepthLevel` walk. The
|
|
8
|
-
* builder pre-resolves every per-level decision (
|
|
9
|
-
*
|
|
7
|
+
* builder pre-resolves every per-level decision (container query, wrapped
|
|
8
|
+
* array / template / key, narrowed-outer-param children) so the
|
|
10
9
|
* stringifier is a deterministic walk.
|
|
10
|
+
*
|
|
11
|
+
* Every level gets the reactive `mapArray` shape (#2865) — there used to
|
|
12
|
+
* be a second "static forEach, setup-only" shape for a nested loop whose
|
|
13
|
+
* array didn't reference the outer item, but that gate answered the wrong
|
|
14
|
+
* question (it never checked whether the array was reactive at all, only
|
|
15
|
+
* whether it mentioned the outer item's name) and silently froze any other
|
|
16
|
+
* reactivity in the row. See `build-inner-loop.ts`'s module docstring.
|
|
11
17
|
*/
|
|
12
18
|
|
|
13
19
|
import type { LoopChildEvent } from '../../types.ts'
|
|
@@ -64,20 +70,9 @@ export interface InnerLoopReactiveAttr {
|
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
/**
|
|
67
|
-
* One inner loop level inside a composite renderItem
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* - `reactive`: full `mapArray(...)` with renderItem (template clone,
|
|
72
|
-
* key attr, components/events with inner-wrapped props, reactive text
|
|
73
|
-
* effects, recursive childLevels).
|
|
74
|
-
* - `static`: `forEach(...)` for setup-only (children are rendered
|
|
75
|
-
* into the SSR HTML); components/events use the raw param, no
|
|
76
|
-
* wrap, no template clone.
|
|
77
|
-
*
|
|
78
|
-
* Choosing the mode requires checking whether `inner.array` references
|
|
79
|
-
* the outer loop param at *this* level (legacy O-8 fix). The builder
|
|
80
|
-
* does that check; the stringifier just dispatches on `mode`.
|
|
73
|
+
* One inner loop level inside a composite renderItem: a full `mapArray(...)`
|
|
74
|
+
* with renderItem (template clone, key attr, components/events with
|
|
75
|
+
* inner-wrapped props, reactive text/attr effects, recursive childLevels).
|
|
81
76
|
*/
|
|
82
77
|
export interface InnerLoopPlan {
|
|
83
78
|
/** Unique suffix used in `__ic` / `__innerEl` / `__innerIdx` var names. */
|
|
@@ -101,21 +96,25 @@ export interface InnerLoopPlan {
|
|
|
101
96
|
* `// Initialize <array> loop components and events` comments.
|
|
102
97
|
*/
|
|
103
98
|
arraySrc: string
|
|
104
|
-
/** Inner loop parameter identifier
|
|
99
|
+
/** Inner loop parameter identifier. */
|
|
105
100
|
param: string
|
|
106
101
|
/** Depth used by `keyAttrName(...)`. Same as the IR's `inner.depth`. */
|
|
107
102
|
keyDepth: number
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
* narrowed and prevents accidental cross-talk.
|
|
111
|
-
*/
|
|
112
|
-
emit: InnerLoopReactiveEmit | InnerLoopStaticEmit
|
|
103
|
+
/** Emission data for this level's `mapArray` renderItem. */
|
|
104
|
+
emit: InnerLoopReactiveEmit
|
|
113
105
|
/** Recursive child levels — narrowed-outer-param at build time. */
|
|
114
106
|
childLevels: readonly InnerLoopPlan[]
|
|
115
107
|
/** Outer loop param threaded into emitComponentAndEventSetup. */
|
|
116
108
|
outerLoopParam: string | undefined
|
|
117
109
|
/** Outer loop param destructuring metadata. */
|
|
118
110
|
outerLoopParamBindings?: readonly LoopParamBinding[]
|
|
111
|
+
/**
|
|
112
|
+
* Outer loop's index param name, when present (#2861) — threaded into
|
|
113
|
+
* `emitComponentAndEventSetup` so a component prop / event handler in
|
|
114
|
+
* this row that closes over the OUTER loop's index reads it through the
|
|
115
|
+
* live accessor instead of a value frozen at row-creation time.
|
|
116
|
+
*/
|
|
117
|
+
outerLoopIndex?: string | null
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
export interface InnerLoopReactiveEmit {
|
|
@@ -164,24 +163,4 @@ export interface InnerLoopReactiveEmit {
|
|
|
164
163
|
childRefs: readonly LoopChildRefBinding[]
|
|
165
164
|
}
|
|
166
165
|
|
|
167
|
-
export interface InnerLoopStaticEmit {
|
|
168
|
-
mode: 'static'
|
|
169
|
-
/** Raw key expression (used as-is in setAttribute) — null when no key. */
|
|
170
|
-
rawKey: string | null
|
|
171
|
-
/**
|
|
172
|
-
* Body-entry statements (see `PreludeStatements`) emitted at the top of
|
|
173
|
-
* the static `forEach(...)` body, after the existence guard. Holds the
|
|
174
|
-
* inner `.map()` callback preamble locals (#1064). Emitted unwrapped
|
|
175
|
-
* because the forEach param is the literal item, not a signal accessor —
|
|
176
|
-
* no accessor rewrite is needed.
|
|
177
|
-
*/
|
|
178
|
-
preludeStatements: PreludeStatements
|
|
179
|
-
/** Raw components (no inner-wrap; the static body has no signal accessor). */
|
|
180
|
-
components: readonly IRLoopChildComponent[]
|
|
181
|
-
/** Raw events (no inner-wrap). */
|
|
182
|
-
events: readonly LoopChildEvent[]
|
|
183
|
-
/** Imperative ref callbacks (unwrapped — static body has no signal accessor). */
|
|
184
|
-
childRefs: readonly LoopChildRefBinding[]
|
|
185
|
-
}
|
|
186
|
-
|
|
187
166
|
export type InnerLoopsPlan = readonly InnerLoopPlan[]
|
|
@@ -47,9 +47,11 @@
|
|
|
47
47
|
* defeating the hoist. (A literal `${` in authored TEXT would also refuse
|
|
48
48
|
* here; that is the safe direction — a false refusal costs the eager
|
|
49
49
|
* fallback, a false accept would ship a frozen arm.)
|
|
50
|
-
* 4.
|
|
51
|
-
*
|
|
52
|
-
* `
|
|
50
|
+
* 4. (#2859 follow-up) A condition MAY read the loop index — it is
|
|
51
|
+
* classified like any other binding (`classifyLazyBinding` in
|
|
52
|
+
* `lazy-row-eligibility.ts`), which forces it into `applyItem` so a
|
|
53
|
+
* reorder (a position change the reconciler tracks on `entry.index`)
|
|
54
|
+
* re-evaluates it, not just an item change.
|
|
53
55
|
*
|
|
54
56
|
* Everything refused carries a specific reason, which `lazyRowEligibility`
|
|
55
57
|
* passes through unchanged.
|
|
@@ -99,13 +101,9 @@ function wiringOn(branch: LoopChildBranchSummary): string[] {
|
|
|
99
101
|
|
|
100
102
|
/**
|
|
101
103
|
* Decide whether `cond` can be driven from the loop-level apply bodies.
|
|
102
|
-
*
|
|
103
|
-
* `indexParam` is the loop's index parameter name as the emitter uses it
|
|
104
|
-
* (`elem.index || '__idx'`); a condition reading it is refused.
|
|
105
104
|
*/
|
|
106
105
|
export function analyzeLazyConditional(
|
|
107
106
|
cond: LoopChildConditional,
|
|
108
|
-
indexParam: string,
|
|
109
107
|
arms: PreparedArms,
|
|
110
108
|
): LazyConditionalAnalysis {
|
|
111
109
|
for (const [label, branch] of [['true', cond.whenTrue], ['false', cond.whenFalse]] as const) {
|
|
@@ -135,9 +133,12 @@ export function analyzeLazyConditional(
|
|
|
135
133
|
if (!cond.conditionFreeIdentifiers) {
|
|
136
134
|
return NO(`conditional on slot ${cond.slotId}: condition has no analyzable identifier set`)
|
|
137
135
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
// A condition reading the loop index (#2859 follow-up, widening from a hard
|
|
137
|
+
// refusal) is no longer refused here: the caller classifies the condition
|
|
138
|
+
// like any other binding (`classifyLazyBinding` in `lazy-row-eligibility.ts`),
|
|
139
|
+
// which forces `readsItem: true` for an index reference — the reconciler
|
|
140
|
+
// delivers the row's current position on `entry.index` the same way it
|
|
141
|
+
// delivers the item, so the condition is re-evaluated on a reorder too.
|
|
141
142
|
|
|
142
143
|
return {
|
|
143
144
|
lazySafe: true,
|
|
@@ -68,9 +68,10 @@
|
|
|
68
68
|
* markup, which is `preambleRegions` territory (refused separately).
|
|
69
69
|
* - No `builderNames`. Same shape as above, pinned explicitly so the reason
|
|
70
70
|
* names it rather than surfacing as a confusing "contains a call".
|
|
71
|
-
* - The preamble
|
|
72
|
-
* `
|
|
73
|
-
*
|
|
71
|
+
* - (#2859 follow-up) The preamble MAY read the loop's index parameter — it
|
|
72
|
+
* survives into `freeNames` below like any other read, so a binding that
|
|
73
|
+
* names this preamble local substitutes through to it and is classified
|
|
74
|
+
* the same way a direct index reference is (forced into `applyItem`).
|
|
74
75
|
*
|
|
75
76
|
* Member access is deliberately NOT banned even though a getter could in
|
|
76
77
|
* principle run code: a binding expression like `class={row.cls}` is already
|
|
@@ -130,9 +131,6 @@ const NO = (reason: string): LazyPreambleAnalysis => ({ lazySafe: false, reason
|
|
|
130
131
|
* Decide whether `preamble` may be re-executed inside a lazy row's apply
|
|
131
132
|
* bodies, and if so what it declares and reads.
|
|
132
133
|
*
|
|
133
|
-
* `indexParam` is the loop's index parameter name as the emitter uses it
|
|
134
|
-
* (`elem.index || '__idx'`); a preamble reading it is refused.
|
|
135
|
-
*
|
|
136
134
|
* `primableNames` are the component's signal getters and memos — the only
|
|
137
135
|
* callees a preamble initializer may invoke (see the module docstring). Pass
|
|
138
136
|
* the same names `LazyRowScopeInfo` carries, so "primable here" and "primable
|
|
@@ -140,7 +138,6 @@ const NO = (reason: string): LazyPreambleAnalysis => ({ lazySafe: false, reason
|
|
|
140
138
|
*/
|
|
141
139
|
export function analyzeLazyPreamble(
|
|
142
140
|
preamble: MapCallbackPreamble | undefined,
|
|
143
|
-
indexParam: string,
|
|
144
141
|
primableNames: ReadonlySet<string>,
|
|
145
142
|
): LazyPreambleAnalysis {
|
|
146
143
|
if (!preamble) return NO_PREAMBLE
|
|
@@ -196,13 +193,14 @@ export function analyzeLazyPreamble(
|
|
|
196
193
|
}
|
|
197
194
|
}
|
|
198
195
|
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
//
|
|
196
|
+
// A preamble reading the loop index (#2859 follow-up, widening from a hard
|
|
197
|
+
// refusal) is no longer refused here: `indexParam` survives into
|
|
198
|
+
// `freeNames` below, and any binding that names this preamble local
|
|
199
|
+
// substitutes through to it (`classifyLazyBinding`'s preamble handling),
|
|
200
|
+
// which classifies a free `indexParam` the same way a direct reference
|
|
201
|
+
// would — forcing the binding into `applyItem` so a reorder re-evaluates
|
|
202
|
+
// it via `entry.index`.
|
|
202
203
|
const readNames = extractFreeIdentifiersFromStatementText(text)
|
|
203
|
-
if (readNames.has(indexParam) && !declaredNames.has(indexParam)) {
|
|
204
|
-
return NO(`map-callback preamble reads the loop index parameter '${indexParam}'`)
|
|
205
|
-
}
|
|
206
204
|
|
|
207
205
|
const freeNames = new Set(readNames)
|
|
208
206
|
for (const declared of declaredNames) freeNames.delete(declared)
|
|
@@ -284,9 +284,15 @@ export function lazyRowEligibility(args: LazyRowEligibilityArgs): LazyRowEligibi
|
|
|
284
284
|
|
|
285
285
|
// Per-binding gates.
|
|
286
286
|
for (const b of bindings) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
// A binding that references the loop index (#2859 follow-up, widening
|
|
288
|
+
// from a hard refusal): `applyItem`/`applyOuter` have no index PARAMETER,
|
|
289
|
+
// but the reconciler tracks each entry's current position on `entry.index`
|
|
290
|
+
// (`LazyRowEntry.index`, `map-array-lazy.ts`) exactly like it tracks
|
|
291
|
+
// `entry.item` — a reorder is a position change the reconciler already
|
|
292
|
+
// detects, the same way an item change is. `classifyLazyBinding` forces
|
|
293
|
+
// `readsItem: true` for any binding with `referencesIndex`, so it is
|
|
294
|
+
// ALWAYS emitted into `applyItem`, and the runtime calls `applyItem` on a
|
|
295
|
+
// pure reorder too when `plan.indexDriven` (`LazyRowPlanData.readsIndex`).
|
|
290
296
|
// An identifier set we could not compute at all is different in kind
|
|
291
297
|
// from a name we CAN see but cannot prime. With `free === null` the
|
|
292
298
|
// classifier knows nothing — not the outer reads, and not whether the
|
|
@@ -445,7 +451,11 @@ export function classifyLazyBinding(args: {
|
|
|
445
451
|
return
|
|
446
452
|
}
|
|
447
453
|
if (name === indexParam) {
|
|
454
|
+
// The row's current position (#2859 follow-up) — the reconciler
|
|
455
|
+
// delivers it on `entry.index` exactly like it delivers the item on
|
|
456
|
+
// `entry.item`, so a binding that reads it is item-driven too.
|
|
448
457
|
referencesIndex = true
|
|
458
|
+
readsItem = true
|
|
449
459
|
return
|
|
450
460
|
}
|
|
451
461
|
if (INERT_BINDING_GLOBALS.has(name)) return
|
|
@@ -146,6 +146,13 @@ export interface BranchInnerLoop {
|
|
|
146
146
|
outerLoopParam: string
|
|
147
147
|
/** Outer loop param destructuring metadata. */
|
|
148
148
|
outerLoopParamBindings?: readonly import('../../../types.ts').LoopParamBinding[]
|
|
149
|
+
/**
|
|
150
|
+
* Outer loop's index param name, when present (#2861) — threaded into
|
|
151
|
+
* `emitComponentAndEventSetup`'s own outer-wrap pass alongside
|
|
152
|
+
* `outerLoopParam`/`outerLoopParamBindings`, mirroring `InnerLoopPlan`'s
|
|
153
|
+
* field of the same name.
|
|
154
|
+
*/
|
|
155
|
+
outerLoopIndex?: string | null
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
export type BranchInnerLoopsPlan = readonly BranchInnerLoop[]
|
|
@@ -206,4 +213,11 @@ export interface LoopChildConditionalPlan {
|
|
|
206
213
|
whenFalseTemplateHtml: string
|
|
207
214
|
whenTrueArm: LoopChildArmPlan
|
|
208
215
|
whenFalseArm: LoopChildArmPlan
|
|
216
|
+
/**
|
|
217
|
+
* `wrappedCondition` reads a `.map()` callback preamble local (#2596,
|
|
218
|
+
* same field as `NestedConditionalPlan.readsPreamble` one level up) —
|
|
219
|
+
* the stringifier must run the row's preamble inside the getter passed
|
|
220
|
+
* to `insert()`; the local isn't otherwise in scope there.
|
|
221
|
+
*/
|
|
222
|
+
readsPreamble?: boolean
|
|
209
223
|
}
|
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
TopLevelLoop,
|
|
24
24
|
} from '../../types.ts'
|
|
25
25
|
import type { IRLoopChildComponent } from '../../../types.ts'
|
|
26
|
+
import type { SafeHtml } from '../../safe-html.ts'
|
|
26
27
|
import type { SkeletonSlotPaths } from '../../html-template.ts'
|
|
27
28
|
import type { ReactiveEffectsPlan } from './reactive-effects.ts'
|
|
28
29
|
import type { InnerLoopsPlan } from './inner-loop.ts'
|
|
@@ -83,15 +84,16 @@ interface DynamicLoopCommon extends LoopPlanCommon {
|
|
|
83
84
|
|
|
84
85
|
/**
|
|
85
86
|
* A resolved preamble-patched region (#2389), ready to emit: `valueExpr` is
|
|
86
|
-
* already wrapped with the loop-param accessor and
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
87
|
+
* already wrapped with the loop-param accessor and already went through the
|
|
88
|
+
* child-splice door (`safe-html.ts`) — the exact value `irToHtmlTemplate`
|
|
89
|
+
* computes for the same node in the row template, so a same-key update's
|
|
90
|
+
* re-patch stays byte-identical to what a fresh mount would render. Typed
|
|
91
|
+
* `SafeHtml` because the region writer is an `innerHTML` write: only a
|
|
92
|
+
* value the door (or a named producer) vouched for may reach it.
|
|
91
93
|
*/
|
|
92
94
|
export interface PreambleRegionPlan {
|
|
93
95
|
slotId: string
|
|
94
|
-
valueExpr:
|
|
96
|
+
valueExpr: SafeHtml
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
/** Per-item ref callback resolved against a child slot for emission (#1244). */
|
|
@@ -237,6 +239,8 @@ interface CompositeLoopVariant extends DynamicLoopCommon {
|
|
|
237
239
|
loopParam: string
|
|
238
240
|
/** Destructured-binding metadata for the loop param. */
|
|
239
241
|
loopParamBindings: TopLevelLoop['paramBindings']
|
|
242
|
+
/** This loop's index param name, when it declares one (#2859). */
|
|
243
|
+
loopIndex: TopLevelLoop['index']
|
|
240
244
|
/** Reactive effects rendered after the SSR/CSR split. */
|
|
241
245
|
reactiveEffects: ReactiveEffectsPlan | null
|
|
242
246
|
/**
|
|
@@ -17,6 +17,7 @@ import type { IRLoopChildComponent, LoopParamBinding } from '../../types.ts'
|
|
|
17
17
|
import { preambleAnalysisText } from '../../types.ts'
|
|
18
18
|
import { quotePropName, wrapLoopParamAsAccessor, irChildrenFreeIds, attrValueToString } from '../utils.ts'
|
|
19
19
|
import { irChildrenToJsExpr, jsxChildrenPropGetterExpr } from '../html-template.ts'
|
|
20
|
+
import { spliceChildValue } from '../safe-html.ts'
|
|
20
21
|
import { emitListenerBlock } from './stringify/event-listener.ts'
|
|
21
22
|
import { nameForRegistryRef } from '../component-scope.ts'
|
|
22
23
|
import { BF_SCOPE, BF_HOST, BF_AT } from '@barefootjs/shared'
|
|
@@ -147,11 +148,12 @@ export function buildChildRefBindings(
|
|
|
147
148
|
refs: readonly LoopChildRef[],
|
|
148
149
|
loopParam: string,
|
|
149
150
|
loopParamBindings: readonly LoopParamBinding[] | undefined,
|
|
151
|
+
loopIndex?: string | null,
|
|
150
152
|
): readonly LoopChildRefBinding[] {
|
|
151
153
|
if (refs.length === 0) return []
|
|
152
154
|
return refs.map(r => ({
|
|
153
155
|
childSlotId: r.childSlotId,
|
|
154
|
-
callback: wrapLoopParamAsAccessor(r.callback, loopParam, loopParamBindings),
|
|
156
|
+
callback: wrapLoopParamAsAccessor(r.callback, loopParam, loopParamBindings, loopIndex),
|
|
155
157
|
}))
|
|
156
158
|
}
|
|
157
159
|
|
|
@@ -241,23 +243,27 @@ export function destructureLoopParam(
|
|
|
241
243
|
/**
|
|
242
244
|
* Resolve `IRLoop.preambleRegions` (#2389) into ready-to-emit
|
|
243
245
|
* `PreambleRegionPlan`s: wrap each source expression with the loop-param
|
|
244
|
-
* accessor and
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
246
|
+
* accessor and hand it to the same door (`spliceChildValue`) the row
|
|
247
|
+
* template's `irToHtmlTemplate` uses for the identical node — so the
|
|
248
|
+
* region-patch effect's re-render (a `'markup'` claim writer, i.e. an
|
|
249
|
+
* `innerHTML` write) matches what a fresh mount would have produced, and
|
|
250
|
+
* the escape decision is made in exactly one place. Shared by the
|
|
251
|
+
* top-level (`build-loop.ts`) and branch (`build-branch-loop.ts`)
|
|
252
|
+
* plain-loop-plan builders.
|
|
249
253
|
*/
|
|
250
254
|
export function buildPreambleRegionPlans(
|
|
251
255
|
regions: readonly PreambleRegionSource[] | undefined,
|
|
252
256
|
loopParam: string,
|
|
253
257
|
loopParamBindings: readonly LoopParamBinding[] | undefined,
|
|
258
|
+
loopIndex?: string | null,
|
|
254
259
|
): readonly PreambleRegionPlan[] {
|
|
255
260
|
if (!regions || regions.length === 0) return []
|
|
256
261
|
return regions.map((r) => {
|
|
257
|
-
const wrapped = wrapLoopParamAsAccessor(r.expr, loopParam, loopParamBindings)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
const wrapped = wrapLoopParamAsAccessor(r.expr, loopParam, loopParamBindings, loopIndex)
|
|
263
|
+
// The region's row-template twin carries the same `slotId`, so the door
|
|
264
|
+
// takes the slotted arm; no `markupSlotIds` here — a loop-row slot's
|
|
265
|
+
// initial render is plain `escapeText`, matching `irToHtmlTemplate`.
|
|
266
|
+
const valueExpr = spliceChildValue({ expr: r.expr, slotId: r.slotId, joinArrayChild: r.joinArrayChild }, wrapped, {})
|
|
261
267
|
return { slotId: r.slotId, valueExpr }
|
|
262
268
|
})
|
|
263
269
|
}
|
|
@@ -270,8 +276,9 @@ export function buildComponentPropsExpr(
|
|
|
270
276
|
comp: { props: Array<{ name: string; value: import('../../types.ts').AttrValue; isEventHandler: boolean }>, children?: import('../../types.ts').IRNode[] },
|
|
271
277
|
loopParam?: string,
|
|
272
278
|
loopParamBindings?: readonly LoopParamBinding[],
|
|
279
|
+
loopIndex?: string | null,
|
|
273
280
|
): string {
|
|
274
|
-
const wrap = loopParam ? (expr: string) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings) : (expr: string) => expr
|
|
281
|
+
const wrap = loopParam ? (expr: string) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings, loopIndex) : (expr: string) => expr
|
|
275
282
|
const entries = comp.props.map((p) => {
|
|
276
283
|
if (p.isEventHandler) {
|
|
277
284
|
const handlerExpr = attrValueToString(p.value) ?? 'undefined'
|
|
@@ -347,7 +354,20 @@ export function buildDepthLevels(
|
|
|
347
354
|
}))
|
|
348
355
|
}
|
|
349
356
|
|
|
350
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* Emit a single addEventListener call for a child event on a given element.
|
|
359
|
+
*
|
|
360
|
+
* This is a DIRECT, one-time listener attach (composite/inner/conditional-arm
|
|
361
|
+
* loop shapes) — unlike the top-level delegated click dispatcher
|
|
362
|
+
* (`build-event-delegation.ts`), which re-derives the current index at click
|
|
363
|
+
* time via `arr.findIndex(...)` and is unaffected by this. A handler wired
|
|
364
|
+
* here closes over whatever `renderItem` bound its raw index parameter to at
|
|
365
|
+
* ROW CREATION time, so a reference to it needs the same accessor-call
|
|
366
|
+
* rewrite as every other loop-index read in this row (#2859) — otherwise a
|
|
367
|
+
* row that survives a same-key reorder keeps firing the handler with the
|
|
368
|
+
* stale, as-created index forever, the click-handler analogue of the
|
|
369
|
+
* render-output bug #2859 itself fixes.
|
|
370
|
+
*/
|
|
351
371
|
function emitEventSetup(
|
|
352
372
|
ls: string[],
|
|
353
373
|
indent: string,
|
|
@@ -356,8 +376,9 @@ function emitEventSetup(
|
|
|
356
376
|
loopParam?: string,
|
|
357
377
|
loopParamBindings?: readonly LoopParamBinding[],
|
|
358
378
|
bodyIsMultiRoot: boolean = false,
|
|
379
|
+
loopIndex?: string | null,
|
|
359
380
|
): void {
|
|
360
|
-
const handler = loopParam ? wrapLoopParamAsAccessor(ev.handler, loopParam, loopParamBindings) : ev.handler
|
|
381
|
+
const handler = loopParam ? wrapLoopParamAsAccessor(ev.handler, loopParam, loopParamBindings, loopIndex) : ev.handler
|
|
361
382
|
emitListenerBlock(ls, indent, elVar, ev.childSlotId, '__e', ev.eventName, handler, 'dom', bodyIsMultiRoot)
|
|
362
383
|
}
|
|
363
384
|
|
|
@@ -412,14 +433,15 @@ export function emitComponentAndEventSetup(
|
|
|
412
433
|
loopParam?: string,
|
|
413
434
|
loopParamBindings?: readonly LoopParamBinding[],
|
|
414
435
|
bodyIsMultiRoot: boolean = false,
|
|
436
|
+
loopIndex?: string | null,
|
|
415
437
|
): void {
|
|
416
|
-
const wrap = loopParam ? (expr: string) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings) : (expr: string) => expr
|
|
438
|
+
const wrap = loopParam ? (expr: string) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings, loopIndex) : (expr: string) => expr
|
|
417
439
|
// Multi-root loop bodies (#1212) must search the item's sibling roots
|
|
418
440
|
// and the pre-insertion `__bfExtras` stash; `upsertChildItem` wraps the
|
|
419
441
|
// single-root `upsertChild` semantics in that walk.
|
|
420
442
|
const upsertFn = bodyIsMultiRoot ? 'upsertChildItem' : 'upsertChild'
|
|
421
443
|
for (const comp of comps) {
|
|
422
|
-
const propsExpr = buildComponentPropsExpr(comp, loopParam, loopParamBindings)
|
|
444
|
+
const propsExpr = buildComponentPropsExpr(comp, loopParam, loopParamBindings, loopIndex)
|
|
423
445
|
// Check if children are text-equivalent and reference the loop param — if so,
|
|
424
446
|
// emit a createEffect to reactively update textContent when the signal changes.
|
|
425
447
|
// Text-equivalent: expression, text, or conditional with text-only branches.
|
|
@@ -429,7 +451,8 @@ export function emitComponentAndEventSetup(
|
|
|
429
451
|
const rawChildrenExpr = isTextOnly ? irChildrenToJsExpr(comp.children!) : null
|
|
430
452
|
const childrenFreeIds = isTextOnly && comp.children ? irChildrenFreeIds(comp.children) : undefined
|
|
431
453
|
const childrenRefsLoop = loopParam != null && rawChildrenExpr != null && childrenFreeIds != null
|
|
432
|
-
&& exprRefsLoopBinding(childrenFreeIds, { param: loopParam, paramBindings: loopParamBindings })
|
|
454
|
+
&& (exprRefsLoopBinding(childrenFreeIds, { param: loopParam, paramBindings: loopParamBindings })
|
|
455
|
+
|| (!!loopIndex && childrenFreeIds.has(loopIndex)))
|
|
433
456
|
|
|
434
457
|
const slotIdLit = comp.slotId ? `'${comp.slotId}'` : 'null'
|
|
435
458
|
const keyProp = comp.props.find(p => p.name === 'key')
|
|
@@ -449,7 +472,7 @@ export function emitComponentAndEventSetup(
|
|
|
449
472
|
}
|
|
450
473
|
}
|
|
451
474
|
for (const ev of events) {
|
|
452
|
-
emitEventSetup(ls, indent, elVar, ev, loopParam, loopParamBindings, bodyIsMultiRoot)
|
|
475
|
+
emitEventSetup(ls, indent, elVar, ev, loopParam, loopParamBindings, bodyIsMultiRoot, loopIndex)
|
|
453
476
|
}
|
|
454
477
|
}
|
|
455
478
|
|
|
@@ -53,6 +53,7 @@ export function stringifyCompositeLoop(lines: string[], plan: CompositeLoopPlan)
|
|
|
53
53
|
innerLoops,
|
|
54
54
|
loopParam,
|
|
55
55
|
loopParamBindings,
|
|
56
|
+
loopIndex,
|
|
56
57
|
reactiveEffects,
|
|
57
58
|
childRefs,
|
|
58
59
|
branchClearChildren,
|
|
@@ -124,7 +125,7 @@ export function stringifyCompositeLoop(lines: string[], plan: CompositeLoopPlan)
|
|
|
124
125
|
// variant whose tail needs the row already connected.
|
|
125
126
|
mountRow: true,
|
|
126
127
|
})
|
|
127
|
-
emitComponentAndEventSetup(lines, bodyIndent, '__el', compsArr, eventsArr, loopParam, loopParamBindings, bodyIsMultiRoot)
|
|
128
|
+
emitComponentAndEventSetup(lines, bodyIndent, '__el', compsArr, eventsArr, loopParam, loopParamBindings, bodyIsMultiRoot, loopIndex)
|
|
128
129
|
if (innerLoops.length > 0) {
|
|
129
130
|
stringifyInnerLoops(lines, innerLoops, bodyIndent, pc)
|
|
130
131
|
}
|