@barefootjs/cli 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/docs/core/advanced/compiler-internals.md +8 -7
- package/dist/docs/core/advanced/performance.md +1 -1
- package/dist/docs/core/core-concepts/how-it-works.mdx +23 -7
- package/dist/docs/core/introduction.mdx +6 -4
- package/dist/docs/core/rendering/client-directive.md +24 -7
- package/dist/index.js +1001 -140
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3926,6 +3926,10 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3926
3926
|
return escapeHtml(node.value);
|
|
3927
3927
|
case "expression": {
|
|
3928
3928
|
if (node.expr === "null" || node.expr === "undefined") return "";
|
|
3929
|
+
if (node.markerless) {
|
|
3930
|
+
const bare = wrapInterpolation(wrapExpr(node.expr));
|
|
3931
|
+
return `\${${bare}}`;
|
|
3932
|
+
}
|
|
3929
3933
|
const inner = wrapInterpolation(wrapExpr(node.expr));
|
|
3930
3934
|
const valueExpr = node.joinArrayChild ? `Array.isArray(${inner}) ? ${inner}.join('') : (${inner} ?? '')` : inner;
|
|
3931
3935
|
if (node.slotId) {
|
|
@@ -4741,7 +4745,7 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4741
4745
|
case "expression":
|
|
4742
4746
|
if (node.expr === "null" || node.expr === "undefined") return "";
|
|
4743
4747
|
if (node.clientOnly && node.slotId) {
|
|
4744
|
-
return `<!--bf
|
|
4748
|
+
return `<!--bf:${node.slotId}--><!--/-->`;
|
|
4745
4749
|
}
|
|
4746
4750
|
{
|
|
4747
4751
|
const transformed = transformExpr(node.expr, node.templateExpr);
|
|
@@ -11157,7 +11161,8 @@ function transformConditionalBranch(node, ctx2) {
|
|
|
11157
11161
|
const callsReactive = exprCallsReactiveGetters(node, ctx2);
|
|
11158
11162
|
const hasCalls = exprHasFunctionCalls(node);
|
|
11159
11163
|
const reactive = isReactiveExpression(exprText, ctx2, node) || isReactiveOrigin(branchOrigin);
|
|
11160
|
-
const
|
|
11164
|
+
const refsLoopParam = branchOrigin.freeRefs?.some((r2) => r2.kind === "render-item") ?? false;
|
|
11165
|
+
const needsSlot = reactive || callsReactive || refsLoopParam;
|
|
11161
11166
|
const slotId = needsSlot ? generateSlotId(ctx2) : null;
|
|
11162
11167
|
return {
|
|
11163
11168
|
type: "expression",
|
|
@@ -14323,7 +14328,11 @@ function collectElements(node, ctx2, siblingOffsets, insideConditional = false)
|
|
|
14323
14328
|
},
|
|
14324
14329
|
expression: ({ node: ex, scope: inCond }) => {
|
|
14325
14330
|
if (ex.clientOnly && ex.slotId) {
|
|
14326
|
-
ctx2.clientOnlyElements.push({
|
|
14331
|
+
ctx2.clientOnlyElements.push({
|
|
14332
|
+
slotId: ex.slotId,
|
|
14333
|
+
expression: ex.expr,
|
|
14334
|
+
elidedPath: ex.markerless ? ex.elidedPath : void 0
|
|
14335
|
+
});
|
|
14327
14336
|
return;
|
|
14328
14337
|
}
|
|
14329
14338
|
if (!ex.slotId || inCond) return;
|
|
@@ -14753,19 +14762,54 @@ function summarizeLoopChildBranch(node, ctx2, siblingOffsets, loopParam, loopPar
|
|
|
14753
14762
|
// on the branch root yields exactly this branch's direct bindings
|
|
14754
14763
|
// without re-collecting what a nested arm already owns (#2347).
|
|
14755
14764
|
reactiveAttrs: collectLoopChildReactiveAttrs(node, ctx2, loopParam, loopParamBindings, true),
|
|
14756
|
-
// Skip when the branch's
|
|
14757
|
-
// (no wrapping element)
|
|
14758
|
-
//
|
|
14759
|
-
//
|
|
14760
|
-
//
|
|
14761
|
-
//
|
|
14762
|
-
//
|
|
14763
|
-
// and the
|
|
14764
|
-
//
|
|
14765
|
-
//
|
|
14766
|
-
//
|
|
14767
|
-
//
|
|
14768
|
-
|
|
14765
|
+
// Skip ONLY when the branch's entire content is a single bare
|
|
14766
|
+
// `expression` (no wrapping element) that MAY yield a live DOM node —
|
|
14767
|
+
// i.e. it contains a call anywhere (`node.hasFunctionCalls`, computed
|
|
14768
|
+
// by the AST walk in `exprHasFunctionCalls`/jsx-to-ir.ts, recursively —
|
|
14769
|
+
// catches a call nested in a template literal or a nested ternary, not
|
|
14770
|
+
// just a top-level call). A call can return an Element (a hoisted
|
|
14771
|
+
// `renderNode={(n) => <Pill/>}` callback lowered to a component call,
|
|
14772
|
+
// #1211/#1213) and the compiler cannot tell from syntax whether it does
|
|
14773
|
+
// — both `renderChild(...)` and `_p.renderCell(...)` are a
|
|
14774
|
+
// `CallExpression` — so this stays conservative for ANY call, not just
|
|
14775
|
+
// ones known to return JSX. Re-evaluating a non-idempotent call inside
|
|
14776
|
+
// an *additional* nested createEffect (on top of the eval already done
|
|
14777
|
+
// for the `__bfSlot`-wrapped splice whenever `insert()` (re-)mounts this
|
|
14778
|
+
// branch) would call it again on every unrelated tick and discard the
|
|
14779
|
+
// previous element's listeners/state.
|
|
14780
|
+
//
|
|
14781
|
+
// Everything else — a property access (`row.label`), an identifier, a
|
|
14782
|
+
// literal, a template literal, string concatenation, or a nested
|
|
14783
|
+
// ternary of those — cannot itself construct a DOM node (only a JSX
|
|
14784
|
+
// literal or a call can, and a JSX literal branch is never `type:
|
|
14785
|
+
// 'expression'` in the first place — see `transformJsxExpression`), so
|
|
14786
|
+
// it is safe to collect. This is the fix for the loop-branch-stale-text
|
|
14787
|
+
// defect: a keyed loop row whose branch is e.g. `row.done ? row.label :
|
|
14788
|
+
// 'pending'` previously had NO update path at all when `row.label`
|
|
14789
|
+
// changed without `row.done` flipping — `insert()` (runtime/insert.ts)
|
|
14790
|
+
// correctly no-ops when its condition is unchanged (branch-internal
|
|
14791
|
+
// updates are deliberately the effect system's job, not DOM
|
|
14792
|
+
// replacement's), but with reactiveTexts always `[]` for this shape,
|
|
14793
|
+
// no effect existed either, so the branch was frozen at its mount-time
|
|
14794
|
+
// value. The stale rationale in a prior version of this comment blamed
|
|
14795
|
+
// "the loop-child arm's `$t()`-based anchor lookup", but `$t()` no
|
|
14796
|
+
// longer exists — it was one of four content mechanisms deleted by the
|
|
14797
|
+
// slot-unification work. The current claim door
|
|
14798
|
+
// (`stringifyLoopChildArm` → `lazySlots(..., kind: 'markup')` →
|
|
14799
|
+
// `writeMarkup`, runtime/claim-slots.ts) clears the claimed range and
|
|
14800
|
+
// splices the Node by identity, so "lands beside the first" cannot
|
|
14801
|
+
// happen through it; only the call's non-idempotence still applies, and
|
|
14802
|
+
// that alone is why the skip narrows rather than disappears.
|
|
14803
|
+
//
|
|
14804
|
+
// Collecting here is necessary but not sufficient: `n.slotId` must also
|
|
14805
|
+
// be set for `collectLoopChildReactiveTexts` (ir-to-client-js/
|
|
14806
|
+
// reactivity.ts) to do anything — see `transformConditionalBranch`'s
|
|
14807
|
+
// `refsLoopParam` check (jsx-to-ir.ts) for the matching half of this fix
|
|
14808
|
+
// that gives a bare loop-item-reading branch a slotId at all, which also
|
|
14809
|
+
// makes `irToHtmlTemplate` emit its `<!--bf:sN-->…<!--/-->` marker (the
|
|
14810
|
+
// same call builds both the SSR and the CSR/hydration template, so the
|
|
14811
|
+
// two can't disagree on shape).
|
|
14812
|
+
reactiveTexts: node.type === "expression" && node.hasFunctionCalls ? [] : collectLoopChildReactiveTexts(node, ctx2, loopParam, loopParamBindings, true)
|
|
14769
14813
|
};
|
|
14770
14814
|
}
|
|
14771
14815
|
var EMPTY_RENDER_EXPRS, branchInnerLoopOptions;
|
|
@@ -15327,13 +15371,12 @@ var init_imports = __esm({
|
|
|
15327
15371
|
"onMount",
|
|
15328
15372
|
"hydrate",
|
|
15329
15373
|
"insert",
|
|
15330
|
-
"reconcileElements",
|
|
15331
15374
|
"getLoopChildren",
|
|
15332
15375
|
"getLoopNodes",
|
|
15333
15376
|
"mapArray",
|
|
15334
15377
|
"mapArrayAnchored",
|
|
15378
|
+
"mapArrayLazy",
|
|
15335
15379
|
"patchLeaf",
|
|
15336
|
-
"patchSlotRange",
|
|
15337
15380
|
"createDisposableEffect",
|
|
15338
15381
|
"createComponent",
|
|
15339
15382
|
"renderChild",
|
|
@@ -15341,7 +15384,6 @@ var init_imports = __esm({
|
|
|
15341
15384
|
"registerTemplate",
|
|
15342
15385
|
"initChild",
|
|
15343
15386
|
"upsertChild",
|
|
15344
|
-
"updateClientMarker",
|
|
15345
15387
|
"createPortal",
|
|
15346
15388
|
"provideContext",
|
|
15347
15389
|
"createContext",
|
|
@@ -15353,6 +15395,7 @@ var init_imports = __esm({
|
|
|
15353
15395
|
"styleToCss",
|
|
15354
15396
|
"escapeAttr",
|
|
15355
15397
|
"escapeText",
|
|
15398
|
+
"escapeTextOrNode",
|
|
15356
15399
|
"qsa",
|
|
15357
15400
|
"qsaItem",
|
|
15358
15401
|
"qsaChildScope",
|
|
@@ -15361,7 +15404,19 @@ var init_imports = __esm({
|
|
|
15361
15404
|
"__slot",
|
|
15362
15405
|
"__bfSlot",
|
|
15363
15406
|
"__bfText",
|
|
15364
|
-
|
|
15407
|
+
// Claim-plan interpreter (slot unification A2/A3, spec/slot-unification.md)
|
|
15408
|
+
// — the "one claim mechanism" that replaced `patchSlotRange` and
|
|
15409
|
+
// `updateClientMarker` (both deleted) as the content-slot update door.
|
|
15410
|
+
// `lazyClaimSlots` is the read-capable twin of `lazySlots` over the same
|
|
15411
|
+
// claim — emitted only by lazy loops that seed an outer-involving TEXT
|
|
15412
|
+
// binding by read-compare-write (§9.3(1)).
|
|
15413
|
+
// `textOrNode` is the 'text' door's Node guard: a child-position value that
|
|
15414
|
+
// turns out to be a live Node must reach the writer as a Node so the claim
|
|
15415
|
+
// can promote to 'markup', never as `String(node)`.
|
|
15416
|
+
"claimSlots",
|
|
15417
|
+
"lazySlots",
|
|
15418
|
+
"lazyClaimSlots",
|
|
15419
|
+
"textOrNode",
|
|
15365
15420
|
// Profile mode (#1690, SR3) — turn-boundary markers around event handlers.
|
|
15366
15421
|
"beginTurn",
|
|
15367
15422
|
"endTurn",
|
|
@@ -18484,8 +18539,340 @@ var init_build_event_delegation = __esm({
|
|
|
18484
18539
|
}
|
|
18485
18540
|
});
|
|
18486
18541
|
|
|
18542
|
+
// ../jsx/src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts
|
|
18543
|
+
function lazyRowEligibility(args2) {
|
|
18544
|
+
const { shape, bindings, arraySourceIdentifiers, scope } = args2;
|
|
18545
|
+
if (scope.profile) return NO("profile mode keeps the granular eager emission");
|
|
18546
|
+
if (shape.callSite !== "plain" && shape.callSite !== "branch-plain") {
|
|
18547
|
+
return NO(`call site '${shape.callSite}' is not a plain loop row`);
|
|
18548
|
+
}
|
|
18549
|
+
if (shape.flatMapLeafItem) return NO("flatMap descriptor loop (build-or-patch renderItem)");
|
|
18550
|
+
if (shape.anchored) return NO("anchored whole-item-conditional loop");
|
|
18551
|
+
if (shape.bodyIsMultiRoot) return NO("multi-root (Fragment) row");
|
|
18552
|
+
if (!shape.hasExplicitKey) return NO("index-keyed loop (no explicit key)");
|
|
18553
|
+
if (shape.conditionalCount > 0) return NO("row contains a reactive conditional");
|
|
18554
|
+
if (shape.childRefCount > 0) return NO("row has imperative child refs");
|
|
18555
|
+
if (shape.hasChildComponent) return NO("row body is a child component");
|
|
18556
|
+
if (shape.nestedComponentCount > 0) return NO("row contains nested child components");
|
|
18557
|
+
if (shape.innerLoopCount > 0) return NO("row contains an inner loop");
|
|
18558
|
+
if (shape.hasMapPreamble) return NO("row has a map-callback preamble (may declare row-local reactivity)");
|
|
18559
|
+
if (shape.preambleRegionCount > 0) return NO("row has preamble-patched regions");
|
|
18560
|
+
if (shape.hasParamUnwrap) return NO("destructured loop param without param bindings");
|
|
18561
|
+
for (const b of bindings) {
|
|
18562
|
+
if (b.referencesIndex) {
|
|
18563
|
+
return NO(`binding on slot ${b.slotId} references the loop index parameter`);
|
|
18564
|
+
}
|
|
18565
|
+
if (b.opaqueOuterNames.includes(UNKNOWN_IDENTIFIERS)) {
|
|
18566
|
+
return NO(`binding on slot ${b.slotId} has no analyzable identifier set`);
|
|
18567
|
+
}
|
|
18568
|
+
}
|
|
18569
|
+
if (!arraySourceIdentifiers) return NO("loop source free identifiers unavailable");
|
|
18570
|
+
const sourceGate = checkSourceConsistency(arraySourceIdentifiers, scope);
|
|
18571
|
+
if (sourceGate) return NO(`loop source is not provably hydration-consistent: ${sourceGate}`);
|
|
18572
|
+
return { eligible: true };
|
|
18573
|
+
}
|
|
18574
|
+
function checkSourceConsistency(names, scope) {
|
|
18575
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18576
|
+
const resolve12 = (name2) => {
|
|
18577
|
+
if (seen.has(name2)) return null;
|
|
18578
|
+
seen.add(name2);
|
|
18579
|
+
if (scope.props.has(name2)) return null;
|
|
18580
|
+
if (PURE_SOURCE_GLOBALS.has(name2)) return null;
|
|
18581
|
+
const constFree = scope.constants.get(name2);
|
|
18582
|
+
if (constFree !== void 0) {
|
|
18583
|
+
if (constFree === null) return `constant '${name2}' has no analyzable value`;
|
|
18584
|
+
for (const inner of constFree) {
|
|
18585
|
+
const failure = resolve12(inner);
|
|
18586
|
+
if (failure) return failure;
|
|
18587
|
+
}
|
|
18588
|
+
return null;
|
|
18589
|
+
}
|
|
18590
|
+
const signal2 = scope.signals.get(name2);
|
|
18591
|
+
if (signal2 !== void 0) {
|
|
18592
|
+
if (signal2.initializerFreeIdentifiers === null) {
|
|
18593
|
+
return `signal '${name2}' has no structured initializer to prove props/literal derivation`;
|
|
18594
|
+
}
|
|
18595
|
+
for (const inner of signal2.initializerFreeIdentifiers) {
|
|
18596
|
+
const failure = resolve12(inner);
|
|
18597
|
+
if (failure) return failure;
|
|
18598
|
+
}
|
|
18599
|
+
return null;
|
|
18600
|
+
}
|
|
18601
|
+
if (scope.memos.has(name2)) return `memo '${name2}' initializer is not analyzed by the v1 gate`;
|
|
18602
|
+
if (scope.inert.has(name2)) return `'${name2}' is an import or local function`;
|
|
18603
|
+
return `'${name2}' does not resolve to a prop, literal-derived const, or props/literal-derived signal`;
|
|
18604
|
+
};
|
|
18605
|
+
for (const name2 of names) {
|
|
18606
|
+
const failure = resolve12(name2);
|
|
18607
|
+
if (failure) return failure;
|
|
18608
|
+
}
|
|
18609
|
+
return null;
|
|
18610
|
+
}
|
|
18611
|
+
function classifyLazyBinding(args2) {
|
|
18612
|
+
const { kind: kind2, slotId, free, rowLocalNames, indexParam, scope } = args2;
|
|
18613
|
+
if (free === null) {
|
|
18614
|
+
return {
|
|
18615
|
+
kind: kind2,
|
|
18616
|
+
slotId,
|
|
18617
|
+
readsItem: true,
|
|
18618
|
+
readsOuter: true,
|
|
18619
|
+
reactiveOuterNames: [],
|
|
18620
|
+
opaqueOuterNames: [UNKNOWN_IDENTIFIERS],
|
|
18621
|
+
// An ASSUMPTION, not knowledge — which is precisely why
|
|
18622
|
+
// `UNKNOWN_IDENTIFIERS` must keep refusing the loop: with no
|
|
18623
|
+
// identifier set we cannot rule out an index read either, and
|
|
18624
|
+
// `applyItem` / `applyOuter` have no index parameter to give it.
|
|
18625
|
+
referencesIndex: false
|
|
18626
|
+
};
|
|
18627
|
+
}
|
|
18628
|
+
let readsItem = false;
|
|
18629
|
+
let referencesIndex = false;
|
|
18630
|
+
const reactiveOuterNames = [];
|
|
18631
|
+
const opaqueOuterNames = [];
|
|
18632
|
+
for (const name2 of free) {
|
|
18633
|
+
if (rowLocalNames.has(name2)) {
|
|
18634
|
+
readsItem = true;
|
|
18635
|
+
continue;
|
|
18636
|
+
}
|
|
18637
|
+
if (name2 === indexParam) {
|
|
18638
|
+
referencesIndex = true;
|
|
18639
|
+
continue;
|
|
18640
|
+
}
|
|
18641
|
+
if (INERT_BINDING_GLOBALS.has(name2)) continue;
|
|
18642
|
+
if (scope.signals.has(name2) || scope.memos.has(name2)) {
|
|
18643
|
+
if (!reactiveOuterNames.includes(name2)) reactiveOuterNames.push(name2);
|
|
18644
|
+
continue;
|
|
18645
|
+
}
|
|
18646
|
+
const constFree = scope.constants.get(name2);
|
|
18647
|
+
if (constFree !== void 0 && constFree !== null && constFree.size === 0) continue;
|
|
18648
|
+
opaqueOuterNames.push(name2);
|
|
18649
|
+
}
|
|
18650
|
+
return {
|
|
18651
|
+
kind: kind2,
|
|
18652
|
+
slotId,
|
|
18653
|
+
readsItem,
|
|
18654
|
+
readsOuter: reactiveOuterNames.length > 0 || opaqueOuterNames.length > 0,
|
|
18655
|
+
reactiveOuterNames,
|
|
18656
|
+
opaqueOuterNames,
|
|
18657
|
+
referencesIndex
|
|
18658
|
+
};
|
|
18659
|
+
}
|
|
18660
|
+
var PURE_SOURCE_GLOBALS, INERT_BINDING_GLOBALS, UNKNOWN_IDENTIFIERS, NO;
|
|
18661
|
+
var init_lazy_row_eligibility = __esm({
|
|
18662
|
+
"../jsx/src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts"() {
|
|
18663
|
+
"use strict";
|
|
18664
|
+
PURE_SOURCE_GLOBALS = /* @__PURE__ */ new Set([
|
|
18665
|
+
"Object",
|
|
18666
|
+
"Array",
|
|
18667
|
+
"JSON",
|
|
18668
|
+
"Number",
|
|
18669
|
+
"String",
|
|
18670
|
+
"Boolean"
|
|
18671
|
+
]);
|
|
18672
|
+
INERT_BINDING_GLOBALS = /* @__PURE__ */ new Set([
|
|
18673
|
+
"Object",
|
|
18674
|
+
"Array",
|
|
18675
|
+
"JSON",
|
|
18676
|
+
"Number",
|
|
18677
|
+
"String",
|
|
18678
|
+
"Boolean",
|
|
18679
|
+
"Math",
|
|
18680
|
+
"Date",
|
|
18681
|
+
"Intl",
|
|
18682
|
+
"Symbol",
|
|
18683
|
+
"Map",
|
|
18684
|
+
"Set",
|
|
18685
|
+
"WeakMap",
|
|
18686
|
+
"WeakSet",
|
|
18687
|
+
"Promise",
|
|
18688
|
+
"RegExp",
|
|
18689
|
+
"Error",
|
|
18690
|
+
"BigInt",
|
|
18691
|
+
"console",
|
|
18692
|
+
"undefined",
|
|
18693
|
+
"NaN",
|
|
18694
|
+
"Infinity",
|
|
18695
|
+
"globalThis",
|
|
18696
|
+
"parseInt",
|
|
18697
|
+
"parseFloat",
|
|
18698
|
+
"isNaN",
|
|
18699
|
+
"isFinite",
|
|
18700
|
+
"encodeURIComponent",
|
|
18701
|
+
"decodeURIComponent",
|
|
18702
|
+
"encodeURI",
|
|
18703
|
+
"decodeURI"
|
|
18704
|
+
]);
|
|
18705
|
+
UNKNOWN_IDENTIFIERS = "<unknown>";
|
|
18706
|
+
NO = (reason2) => ({ eligible: false, reason: reason2 });
|
|
18707
|
+
}
|
|
18708
|
+
});
|
|
18709
|
+
|
|
18710
|
+
// ../jsx/src/ir-to-client-js/control-flow/plan/build-lazy-row.ts
|
|
18711
|
+
function buildLazyRowPlan(args2) {
|
|
18712
|
+
return decideLazyRow(args2).plan;
|
|
18713
|
+
}
|
|
18714
|
+
function decideLazyRow(args2) {
|
|
18715
|
+
const { loop, scope } = args2;
|
|
18716
|
+
if (!scope) {
|
|
18717
|
+
return { plan: null, decision: { eligible: false, reason: "no component scope info supplied" } };
|
|
18718
|
+
}
|
|
18719
|
+
const wrap = (expr) => wrapLoopParamAsAccessor(expr, loop.param, loop.paramBindings);
|
|
18720
|
+
const rowLocalNames = /* @__PURE__ */ new Set([loop.param]);
|
|
18721
|
+
for (const b of loop.paramBindings ?? []) rowLocalNames.add(b.name);
|
|
18722
|
+
const classified = [];
|
|
18723
|
+
const attrClass = /* @__PURE__ */ new Map();
|
|
18724
|
+
loop.bindings.reactiveAttrs.forEach((attr, i) => {
|
|
18725
|
+
const c = classifyLazyBinding({
|
|
18726
|
+
kind: "attr",
|
|
18727
|
+
slotId: attr.childSlotId,
|
|
18728
|
+
free: attrFreeIdentifiers2(attr.expression),
|
|
18729
|
+
rowLocalNames,
|
|
18730
|
+
indexParam: args2.indexParam,
|
|
18731
|
+
scope
|
|
18732
|
+
});
|
|
18733
|
+
attrClass.set(i, c);
|
|
18734
|
+
classified.push(c);
|
|
18735
|
+
});
|
|
18736
|
+
const textClass = /* @__PURE__ */ new Map();
|
|
18737
|
+
loop.bindings.reactiveTexts.forEach((text, i) => {
|
|
18738
|
+
const c = classifyLazyBinding({
|
|
18739
|
+
kind: "text",
|
|
18740
|
+
slotId: text.slotId,
|
|
18741
|
+
free: text.freeIdentifiers ?? null,
|
|
18742
|
+
rowLocalNames,
|
|
18743
|
+
indexParam: args2.indexParam,
|
|
18744
|
+
scope
|
|
18745
|
+
});
|
|
18746
|
+
textClass.set(i, c);
|
|
18747
|
+
classified.push(c);
|
|
18748
|
+
});
|
|
18749
|
+
const shape = {
|
|
18750
|
+
callSite: args2.callSite,
|
|
18751
|
+
flatMapLeafItem: args2.flatMapLeafItem,
|
|
18752
|
+
anchored: args2.anchored,
|
|
18753
|
+
bodyIsMultiRoot: loop.bodyIsMultiRoot ?? false,
|
|
18754
|
+
hasExplicitKey: loop.key != null,
|
|
18755
|
+
conditionalCount: loop.bindings.conditionals?.length ?? 0,
|
|
18756
|
+
childRefCount: loop.bindings.refs?.length ?? 0,
|
|
18757
|
+
nestedComponentCount: loop.nestedComponents?.length ?? 0,
|
|
18758
|
+
innerLoopCount: loop.innerLoops?.length ?? 0,
|
|
18759
|
+
hasChildComponent: "childComponent" in loop && loop.childComponent != null,
|
|
18760
|
+
hasMapPreamble: args2.mapPreambleWrapped.length > 0,
|
|
18761
|
+
preambleRegionCount: args2.preambleRegionCount,
|
|
18762
|
+
hasParamUnwrap: args2.paramUnwrap.length > 0
|
|
18763
|
+
};
|
|
18764
|
+
const decision = lazyRowEligibility({
|
|
18765
|
+
shape,
|
|
18766
|
+
bindings: classified,
|
|
18767
|
+
arraySourceIdentifiers: loopSourceIdentifiers(loop, args2.arrayExpr),
|
|
18768
|
+
scope
|
|
18769
|
+
});
|
|
18770
|
+
if (!decision.eligible) return { plan: null, decision };
|
|
18771
|
+
const attrSlotIds = [];
|
|
18772
|
+
for (const attr of loop.bindings.reactiveAttrs) {
|
|
18773
|
+
if (!attrSlotIds.includes(attr.childSlotId)) attrSlotIds.push(attr.childSlotId);
|
|
18774
|
+
}
|
|
18775
|
+
let ordinal = 0;
|
|
18776
|
+
const attrs = loop.bindings.reactiveAttrs.map((attr, i) => {
|
|
18777
|
+
const c = attrClass.get(i);
|
|
18778
|
+
return {
|
|
18779
|
+
slotId: attr.childSlotId,
|
|
18780
|
+
attrName: attr.attrName,
|
|
18781
|
+
wrappedExpression: wrap(attr.expression),
|
|
18782
|
+
meta: pickAttrMeta(attr),
|
|
18783
|
+
refIndex: attrSlotIds.indexOf(attr.childSlotId),
|
|
18784
|
+
ordinal: ordinal++,
|
|
18785
|
+
readsItem: c.readsItem,
|
|
18786
|
+
readsOuter: c.readsOuter
|
|
18787
|
+
};
|
|
18788
|
+
});
|
|
18789
|
+
const texts = loop.bindings.reactiveTexts.map((text, i) => {
|
|
18790
|
+
const c = textClass.get(i);
|
|
18791
|
+
return {
|
|
18792
|
+
slotId: text.slotId,
|
|
18793
|
+
wrappedExpression: wrap(text.expression),
|
|
18794
|
+
ordinal: ordinal++,
|
|
18795
|
+
// A text that classified as NEITHER item- nor outer-driven still gets
|
|
18796
|
+
// applied on item change (harmless, dedup-guarded) rather than
|
|
18797
|
+
// silently never being written. Anything the classifier did place in
|
|
18798
|
+
// a list keeps exactly the classifier's answer.
|
|
18799
|
+
readsItem: c.readsItem || !c.readsOuter,
|
|
18800
|
+
readsOuter: c.readsOuter
|
|
18801
|
+
};
|
|
18802
|
+
});
|
|
18803
|
+
const outerPrimeGetters = [];
|
|
18804
|
+
for (const c of classified) {
|
|
18805
|
+
for (const name2 of c.reactiveOuterNames) {
|
|
18806
|
+
if (!outerPrimeGetters.includes(name2)) outerPrimeGetters.push(name2);
|
|
18807
|
+
}
|
|
18808
|
+
}
|
|
18809
|
+
return {
|
|
18810
|
+
plan: {
|
|
18811
|
+
attrSlotIds,
|
|
18812
|
+
attrs,
|
|
18813
|
+
texts,
|
|
18814
|
+
writerIndex: texts.length > 0 ? attrSlotIds.length : -1,
|
|
18815
|
+
textNeedsRead: texts.some((t) => t.readsOuter),
|
|
18816
|
+
lastCount: ordinal,
|
|
18817
|
+
outerPrimeGetters,
|
|
18818
|
+
hasOuter: attrs.some((a) => a.readsOuter) || texts.some((t) => t.readsOuter)
|
|
18819
|
+
},
|
|
18820
|
+
decision
|
|
18821
|
+
};
|
|
18822
|
+
}
|
|
18823
|
+
function buildLazyRowScopeInfo(ctx2) {
|
|
18824
|
+
const signals = /* @__PURE__ */ new Map();
|
|
18825
|
+
for (const s of ctx2.signals) {
|
|
18826
|
+
signals.set(s.getter, {
|
|
18827
|
+
// `parsed` is the analyzer's structured initializer. Absent (or
|
|
18828
|
+
// refused by `freeIdentifiers`) ⇒ unprovable, which the source gate
|
|
18829
|
+
// treats as a hard stop rather than an assumption.
|
|
18830
|
+
initializerFreeIdentifiers: s.parsed ? freeIdentifiers(s.parsed) : null
|
|
18831
|
+
});
|
|
18832
|
+
}
|
|
18833
|
+
const memos = new Set(ctx2.memos.map((m) => m.name));
|
|
18834
|
+
const props = /* @__PURE__ */ new Set([PROPS_PARAM]);
|
|
18835
|
+
if (ctx2.propsObjectName) props.add(ctx2.propsObjectName);
|
|
18836
|
+
for (const p of ctx2.propsParams) props.add(p.name);
|
|
18837
|
+
const constants = /* @__PURE__ */ new Map();
|
|
18838
|
+
for (const c of ctx2.localConstants) {
|
|
18839
|
+
constants.set(c.name, c.freeIdentifiers ?? null);
|
|
18840
|
+
}
|
|
18841
|
+
const inert = /* @__PURE__ */ new Set();
|
|
18842
|
+
for (const f of ctx2.localFunctions) inert.add(f.name);
|
|
18843
|
+
for (const imp of ctx2.imports) {
|
|
18844
|
+
if (imp.isTypeOnly) continue;
|
|
18845
|
+
for (const spec of imp.specifiers) inert.add(spec.alias || spec.name);
|
|
18846
|
+
}
|
|
18847
|
+
return { signals, memos, props, constants, inert, profile: ctx2.profile };
|
|
18848
|
+
}
|
|
18849
|
+
function attrFreeIdentifiers2(expression) {
|
|
18850
|
+
if (!expression || expression.trim().length === 0) return /* @__PURE__ */ new Set();
|
|
18851
|
+
try {
|
|
18852
|
+
return freeIdentifiers(parseExpression(expression));
|
|
18853
|
+
} catch {
|
|
18854
|
+
return null;
|
|
18855
|
+
}
|
|
18856
|
+
}
|
|
18857
|
+
function loopSourceIdentifiers(loop, arrayExpr) {
|
|
18858
|
+
if (!loop.arrayFreeIdentifiers) return null;
|
|
18859
|
+
const names = new Set(loop.arrayFreeIdentifiers);
|
|
18860
|
+
for (const name2 of extractFreeIdentifiersFromText(arrayExpr)) names.add(name2);
|
|
18861
|
+
return names;
|
|
18862
|
+
}
|
|
18863
|
+
var init_build_lazy_row = __esm({
|
|
18864
|
+
"../jsx/src/ir-to-client-js/control-flow/plan/build-lazy-row.ts"() {
|
|
18865
|
+
"use strict";
|
|
18866
|
+
init_expression_parser();
|
|
18867
|
+
init_types();
|
|
18868
|
+
init_csr_substitute();
|
|
18869
|
+
init_utils();
|
|
18870
|
+
init_lazy_row_eligibility();
|
|
18871
|
+
}
|
|
18872
|
+
});
|
|
18873
|
+
|
|
18487
18874
|
// ../jsx/src/ir-to-client-js/control-flow/plan/build-branch-loop.ts
|
|
18488
|
-
function buildBranchLoopPlan(loop, profileComponentName) {
|
|
18875
|
+
function buildBranchLoopPlan(loop, profileComponentName, lazyScope) {
|
|
18489
18876
|
const containerSlotId = loop.containerSlotId;
|
|
18490
18877
|
const cv = varSlotId(containerSlotId);
|
|
18491
18878
|
const containerVar = `__loop_${cv}`;
|
|
@@ -18501,6 +18888,13 @@ function buildBranchLoopPlan(loop, profileComponentName) {
|
|
|
18501
18888
|
const { head: paramHead, unwrap: paramUnwrap } = destructureLoopParam(loop.param, loop.paramBindings);
|
|
18502
18889
|
const hasReactiveEffects = loop.bindings.reactiveAttrs.length > 0 || loop.bindings.reactiveTexts.length > 0 || loop.bindings.conditionals.length > 0;
|
|
18503
18890
|
const fm = loop.flatMapClient;
|
|
18891
|
+
const arrayExpr = fm ? `(${buildChainedArrayExpr(loop)}).flatMap(${fm.params} => ${fm.body})` : buildChainedArrayExpr(loop);
|
|
18892
|
+
const indexParam = loop.index || "__idx";
|
|
18893
|
+
const mapPreambleWrapped = loop.preamble ? renderPreamble(loop.preamble, {
|
|
18894
|
+
transformJs: (t) => wrapLoopParamAsAccessor(t, loop.param, loop.paramBindings),
|
|
18895
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1, [{ param: loop.param, bindings: loop.paramBindings }], void 0, true)
|
|
18896
|
+
}) : "";
|
|
18897
|
+
const preambleRegions = buildPreambleRegionPlans(loop.preambleRegions, loop.param, loop.paramBindings);
|
|
18504
18898
|
const plan = {
|
|
18505
18899
|
kind: "plain",
|
|
18506
18900
|
rowConstruction: "string-template",
|
|
@@ -18508,17 +18902,27 @@ function buildBranchLoopPlan(loop, profileComponentName) {
|
|
|
18508
18902
|
containerVar,
|
|
18509
18903
|
markerId: loop.markerId,
|
|
18510
18904
|
flatMapLeafItem: fm ? true : void 0,
|
|
18511
|
-
arrayExpr
|
|
18905
|
+
arrayExpr,
|
|
18512
18906
|
keyFn: fm ? fm.keyed ? "(__bfD, __bfI) => String(__bfD.k ?? __bfI)" : "null" : loopKeyFn(loop),
|
|
18513
18907
|
paramHead,
|
|
18514
18908
|
paramUnwrap,
|
|
18515
|
-
indexParam
|
|
18909
|
+
indexParam,
|
|
18516
18910
|
// Wrap loop-param references to signal-accessor form so the preamble
|
|
18517
18911
|
// matches the template literal's already-wrapped reads (#1065).
|
|
18518
|
-
mapPreambleWrapped
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18912
|
+
mapPreambleWrapped,
|
|
18913
|
+
// Lazy row graph (§9, L3) — undefined for every ineligible loop.
|
|
18914
|
+
lazyRow: buildLazyRowPlan({
|
|
18915
|
+
loop,
|
|
18916
|
+
arrayExpr,
|
|
18917
|
+
indexParam,
|
|
18918
|
+
paramUnwrap,
|
|
18919
|
+
mapPreambleWrapped,
|
|
18920
|
+
preambleRegionCount: preambleRegions.length,
|
|
18921
|
+
callSite: "branch-plain",
|
|
18922
|
+
flatMapLeafItem: Boolean(fm),
|
|
18923
|
+
anchored: false,
|
|
18924
|
+
scope: lazyScope
|
|
18925
|
+
}) ?? void 0,
|
|
18522
18926
|
template: loop.template,
|
|
18523
18927
|
reactiveEffects: hasReactiveEffects ? buildReactiveEffectsPlan({
|
|
18524
18928
|
attrs: loop.bindings.reactiveAttrs,
|
|
@@ -18530,7 +18934,7 @@ function buildBranchLoopPlan(loop, profileComponentName) {
|
|
|
18530
18934
|
}) : null,
|
|
18531
18935
|
eventDelegation: buildBranchLoopDelegationPlan(loop, cv, profileComponentName),
|
|
18532
18936
|
childRefs: buildChildRefBindings(loop.bindings.refs, loop.param, loop.paramBindings),
|
|
18533
|
-
preambleRegions
|
|
18937
|
+
preambleRegions,
|
|
18534
18938
|
bodyIsMultiRoot: loop.bodyIsMultiRoot ?? false,
|
|
18535
18939
|
profileLoopId: profileComponentName ? `${profileComponentName}#binding:${containerSlotId}` : void 0
|
|
18536
18940
|
};
|
|
@@ -18543,6 +18947,7 @@ var init_build_branch_loop = __esm({
|
|
|
18543
18947
|
init_build_composite_loop();
|
|
18544
18948
|
init_build_event_delegation();
|
|
18545
18949
|
init_build_reactive_effects();
|
|
18950
|
+
init_build_lazy_row();
|
|
18546
18951
|
init_shared();
|
|
18547
18952
|
init_html_template();
|
|
18548
18953
|
}
|
|
@@ -18599,13 +19004,13 @@ function buildArmBody(branch, options2) {
|
|
|
18599
19004
|
expression: t.expression
|
|
18600
19005
|
})),
|
|
18601
19006
|
// Branch-scoped loops, fully Plan-built (Item 2 final migration).
|
|
18602
|
-
loops: branch.loops.map((l) => buildBranchLoopPlan(l, pc)),
|
|
19007
|
+
loops: branch.loops.map((l) => buildBranchLoopPlan(l, pc, options2.lazyScope)),
|
|
18603
19008
|
// Nested conditionals are themselves InsertPlans — built recursively so
|
|
18604
19009
|
// the same stringifier handles arbitrary depth. Their scope is always
|
|
18605
19010
|
// `__branchScope` (the parent arm's bindEvents argument), regardless of
|
|
18606
19011
|
// the outer scope; only the eventNameMode is inherited.
|
|
18607
19012
|
conditionals: branch.conditionals.map(
|
|
18608
|
-
(c) => buildInsertPlan(c, { scope: { kind: "branchScope" }, eventNameMode: options2.eventNameMode, profileComponentName: pc })
|
|
19013
|
+
(c) => buildInsertPlan(c, { scope: { kind: "branchScope" }, eventNameMode: options2.eventNameMode, profileComponentName: pc, lazyScope: options2.lazyScope })
|
|
18609
19014
|
)
|
|
18610
19015
|
};
|
|
18611
19016
|
}
|
|
@@ -18617,6 +19022,25 @@ var init_build_insert = __esm({
|
|
|
18617
19022
|
}
|
|
18618
19023
|
});
|
|
18619
19024
|
|
|
19025
|
+
// ../jsx/src/ir-to-client-js/control-flow/stringify/claim-plan.ts
|
|
19026
|
+
function slotSpecLiteral(slot) {
|
|
19027
|
+
const pathSrc = slot.pathExpr ?? `[${slot.path.join(", ")}]`;
|
|
19028
|
+
const markerlessSrc = slot.markerless ? ", markerless: true" : "";
|
|
19029
|
+
return `{ id: '${slot.id}', kind: '${slot.kind}', path: ${pathSrc}${markerlessSrc} }`;
|
|
19030
|
+
}
|
|
19031
|
+
function claimPlanLiteral(slots) {
|
|
19032
|
+
return `[${slots.map(slotSpecLiteral).join(", ")}]`;
|
|
19033
|
+
}
|
|
19034
|
+
function claimWriterVarName(slots, sanitize) {
|
|
19035
|
+
const first = slots[0]?.id ?? "0";
|
|
19036
|
+
return `__bfw_${sanitize(first)}`;
|
|
19037
|
+
}
|
|
19038
|
+
var init_claim_plan = __esm({
|
|
19039
|
+
"../jsx/src/ir-to-client-js/control-flow/stringify/claim-plan.ts"() {
|
|
19040
|
+
"use strict";
|
|
19041
|
+
}
|
|
19042
|
+
});
|
|
19043
|
+
|
|
18620
19044
|
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
18621
19045
|
import ts14 from "typescript";
|
|
18622
19046
|
function bindingIdArg(ctx2, slotId) {
|
|
@@ -18795,17 +19219,18 @@ function emitDynamicTextUpdates(lines, ctx2) {
|
|
|
18795
19219
|
const conditionalElems = elems.filter((e) => e.insideConditional);
|
|
18796
19220
|
const normalElems = elems.filter((e) => !e.insideConditional);
|
|
18797
19221
|
if (normalElems.length > 0 || conditionalElems.length > 0) {
|
|
18798
|
-
for (const elem of normalElems) {
|
|
18799
|
-
const v = varSlotId(elem.slotId);
|
|
18800
|
-
lines.push(` let __anchor_${v} = _${v}`);
|
|
18801
|
-
}
|
|
18802
19222
|
const __textSlot = (normalElems[0] ?? conditionalElems[0])?.slotId;
|
|
19223
|
+
let writer = "";
|
|
19224
|
+
if (normalElems.length > 0) {
|
|
19225
|
+
const slots = normalElems.map((elem) => ({ id: elem.slotId, kind: "markup", path: [] }));
|
|
19226
|
+
writer = claimWriterVarName(slots, varSlotId);
|
|
19227
|
+
lines.push(` const ${writer} = lazySlots(__scope, ${claimPlanLiteral(slots)})`);
|
|
19228
|
+
}
|
|
18803
19229
|
lines.push(` createEffect(() => {`);
|
|
18804
19230
|
if (normalElems.length > 0) {
|
|
18805
19231
|
lines.push(` const __val = ${expr}`);
|
|
18806
19232
|
for (const elem of normalElems) {
|
|
18807
|
-
|
|
18808
|
-
lines.push(` __anchor_${v} = __bfText(__anchor_${v}, __val)`);
|
|
19233
|
+
lines.push(` ${writer}('${elem.slotId}', escapeTextOrNode(__val))`);
|
|
18809
19234
|
}
|
|
18810
19235
|
for (const elem of conditionalElems) {
|
|
18811
19236
|
const v = varSlotId(elem.slotId);
|
|
@@ -18828,10 +19253,13 @@ function emitDynamicTextUpdates(lines, ctx2) {
|
|
|
18828
19253
|
}
|
|
18829
19254
|
function emitClientOnlyExpressions(lines, ctx2) {
|
|
18830
19255
|
for (const elem of ctx2.clientOnlyElements) {
|
|
19256
|
+
const slots = elem.elidedPath ? [{ id: elem.slotId, kind: "text", path: elem.elidedPath, markerless: true }] : [{ id: elem.slotId, kind: "text", path: [] }];
|
|
19257
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
18831
19258
|
lines.push(` // @client: ${elem.slotId}`);
|
|
19259
|
+
lines.push(` { const ${writer} = lazySlots(__scope, ${claimPlanLiteral(slots)})`);
|
|
18832
19260
|
lines.push(` createEffect(() => {`);
|
|
18833
|
-
lines.push(`
|
|
18834
|
-
lines.push(` }${bindingIdArg(ctx2, elem.slotId)})`);
|
|
19261
|
+
lines.push(` ${writer}('${elem.slotId}', ${elem.expression})`);
|
|
19262
|
+
lines.push(` }${bindingIdArg(ctx2, elem.slotId)}) }`);
|
|
18835
19263
|
lines.push("");
|
|
18836
19264
|
}
|
|
18837
19265
|
}
|
|
@@ -18939,6 +19367,7 @@ var init_emit_reactive = __esm({
|
|
|
18939
19367
|
"use strict";
|
|
18940
19368
|
init_html_constants();
|
|
18941
19369
|
init_utils();
|
|
19370
|
+
init_claim_plan();
|
|
18942
19371
|
init_html_template();
|
|
18943
19372
|
init_date_lowering();
|
|
18944
19373
|
init_to_locale_date_lowering();
|
|
@@ -18974,7 +19403,7 @@ function stringifyBranchEventBindings(lines, plan, indent) {
|
|
|
18974
19403
|
}
|
|
18975
19404
|
function stringifyBranchChildComponentInits(lines, plan, indent) {
|
|
18976
19405
|
for (const init of plan) {
|
|
18977
|
-
lines.push(`${indent}{ let __c = qsa(__branchScope, ${init.selector}); if (!__c) { const __ph = __branchScope.querySelector('[${BF_PLACEHOLDER}="${init.placeholderId}"]'); if (__ph) { __c = createComponent('${nameForRegistryRef(init.name)}', ${init.propsExpr}
|
|
19406
|
+
lines.push(`${indent}{ let __c = qsa(__branchScope, ${init.selector}); if (!__c) { const __ph = __branchScope.querySelector('[${BF_PLACEHOLDER}="${init.placeholderId}"]'); if (__ph) { __c = createComponent('${nameForRegistryRef(init.name)}', ${init.propsExpr}, undefined, undefined, __ph) } } if (__c) initChild('${nameForRegistryRef(init.name)}', __c, ${init.propsExpr}) }`);
|
|
18978
19407
|
}
|
|
18979
19408
|
}
|
|
18980
19409
|
function stringifyBranchInnerLoops(lines, plan, indent, pc) {
|
|
@@ -19008,13 +19437,18 @@ function stringifyBranchInnerLoops(lines, plan, indent, pc) {
|
|
|
19008
19437
|
inner.outerLoopParamBindings
|
|
19009
19438
|
);
|
|
19010
19439
|
}
|
|
19011
|
-
|
|
19440
|
+
const conditionalTexts = inner.reactiveTexts.filter((t) => t.insideConditional);
|
|
19441
|
+
const plainTexts = inner.reactiveTexts.filter((t) => !t.insideConditional);
|
|
19442
|
+
for (const text of conditionalTexts) {
|
|
19012
19443
|
const bf = profileBindingId(pc, text.slotId);
|
|
19013
|
-
|
|
19014
|
-
|
|
19015
|
-
|
|
19016
|
-
|
|
19017
|
-
|
|
19444
|
+
lines.push(`${indent} createEffect(() => { claimSlots(__bel${uid}, [{ id: '${text.slotId}', kind: 'text', path: [] }]).write('${text.slotId}', String(${text.wrappedExpression})) }${bf})`);
|
|
19445
|
+
}
|
|
19446
|
+
if (plainTexts.length > 0) {
|
|
19447
|
+
const slots = plainTexts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
19448
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19449
|
+
lines.push(`${indent} const ${writer} = lazySlots(__bel${uid}, ${claimPlanLiteral(slots)})`);
|
|
19450
|
+
for (const text of plainTexts) {
|
|
19451
|
+
lines.push(`${indent} createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) }${profileBindingId(pc, text.slotId)})`);
|
|
19018
19452
|
}
|
|
19019
19453
|
}
|
|
19020
19454
|
if (inner.nestedConditionals.length > 0) {
|
|
@@ -19056,10 +19490,13 @@ function stringifyLoopChildArm(lines, arm, armIndent, pc) {
|
|
|
19056
19490
|
stringifyLoopChildConditional(lines, cond, `${armIndent} `, pc);
|
|
19057
19491
|
lines.push(`${armIndent}}))`);
|
|
19058
19492
|
}
|
|
19059
|
-
|
|
19060
|
-
const
|
|
19061
|
-
|
|
19062
|
-
lines.push(`${armIndent}
|
|
19493
|
+
if (arm.texts.length > 0) {
|
|
19494
|
+
const slots = arm.texts.map((t) => ({ id: t.slotId, kind: "markup", path: [] }));
|
|
19495
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19496
|
+
lines.push(`${armIndent}const ${writer} = lazySlots(__branchScope, ${claimPlanLiteral(slots)})`);
|
|
19497
|
+
for (const text of arm.texts) {
|
|
19498
|
+
lines.push(`${armIndent}__disposers.push(createDisposableEffect(() => { ${writer}('${text.slotId}', escapeTextOrNode(${text.wrappedExpression})) }${profileBindingId(pc, text.slotId)}))`);
|
|
19499
|
+
}
|
|
19063
19500
|
}
|
|
19064
19501
|
lines.push(`${armIndent}return () => __disposers.forEach(d => d())`);
|
|
19065
19502
|
}
|
|
@@ -19072,19 +19509,45 @@ var init_loop_child_arm = __esm({
|
|
|
19072
19509
|
init_template_parse();
|
|
19073
19510
|
init_event_listener();
|
|
19074
19511
|
init_component_scope();
|
|
19512
|
+
init_claim_plan();
|
|
19075
19513
|
}
|
|
19076
19514
|
});
|
|
19077
19515
|
|
|
19078
19516
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts
|
|
19079
19517
|
function stringifyReactiveEffects(lines, plan, opts) {
|
|
19080
|
-
const { indent, elVar, bodyIsMultiRoot, elementIndexBySlot,
|
|
19518
|
+
const { indent, elVar, bodyIsMultiRoot, elementIndexBySlot, textClaimPathExprs, preambleRegions = [], mapPreambleWrapped } = opts;
|
|
19081
19519
|
const lookup = bodyIsMultiRoot ? "qsaItem" : "qsa";
|
|
19082
|
-
const pc = plan
|
|
19520
|
+
const pc = plan?.profileComponentName;
|
|
19083
19521
|
const bindingBfId = (slotId) => profileBindingId(pc, slotId);
|
|
19084
|
-
|
|
19522
|
+
const attrSlots = plan?.attrSlots ?? [];
|
|
19523
|
+
const outerTexts = plan?.outerTexts ?? [];
|
|
19524
|
+
const conditionals = plan?.conditionals ?? [];
|
|
19525
|
+
if (pc) {
|
|
19526
|
+
emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId);
|
|
19527
|
+
emitOuterTexts(lines, indent, elVar, outerTexts, bindingBfId, textClaimPathExprs);
|
|
19528
|
+
emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPreambleWrapped);
|
|
19529
|
+
} else {
|
|
19530
|
+
emitConsolidatedRowEffect(
|
|
19531
|
+
lines,
|
|
19532
|
+
indent,
|
|
19533
|
+
elVar,
|
|
19534
|
+
lookup,
|
|
19535
|
+
attrSlots,
|
|
19536
|
+
outerTexts,
|
|
19537
|
+
elementIndexBySlot,
|
|
19538
|
+
textClaimPathExprs,
|
|
19539
|
+
preambleRegions,
|
|
19540
|
+
mapPreambleWrapped
|
|
19541
|
+
);
|
|
19542
|
+
}
|
|
19543
|
+
for (const cond of conditionals) {
|
|
19544
|
+
emitOuterConditional(lines, indent, elVar, cond, pc);
|
|
19545
|
+
}
|
|
19546
|
+
}
|
|
19547
|
+
function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId) {
|
|
19548
|
+
for (const slot of attrSlots) {
|
|
19085
19549
|
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19086
|
-
const
|
|
19087
|
-
const lookupExpr = pIdx !== void 0 ? `__p ? __p[${pIdx}] : ${lookup}(${elVar}, '[bf="${slot.slotId}"]')` : `${lookup}(${elVar}, '[bf="${slot.slotId}"]')`;
|
|
19550
|
+
const lookupExpr = attrLookupExpr(slot.slotId, varName, elVar, lookup, elementIndexBySlot);
|
|
19088
19551
|
lines.push(`${indent}{ const ${varName} = ${lookupExpr}`);
|
|
19089
19552
|
lines.push(`${indent}if (${varName}) {`);
|
|
19090
19553
|
for (const attr of slot.attrs) {
|
|
@@ -19096,21 +19559,79 @@ function stringifyReactiveEffects(lines, plan, opts) {
|
|
|
19096
19559
|
}
|
|
19097
19560
|
lines.push(`${indent}} }`);
|
|
19098
19561
|
}
|
|
19099
|
-
|
|
19100
|
-
|
|
19562
|
+
}
|
|
19563
|
+
function emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPreambleWrapped) {
|
|
19564
|
+
if (preambleRegions.length === 0) return;
|
|
19565
|
+
const slots = preambleRegions.map((r2) => ({ id: r2.slotId, kind: "markup", path: [] }));
|
|
19566
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19567
|
+
lines.push(`${indent}const ${writer} = lazySlots(${elVar}, ${claimPlanLiteral(slots)})`);
|
|
19568
|
+
lines.push(`${indent}createEffect(() => {`);
|
|
19569
|
+
if (mapPreambleWrapped) lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19570
|
+
for (const region of preambleRegions) {
|
|
19571
|
+
lines.push(`${indent} ${writer}('${region.slotId}', ${region.valueExpr})`);
|
|
19101
19572
|
}
|
|
19102
|
-
|
|
19103
|
-
|
|
19573
|
+
lines.push(`${indent}})`);
|
|
19574
|
+
}
|
|
19575
|
+
function attrLookupExpr(slotId, varName, elVar, lookup, elementIndexBySlot) {
|
|
19576
|
+
const pIdx = elementIndexBySlot?.get(slotId);
|
|
19577
|
+
return pIdx !== void 0 ? `__p ? __p[${pIdx}] : ${lookup}(${elVar}, '[bf="${slotId}"]')` : `${lookup}(${elVar}, '[bf="${slotId}"]')`;
|
|
19578
|
+
}
|
|
19579
|
+
function emitConsolidatedRowEffect(lines, indent, elVar, lookup, attrSlots, outerTexts, elementIndexBySlot, textClaimPathExprs, preambleRegions, mapPreambleWrapped) {
|
|
19580
|
+
if (attrSlots.length === 0 && outerTexts.length === 0 && preambleRegions.length === 0) return;
|
|
19581
|
+
for (const slot of attrSlots) {
|
|
19582
|
+
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19583
|
+
lines.push(`${indent}const ${varName} = ${attrLookupExpr(slot.slotId, varName, elVar, lookup, elementIndexBySlot)}`);
|
|
19104
19584
|
}
|
|
19585
|
+
const claimSlots = [
|
|
19586
|
+
...outerTexts.map((t) => ({ id: t.slotId, kind: "text", path: [], pathExpr: textClaimPathExprs?.get(t.slotId) })),
|
|
19587
|
+
...preambleRegions.map((r2) => ({ id: r2.slotId, kind: "markup", path: [] }))
|
|
19588
|
+
];
|
|
19589
|
+
const writer = claimSlots.length > 0 ? claimWriterVarName(claimSlots, varSlotId) : null;
|
|
19590
|
+
if (writer) {
|
|
19591
|
+
lines.push(`${indent}const ${writer} = lazySlots(${elVar}, ${claimPlanLiteral(claimSlots)})`);
|
|
19592
|
+
}
|
|
19593
|
+
if (attrSlots.length === 0 && preambleRegions.length === 0 && outerTexts.length === 1) {
|
|
19594
|
+
const text = outerTexts[0];
|
|
19595
|
+
lines.push(`${indent}createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) })`);
|
|
19596
|
+
return;
|
|
19597
|
+
}
|
|
19598
|
+
lines.push(`${indent}createEffect(() => {`);
|
|
19599
|
+
for (const slot of attrSlots) {
|
|
19600
|
+
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19601
|
+
lines.push(`${indent} if (${varName}) {`);
|
|
19602
|
+
for (const attr of slot.attrs) {
|
|
19603
|
+
lines.push(`${indent} {`);
|
|
19604
|
+
for (const stmt of emitAttrUpdate(varName, attr.attrName, attr.wrappedExpression, attr.meta)) {
|
|
19605
|
+
lines.push(`${indent} ${stmt}`);
|
|
19606
|
+
}
|
|
19607
|
+
lines.push(`${indent} }`);
|
|
19608
|
+
}
|
|
19609
|
+
lines.push(`${indent} }`);
|
|
19610
|
+
}
|
|
19611
|
+
if (preambleRegions.length > 0 && mapPreambleWrapped) {
|
|
19612
|
+
lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19613
|
+
}
|
|
19614
|
+
for (const text of outerTexts) {
|
|
19615
|
+
lines.push(`${indent} ${writer}('${text.slotId}', String(${text.wrappedExpression}))`);
|
|
19616
|
+
}
|
|
19617
|
+
for (const region of preambleRegions) {
|
|
19618
|
+
lines.push(`${indent} ${writer}('${region.slotId}', ${region.valueExpr})`);
|
|
19619
|
+
}
|
|
19620
|
+
lines.push(`${indent}})`);
|
|
19105
19621
|
}
|
|
19106
|
-
function
|
|
19107
|
-
|
|
19108
|
-
|
|
19109
|
-
|
|
19110
|
-
|
|
19111
|
-
|
|
19622
|
+
function emitOuterTexts(lines, indent, elVar, texts, bindingBfId, textClaimPathExprs) {
|
|
19623
|
+
if (texts.length === 0) return;
|
|
19624
|
+
const slots = texts.map((t) => ({
|
|
19625
|
+
id: t.slotId,
|
|
19626
|
+
kind: "text",
|
|
19627
|
+
path: [],
|
|
19628
|
+
pathExpr: textClaimPathExprs?.get(t.slotId)
|
|
19629
|
+
}));
|
|
19630
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19631
|
+
lines.push(`${indent}const ${writer} = lazySlots(${elVar}, ${claimPlanLiteral(slots)})`);
|
|
19632
|
+
for (const text of texts) {
|
|
19633
|
+
lines.push(`${indent}createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) }${bindingBfId(text.slotId)})`);
|
|
19112
19634
|
}
|
|
19113
|
-
lines.push(`${indent}if (${varName}) createEffect(() => { ${varName}.textContent = String(${text.wrappedExpression}) }${bfId}) }`);
|
|
19114
19635
|
}
|
|
19115
19636
|
function emitOuterConditional(lines, indent, elVar, cond, pc) {
|
|
19116
19637
|
const armIndent = `${indent} `;
|
|
@@ -19132,6 +19653,7 @@ var init_reactive_effects = __esm({
|
|
|
19132
19653
|
init_utils();
|
|
19133
19654
|
init_emit_reactive();
|
|
19134
19655
|
init_loop_child_arm();
|
|
19656
|
+
init_claim_plan();
|
|
19135
19657
|
}
|
|
19136
19658
|
});
|
|
19137
19659
|
|
|
@@ -19229,6 +19751,179 @@ var init_component_loop = __esm({
|
|
|
19229
19751
|
}
|
|
19230
19752
|
});
|
|
19231
19753
|
|
|
19754
|
+
// ../jsx/src/ir-to-client-js/control-flow/stringify/lazy-row.ts
|
|
19755
|
+
function stringifyLazyRowLoop(lines, o) {
|
|
19756
|
+
const { indent, lazyRow, paramHead } = o;
|
|
19757
|
+
const mid = o.markerId.replace(/[^A-Za-z0-9_$]/g, "_");
|
|
19758
|
+
const tplVar = `__tpl_${mid}`;
|
|
19759
|
+
const claimVar = `__lzc_${mid}`;
|
|
19760
|
+
const hasRefs = lazyRow.attrSlotIds.length > 0 || lazyRow.texts.length > 0;
|
|
19761
|
+
const hasBindings = lazyRow.attrs.length > 0 || lazyRow.texts.length > 0;
|
|
19762
|
+
const rwDoor = lazyRow.textNeedsRead;
|
|
19763
|
+
const paths = o.skeletonPaths;
|
|
19764
|
+
const useHoisted = Boolean(o.skeletonTemplate);
|
|
19765
|
+
if (useHoisted) emitHoistedTemplateDecl(lines, indent, tplVar, o.skeletonTemplate);
|
|
19766
|
+
const textPathVar = useHoisted && paths && lazyRow.texts.length > 0 ? `__lzp_${mid}` : null;
|
|
19767
|
+
if (textPathVar) {
|
|
19768
|
+
const arrays = lazyRow.texts.map((t) => `[${(paths.textMarkerPaths.get(t.slotId) ?? []).join(", ")}]`);
|
|
19769
|
+
lines.push(`${indent}const ${textPathVar} = [${arrays.join(", ")}]`);
|
|
19770
|
+
}
|
|
19771
|
+
let adoptedPlanVar = null;
|
|
19772
|
+
let freshPlanVar = null;
|
|
19773
|
+
if (lazyRow.texts.length > 0) {
|
|
19774
|
+
adoptedPlanVar = `__lzs_${mid}`;
|
|
19775
|
+
const adoptedSlots = lazyRow.texts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
19776
|
+
lines.push(`${indent}const ${adoptedPlanVar} = ${claimPlanLiteral(adoptedSlots)}`);
|
|
19777
|
+
if (textPathVar) {
|
|
19778
|
+
freshPlanVar = `__lzsc_${mid}`;
|
|
19779
|
+
const freshSlots = lazyRow.texts.map((t, i) => ({
|
|
19780
|
+
id: t.slotId,
|
|
19781
|
+
kind: "text",
|
|
19782
|
+
path: [],
|
|
19783
|
+
pathExpr: `${textPathVar}[${i}]`
|
|
19784
|
+
}));
|
|
19785
|
+
lines.push(`${indent}const ${freshPlanVar} = ${claimPlanLiteral(freshSlots)}`);
|
|
19786
|
+
} else {
|
|
19787
|
+
freshPlanVar = adoptedPlanVar;
|
|
19788
|
+
}
|
|
19789
|
+
}
|
|
19790
|
+
if (hasRefs) {
|
|
19791
|
+
const parts = refParts(lazyRow, "__el", null, adoptedPlanVar, true);
|
|
19792
|
+
lines.push(`${indent}const ${claimVar} = (__e) => {`);
|
|
19793
|
+
if (parts.some((p) => p.includes("__el"))) lines.push(`${indent} const __el = __e.primaryEl`);
|
|
19794
|
+
lines.push(`${indent} return [${parts.join(", ")}]`);
|
|
19795
|
+
lines.push(`${indent}}`);
|
|
19796
|
+
}
|
|
19797
|
+
const call = `mapArrayLazy(() => ${o.arrayExpr}, ${o.containerVar}, ${o.keyFn}, {`;
|
|
19798
|
+
lines.push(`${indent}${o.guardContainer ? `if (${o.containerVar}) ` : ""}${call}`);
|
|
19799
|
+
const b1 = `${indent} `;
|
|
19800
|
+
const b2 = `${indent} `;
|
|
19801
|
+
lines.push(`${b1}createRow: (__e, ${o.indexParam}) => {`);
|
|
19802
|
+
lines.push(`${b2}const ${paramHead} = () => __e.item`);
|
|
19803
|
+
const cloneExpr = useHoisted ? hoistedCloneExpr(tplVar, o.skeletonTemplate) : `(() => { ${emitTemplateCloneInline(o.template)} })()`;
|
|
19804
|
+
lines.push(`${b2}const __el = ${cloneExpr}`);
|
|
19805
|
+
if (hasRefs) {
|
|
19806
|
+
lines.push(`${b2}const __r = __e.refs = [${refParts(lazyRow, "__el", useHoisted ? paths ?? null : null, freshPlanVar).join(", ")}]`);
|
|
19807
|
+
}
|
|
19808
|
+
if (hasBindings) {
|
|
19809
|
+
lines.push(`${b2}const __l = __e.last = []`);
|
|
19810
|
+
for (const a of lazyRow.attrs) emitAttrBinding(lines, b2, a, "create");
|
|
19811
|
+
const createDoor = `__r[${lazyRow.writerIndex}]`;
|
|
19812
|
+
for (const t of lazyRow.texts) emitTextBinding(lines, b2, t, createDoor, "create", rwDoor);
|
|
19813
|
+
}
|
|
19814
|
+
lines.push(`${b2}return __el`);
|
|
19815
|
+
lines.push(`${b1}},`);
|
|
19816
|
+
const itemAttrs = lazyRow.attrs.filter((a) => a.readsItem);
|
|
19817
|
+
const itemTexts = lazyRow.texts.filter((t) => t.readsItem);
|
|
19818
|
+
if (itemAttrs.length === 0 && itemTexts.length === 0) {
|
|
19819
|
+
lines.push(`${b1}applyItem: () => {},`);
|
|
19820
|
+
} else {
|
|
19821
|
+
lines.push(`${b1}applyItem: (__e) => {`);
|
|
19822
|
+
lines.push(`${b2}const ${paramHead} = () => __e.item`);
|
|
19823
|
+
lines.push(`${b2}const __r = __e.refs ?? (__e.refs = ${claimVar}(__e))`);
|
|
19824
|
+
lines.push(`${b2}const __l = __e.last ?? (__e.last = [])`);
|
|
19825
|
+
for (const a of itemAttrs) emitAttrBinding(lines, b2, a, "item");
|
|
19826
|
+
if (itemTexts.length > 0) {
|
|
19827
|
+
lines.push(`${b2}const __d = ${doorAccess(lazyRow, lazyRow.writerIndex, adoptedPlanVar)}`);
|
|
19828
|
+
for (const t of itemTexts) emitTextBinding(lines, b2, t, "__d", "item", rwDoor);
|
|
19829
|
+
}
|
|
19830
|
+
lines.push(`${b1}},`);
|
|
19831
|
+
}
|
|
19832
|
+
const outerAttrs = lazyRow.attrs.filter((a) => a.readsOuter);
|
|
19833
|
+
const outerTexts = lazyRow.texts.filter((t) => t.readsOuter);
|
|
19834
|
+
if (outerAttrs.length > 0 || outerTexts.length > 0) {
|
|
19835
|
+
const b3 = `${indent} `;
|
|
19836
|
+
lines.push(`${b1}applyOuter: (__es, __seed) => {`);
|
|
19837
|
+
for (const g of lazyRow.outerPrimeGetters) lines.push(`${b2}${g}()`);
|
|
19838
|
+
lines.push(`${b2}for (const __e of __es) {`);
|
|
19839
|
+
lines.push(`${b3}const ${paramHead} = () => __e.item`);
|
|
19840
|
+
lines.push(`${b3}const __r = __e.refs ?? (__e.refs = ${claimVar}(__e))`);
|
|
19841
|
+
lines.push(`${b3}const __l = __e.last ?? (__e.last = [])`);
|
|
19842
|
+
for (const a of outerAttrs) emitAttrBinding(lines, b3, a, "outer");
|
|
19843
|
+
if (outerTexts.length > 0) {
|
|
19844
|
+
lines.push(`${b3}const __d = ${doorAccess(lazyRow, lazyRow.writerIndex, adoptedPlanVar)}`);
|
|
19845
|
+
for (const t of outerTexts) emitTextBinding(lines, b3, t, "__d", "outer", rwDoor);
|
|
19846
|
+
}
|
|
19847
|
+
lines.push(`${b2}}`);
|
|
19848
|
+
lines.push(`${b1}},`);
|
|
19849
|
+
}
|
|
19850
|
+
lines.push(`${indent}}, '${o.markerId}')`);
|
|
19851
|
+
}
|
|
19852
|
+
function refParts(lazyRow, elVar, skeletonPaths, planVar, deferDoor = false) {
|
|
19853
|
+
const parts = [];
|
|
19854
|
+
for (const slotId of lazyRow.attrSlotIds) {
|
|
19855
|
+
const path25 = skeletonPaths?.elementPaths.get(slotId);
|
|
19856
|
+
parts.push(path25 ? pathExpr(elVar, path25) : `qsa(${elVar}, '[bf="${slotId}"]')`);
|
|
19857
|
+
}
|
|
19858
|
+
if (lazyRow.texts.length > 0) {
|
|
19859
|
+
parts.push(deferDoor ? "null" : `${doorCtor(lazyRow)}(${elVar}, ${planVar})`);
|
|
19860
|
+
}
|
|
19861
|
+
return parts;
|
|
19862
|
+
}
|
|
19863
|
+
function doorCtor(lazyRow) {
|
|
19864
|
+
return lazyRow.textNeedsRead ? "lazyClaimSlots" : "lazySlots";
|
|
19865
|
+
}
|
|
19866
|
+
function doorAccess(lazyRow, writerIndex, adoptedPlanVar) {
|
|
19867
|
+
const slot = `__r[${writerIndex}]`;
|
|
19868
|
+
return `${slot} ?? (${slot} = ${doorCtor(lazyRow)}(__e.primaryEl, ${adoptedPlanVar}))`;
|
|
19869
|
+
}
|
|
19870
|
+
function dedupGuard(ordinal) {
|
|
19871
|
+
return `!(${ordinal} in __l) || !Object.is(__l[${ordinal}], __x)`;
|
|
19872
|
+
}
|
|
19873
|
+
function emitAttrBinding(lines, ind, a, mode2) {
|
|
19874
|
+
lines.push(`${ind}{ const __t = __r[${a.refIndex}]`);
|
|
19875
|
+
lines.push(`${ind}if (__t) {`);
|
|
19876
|
+
lines.push(`${ind} const __x = ${a.wrappedExpression}`);
|
|
19877
|
+
const guard = mode2 === "create" ? null : mode2 === "item" ? dedupGuard(a.ordinal) : `__seed ? (${seedDiffersExpr("__t", a)}) : (${dedupGuard(a.ordinal)})`;
|
|
19878
|
+
const writeIndent = guard ? `${ind} ` : `${ind} `;
|
|
19879
|
+
if (guard) lines.push(`${ind} if (${guard}) {`);
|
|
19880
|
+
for (const stmt of emitAttrUpdate("__t", a.attrName, "__x", a.meta)) {
|
|
19881
|
+
lines.push(`${writeIndent}${stmt}`);
|
|
19882
|
+
}
|
|
19883
|
+
if (guard) lines.push(`${ind} }`);
|
|
19884
|
+
lines.push(`${ind} __l[${a.ordinal}] = __x`);
|
|
19885
|
+
lines.push(`${ind}} }`);
|
|
19886
|
+
}
|
|
19887
|
+
function emitTextBinding(lines, ind, t, doorExpr, mode2, rwDoor) {
|
|
19888
|
+
lines.push(`${ind}{ const __x = ${t.wrappedExpression}`);
|
|
19889
|
+
const writeOf = (valueExpr) => rwDoor ? `${doorExpr}.write('${t.slotId}', ${valueExpr})` : `${doorExpr}('${t.slotId}', ${valueExpr})`;
|
|
19890
|
+
if (mode2 === "outer") {
|
|
19891
|
+
lines.push(`${ind}if (__seed) {`);
|
|
19892
|
+
lines.push(`${ind} const __s = textOrNode(__x)`);
|
|
19893
|
+
lines.push(`${ind} if (${doorExpr}.read('${t.slotId}') !== __s) ${writeOf("__s")}`);
|
|
19894
|
+
lines.push(`${ind}} else if (${dedupGuard(t.ordinal)}) ${writeOf("textOrNode(__x)")}`);
|
|
19895
|
+
} else if (mode2 === "item") {
|
|
19896
|
+
lines.push(`${ind}if (${dedupGuard(t.ordinal)}) ${writeOf("textOrNode(__x)")}`);
|
|
19897
|
+
} else {
|
|
19898
|
+
lines.push(`${ind}${writeOf("textOrNode(__x)")}`);
|
|
19899
|
+
}
|
|
19900
|
+
lines.push(`${ind}__l[${t.ordinal}] = __x }`);
|
|
19901
|
+
}
|
|
19902
|
+
function seedDiffersExpr(target2, a) {
|
|
19903
|
+
const html = toHTMLAttrName(a.attrName);
|
|
19904
|
+
if (a.attrName === "dangerouslySetInnerHTML" || html === "dangerouslySetInnerHTML") return "true";
|
|
19905
|
+
if (html === "style") return `${target2}.getAttribute('style') !== styleToCss(__x)`;
|
|
19906
|
+
if (html === "class") return `${target2}.getAttribute('class') !== (__x != null ? String(__x) : null)`;
|
|
19907
|
+
if (html === "value") return `${target2}.value !== String(__x)`;
|
|
19908
|
+
if (isBooleanAttr(html)) return `${target2}.${html} !== !!(__x)`;
|
|
19909
|
+
if (a.meta.presenceOrUndefined) {
|
|
19910
|
+
const written = html.startsWith("aria-") ? "true" : "";
|
|
19911
|
+
return `${target2}.getAttribute('${html}') !== (__x ? '${written}' : null)`;
|
|
19912
|
+
}
|
|
19913
|
+
return `${target2}.getAttribute('${html}') !== (__x != null ? String(__x) : null)`;
|
|
19914
|
+
}
|
|
19915
|
+
var init_lazy_row = __esm({
|
|
19916
|
+
"../jsx/src/ir-to-client-js/control-flow/stringify/lazy-row.ts"() {
|
|
19917
|
+
"use strict";
|
|
19918
|
+
init_html_constants();
|
|
19919
|
+
init_emit_reactive();
|
|
19920
|
+
init_utils();
|
|
19921
|
+
init_claim_plan();
|
|
19922
|
+
init_skeleton_paths();
|
|
19923
|
+
init_template_parse();
|
|
19924
|
+
}
|
|
19925
|
+
});
|
|
19926
|
+
|
|
19232
19927
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/loop.ts
|
|
19233
19928
|
function emitLoopChildRefs(lines, refs, opts) {
|
|
19234
19929
|
if (refs.length === 0) return;
|
|
@@ -19242,20 +19937,6 @@ function emitLoopChildRefs(lines, refs, opts) {
|
|
|
19242
19937
|
lines.push(`${indent}if (${varName}) ${emitRefCall(ref.callback, varName)} }`);
|
|
19243
19938
|
}
|
|
19244
19939
|
}
|
|
19245
|
-
function emitPreambleRegionEffects(lines, regions, mapPreambleWrapped, opts) {
|
|
19246
|
-
if (regions.length === 0) return;
|
|
19247
|
-
const { indent, elVar } = opts;
|
|
19248
|
-
for (const region of regions) {
|
|
19249
|
-
const v = varSlotId(region.slotId);
|
|
19250
|
-
lines.push(`${indent}{ let __last_${v}`);
|
|
19251
|
-
lines.push(`${indent}createEffect(() => {`);
|
|
19252
|
-
if (mapPreambleWrapped) lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19253
|
-
lines.push(`${indent} const __html_${v} = ${region.valueExpr}`);
|
|
19254
|
-
lines.push(`${indent} if (__last_${v} === undefined) { __last_${v} = __html_${v}; return }`);
|
|
19255
|
-
lines.push(`${indent} if (__html_${v} !== __last_${v}) { __last_${v} = __html_${v}; patchSlotRange(${elVar}, '${region.slotId}', __html_${v}) }`);
|
|
19256
|
-
lines.push(`${indent}}) }`);
|
|
19257
|
-
}
|
|
19258
|
-
}
|
|
19259
19940
|
function stringifyLoop(lines, plan) {
|
|
19260
19941
|
switch (plan.kind) {
|
|
19261
19942
|
case "static":
|
|
@@ -19319,6 +20000,23 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
19319
20000
|
stringifyAnchoredLoop(lines, plan, topIndent, anchorKeyExpr);
|
|
19320
20001
|
return;
|
|
19321
20002
|
}
|
|
20003
|
+
if (plan.lazyRow) {
|
|
20004
|
+
stringifyLazyRowLoop(lines, {
|
|
20005
|
+
indent: topIndent,
|
|
20006
|
+
containerVar,
|
|
20007
|
+
guardContainer: false,
|
|
20008
|
+
markerId,
|
|
20009
|
+
arrayExpr,
|
|
20010
|
+
keyFn,
|
|
20011
|
+
paramHead,
|
|
20012
|
+
indexParam,
|
|
20013
|
+
template,
|
|
20014
|
+
skeletonTemplate,
|
|
20015
|
+
skeletonPaths: plan.skeletonPaths,
|
|
20016
|
+
lazyRow: plan.lazyRow
|
|
20017
|
+
});
|
|
20018
|
+
return;
|
|
20019
|
+
}
|
|
19322
20020
|
const hoistedTpl = !bodyIsMultiRoot && skeletonTemplate ? skeletonTemplate : null;
|
|
19323
20021
|
const tplVar = `__tpl_${markerId.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
19324
20022
|
if (hoistedTpl) {
|
|
@@ -19354,26 +20052,33 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
19354
20052
|
...reactiveEffects?.attrSlots.map((s) => s.slotId) ?? [],
|
|
19355
20053
|
...childRefs.map((r2) => r2.childSlotId)
|
|
19356
20054
|
];
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
const built = buildSkeletonPathPlan(plan.skeletonPaths, "__el", { elementSlotIds, textSlotIds });
|
|
20055
|
+
if (elementSlotIds.length > 0) {
|
|
20056
|
+
const built = buildSkeletonPathPlan(plan.skeletonPaths, "__el", { elementSlotIds, textSlotIds: [] });
|
|
19360
20057
|
if (built.arrayElems.length > 0) {
|
|
19361
20058
|
pathPlan = built;
|
|
19362
20059
|
lines.push(`${bodyIndent}const __p = __existing ? null : [${built.arrayElems.join(", ")}]`);
|
|
19363
20060
|
}
|
|
19364
20061
|
}
|
|
19365
20062
|
}
|
|
19366
|
-
|
|
20063
|
+
const textClaimPathExprs = /* @__PURE__ */ new Map();
|
|
20064
|
+
if (hoistedTpl && plan.skeletonPaths) {
|
|
20065
|
+
for (const text of reactiveEffects?.outerTexts ?? []) {
|
|
20066
|
+
const path25 = plan.skeletonPaths.textMarkerPaths.get(text.slotId);
|
|
20067
|
+
if (path25) textClaimPathExprs.set(text.slotId, `__existing ? [] : [${path25.join(", ")}]`);
|
|
20068
|
+
}
|
|
20069
|
+
}
|
|
20070
|
+
if (reactiveEffects !== null || preambleRegions.length > 0) {
|
|
19367
20071
|
stringifyReactiveEffects(lines, reactiveEffects, {
|
|
19368
20072
|
indent: bodyIndent,
|
|
19369
20073
|
elVar: "__el",
|
|
19370
20074
|
bodyIsMultiRoot,
|
|
19371
20075
|
elementIndexBySlot: pathPlan?.elementIndexBySlot,
|
|
19372
|
-
|
|
20076
|
+
textClaimPathExprs,
|
|
20077
|
+
preambleRegions,
|
|
20078
|
+
mapPreambleWrapped
|
|
19373
20079
|
});
|
|
19374
20080
|
}
|
|
19375
20081
|
emitLoopChildRefs(lines, childRefs, { indent: bodyIndent, elVar: "__el", bodyIsMultiRoot, elementIndexBySlot: pathPlan?.elementIndexBySlot });
|
|
19376
|
-
emitPreambleRegionEffects(lines, preambleRegions, mapPreambleWrapped, { indent: bodyIndent, elVar: "__el" });
|
|
19377
20082
|
lines.push(`${bodyIndent}return __el`);
|
|
19378
20083
|
lines.push(`${topIndent}}, '${markerId}'${loopBfId})`);
|
|
19379
20084
|
}
|
|
@@ -19474,10 +20179,13 @@ function stringifyStaticLoop(lines, plan) {
|
|
|
19474
20179
|
}
|
|
19475
20180
|
lines.push(` }`);
|
|
19476
20181
|
}
|
|
19477
|
-
|
|
19478
|
-
const
|
|
19479
|
-
|
|
19480
|
-
lines.push(`
|
|
20182
|
+
if (texts.length > 0) {
|
|
20183
|
+
const slots = texts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
20184
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
20185
|
+
lines.push(` const ${writer} = lazySlots(__iterEl, ${claimPlanLiteral(slots)})`);
|
|
20186
|
+
for (const text of texts) {
|
|
20187
|
+
lines.push(` createEffect(() => { ${writer}('${text.slotId}', String(${text.expression})) }${profileBindingId(pc, text.slotId)})`);
|
|
20188
|
+
}
|
|
19481
20189
|
}
|
|
19482
20190
|
emitLoopChildRefs(lines, childRefs, { indent: " ", elVar: "__iterEl", bodyIsMultiRoot: false });
|
|
19483
20191
|
lines.push(` }`);
|
|
@@ -19495,6 +20203,8 @@ var init_loop = __esm({
|
|
|
19495
20203
|
init_skeleton_paths();
|
|
19496
20204
|
init_component_loop();
|
|
19497
20205
|
init_composite_loop();
|
|
20206
|
+
init_claim_plan();
|
|
20207
|
+
init_lazy_row();
|
|
19498
20208
|
}
|
|
19499
20209
|
});
|
|
19500
20210
|
|
|
@@ -19550,13 +20260,18 @@ function emitReactive(lines, inner, indent, pc) {
|
|
|
19550
20260
|
if (inner.childLevels.length > 0) {
|
|
19551
20261
|
stringifyInnerLoops(lines, inner.childLevels, `${indent} `, pc);
|
|
19552
20262
|
}
|
|
19553
|
-
|
|
20263
|
+
const conditionalTexts = emit.reactiveTexts.filter((t) => t.insideConditional);
|
|
20264
|
+
const plainTexts = emit.reactiveTexts.filter((t) => !t.insideConditional);
|
|
20265
|
+
for (const text of conditionalTexts) {
|
|
19554
20266
|
const bf = profileBindingId(pc, text.slotId);
|
|
19555
|
-
|
|
19556
|
-
|
|
19557
|
-
|
|
19558
|
-
|
|
19559
|
-
|
|
20267
|
+
lines.push(`${indent} createEffect(() => { claimSlots(__innerEl${uid}, [{ id: '${text.slotId}', kind: 'text', path: [] }]).write('${text.slotId}', String(${text.wrappedExpression})) }${bf})`);
|
|
20268
|
+
}
|
|
20269
|
+
if (plainTexts.length > 0) {
|
|
20270
|
+
const slots = plainTexts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
20271
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
20272
|
+
lines.push(`${indent} const ${writer} = lazySlots(__innerEl${uid}, ${claimPlanLiteral(slots)})`);
|
|
20273
|
+
for (const text of plainTexts) {
|
|
20274
|
+
lines.push(`${indent} createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) }${profileBindingId(pc, text.slotId)})`);
|
|
19560
20275
|
}
|
|
19561
20276
|
}
|
|
19562
20277
|
for (const attr of emit.reactiveAttrs) {
|
|
@@ -19618,6 +20333,7 @@ var init_inner_loop = __esm({
|
|
|
19618
20333
|
init_emit_reactive();
|
|
19619
20334
|
init_template_parse();
|
|
19620
20335
|
init_loop();
|
|
20336
|
+
init_claim_plan();
|
|
19621
20337
|
}
|
|
19622
20338
|
});
|
|
19623
20339
|
|
|
@@ -19922,6 +20638,23 @@ function emitPlain(lines, plan) {
|
|
|
19922
20638
|
stringifyEventDelegation(lines, eventDelegation);
|
|
19923
20639
|
return;
|
|
19924
20640
|
}
|
|
20641
|
+
if (plan.lazyRow) {
|
|
20642
|
+
stringifyLazyRowLoop(lines, {
|
|
20643
|
+
indent: " ",
|
|
20644
|
+
containerVar,
|
|
20645
|
+
guardContainer: true,
|
|
20646
|
+
markerId,
|
|
20647
|
+
arrayExpr,
|
|
20648
|
+
keyFn,
|
|
20649
|
+
paramHead,
|
|
20650
|
+
indexParam,
|
|
20651
|
+
template,
|
|
20652
|
+
lazyRow: plan.lazyRow
|
|
20653
|
+
});
|
|
20654
|
+
lines.push(` }))`);
|
|
20655
|
+
stringifyEventDelegation(lines, eventDelegation);
|
|
20656
|
+
return;
|
|
20657
|
+
}
|
|
19925
20658
|
if (reactiveEffects === null && !bodyIsMultiRoot && childRefs.length === 0 && preambleRegions.length === 0) {
|
|
19926
20659
|
const cloneExpr = emitTemplateCloneInline(template);
|
|
19927
20660
|
if (mapPreambleWrapped) {
|
|
@@ -19943,11 +20676,16 @@ function emitPlain(lines, plan) {
|
|
|
19943
20676
|
indent: " ",
|
|
19944
20677
|
singleRootLayout: "inline"
|
|
19945
20678
|
});
|
|
19946
|
-
if (reactiveEffects !== null) {
|
|
19947
|
-
stringifyReactiveEffects(lines, reactiveEffects, {
|
|
20679
|
+
if (reactiveEffects !== null || preambleRegions.length > 0) {
|
|
20680
|
+
stringifyReactiveEffects(lines, reactiveEffects, {
|
|
20681
|
+
indent: " ",
|
|
20682
|
+
elVar: "__el",
|
|
20683
|
+
bodyIsMultiRoot,
|
|
20684
|
+
preambleRegions,
|
|
20685
|
+
mapPreambleWrapped
|
|
20686
|
+
});
|
|
19948
20687
|
}
|
|
19949
20688
|
emitLoopChildRefs(lines, childRefs, { indent: " ", elVar: "__el", bodyIsMultiRoot });
|
|
19950
|
-
emitPreambleRegionEffects(lines, preambleRegions, mapPreambleWrapped, { indent: " ", elVar: "__el" });
|
|
19951
20689
|
lines.push(` return __el`);
|
|
19952
20690
|
lines.push(` }, '${markerId}'${loopBfId})`);
|
|
19953
20691
|
}
|
|
@@ -19962,6 +20700,7 @@ var init_branch_loop = __esm({
|
|
|
19962
20700
|
init_reactive_effects();
|
|
19963
20701
|
init_template_parse();
|
|
19964
20702
|
init_loop();
|
|
20703
|
+
init_lazy_row();
|
|
19965
20704
|
}
|
|
19966
20705
|
});
|
|
19967
20706
|
|
|
@@ -20038,13 +20777,13 @@ function emitArmBody(lines, body2, mode2, indent, profileComponentName) {
|
|
|
20038
20777
|
}
|
|
20039
20778
|
lines.push(`${indent}} }`);
|
|
20040
20779
|
}
|
|
20041
|
-
|
|
20042
|
-
const
|
|
20043
|
-
|
|
20044
|
-
lines.push(`${indent}
|
|
20045
|
-
|
|
20046
|
-
|
|
20047
|
-
|
|
20780
|
+
if (body2.textEffects.length > 0) {
|
|
20781
|
+
const slots = body2.textEffects.map((te) => ({ id: te.slotId, kind: "markup", path: [] }));
|
|
20782
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
20783
|
+
lines.push(`${indent}const ${writer} = lazySlots(__branchScope, ${claimPlanLiteral(slots)})`);
|
|
20784
|
+
for (const te of body2.textEffects) {
|
|
20785
|
+
lines.push(`${indent}__disposers.push(createDisposableEffect(() => { ${writer}('${te.slotId}', escapeTextOrNode(${te.expression})) }${bindingBfId(te.slotId)}))`);
|
|
20786
|
+
}
|
|
20048
20787
|
}
|
|
20049
20788
|
if (body2.loops.length > 0) {
|
|
20050
20789
|
stringifyBranchLoops(lines, body2.loops);
|
|
@@ -20077,6 +20816,7 @@ var init_insert = __esm({
|
|
|
20077
20816
|
init_branch_loop();
|
|
20078
20817
|
init_event_listener();
|
|
20079
20818
|
init_component_scope();
|
|
20819
|
+
init_claim_plan();
|
|
20080
20820
|
}
|
|
20081
20821
|
});
|
|
20082
20822
|
|
|
@@ -20147,7 +20887,7 @@ var init_build_component_loop = __esm({
|
|
|
20147
20887
|
// ../jsx/src/ir-to-client-js/control-flow/plan/build-loop.ts
|
|
20148
20888
|
function buildLoopPlan(elem, opts) {
|
|
20149
20889
|
if (elem.bodyIsItemConditional) {
|
|
20150
|
-
return buildPlainLoopPlan(elem, opts.profileComponentName);
|
|
20890
|
+
return buildPlainLoopPlan(elem, opts.profileComponentName, opts.lazyScope);
|
|
20151
20891
|
}
|
|
20152
20892
|
if (elem.isStaticArray) {
|
|
20153
20893
|
return buildStaticLoopPlan(elem, opts.unsafeLocalNames, opts.profileComponentName);
|
|
@@ -20159,9 +20899,9 @@ function buildLoopPlan(elem, opts) {
|
|
|
20159
20899
|
if (elem.childComponent) {
|
|
20160
20900
|
return buildComponentLoopPlan(elem, opts.profileComponentName);
|
|
20161
20901
|
}
|
|
20162
|
-
return buildPlainLoopPlan(elem, opts.profileComponentName);
|
|
20902
|
+
return buildPlainLoopPlan(elem, opts.profileComponentName, opts.lazyScope);
|
|
20163
20903
|
}
|
|
20164
|
-
function buildPlainLoopPlan(elem, profileComponentName) {
|
|
20904
|
+
function buildPlainLoopPlan(elem, profileComponentName, lazyScope) {
|
|
20165
20905
|
const wrap = (expr) => wrapLoopParamAsAccessor(expr, elem.param, elem.paramBindings);
|
|
20166
20906
|
const { head: paramHead, unwrap: paramUnwrap } = destructureLoopParam(elem.param, elem.paramBindings);
|
|
20167
20907
|
const hasReactive2 = elem.bindings.reactiveAttrs.length > 0 || elem.bindings.reactiveTexts.length > 0 || elem.bindings.conditionals.length > 0;
|
|
@@ -20190,30 +20930,48 @@ function buildPlainLoopPlan(elem, profileComponentName) {
|
|
|
20190
20930
|
preambleRegions: []
|
|
20191
20931
|
};
|
|
20192
20932
|
}
|
|
20933
|
+
const arrayExpr = buildChainedArrayExpr(elem);
|
|
20934
|
+
const indexParam = elem.index || "__idx";
|
|
20935
|
+
const mapPreambleWrapped = elem.preamble ? renderPreamble(elem.preamble, {
|
|
20936
|
+
transformJs: wrap,
|
|
20937
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1, [{ param: elem.param, bindings: elem.paramBindings }], void 0, true)
|
|
20938
|
+
}) : "";
|
|
20939
|
+
const preambleRegions = buildPreambleRegionPlans(elem.preambleRegions, elem.param, elem.paramBindings);
|
|
20193
20940
|
return {
|
|
20194
20941
|
kind: "plain",
|
|
20195
20942
|
rowConstruction: "string-template",
|
|
20196
20943
|
containerVar: `_${varSlotId(elem.slotId)}`,
|
|
20197
20944
|
markerId: elem.markerId,
|
|
20198
20945
|
profileLoopId: profileComponentName ? `${profileComponentName}#binding:${elem.slotId}` : void 0,
|
|
20199
|
-
arrayExpr
|
|
20946
|
+
arrayExpr,
|
|
20200
20947
|
keyFn: loopKeyFn(elem),
|
|
20201
20948
|
paramHead,
|
|
20202
20949
|
paramUnwrap,
|
|
20203
|
-
indexParam
|
|
20950
|
+
indexParam,
|
|
20951
|
+
// Lazy row graph (§9, L3). `null` for every ineligible loop, which then
|
|
20952
|
+
// keeps the eager emission below byte-for-byte.
|
|
20953
|
+
lazyRow: buildLazyRowPlan({
|
|
20954
|
+
loop: elem,
|
|
20955
|
+
arrayExpr,
|
|
20956
|
+
indexParam,
|
|
20957
|
+
paramUnwrap,
|
|
20958
|
+
mapPreambleWrapped,
|
|
20959
|
+
preambleRegionCount: preambleRegions.length,
|
|
20960
|
+
callSite: "plain",
|
|
20961
|
+
flatMapLeafItem: false,
|
|
20962
|
+
anchored: elem.bodyIsItemConditional ?? false,
|
|
20963
|
+
scope: lazyScope
|
|
20964
|
+
}) ?? void 0,
|
|
20204
20965
|
// Stage 3 / D4 — js segments get the loop-param accessor wrap; jsx leaves
|
|
20205
20966
|
// render as HTML-string templates under this loop's param context so a
|
|
20206
20967
|
// leaf that reads the item (`r`) becomes `r()`.
|
|
20207
|
-
mapPreambleWrapped
|
|
20208
|
-
transformJs: wrap,
|
|
20209
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1, [{ param: elem.param, bindings: elem.paramBindings }], void 0, true)
|
|
20210
|
-
}) : "",
|
|
20968
|
+
mapPreambleWrapped,
|
|
20211
20969
|
template: elem.template,
|
|
20212
20970
|
skeletonTemplate: elem.skeletonTemplate,
|
|
20213
20971
|
skeletonPaths: elem.skeletonPaths,
|
|
20214
20972
|
reactiveEffects: hasReactive2 ? buildLoopReactiveEffectsPlan(elem, profileComponentName) : null,
|
|
20215
20973
|
childRefs: buildChildRefBindings(elem.bindings.refs, elem.param, elem.paramBindings),
|
|
20216
|
-
preambleRegions
|
|
20974
|
+
preambleRegions,
|
|
20217
20975
|
bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false,
|
|
20218
20976
|
anchored: elem.bodyIsItemConditional ?? false,
|
|
20219
20977
|
// Fall back to the iteration index when the loop has no key. A whole-item
|
|
@@ -20275,6 +21033,7 @@ var init_build_loop = __esm({
|
|
|
20275
21033
|
init_utils();
|
|
20276
21034
|
init_shared();
|
|
20277
21035
|
init_build_reactive_effects();
|
|
21036
|
+
init_build_lazy_row();
|
|
20278
21037
|
init_build_component_loop();
|
|
20279
21038
|
init_build_composite_loop();
|
|
20280
21039
|
init_html_template();
|
|
@@ -20285,7 +21044,7 @@ var init_build_loop = __esm({
|
|
|
20285
21044
|
function emitConditionalUpdates(lines, ctx2) {
|
|
20286
21045
|
const profileComponentName = ctx2.profile ? ctx2.componentName : void 0;
|
|
20287
21046
|
for (const elem of ctx2.conditionalElements) {
|
|
20288
|
-
const plan = buildInsertPlan(elem, { scope: { kind: "top" }, eventNameMode: "dom", profileComponentName });
|
|
21047
|
+
const plan = buildInsertPlan(elem, { scope: { kind: "top" }, eventNameMode: "dom", profileComponentName, lazyScope: buildLazyRowScopeInfo(ctx2) });
|
|
20289
21048
|
stringifyInsert(lines, plan, { leadingIndent: " ", bodyIndent: " " });
|
|
20290
21049
|
lines.push("");
|
|
20291
21050
|
}
|
|
@@ -20293,17 +21052,19 @@ function emitConditionalUpdates(lines, ctx2) {
|
|
|
20293
21052
|
function emitClientOnlyConditionals(lines, ctx2) {
|
|
20294
21053
|
const profileComponentName = ctx2.profile ? ctx2.componentName : void 0;
|
|
20295
21054
|
for (const elem of ctx2.clientOnlyConditionals) {
|
|
20296
|
-
const plan = buildInsertPlan(elem, { scope: { kind: "top" }, eventNameMode: "raw", profileComponentName });
|
|
21055
|
+
const plan = buildInsertPlan(elem, { scope: { kind: "top" }, eventNameMode: "raw", profileComponentName, lazyScope: buildLazyRowScopeInfo(ctx2) });
|
|
20297
21056
|
lines.push(` // @client conditional: ${elem.slotId}`);
|
|
20298
21057
|
stringifyInsert(lines, plan, { leadingIndent: " ", bodyIndent: " " });
|
|
20299
21058
|
lines.push("");
|
|
20300
21059
|
}
|
|
20301
21060
|
}
|
|
20302
21061
|
function emitLoopUpdates(lines, ctx2, unsafeLocalNames) {
|
|
21062
|
+
const lazyScope = buildLazyRowScopeInfo(ctx2);
|
|
20303
21063
|
for (const elem of ctx2.loopElements) {
|
|
20304
21064
|
const plan = buildLoopPlan(elem, {
|
|
20305
21065
|
unsafeLocalNames,
|
|
20306
|
-
profileComponentName: ctx2.profile ? ctx2.componentName : void 0
|
|
21066
|
+
profileComponentName: ctx2.profile ? ctx2.componentName : void 0,
|
|
21067
|
+
lazyScope
|
|
20307
21068
|
});
|
|
20308
21069
|
internalInvariant(
|
|
20309
21070
|
!(elem.preamble && elem.preamble.builderNames.length > 0 && plan.rowConstruction === "dom-ops"),
|
|
@@ -20331,6 +21092,7 @@ var init_control_flow = __esm({
|
|
|
20331
21092
|
init_build_insert();
|
|
20332
21093
|
init_insert();
|
|
20333
21094
|
init_build_loop();
|
|
21095
|
+
init_build_lazy_row();
|
|
20334
21096
|
init_loop();
|
|
20335
21097
|
init_build_event_delegation();
|
|
20336
21098
|
init_event_delegation();
|
|
@@ -20340,7 +21102,6 @@ var init_control_flow = __esm({
|
|
|
20340
21102
|
// ../jsx/src/ir-to-client-js/element-refs.ts
|
|
20341
21103
|
function generateElementRefs(ctx2) {
|
|
20342
21104
|
const regularSlots = /* @__PURE__ */ new Set();
|
|
20343
|
-
const textSlots = /* @__PURE__ */ new Set();
|
|
20344
21105
|
const componentSlots = /* @__PURE__ */ new Set();
|
|
20345
21106
|
const conditionalSlotIds = collectConditionalSlotIds(ctx2);
|
|
20346
21107
|
for (const elem of ctx2.interactiveElements) {
|
|
@@ -20348,11 +21109,6 @@ function generateElementRefs(ctx2) {
|
|
|
20348
21109
|
regularSlots.add(elem.slotId);
|
|
20349
21110
|
}
|
|
20350
21111
|
}
|
|
20351
|
-
for (const elem of ctx2.dynamicElements) {
|
|
20352
|
-
if (!elem.insideConditional) {
|
|
20353
|
-
textSlots.add(elem.slotId);
|
|
20354
|
-
}
|
|
20355
|
-
}
|
|
20356
21112
|
for (const elem of ctx2.conditionalElements) {
|
|
20357
21113
|
regularSlots.add(elem.slotId);
|
|
20358
21114
|
}
|
|
@@ -20381,10 +21137,9 @@ function generateElementRefs(ctx2) {
|
|
|
20381
21137
|
for (const slotId of componentSlots) {
|
|
20382
21138
|
regularSlots.delete(slotId);
|
|
20383
21139
|
}
|
|
20384
|
-
if (regularSlots.size === 0 &&
|
|
21140
|
+
if (regularSlots.size === 0 && componentSlots.size === 0) return "";
|
|
20385
21141
|
const refLines = [];
|
|
20386
21142
|
emitSlotRefs(refLines, [...regularSlots], "$");
|
|
20387
|
-
emitSlotRefs(refLines, [...textSlots], "$t");
|
|
20388
21143
|
emitSlotRefs(refLines, [...componentSlots], "$c");
|
|
20389
21144
|
return refLines.join("\n");
|
|
20390
21145
|
}
|
|
@@ -21034,6 +21789,107 @@ var init_ir_to_client_js = __esm({
|
|
|
21034
21789
|
}
|
|
21035
21790
|
});
|
|
21036
21791
|
|
|
21792
|
+
// ../jsx/src/ir-to-client-js/client-only-elision.ts
|
|
21793
|
+
function decideClientOnlyElision(root2) {
|
|
21794
|
+
walkNode(root2, [], /* @__PURE__ */ new Set(), { bailed: false });
|
|
21795
|
+
}
|
|
21796
|
+
function walkNode(node, path25, forceCloseAncestors, state2) {
|
|
21797
|
+
if (state2.bailed) return;
|
|
21798
|
+
if (node.type === "element") {
|
|
21799
|
+
if (!elementIsPathSafe(node.tag, flattenSkeletonChildren(node.children))) {
|
|
21800
|
+
state2.bailed = true;
|
|
21801
|
+
return;
|
|
21802
|
+
}
|
|
21803
|
+
const groupIdx = skeletonForceCloseGroup(node.tag);
|
|
21804
|
+
if (groupIdx >= 0 && forceCloseAncestors.has(groupIdx)) {
|
|
21805
|
+
state2.bailed = true;
|
|
21806
|
+
return;
|
|
21807
|
+
}
|
|
21808
|
+
const nextAncestors = groupIdx >= 0 ? /* @__PURE__ */ new Set([...forceCloseAncestors, groupIdx]) : forceCloseAncestors;
|
|
21809
|
+
walkChildren(flattenSkeletonChildren(node.children), path25, nextAncestors, state2);
|
|
21810
|
+
} else if (node.type === "fragment") {
|
|
21811
|
+
walkChildren(flattenSkeletonChildren(node.children), path25, forceCloseAncestors, state2);
|
|
21812
|
+
}
|
|
21813
|
+
}
|
|
21814
|
+
function walkChildren(children2, parentPath, forceCloseAncestors, state2) {
|
|
21815
|
+
let frozen = false;
|
|
21816
|
+
let idx = 0;
|
|
21817
|
+
let pendingText = false;
|
|
21818
|
+
for (let i = 0; i < children2.length; i++) {
|
|
21819
|
+
if (state2.bailed) return;
|
|
21820
|
+
const child = children2[i];
|
|
21821
|
+
switch (child.type) {
|
|
21822
|
+
case "text": {
|
|
21823
|
+
if (child.value === "") continue;
|
|
21824
|
+
if (!pendingText) idx += 1;
|
|
21825
|
+
pendingText = true;
|
|
21826
|
+
continue;
|
|
21827
|
+
}
|
|
21828
|
+
case "expression": {
|
|
21829
|
+
if (child.expr === "null" || child.expr === "undefined") continue;
|
|
21830
|
+
if (child.clientOnly && child.slotId) {
|
|
21831
|
+
const adjacent = isTextLike(children2[i - 1]) || isTextLike(children2[i + 1]);
|
|
21832
|
+
if (!frozen && !adjacent) {
|
|
21833
|
+
markElided(child, [...parentPath, idx]);
|
|
21834
|
+
frozen = true;
|
|
21835
|
+
} else {
|
|
21836
|
+
frozen = true;
|
|
21837
|
+
}
|
|
21838
|
+
idx += 1;
|
|
21839
|
+
pendingText = false;
|
|
21840
|
+
continue;
|
|
21841
|
+
}
|
|
21842
|
+
frozen = true;
|
|
21843
|
+
idx += 1;
|
|
21844
|
+
pendingText = false;
|
|
21845
|
+
continue;
|
|
21846
|
+
}
|
|
21847
|
+
case "element": {
|
|
21848
|
+
if (!elementIsPathSafe(child.tag, flattenSkeletonChildren(child.children))) {
|
|
21849
|
+
state2.bailed = true;
|
|
21850
|
+
return;
|
|
21851
|
+
}
|
|
21852
|
+
if (!frozen) {
|
|
21853
|
+
walkNode(child, [...parentPath, idx], forceCloseAncestors, state2);
|
|
21854
|
+
}
|
|
21855
|
+
idx += 1;
|
|
21856
|
+
pendingText = false;
|
|
21857
|
+
continue;
|
|
21858
|
+
}
|
|
21859
|
+
case "fragment":
|
|
21860
|
+
continue;
|
|
21861
|
+
// already flattened
|
|
21862
|
+
default:
|
|
21863
|
+
frozen = true;
|
|
21864
|
+
idx += 1;
|
|
21865
|
+
pendingText = false;
|
|
21866
|
+
continue;
|
|
21867
|
+
}
|
|
21868
|
+
}
|
|
21869
|
+
}
|
|
21870
|
+
function isTextLike(node) {
|
|
21871
|
+
if (!node) return false;
|
|
21872
|
+
if (node.type === "text") return node.value !== "";
|
|
21873
|
+
if (node.type === "expression") return node.expr !== "null" && node.expr !== "undefined";
|
|
21874
|
+
return false;
|
|
21875
|
+
}
|
|
21876
|
+
function markElided(expr, path25) {
|
|
21877
|
+
expr.markerless = true;
|
|
21878
|
+
expr.elidedPath = path25;
|
|
21879
|
+
}
|
|
21880
|
+
function elementIsPathSafe(tag, flatChildren) {
|
|
21881
|
+
if (SKELETON_PATH_HAZARD_TAGS.has(tag)) return false;
|
|
21882
|
+
if (VOID_ELEMENTS.has(tag) && flatChildren.length > 0) return false;
|
|
21883
|
+
if (tag === "tr" && hasForeignTableRowContent(flatChildren)) return false;
|
|
21884
|
+
return true;
|
|
21885
|
+
}
|
|
21886
|
+
var init_client_only_elision = __esm({
|
|
21887
|
+
"../jsx/src/ir-to-client-js/client-only-elision.ts"() {
|
|
21888
|
+
"use strict";
|
|
21889
|
+
init_html_template();
|
|
21890
|
+
}
|
|
21891
|
+
});
|
|
21892
|
+
|
|
21037
21893
|
// ../jsx/src/css-layer-prefixer.ts
|
|
21038
21894
|
function prefixClass(cls, layerName) {
|
|
21039
21895
|
if (!cls || cls.startsWith("layer-")) return cls;
|
|
@@ -22208,7 +23064,7 @@ function checkRichTypeMethodCalls(root2, metadata, errors) {
|
|
|
22208
23064
|
if (!metadata.propsType) return;
|
|
22209
23065
|
const matchers = prepareLoweringMatchers(metadata);
|
|
22210
23066
|
const seen = /* @__PURE__ */ new Set();
|
|
22211
|
-
|
|
23067
|
+
walkNode2(root2, metadata, EMPTY_BINDINGS2, matchers, errors, seen);
|
|
22212
23068
|
}
|
|
22213
23069
|
function isLoweringClaimed(matchers, callee, args2) {
|
|
22214
23070
|
return matchers.some((m) => m(callee, args2) !== null);
|
|
@@ -22336,7 +23192,7 @@ function walkAttrValue(value2, clientOnly, loc, meta, bindings, matchers, errors
|
|
|
22336
23192
|
walkTemplateParts(value2.parts, loc, meta, bindings, matchers, errors, seen);
|
|
22337
23193
|
}
|
|
22338
23194
|
}
|
|
22339
|
-
function
|
|
23195
|
+
function walkNode2(node, meta, bindings, matchers, errors, seen) {
|
|
22340
23196
|
if (node.type === "expression") {
|
|
22341
23197
|
if (!node.clientOnly && node.parsed) checkExpr(node.parsed, node.loc, meta, bindings, matchers, errors, seen);
|
|
22342
23198
|
} else if (node.type === "conditional") {
|
|
@@ -22356,11 +23212,11 @@ function walkNode(node, meta, bindings, matchers, errors, seen) {
|
|
|
22356
23212
|
case "component":
|
|
22357
23213
|
case "fragment":
|
|
22358
23214
|
case "provider":
|
|
22359
|
-
for (const child of node.children)
|
|
23215
|
+
for (const child of node.children) walkNode2(child, meta, bindings, matchers, errors, seen);
|
|
22360
23216
|
break;
|
|
22361
23217
|
case "async":
|
|
22362
|
-
|
|
22363
|
-
for (const child of node.children)
|
|
23218
|
+
walkNode2(node.fallback, meta, bindings, matchers, errors, seen);
|
|
23219
|
+
for (const child of node.children) walkNode2(child, meta, bindings, matchers, errors, seen);
|
|
22364
23220
|
break;
|
|
22365
23221
|
case "loop": {
|
|
22366
23222
|
if (node.clientOnly) break;
|
|
@@ -22369,29 +23225,29 @@ function walkNode(node, meta, bindings, matchers, errors, seen) {
|
|
|
22369
23225
|
const arrayType = node.arrayParsed ? resolveReceiverType(node.arrayParsed, meta, bindings) : null;
|
|
22370
23226
|
loopBindings.set(node.param, arrayType?.kind === "array" ? arrayType.elementType ?? null : null);
|
|
22371
23227
|
if (node.index) loopBindings.set(node.index, null);
|
|
22372
|
-
for (const child of node.children)
|
|
23228
|
+
for (const child of node.children) walkNode2(child, meta, loopBindings, matchers, errors, seen);
|
|
22373
23229
|
if (node.childComponent) {
|
|
22374
|
-
for (const child of node.childComponent.children)
|
|
23230
|
+
for (const child of node.childComponent.children) walkNode2(child, meta, loopBindings, matchers, errors, seen);
|
|
22375
23231
|
}
|
|
22376
23232
|
for (const nested of node.nestedComponents ?? []) {
|
|
22377
|
-
for (const child of nested.children)
|
|
23233
|
+
for (const child of nested.children) walkNode2(child, meta, loopBindings, matchers, errors, seen);
|
|
22378
23234
|
}
|
|
22379
23235
|
for (const seg of node.flatMapCallback?.segments ?? []) {
|
|
22380
|
-
if (seg.kind === "jsx")
|
|
23236
|
+
if (seg.kind === "jsx") walkNode2(seg.ir, meta, loopBindings, matchers, errors, seen);
|
|
22381
23237
|
}
|
|
22382
23238
|
for (const seg of node.preamble?.segments ?? []) {
|
|
22383
|
-
if (seg.kind === "jsx")
|
|
23239
|
+
if (seg.kind === "jsx") walkNode2(seg.ir, meta, loopBindings, matchers, errors, seen);
|
|
22384
23240
|
}
|
|
22385
23241
|
break;
|
|
22386
23242
|
}
|
|
22387
23243
|
case "conditional":
|
|
22388
23244
|
if (node.clientOnly) break;
|
|
22389
|
-
|
|
22390
|
-
|
|
23245
|
+
walkNode2(node.whenTrue, meta, bindings, matchers, errors, seen);
|
|
23246
|
+
walkNode2(node.whenFalse, meta, bindings, matchers, errors, seen);
|
|
22391
23247
|
break;
|
|
22392
23248
|
case "if-statement":
|
|
22393
|
-
|
|
22394
|
-
if (node.alternate)
|
|
23249
|
+
walkNode2(node.consequent, meta, bindings, matchers, errors, seen);
|
|
23250
|
+
if (node.alternate) walkNode2(node.alternate, meta, bindings, matchers, errors, seen);
|
|
22395
23251
|
break;
|
|
22396
23252
|
}
|
|
22397
23253
|
}
|
|
@@ -22464,6 +23320,7 @@ function compileMultipleComponents(source, filePath, componentNames, options2) {
|
|
|
22464
23320
|
};
|
|
22465
23321
|
componentIR.metadata.clientAnalysis = analyzeClientNeeds(componentIR);
|
|
22466
23322
|
checkRichTypeMethodCalls(componentIR.root, componentIR.metadata, errors);
|
|
23323
|
+
decideClientOnlyElision(componentIR.root);
|
|
22467
23324
|
if (options2.cssLayerPrefix) {
|
|
22468
23325
|
applyCssLayerPrefix(componentIR, options2.cssLayerPrefix);
|
|
22469
23326
|
}
|
|
@@ -22801,6 +23658,7 @@ function compileJSX(source, filePath, options2) {
|
|
|
22801
23658
|
};
|
|
22802
23659
|
componentIR.metadata.clientAnalysis = analyzeClientNeeds(componentIR);
|
|
22803
23660
|
checkRichTypeMethodCalls(componentIR.root, componentIR.metadata, errors);
|
|
23661
|
+
decideClientOnlyElision(componentIR.root);
|
|
22804
23662
|
if (ctx2.importedClientSignalNames.size > 0) {
|
|
22805
23663
|
const sources = /* @__PURE__ */ new Set();
|
|
22806
23664
|
for (const imp of ctx2.imports) {
|
|
@@ -22922,6 +23780,7 @@ var init_compiler = __esm({
|
|
|
22922
23780
|
init_jsx_to_ir();
|
|
22923
23781
|
init_builtins();
|
|
22924
23782
|
init_ir_to_client_js();
|
|
23783
|
+
init_client_only_elision();
|
|
22925
23784
|
init_emit_module_level();
|
|
22926
23785
|
init_imports();
|
|
22927
23786
|
init_component_scope();
|
|
@@ -26867,6 +27726,7 @@ __export(src_exports, {
|
|
|
26867
27726
|
createProgramForFile: () => createProgramForFile,
|
|
26868
27727
|
dangerousInnerHtmlDiagnostic: () => dangerousInnerHtmlDiagnostic,
|
|
26869
27728
|
dangerousInnerHtmlMetacharViolation: () => dangerousInnerHtmlMetacharViolation,
|
|
27729
|
+
decideClientOnlyElision: () => decideClientOnlyElision,
|
|
26870
27730
|
describeFallback: () => describeFallback,
|
|
26871
27731
|
diffProfiles: () => diffProfiles,
|
|
26872
27732
|
diffStaticBudget: () => diffStaticBudget,
|
|
@@ -26981,6 +27841,7 @@ var init_src2 = __esm({
|
|
|
26981
27841
|
init_analyzer();
|
|
26982
27842
|
init_shared_program();
|
|
26983
27843
|
init_jsx_to_ir();
|
|
27844
|
+
init_client_only_elision();
|
|
26984
27845
|
init_module_exports();
|
|
26985
27846
|
init_interface();
|
|
26986
27847
|
init_test_adapter();
|