@barefootjs/jsx 0.29.0 → 0.30.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/adapters/child-scope.d.ts +17 -0
- package/dist/adapters/child-scope.d.ts.map +1 -0
- package/dist/adapters/loop-bound-names.d.ts.map +1 -1
- package/dist/analyzer-context.d.ts.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +876 -352
- package/dist/ir-to-client-js/collect-elements.d.ts +5 -25
- package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts +66 -2
- 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-reactive-effects.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/lazy-conditional.d.ts +92 -0
- package/dist/ir-to-client-js/control-flow/plan/lazy-conditional.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/plan/lazy-preamble.d.ts +134 -0
- package/dist/ir-to-client-js/control-flow/plan/lazy-preamble.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/plan/lazy-row-eligibility.d.ts +46 -11
- 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/reactive-effects.d.ts +7 -0
- package/dist/ir-to-client-js/control-flow/plan/reactive-effects.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/lazy-row.d.ts.map +1 -1
- package/dist/ir-to-client-js/csr-substitute.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts +2 -3
- package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
- package/dist/ir-to-client-js/plan/declaration-emit.d.ts +6 -0
- package/dist/ir-to-client-js/plan/declaration-emit.d.ts.map +1 -1
- package/dist/ir-to-client-js/reactivity.d.ts +1 -10
- package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
- package/dist/ir-to-client-js/types.d.ts +12 -0
- package/dist/ir-to-client-js/types.d.ts.map +1 -1
- package/dist/jsx-to-ir.d.ts.map +1 -1
- package/dist/rich-type-evidence.d.ts.map +1 -1
- package/dist/ssr-defaults.d.ts.map +1 -1
- package/dist/to-locale-date-lowering.d.ts.map +1 -1
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +6 -24
- package/src/__tests__/branch-loop-plain.test.ts +28 -45
- package/src/__tests__/csr-substitution-safety-divergence.test.ts +9 -3
- package/src/__tests__/csr-template-scope-soundness.test.ts +96 -0
- package/src/__tests__/early-return-branch-switch.test.ts +96 -0
- package/src/__tests__/form-control-value-ssr.test.ts +102 -0
- package/src/__tests__/lazy-conditional.test.ts +190 -0
- package/src/__tests__/lazy-preamble.test.ts +297 -0
- package/src/__tests__/lazy-row-eligibility.test.ts +97 -28
- package/src/__tests__/loop-item-root-scope.test.ts +213 -0
- package/src/__tests__/map-multi-return-body.test.ts +30 -3
- package/src/__tests__/nested-loop-conditional.test.ts +27 -6
- package/src/__tests__/preamble-attr-reactivity.test.ts +217 -0
- package/src/__tests__/preamble-declarations.test.ts +207 -0
- package/src/__tests__/ssr-defaults.test.ts +44 -0
- package/src/adapters/child-scope.ts +22 -0
- package/src/adapters/loop-bound-names.ts +6 -0
- package/src/analyzer-context.ts +43 -0
- package/src/analyzer.ts +33 -3
- package/src/index.ts +1 -0
- package/src/ir-to-client-js/collect-elements.ts +51 -10
- package/src/ir-to-client-js/control-flow/plan/build-branch-loop.ts +1 -1
- package/src/ir-to-client-js/control-flow/plan/build-composite-loop.ts +2 -2
- package/src/ir-to-client-js/control-flow/plan/build-event-delegation.ts +3 -3
- package/src/ir-to-client-js/control-flow/plan/build-inner-loop.ts +2 -2
- package/src/ir-to-client-js/control-flow/plan/build-lazy-row.ts +147 -5
- package/src/ir-to-client-js/control-flow/plan/build-loop.ts +2 -2
- package/src/ir-to-client-js/control-flow/plan/build-reactive-effects.ts +1 -0
- package/src/ir-to-client-js/control-flow/plan/lazy-conditional.ts +151 -0
- package/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts +287 -0
- package/src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts +85 -22
- package/src/ir-to-client-js/control-flow/plan/reactive-effects.ts +7 -0
- package/src/ir-to-client-js/control-flow/stringify/lazy-row.ts +133 -35
- package/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts +24 -4
- package/src/ir-to-client-js/csr-substitute.ts +6 -1
- package/src/ir-to-client-js/emit-registration.ts +1 -1
- package/src/ir-to-client-js/html-template.ts +51 -40
- package/src/ir-to-client-js/index.ts +1 -1
- package/src/ir-to-client-js/plan/build-declaration-emit.ts +2 -0
- package/src/ir-to-client-js/plan/build-static-array-child-init.ts +1 -1
- package/src/ir-to-client-js/plan/declaration-emit.ts +6 -0
- package/src/ir-to-client-js/reactivity.ts +25 -0
- package/src/ir-to-client-js/stringify/declaration-emit.ts +9 -4
- package/src/ir-to-client-js/types.ts +12 -0
- package/src/jsx-to-ir.ts +400 -24
- package/src/rich-type-evidence.ts +6 -7
- package/src/ssr-defaults.ts +7 -2
- package/src/to-locale-date-lowering.ts +8 -2
- package/src/types.ts +80 -0
package/dist/index.js
CHANGED
|
@@ -3073,7 +3073,7 @@ function buildSignalMemoEnv(signals, memos, propsObjectName) {
|
|
|
3073
3073
|
for (const m of memos) {
|
|
3074
3074
|
substitutions.set(m.name, {
|
|
3075
3075
|
kind: "call",
|
|
3076
|
-
replacement: extractMemoBodyExpr(m.computation),
|
|
3076
|
+
replacement: extractMemoBodyExpr(m.templateComputation ?? m.computation),
|
|
3077
3077
|
freeIdentifiers: m.computationFreeIdentifiers ?? new Set
|
|
3078
3078
|
});
|
|
3079
3079
|
}
|
|
@@ -3091,6 +3091,13 @@ function normalizeSignalInitial(signal, propsObjectName) {
|
|
|
3091
3091
|
|
|
3092
3092
|
// src/ir-to-client-js/html-template.ts
|
|
3093
3093
|
import { BF_PARENT_SCOPE_PLACEHOLDER, BF_SCOPE, escapeHtml } from "@barefootjs/shared";
|
|
3094
|
+
|
|
3095
|
+
// src/adapters/child-scope.ts
|
|
3096
|
+
function derivesScopeFromSlot(comp) {
|
|
3097
|
+
return comp.slotId != null && comp.loopItemRoot !== true;
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
// src/ir-to-client-js/html-template.ts
|
|
3094
3101
|
function createStringProtector() {
|
|
3095
3102
|
const strings = [];
|
|
3096
3103
|
const protect = (s) => {
|
|
@@ -3423,7 +3430,7 @@ function renderFlatMapClientBody(cb, restSpreadNames) {
|
|
|
3423
3430
|
rawLeaf: true,
|
|
3424
3431
|
renderLeaf: (ir) => {
|
|
3425
3432
|
const key = flatMapLeafKeyExpr(ir);
|
|
3426
|
-
const html = irToHtmlTemplate(stripLeafKeyAttr(ir), restSpreadNames, 1, undefined, undefined
|
|
3433
|
+
const html = irToHtmlTemplate(stripLeafKeyAttr(ir), restSpreadNames, 1, undefined, undefined);
|
|
3427
3434
|
return `({ k: ${key ?? "undefined"}, h: \`${html}\` })`;
|
|
3428
3435
|
}
|
|
3429
3436
|
});
|
|
@@ -3435,7 +3442,7 @@ function renderFlatMapProjectionClientBody(inner, restSpreadNames) {
|
|
|
3435
3442
|
const chained = applyLoopChain(inner);
|
|
3436
3443
|
const params = inner.index ? `(${inner.param}, ${inner.index})` : `(${inner.param})`;
|
|
3437
3444
|
const key = inner.key ? `(${inner.key})` : "undefined";
|
|
3438
|
-
const html = inner.children.map((c) => irToHtmlTemplate(escapeLeafTextExpressions(c), restSpreadNames, 1, undefined, undefined
|
|
3445
|
+
const html = inner.children.map((c) => irToHtmlTemplate(escapeLeafTextExpressions(c), restSpreadNames, 1, undefined, undefined)).join("");
|
|
3439
3446
|
return `${chained}.map(${params} => ({ k: ${key}, h: \`${html}\` }))`;
|
|
3440
3447
|
}
|
|
3441
3448
|
function escapeLeafTextExpressions(ir) {
|
|
@@ -3461,8 +3468,8 @@ function escapeLeafTextExpressions(ir) {
|
|
|
3461
3468
|
return ir;
|
|
3462
3469
|
}
|
|
3463
3470
|
}
|
|
3464
|
-
function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, branchSlotsVar,
|
|
3465
|
-
const recurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar,
|
|
3471
|
+
function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, branchSlotsVar, inHoistedChildren = false) {
|
|
3472
|
+
const recurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar, inHoistedChildren);
|
|
3466
3473
|
const wrapExpr = (expr) => wrapExprWithLoopParams(expr, loopParams);
|
|
3467
3474
|
const wrapInterpolation = (expr) => branchSlotsVar ? `__bfSlot(${expr}, ${branchSlotsVar})` : expr;
|
|
3468
3475
|
switch (node.type) {
|
|
@@ -3493,7 +3500,7 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3493
3500
|
attrParts.push(`bf="${node.slotId}"`);
|
|
3494
3501
|
}
|
|
3495
3502
|
const attrs = attrParts.join(" ");
|
|
3496
|
-
const childrenRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar,
|
|
3503
|
+
const childrenRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar, false);
|
|
3497
3504
|
const children = dangerouslyHtmlChildren(node.attrs, (v) => wrapExpr(v.expr)) ?? node.children.map(childrenRecurse).join("");
|
|
3498
3505
|
if (children || !VOID_ELEMENTS.has(node.tag)) {
|
|
3499
3506
|
return `<${node.tag}${attrs ? " " + attrs : ""}>${children}</${node.tag}>`;
|
|
@@ -3530,12 +3537,12 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3530
3537
|
if (node.name === "Portal") {
|
|
3531
3538
|
return node.children.map(recurse).join("");
|
|
3532
3539
|
}
|
|
3533
|
-
const propsEntries = node.props.filter((p) => p.name !== "..." && !p.name.startsWith("...") && p.name !== "key").filter((p) => !(p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())).map((p) => {
|
|
3540
|
+
const propsEntries = node.props.filter((p) => p.name !== "..." && !p.name.startsWith("...") && p.name !== "key").filter((p) => p.name !== "ref" && !(p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())).map((p) => {
|
|
3534
3541
|
if (p.clientOnly)
|
|
3535
3542
|
return null;
|
|
3536
3543
|
switch (p.value.kind) {
|
|
3537
3544
|
case "jsx-children": {
|
|
3538
|
-
const hoistedRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar,
|
|
3545
|
+
const hoistedRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar, true);
|
|
3539
3546
|
const childHtml = p.value.children.map((c) => hoistedRecurse(c)).join("");
|
|
3540
3547
|
return `${quotePropName(p.name)}: \`${childHtml}\``;
|
|
3541
3548
|
}
|
|
@@ -3548,7 +3555,7 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3548
3555
|
case "expression":
|
|
3549
3556
|
case "template":
|
|
3550
3557
|
case "spread": {
|
|
3551
|
-
const expr = attrValueToString(p.value) ?? "undefined";
|
|
3558
|
+
const expr = attrValueToString(p.value, { useTemplate: true }) ?? "undefined";
|
|
3552
3559
|
return `${quotePropName(p.name)}: ${expr}`;
|
|
3553
3560
|
}
|
|
3554
3561
|
}
|
|
@@ -3559,11 +3566,11 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3559
3566
|
const propsExpr = propsEntries.length > 0 ? `{${propsEntries.join(", ")}}` : "{}";
|
|
3560
3567
|
const keyProp = node.props.find((p) => p.name === "key");
|
|
3561
3568
|
const keyArg = keyProp ? `, ${attrValueToString(keyProp.value) ?? "undefined"}` : "";
|
|
3562
|
-
const slotArg =
|
|
3569
|
+
const slotArg = derivesScopeFromSlot(node) ? `, '${node.slotId}'` : "";
|
|
3563
3570
|
return `\${renderChild('${nameForRegistryRef(node.name)}', ${propsExpr}${keyArg || (slotArg ? ", undefined" : "")}${slotArg})}`;
|
|
3564
3571
|
}
|
|
3565
3572
|
case "loop": {
|
|
3566
|
-
const innerRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar
|
|
3573
|
+
const innerRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar);
|
|
3567
3574
|
let childTemplate = node.children.map(innerRecurse).join("");
|
|
3568
3575
|
if (node.bodyIsItemConditional && node.key) {
|
|
3569
3576
|
childTemplate = `${itemAnchorTemplate(node.key)}${childTemplate}`;
|
|
@@ -3576,11 +3583,11 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3576
3583
|
let mapExpr;
|
|
3577
3584
|
if (node.flatMapCallback) {
|
|
3578
3585
|
const body = renderPreamble(node.flatMapCallback, {
|
|
3579
|
-
renderLeaf: (ir) => irToHtmlTemplate(stripLeafKeyAttr(ir), restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar
|
|
3586
|
+
renderLeaf: (ir) => irToHtmlTemplate(stripLeafKeyAttr(ir), restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar)
|
|
3580
3587
|
});
|
|
3581
3588
|
mapExpr = `\${${wrappedArray}.flatMap(${node.flatMapCallback.params} => ${body}).join('')}`;
|
|
3582
3589
|
} else if (node.preamble) {
|
|
3583
|
-
const preamble = renderPreamble(node.preamble, { textVariant: "client", renderLeaf: (ir) => irToHtmlTemplate(ir, restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar
|
|
3590
|
+
const preamble = renderPreamble(node.preamble, { textVariant: "client", renderLeaf: (ir) => irToHtmlTemplate(ir, restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar) });
|
|
3584
3591
|
mapExpr = `\${${wrappedArray}.${iterMethod}(${callbackParam} => { ${preamble} return \`${childTemplate}\` }).join('')}`;
|
|
3585
3592
|
} else {
|
|
3586
3593
|
mapExpr = `\${${wrappedArray}.${iterMethod}(${callbackParam} => \`${childTemplate}\`).join('')}`;
|
|
@@ -4085,7 +4092,7 @@ function irToComponentTemplateWithOpts(node, opts) {
|
|
|
4085
4092
|
if (node.name === "Portal") {
|
|
4086
4093
|
return node.children.map(recurse).join("");
|
|
4087
4094
|
}
|
|
4088
|
-
const propsEntries = node.props.filter((p) => p.name !== "..." && !p.name.startsWith("...") && p.name !== "key").filter((p) => !(p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())).map((p) => {
|
|
4095
|
+
const propsEntries = node.props.filter((p) => p.name !== "..." && !p.name.startsWith("...") && p.name !== "key").filter((p) => p.name !== "ref" && !(p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())).map((p) => {
|
|
4089
4096
|
if (p.clientOnly)
|
|
4090
4097
|
return null;
|
|
4091
4098
|
switch (p.value.kind) {
|
|
@@ -4202,7 +4209,7 @@ function canGenerateStaticTemplate(node, propNames, inlinableConstants, unsafeLo
|
|
|
4202
4209
|
return assertNever(node);
|
|
4203
4210
|
}
|
|
4204
4211
|
}
|
|
4205
|
-
function generateCsrTemplate(node, inlinableConstants, ctx,
|
|
4212
|
+
function generateCsrTemplate(node, inlinableConstants, ctx, restSpreadNames, propsObjectName, unsafeLocalNames, deferredChildSlots) {
|
|
4206
4213
|
const base = buildSignalMemoEnv(ctx.signals, ctx.memos, propsObjectName ?? null);
|
|
4207
4214
|
const csrEnv = { substitutions: new Map(base.substitutions), propsObjectName: base.propsObjectName };
|
|
4208
4215
|
if (inlinableConstants) {
|
|
@@ -4213,7 +4220,7 @@ function generateCsrTemplate(node, inlinableConstants, ctx, insideLoop, restSpre
|
|
|
4213
4220
|
}
|
|
4214
4221
|
}
|
|
4215
4222
|
const effectiveUnsafeLocalNames = mergeCsrNullUnsafe(ctx, unsafeLocalNames);
|
|
4216
|
-
return generateCsrTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, csrEnv,
|
|
4223
|
+
return generateCsrTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, csrEnv, unsafeLocalNames: effectiveUnsafeLocalNames, deferredChildSlots, loopDepth: -1 });
|
|
4217
4224
|
}
|
|
4218
4225
|
function mergeCsrNullUnsafe(ctx, unsafeLocalNames) {
|
|
4219
4226
|
let merged = null;
|
|
@@ -4278,6 +4285,8 @@ function computeDeferredChildSlots(node, ctx, inlinableConstants, unsafeLocalNam
|
|
|
4278
4285
|
const dropped = n.props.some((p) => {
|
|
4279
4286
|
if (p.name === "..." || p.name.startsWith("...") || p.name === "key")
|
|
4280
4287
|
return false;
|
|
4288
|
+
if (p.name === "ref")
|
|
4289
|
+
return false;
|
|
4281
4290
|
if (p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())
|
|
4282
4291
|
return false;
|
|
4283
4292
|
if (p.clientOnly)
|
|
@@ -4307,7 +4316,7 @@ function computeDeferredChildSlots(node, ctx, inlinableConstants, unsafeLocalNam
|
|
|
4307
4316
|
return deferred;
|
|
4308
4317
|
}
|
|
4309
4318
|
function generateCsrTemplateWithOpts(node, opts) {
|
|
4310
|
-
const { restSpreadNames, propsObjectName, csrEnv,
|
|
4319
|
+
const { restSpreadNames, propsObjectName, csrEnv, unsafeLocalNames, loopDepth = 0 } = opts;
|
|
4311
4320
|
const env = csrEnv ?? { substitutions: new Map, propsObjectName: propsObjectName ?? null };
|
|
4312
4321
|
const transformExpr = (expr, templateExpr) => {
|
|
4313
4322
|
const source = templateExpr ?? expr;
|
|
@@ -4321,7 +4330,6 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4321
4330
|
};
|
|
4322
4331
|
const recurse = (n) => generateCsrTemplateWithOpts(n, opts);
|
|
4323
4332
|
const childrenRecurse = (n) => generateCsrTemplateWithOpts(n, { ...opts, inHoistedChildren: false });
|
|
4324
|
-
const recurseInLoop = (n) => generateCsrTemplateWithOpts(n, { ...opts, insideLoop: true, loopDepth: loopDepth + 1, inHoistedChildren: false });
|
|
4325
4333
|
switch (node.type) {
|
|
4326
4334
|
case "element": {
|
|
4327
4335
|
const mergeCtx = {
|
|
@@ -4414,7 +4422,7 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4414
4422
|
if (node.slotId && opts.deferredChildSlots?.has(node.slotId)) {
|
|
4415
4423
|
return `<div ${DATA_BF_PH}="${node.slotId}"></div>`;
|
|
4416
4424
|
}
|
|
4417
|
-
const propsEntries = node.props.filter((p) => p.name !== "..." && !p.name.startsWith("...") && p.name !== "key").filter((p) => !(p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())).map((p) => {
|
|
4425
|
+
const propsEntries = node.props.filter((p) => p.name !== "..." && !p.name.startsWith("...") && p.name !== "key").filter((p) => p.name !== "ref" && !(p.name.startsWith("on") && p.name.length > 2 && p.name[2] === p.name[2].toUpperCase())).map((p) => {
|
|
4418
4426
|
if (p.clientOnly)
|
|
4419
4427
|
return null;
|
|
4420
4428
|
switch (p.value.kind) {
|
|
@@ -4452,7 +4460,7 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4452
4460
|
const propsExpr = propsEntries.length > 0 ? `{${propsEntries.join(", ")}}` : "{}";
|
|
4453
4461
|
const keyProp = node.props.find((p) => p.name === "key");
|
|
4454
4462
|
const keyArg = keyProp ? `, ${transformKeyValue(keyProp.value, transformExpr)}` : "";
|
|
4455
|
-
const slotArg =
|
|
4463
|
+
const slotArg = derivesScopeFromSlot(node) ? `, '${node.slotId}'` : "";
|
|
4456
4464
|
return `\${renderChild('${nameForRegistryRef(node.name)}', ${propsExpr}${keyArg || (slotArg ? ", undefined" : "")}${slotArg})}`;
|
|
4457
4465
|
}
|
|
4458
4466
|
case "loop": {
|
|
@@ -4471,7 +4479,6 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4471
4479
|
};
|
|
4472
4480
|
const recurseInLoopBody = (n) => generateCsrTemplateWithOpts(n, {
|
|
4473
4481
|
...opts,
|
|
4474
|
-
insideLoop: true,
|
|
4475
4482
|
loopDepth: loopDepth + 1,
|
|
4476
4483
|
inHoistedChildren: false,
|
|
4477
4484
|
loopBoundNames: boundHere,
|
|
@@ -4948,6 +4955,30 @@ function typeNodeToTypeInfo(typeNode, sourceFile, rawOf) {
|
|
|
4948
4955
|
if (ts7.isArrayTypeNode(typeNode)) {
|
|
4949
4956
|
return { kind: "array", raw, elementType: recurse(typeNode.elementType) };
|
|
4950
4957
|
}
|
|
4958
|
+
if (ts7.isLiteralTypeNode(typeNode)) {
|
|
4959
|
+
const lit = typeNode.literal;
|
|
4960
|
+
if (ts7.isStringLiteral(lit) || ts7.isNoSubstitutionTemplateLiteral(lit)) {
|
|
4961
|
+
return { kind: "primitive", raw, primitive: "string", literalValue: lit.text };
|
|
4962
|
+
}
|
|
4963
|
+
if (ts7.isNumericLiteral(lit)) {
|
|
4964
|
+
return { kind: "primitive", raw, primitive: "number", literalValue: lit.text };
|
|
4965
|
+
}
|
|
4966
|
+
if (ts7.isPrefixUnaryExpression(lit) && lit.operator === ts7.SyntaxKind.MinusToken && ts7.isNumericLiteral(lit.operand)) {
|
|
4967
|
+
return { kind: "primitive", raw, primitive: "number", literalValue: `-${lit.operand.text}` };
|
|
4968
|
+
}
|
|
4969
|
+
if (lit.kind === ts7.SyntaxKind.TrueKeyword || lit.kind === ts7.SyntaxKind.FalseKeyword) {
|
|
4970
|
+
return {
|
|
4971
|
+
kind: "primitive",
|
|
4972
|
+
raw,
|
|
4973
|
+
primitive: "boolean",
|
|
4974
|
+
literalValue: lit.kind === ts7.SyntaxKind.TrueKeyword ? "true" : "false"
|
|
4975
|
+
};
|
|
4976
|
+
}
|
|
4977
|
+
if (lit.kind === ts7.SyntaxKind.NullKeyword) {
|
|
4978
|
+
return { kind: "primitive", raw, primitive: "null" };
|
|
4979
|
+
}
|
|
4980
|
+
return { kind: "unknown", raw };
|
|
4981
|
+
}
|
|
4951
4982
|
if (ts7.isUnionTypeNode(typeNode)) {
|
|
4952
4983
|
return { kind: "union", raw, unionTypes: typeNode.types.map(recurse) };
|
|
4953
4984
|
}
|
|
@@ -5515,9 +5546,7 @@ function baseTypeName(raw) {
|
|
|
5515
5546
|
return (idx === -1 ? raw : raw.slice(0, idx)).trim();
|
|
5516
5547
|
}
|
|
5517
5548
|
function isNullishArm(t) {
|
|
5518
|
-
|
|
5519
|
-
return true;
|
|
5520
|
-
return t.kind === "unknown" && (t.raw === "null" || t.raw === "undefined");
|
|
5549
|
+
return t.kind === "primitive" && (t.primitive === "null" || t.primitive === "undefined");
|
|
5521
5550
|
}
|
|
5522
5551
|
function stripUnion(type) {
|
|
5523
5552
|
if (!type || type.kind !== "union" || !type.unionTypes)
|
|
@@ -6236,14 +6265,17 @@ function collectSignal(node, ctx) {
|
|
|
6236
6265
|
const pattern = node.name;
|
|
6237
6266
|
const callExpr = node.initializer;
|
|
6238
6267
|
const elements = pattern.elements;
|
|
6239
|
-
|
|
6268
|
+
const getterElided = elements.length === 2 && ts8.isOmittedExpression(elements[0]);
|
|
6269
|
+
if (elements.length < 1 || elements.length > 2 || !getterElided && (!ts8.isBindingElement(elements[0]) || !ts8.isIdentifier(elements[0].name))) {
|
|
6240
6270
|
return;
|
|
6241
6271
|
}
|
|
6242
6272
|
if (elements.length === 2 && (!ts8.isBindingElement(elements[1]) || !ts8.isIdentifier(elements[1].name))) {
|
|
6243
6273
|
return;
|
|
6244
6274
|
}
|
|
6245
|
-
const getter = elements[0].name.text;
|
|
6246
6275
|
const setter = elements.length === 2 && ts8.isBindingElement(elements[1]) && ts8.isIdentifier(elements[1].name) ? elements[1].name.text : null;
|
|
6276
|
+
if (getterElided && !setter)
|
|
6277
|
+
return;
|
|
6278
|
+
const getter = getterElided ? `__bfGet_${setter}` : elements[0].name.text;
|
|
6247
6279
|
const initialValue = callExpr.arguments[0] ? ctx.getJS(callExpr.arguments[0]) : "";
|
|
6248
6280
|
const typedInitialValue = callExpr.arguments[0] ? callExpr.arguments[0].getText(ctx.sourceFile) : undefined;
|
|
6249
6281
|
let type = { kind: "unknown", raw: "unknown" };
|
|
@@ -6264,6 +6296,7 @@ function collectSignal(node, ctx) {
|
|
|
6264
6296
|
ctx.signals.push({
|
|
6265
6297
|
getter,
|
|
6266
6298
|
setter,
|
|
6299
|
+
getterElided: getterElided || undefined,
|
|
6267
6300
|
initialValue,
|
|
6268
6301
|
typedInitialValue: typedInitialValue !== initialValue ? typedInitialValue : undefined,
|
|
6269
6302
|
templateInitialValue,
|
|
@@ -6454,9 +6487,17 @@ function collectMemo(node, ctx) {
|
|
|
6454
6487
|
const blockBody = arrowNode && ts8.isArrowFunction(arrowNode) && ts8.isBlock(arrowNode.body) ? arrowNode.body : undefined;
|
|
6455
6488
|
const parsedBlock = blockBody ? parseBlockBodyTolerant(blockBody, ctx.sourceFile, (node2) => ctx.getJS(node2)) : undefined;
|
|
6456
6489
|
const parsedBlockComplete = parsedBlock && blockBody ? parsedBlock.length === blockBody.statements.length : undefined;
|
|
6490
|
+
let templateComputation;
|
|
6491
|
+
if (!ctx.propsObjectName && callExpr.arguments[0]) {
|
|
6492
|
+
const propNames = new Set(ctx.propsParams.map((p) => p.name));
|
|
6493
|
+
if (propNames.size > 0) {
|
|
6494
|
+
templateComputation = rewriteBarePropRefs(computation, callExpr.arguments[0], propNames);
|
|
6495
|
+
}
|
|
6496
|
+
}
|
|
6457
6497
|
ctx.memos.push({
|
|
6458
6498
|
name,
|
|
6459
6499
|
computation,
|
|
6500
|
+
templateComputation,
|
|
6460
6501
|
parsedBlock,
|
|
6461
6502
|
parsedBlockComplete,
|
|
6462
6503
|
typedComputation: typedComputation !== computation ? typedComputation : undefined,
|
|
@@ -9677,8 +9718,10 @@ function deriveFormat(locale, probeOptions) {
|
|
|
9677
9718
|
return { pattern, names };
|
|
9678
9719
|
}
|
|
9679
9720
|
function unionMemberLiteral(member) {
|
|
9680
|
-
|
|
9681
|
-
|
|
9721
|
+
if (member.kind === "primitive" && member.primitive === "string" && member.literalValue !== undefined) {
|
|
9722
|
+
return member.literalValue;
|
|
9723
|
+
}
|
|
9724
|
+
return null;
|
|
9682
9725
|
}
|
|
9683
9726
|
function resolveLocaleUnionMembers(locale, metadata) {
|
|
9684
9727
|
let sourcePropName = null;
|
|
@@ -10284,6 +10327,13 @@ function jsxToIR(analyzer) {
|
|
|
10284
10327
|
function buildIRRoot(analyzer) {
|
|
10285
10328
|
if (analyzer.conditionalReturns.length > 0) {
|
|
10286
10329
|
const ctx2 = createTransformContext(analyzer);
|
|
10330
|
+
const allReactiveNoLocals = analyzer.jsxReturn != null && analyzer.conditionalReturns.every((cr) => cr.scopeVariables.length === 0 && exprCallsReactiveGetters(cr.condition, ctx2));
|
|
10331
|
+
if (allReactiveNoLocals) {
|
|
10332
|
+
const chain = buildIfStatementChain(analyzer, ctx2, { asConditional: true });
|
|
10333
|
+
if (!chain)
|
|
10334
|
+
return null;
|
|
10335
|
+
return chain.type === "conditional" ? wrapInScopeElement(chain) : chain;
|
|
10336
|
+
}
|
|
10287
10337
|
return buildIfStatementChain(analyzer, ctx2);
|
|
10288
10338
|
}
|
|
10289
10339
|
if (!analyzer.jsxReturn)
|
|
@@ -10439,11 +10489,52 @@ function transformJsxElement(node, ctx) {
|
|
|
10439
10489
|
}
|
|
10440
10490
|
return transformHtmlElement(node, ctx, tagName);
|
|
10441
10491
|
}
|
|
10492
|
+
function lowerFormControlValueSsr(tagName, attrs, children) {
|
|
10493
|
+
if (tagName !== "textarea" && tagName !== "select")
|
|
10494
|
+
return;
|
|
10495
|
+
const valueAttr = attrs.find((a) => a.name === "value");
|
|
10496
|
+
if (!valueAttr || valueAttr.clientOnly || valueAttr.value.kind !== "expression")
|
|
10497
|
+
return;
|
|
10498
|
+
const { expr, templateExpr } = valueAttr.value;
|
|
10499
|
+
valueAttr.clientOnly = true;
|
|
10500
|
+
if (tagName === "textarea") {
|
|
10501
|
+
if (children.length > 0)
|
|
10502
|
+
return;
|
|
10503
|
+
children.push({
|
|
10504
|
+
type: "expression",
|
|
10505
|
+
expr,
|
|
10506
|
+
templateExpr: `escapeText(${templateExpr ?? expr})`,
|
|
10507
|
+
typeInfo: null,
|
|
10508
|
+
reactive: false,
|
|
10509
|
+
slotId: null,
|
|
10510
|
+
loc: valueAttr.loc,
|
|
10511
|
+
origin: { phase: "ssr", scope: "template", effect: "pure" }
|
|
10512
|
+
});
|
|
10513
|
+
return;
|
|
10514
|
+
}
|
|
10515
|
+
const selectedFor = (optValue) => AttrValueOf.expression(`(${expr}) === ${JSON.stringify(optValue)}`, templateExpr !== undefined ? { templateExpr: `(${templateExpr}) === ${JSON.stringify(optValue)}` } : undefined);
|
|
10516
|
+
const distribute = (nodes) => {
|
|
10517
|
+
for (const n of nodes) {
|
|
10518
|
+
if (n.type === "element" && n.tag === "option") {
|
|
10519
|
+
if (n.attrs.some((a) => a.name === "selected"))
|
|
10520
|
+
continue;
|
|
10521
|
+
const optValue = n.attrs.find((a) => a.name === "value");
|
|
10522
|
+
if (!optValue || optValue.value.kind !== "literal")
|
|
10523
|
+
continue;
|
|
10524
|
+
n.attrs.push({ name: "selected", value: selectedFor(optValue.value.value), loc: n.loc });
|
|
10525
|
+
} else if (n.type === "fragment" || n.type === "element" && n.tag === "optgroup") {
|
|
10526
|
+
distribute(n.children);
|
|
10527
|
+
}
|
|
10528
|
+
}
|
|
10529
|
+
};
|
|
10530
|
+
distribute(children);
|
|
10531
|
+
}
|
|
10442
10532
|
function transformHtmlElement(node, ctx, tagName) {
|
|
10443
10533
|
const { attrs, events, ref } = processAttributes(node.openingElement.attributes, ctx);
|
|
10444
10534
|
const needsScope = ctx.isRoot;
|
|
10445
10535
|
ctx.isRoot = false;
|
|
10446
10536
|
const children = transformChildren(node.children, ctx);
|
|
10537
|
+
lowerFormControlValueSsr(tagName, attrs, children);
|
|
10447
10538
|
const needsSlot = events.length > 0 || hasDynamicContent(children) || hasReactiveAttributes(attrs, ctx) || ref !== null;
|
|
10448
10539
|
const slotId = needsSlot ? generateSlotId(ctx) : null;
|
|
10449
10540
|
if (slotId) {
|
|
@@ -10475,6 +10566,8 @@ function transformSelfClosingElement(node, ctx) {
|
|
|
10475
10566
|
return transformSelfClosingComponent(node, ctx, resolved ?? tagName);
|
|
10476
10567
|
}
|
|
10477
10568
|
const { attrs, events, ref } = processAttributes(node.attributes, ctx);
|
|
10569
|
+
const selfClosingChildren = [];
|
|
10570
|
+
lowerFormControlValueSsr(tagName, attrs, selfClosingChildren);
|
|
10478
10571
|
const needsSlot = events.length > 0 || hasReactiveAttributes(attrs, ctx) || ref !== null;
|
|
10479
10572
|
const slotId = needsSlot ? generateSlotId(ctx) : null;
|
|
10480
10573
|
const needsScope = ctx.isRoot;
|
|
@@ -10485,7 +10578,7 @@ function transformSelfClosingElement(node, ctx) {
|
|
|
10485
10578
|
attrs,
|
|
10486
10579
|
events,
|
|
10487
10580
|
ref,
|
|
10488
|
-
children:
|
|
10581
|
+
children: selfClosingChildren,
|
|
10489
10582
|
slotId,
|
|
10490
10583
|
needsScope,
|
|
10491
10584
|
loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
|
|
@@ -11868,6 +11961,15 @@ function branchHasNoElement(node) {
|
|
|
11868
11961
|
}
|
|
11869
11962
|
return true;
|
|
11870
11963
|
}
|
|
11964
|
+
function tagLoopItemRootComponents(nodes) {
|
|
11965
|
+
for (const node of nodes) {
|
|
11966
|
+
if (node.type === "component") {
|
|
11967
|
+
node.loopItemRoot = true;
|
|
11968
|
+
} else if (node.type === "conditional") {
|
|
11969
|
+
tagLoopItemRootComponents([node.whenTrue, node.whenFalse]);
|
|
11970
|
+
}
|
|
11971
|
+
}
|
|
11972
|
+
}
|
|
11871
11973
|
function loopBodyItemConditional(children) {
|
|
11872
11974
|
const real = children.filter((c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim()));
|
|
11873
11975
|
if (real.length !== 1)
|
|
@@ -12105,9 +12207,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
12105
12207
|
const pre = multiReturn.preamble ?? [];
|
|
12106
12208
|
if (pre.length > 0) {
|
|
12107
12209
|
preamble = preambleFromValueStatements(pre, ctx);
|
|
12108
|
-
if (!isClientOnly && !(ctx.analyzer.acceptsCallbackBody?.("map") ?? false)) {
|
|
12210
|
+
if (!preamble.declarations && !isClientOnly && !(ctx.analyzer.acceptsCallbackBody?.("map") ?? false)) {
|
|
12109
12211
|
ctx.analyzer.errors.push(createError(ErrorCodes.UNSUPPORTED_JSX_PATTERN, loc, {
|
|
12110
|
-
message: "A .map() callback body with a
|
|
12212
|
+
message: "A .map() callback body with a preamble before its branches cannot be " + "lowered to a template: the preamble is not a sequence of value " + "declarations, so this backend has no per-row local to carry into the " + "branches.",
|
|
12111
12213
|
suggestion: {
|
|
12112
12214
|
message: "Add /* @client */ to evaluate this expression on the client only"
|
|
12113
12215
|
}
|
|
@@ -12174,6 +12276,14 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
12174
12276
|
}
|
|
12175
12277
|
if (valueStmts.length > 0) {
|
|
12176
12278
|
preamble = preambleFromValueStatements(valueStmts, ctx);
|
|
12279
|
+
if (!preamble.declarations && !isClientOnly && !(ctx.analyzer.acceptsCallbackBody?.("map") ?? false)) {
|
|
12280
|
+
ctx.analyzer.errors.push(createError(ErrorCodes.UNSUPPORTED_JSX_PATTERN, getSourceLocation(body, ctx.sourceFile, ctx.filePath), {
|
|
12281
|
+
message: "A .map() callback preamble that is not a sequence of value " + "declarations cannot be lowered to a template: this backend can " + "declare a per-row local, but cannot run arbitrary statements per row.",
|
|
12282
|
+
suggestion: {
|
|
12283
|
+
message: "Add /* @client */ to evaluate this expression on the client only"
|
|
12284
|
+
}
|
|
12285
|
+
}));
|
|
12286
|
+
}
|
|
12177
12287
|
}
|
|
12178
12288
|
}
|
|
12179
12289
|
}
|
|
@@ -12259,6 +12369,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
12259
12369
|
}));
|
|
12260
12370
|
preamble = undefined;
|
|
12261
12371
|
}
|
|
12372
|
+
tagLoopItemRootComponents(children);
|
|
12262
12373
|
let childComponent;
|
|
12263
12374
|
if (children.length === 1 && children[0].type === "component") {
|
|
12264
12375
|
const comp = children[0];
|
|
@@ -12279,6 +12390,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
12279
12390
|
const isDirectPropArray = method !== "flatMap" && isArrayExprDirectPropRef(arrayExpr, ctx);
|
|
12280
12391
|
const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls && !objectIteration;
|
|
12281
12392
|
const preambleRegions = preamble && !isStaticArray ? collectPreambleRegions(children, new Set(preamble.declaredNames), ctx) : undefined;
|
|
12393
|
+
if (preamble && !isStaticArray) {
|
|
12394
|
+
markPreambleAttrSlots(children, new Set(preamble.declaredNames), ctx);
|
|
12395
|
+
}
|
|
12282
12396
|
const nestedComponents = collectNestedComponents(children).filter((c) => c.name !== childComponent?.name);
|
|
12283
12397
|
return {
|
|
12284
12398
|
type: "loop",
|
|
@@ -12503,6 +12617,52 @@ function collectPreambleRegions(nodes, declared, ctx) {
|
|
|
12503
12617
|
visit2(nodes);
|
|
12504
12618
|
return regions;
|
|
12505
12619
|
}
|
|
12620
|
+
function markPreambleAttrSlots(nodes, declared, ctx) {
|
|
12621
|
+
const readsDeclared = (attr) => {
|
|
12622
|
+
if (attr.name === "key")
|
|
12623
|
+
return false;
|
|
12624
|
+
const value = attr.value;
|
|
12625
|
+
if (value.kind !== "expression" && value.kind !== "template")
|
|
12626
|
+
return false;
|
|
12627
|
+
const refs = attr.freeIdentifiers ?? extractFreeIdentifiersFromText(attrValueText(value));
|
|
12628
|
+
for (const r of refs)
|
|
12629
|
+
if (declared.has(r))
|
|
12630
|
+
return true;
|
|
12631
|
+
return false;
|
|
12632
|
+
};
|
|
12633
|
+
const visit2 = (list) => {
|
|
12634
|
+
for (const node of list) {
|
|
12635
|
+
switch (node.type) {
|
|
12636
|
+
case "element":
|
|
12637
|
+
if (!node.slotId && node.attrs.some(readsDeclared))
|
|
12638
|
+
node.slotId = generateSlotId(ctx);
|
|
12639
|
+
visit2(node.children);
|
|
12640
|
+
break;
|
|
12641
|
+
case "fragment":
|
|
12642
|
+
visit2(node.children);
|
|
12643
|
+
break;
|
|
12644
|
+
case "conditional":
|
|
12645
|
+
visit2([node.whenTrue, ...node.whenFalse ? [node.whenFalse] : []]);
|
|
12646
|
+
break;
|
|
12647
|
+
}
|
|
12648
|
+
}
|
|
12649
|
+
};
|
|
12650
|
+
visit2(nodes);
|
|
12651
|
+
}
|
|
12652
|
+
function attrValueText(value) {
|
|
12653
|
+
if (value.kind === "expression")
|
|
12654
|
+
return value.expr;
|
|
12655
|
+
if (value.kind !== "template")
|
|
12656
|
+
return "";
|
|
12657
|
+
const out = [];
|
|
12658
|
+
for (const p of value.parts) {
|
|
12659
|
+
if (p.type === "ternary")
|
|
12660
|
+
out.push(p.condition, p.whenTrue, p.whenFalse);
|
|
12661
|
+
else if (p.type === "lookup")
|
|
12662
|
+
out.push(p.key);
|
|
12663
|
+
}
|
|
12664
|
+
return out.join(" ");
|
|
12665
|
+
}
|
|
12506
12666
|
function collectBindingNames(name, out) {
|
|
12507
12667
|
if (ts11.isIdentifier(name)) {
|
|
12508
12668
|
out.add(name.text);
|
|
@@ -12540,9 +12700,32 @@ function preambleFromValueStatements(statements, ctx) {
|
|
|
12540
12700
|
segments: trimPreambleSegments(segments),
|
|
12541
12701
|
ssrText: tsxSourceText(typedParts.join(" ")),
|
|
12542
12702
|
declaredNames: [...declared],
|
|
12543
|
-
builderNames: []
|
|
12703
|
+
builderNames: [],
|
|
12704
|
+
declarations: neutralPreambleDeclarations(statements, ctx) ?? undefined
|
|
12544
12705
|
};
|
|
12545
12706
|
}
|
|
12707
|
+
function neutralPreambleDeclarations(statements, ctx) {
|
|
12708
|
+
const out = [];
|
|
12709
|
+
for (const stmt of statements) {
|
|
12710
|
+
if (!ts11.isVariableStatement(stmt))
|
|
12711
|
+
return null;
|
|
12712
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
12713
|
+
if (!ts11.isIdentifier(decl.name))
|
|
12714
|
+
return null;
|
|
12715
|
+
if (!decl.initializer)
|
|
12716
|
+
return null;
|
|
12717
|
+
const valueParsed = tsNodeToParsedExpr(decl.initializer);
|
|
12718
|
+
if (!isSupported(valueParsed).supported)
|
|
12719
|
+
return null;
|
|
12720
|
+
out.push({
|
|
12721
|
+
name: decl.name.text,
|
|
12722
|
+
valueParsed,
|
|
12723
|
+
raw: decl.initializer.getText(ctx.sourceFile)
|
|
12724
|
+
});
|
|
12725
|
+
}
|
|
12726
|
+
}
|
|
12727
|
+
return out.length > 0 ? out : null;
|
|
12728
|
+
}
|
|
12546
12729
|
function trimPreambleSegments(segments) {
|
|
12547
12730
|
const last = segments[segments.length - 1];
|
|
12548
12731
|
if (last?.kind === "js") {
|
|
@@ -12988,6 +13171,9 @@ function tryResolveIdentifierAsTemplateLiteral(ident, ctx) {
|
|
|
12988
13171
|
if (ts11.isNoSubstitutionTemplateLiteral(ast) || ts11.isStringLiteral(ast)) {
|
|
12989
13172
|
return [{ type: "string", value: ast.text }];
|
|
12990
13173
|
}
|
|
13174
|
+
if (ts11.isElementAccessExpression(ast) && !ts11.isStringLiteralLike(ast.argumentExpression) && !ts11.isNumericLiteral(ast.argumentExpression)) {
|
|
13175
|
+
return tryResolveTemplateSpanFromConst(ast, ctx);
|
|
13176
|
+
}
|
|
12991
13177
|
if (!ts11.isTemplateExpression(ast))
|
|
12992
13178
|
return null;
|
|
12993
13179
|
let resolvedAny = false;
|
|
@@ -13235,8 +13421,11 @@ function processComponentProps(attributes, ctx) {
|
|
|
13235
13421
|
}
|
|
13236
13422
|
let value = getAttributeValue(attr, ctx);
|
|
13237
13423
|
if (value.kind === "template") {
|
|
13238
|
-
|
|
13239
|
-
|
|
13424
|
+
const collapsed = templatePartsToJsString(value.parts);
|
|
13425
|
+
const collapsedTemplate = templatePartsToJsString(value.parts, { useTemplate: true });
|
|
13426
|
+
value = AttrValueOf.expression(collapsed, {
|
|
13427
|
+
parts: value.parts,
|
|
13428
|
+
...collapsedTemplate !== collapsed && { templateExpr: collapsedTemplate }
|
|
13240
13429
|
});
|
|
13241
13430
|
} else if (value.kind === "boolean-attr") {
|
|
13242
13431
|
value = AttrValueOf.booleanShorthand();
|
|
@@ -13265,16 +13454,18 @@ function processComponentProps(attributes, ctx) {
|
|
|
13265
13454
|
}
|
|
13266
13455
|
return props;
|
|
13267
13456
|
}
|
|
13268
|
-
function templatePartsToJsString(parts) {
|
|
13457
|
+
function templatePartsToJsString(parts, opts) {
|
|
13269
13458
|
let result = "`";
|
|
13270
13459
|
for (const part of parts) {
|
|
13271
13460
|
if (part.type === "string") {
|
|
13272
|
-
result += part.value;
|
|
13461
|
+
result += opts?.useTemplate && part.templateValue ? part.templateValue : part.value;
|
|
13273
13462
|
} else if (part.type === "ternary") {
|
|
13274
|
-
|
|
13463
|
+
const cond = opts?.useTemplate && part.templateCondition ? part.templateCondition : part.condition;
|
|
13464
|
+
result += `\${${cond} ? '${part.whenTrue}' : '${part.whenFalse}'}`;
|
|
13275
13465
|
} else if (part.type === "lookup") {
|
|
13466
|
+
const key = opts?.useTemplate && part.templateKey ? part.templateKey : part.key;
|
|
13276
13467
|
const obj = "{" + Object.entries(part.cases).map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(", ") + "}";
|
|
13277
|
-
result += `\${(${obj})[${
|
|
13468
|
+
result += `\${(${obj})[${key}]}`;
|
|
13278
13469
|
}
|
|
13279
13470
|
}
|
|
13280
13471
|
result += "`";
|
|
@@ -13485,11 +13676,12 @@ function replaceBranchLocalRefs(text, branchNames, resolve2) {
|
|
|
13485
13676
|
const pattern = new RegExp(`(?<![\\w$])(${branchNames.join("|")})(?![\\w$])`, "g");
|
|
13486
13677
|
return replaceInExprContexts(text, pattern, (_match, name) => resolve2(name));
|
|
13487
13678
|
}
|
|
13488
|
-
function buildIfStatementChain(analyzer, ctx) {
|
|
13679
|
+
function buildIfStatementChain(analyzer, ctx, opts) {
|
|
13489
13680
|
const conditionalReturns = analyzer.conditionalReturns;
|
|
13681
|
+
const asConditional = opts?.asConditional === true;
|
|
13490
13682
|
let alternate = null;
|
|
13491
13683
|
if (analyzer.jsxReturn) {
|
|
13492
|
-
ctx.isRoot =
|
|
13684
|
+
ctx.isRoot = !asConditional;
|
|
13493
13685
|
alternate = transformNode(analyzer.jsxReturn, ctx);
|
|
13494
13686
|
}
|
|
13495
13687
|
for (let i = conditionalReturns.length - 1;i >= 0; i--) {
|
|
@@ -13558,7 +13750,7 @@ function buildIfStatementChain(analyzer, ctx) {
|
|
|
13558
13750
|
ctx.getJS = substitutedGetJS;
|
|
13559
13751
|
ctx.analyzer.getJS = substitutedGetJS;
|
|
13560
13752
|
}
|
|
13561
|
-
ctx.isRoot =
|
|
13753
|
+
ctx.isRoot = !asConditional;
|
|
13562
13754
|
let consequent;
|
|
13563
13755
|
try {
|
|
13564
13756
|
consequent = transformNode(condReturn.jsxReturn, ctx);
|
|
@@ -13588,6 +13780,27 @@ function buildIfStatementChain(analyzer, ctx) {
|
|
|
13588
13780
|
}
|
|
13589
13781
|
}
|
|
13590
13782
|
const loc = getSourceLocation(condReturn.ifStatement, analyzer.sourceFile, analyzer.filePath);
|
|
13783
|
+
if (asConditional && alternate) {
|
|
13784
|
+
const conditional = {
|
|
13785
|
+
type: "conditional",
|
|
13786
|
+
condition,
|
|
13787
|
+
templateCondition,
|
|
13788
|
+
conditionType: null,
|
|
13789
|
+
reactive: true,
|
|
13790
|
+
whenTrue: consequent,
|
|
13791
|
+
whenFalse: alternate,
|
|
13792
|
+
slotId: generateSlotId(ctx),
|
|
13793
|
+
loc,
|
|
13794
|
+
origin: {
|
|
13795
|
+
phase: "tick",
|
|
13796
|
+
scope: "template",
|
|
13797
|
+
effect: "pure",
|
|
13798
|
+
freeRefs: resolveFreeRefs(condReturn.condition, makeBindingEnv(ctx))
|
|
13799
|
+
}
|
|
13800
|
+
};
|
|
13801
|
+
alternate = conditional;
|
|
13802
|
+
continue;
|
|
13803
|
+
}
|
|
13591
13804
|
const ifStmt = {
|
|
13592
13805
|
type: "if-statement",
|
|
13593
13806
|
condition,
|
|
@@ -13901,7 +14114,13 @@ function collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings,
|
|
|
13901
14114
|
});
|
|
13902
14115
|
return texts;
|
|
13903
14116
|
}
|
|
13904
|
-
function
|
|
14117
|
+
function anyNameIn(names, set) {
|
|
14118
|
+
for (const n of names)
|
|
14119
|
+
if (set.has(n))
|
|
14120
|
+
return true;
|
|
14121
|
+
return false;
|
|
14122
|
+
}
|
|
14123
|
+
function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false, preambleNames) {
|
|
13905
14124
|
const attrs = [];
|
|
13906
14125
|
traverseElements(node, (el) => {
|
|
13907
14126
|
if (el.slotId) {
|
|
@@ -13916,7 +14135,8 @@ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings,
|
|
|
13916
14135
|
if (!valueStr)
|
|
13917
14136
|
continue;
|
|
13918
14137
|
const expanded = expandConstantForReactivity(valueStr, ctx, attr.freeIdentifiers);
|
|
13919
|
-
const
|
|
14138
|
+
const readsPreamble = preambleNames !== undefined && preambleNames.size > 0 && anyNameIn(expanded.freeIds ?? extractFreeIdentifiersFromText(expanded.expr), preambleNames);
|
|
14139
|
+
const reactive = classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || readsPreamble || attr.callsReactiveGetters || attr.hasFunctionCalls;
|
|
13920
14140
|
if (!attr.clientOnly && !reactive)
|
|
13921
14141
|
continue;
|
|
13922
14142
|
attrs.push({
|
|
@@ -13924,7 +14144,8 @@ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings,
|
|
|
13924
14144
|
attrName: attr.name,
|
|
13925
14145
|
expression: expanded.expr,
|
|
13926
14146
|
...pickAttrMetaFromIR(attr),
|
|
13927
|
-
...expanded.freeIds !== undefined && { freeIdentifiers: expanded.freeIds }
|
|
14147
|
+
...expanded.freeIds !== undefined && { freeIdentifiers: expanded.freeIds },
|
|
14148
|
+
...readsPreamble && { readsPreamble: true }
|
|
13928
14149
|
});
|
|
13929
14150
|
}
|
|
13930
14151
|
}
|
|
@@ -14220,10 +14441,11 @@ function collectInnerLoops(nodes, siblingOffsets, outerLoopParam, ctx, options)
|
|
|
14220
14441
|
const template = n.children.map((c) => irToPlaceholderTemplate(c, undefined, emitDepth, loopParamsForTemplate)).join("");
|
|
14221
14442
|
const refsOuter = outerLoopParam ? new RegExp(`\\b${outerLoopParam}\\b`).test(n.array) : false;
|
|
14222
14443
|
const bindings = emptyLoopChildBindings();
|
|
14444
|
+
const innerPreambleNames = preambleNamesOf(n);
|
|
14223
14445
|
if (ctx) {
|
|
14224
14446
|
for (const child of n.children) {
|
|
14225
14447
|
bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, n.param, n.paramBindings));
|
|
14226
|
-
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, n.param, n.paramBindings));
|
|
14448
|
+
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, n.param, n.paramBindings, false, innerPreambleNames));
|
|
14227
14449
|
bindings.refs.push(...collectLoopChildRefs(child));
|
|
14228
14450
|
}
|
|
14229
14451
|
}
|
|
@@ -14446,7 +14668,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
14446
14668
|
return;
|
|
14447
14669
|
const projectionInner = l.method === "flatMap" && l.children.length === 1 && l.children[0].type === "loop" ? l.children[0] : undefined;
|
|
14448
14670
|
const childHandlers = [];
|
|
14449
|
-
const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx, siblingOffsets, l.param, l.paramBindings);
|
|
14671
|
+
const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx, siblingOffsets, l.param, l.paramBindings, preambleNamesOf(l));
|
|
14450
14672
|
if (!projectionInner) {
|
|
14451
14673
|
for (const child of l.children) {
|
|
14452
14674
|
childHandlers.push(...collectEventHandlersFromIR(child));
|
|
@@ -14469,7 +14691,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
14469
14691
|
if (l.childComponent) {
|
|
14470
14692
|
template = "";
|
|
14471
14693
|
if (l.isStaticArray && l.children[0]) {
|
|
14472
|
-
staticItemTemplate = irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx), 0, undefined, undefined
|
|
14694
|
+
staticItemTemplate = irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx), 0, undefined, undefined);
|
|
14473
14695
|
}
|
|
14474
14696
|
} else if (l.children[0] && !projectionInner) {
|
|
14475
14697
|
const loopParamSpec = [{ param: l.param, bindings: l.paramBindings }];
|
|
@@ -14701,7 +14923,7 @@ function collectBranchLoops(node, ctx, siblingOffsets) {
|
|
|
14701
14923
|
} else {
|
|
14702
14924
|
childTemplate = n.children.map((c) => irToHtmlTemplate(c, undefined, 0, branchLoopParamSpec)).join("");
|
|
14703
14925
|
}
|
|
14704
|
-
const branchBindings = ctx && !projectionInner ? collectLoopChildBindings(n.children, ctx, siblingOffsets, n.param, n.paramBindings) : emptyLoopChildBindings();
|
|
14926
|
+
const branchBindings = ctx && !projectionInner ? collectLoopChildBindings(n.children, ctx, siblingOffsets, n.param, n.paramBindings, preambleNamesOf(n)) : emptyLoopChildBindings();
|
|
14705
14927
|
loops.push({
|
|
14706
14928
|
kind: "branch",
|
|
14707
14929
|
array: n.array,
|
|
@@ -14781,11 +15003,17 @@ function collectBranchConditionals(node, ctx, siblingOffsets) {
|
|
|
14781
15003
|
});
|
|
14782
15004
|
return result;
|
|
14783
15005
|
}
|
|
14784
|
-
function
|
|
15006
|
+
function preambleNamesOf(loop) {
|
|
15007
|
+
if (loop.isStaticArray)
|
|
15008
|
+
return;
|
|
15009
|
+
const declared = loop.preamble?.declaredNames;
|
|
15010
|
+
return declared && declared.length > 0 ? new Set(declared) : undefined;
|
|
15011
|
+
}
|
|
15012
|
+
function collectLoopChildBindings(children, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames) {
|
|
14785
15013
|
const bindings = emptyLoopChildBindings();
|
|
14786
15014
|
for (const child of children) {
|
|
14787
15015
|
bindings.events.push(...collectLoopChildEventsWithNesting(child));
|
|
14788
|
-
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, loopParam, loopParamBindings, true));
|
|
15016
|
+
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, loopParam, loopParamBindings, true, preambleNames));
|
|
14789
15017
|
bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, loopParam, loopParamBindings, true));
|
|
14790
15018
|
bindings.refs.push(...collectLoopChildRefs(child));
|
|
14791
15019
|
bindings.conditionals.push(...collectLoopChildConditionals(child, ctx, siblingOffsets, loopParam, loopParamBindings));
|
|
@@ -16399,7 +16627,7 @@ function emitRegistrationAndHydration(lines, ctx, _ir, graph, inlinability) {
|
|
|
16399
16627
|
}
|
|
16400
16628
|
} else {
|
|
16401
16629
|
const csrInlinableConstants = csrInlinableConstantsFromCtx(ctx);
|
|
16402
|
-
const templateHtml = generateCsrTemplate(_ir.root, csrInlinableConstants, ctx,
|
|
16630
|
+
const templateHtml = generateCsrTemplate(_ir.root, csrInlinableConstants, ctx, restSpreadNames, ctx.propsObjectName, unsafeLocalNames, ctx.deferredChildSlots);
|
|
16403
16631
|
if (templateHtml) {
|
|
16404
16632
|
defParts.push(`template: (${PROPS_PARAM}) => \`${templateHtml}\``);
|
|
16405
16633
|
}
|
|
@@ -16797,6 +17025,7 @@ function buildSignalPlan(signal, ctx, lookups) {
|
|
|
16797
17025
|
kind: "signal",
|
|
16798
17026
|
getter: signal.getter,
|
|
16799
17027
|
setter: signal.setter,
|
|
17028
|
+
getterElided: signal.getterElided,
|
|
16800
17029
|
initialValueExpr: "",
|
|
16801
17030
|
controlledEffect: null,
|
|
16802
17031
|
initializerOverride: `${factory}()`
|
|
@@ -16811,6 +17040,7 @@ function buildSignalPlan(signal, ctx, lookups) {
|
|
|
16811
17040
|
kind: "signal",
|
|
16812
17041
|
getter: signal.getter,
|
|
16813
17042
|
setter: signal.setter,
|
|
17043
|
+
getterElided: signal.getterElided,
|
|
16814
17044
|
initialValueExpr: resolveSignalInitialValue(signal, ctx, lookups),
|
|
16815
17045
|
controlledEffect,
|
|
16816
17046
|
branchCondition: signal.branchCondition,
|
|
@@ -16882,9 +17112,10 @@ function bfIdArg(bfId) {
|
|
|
16882
17112
|
return bfId ? `, ${JSON.stringify(bfId)}` : "";
|
|
16883
17113
|
}
|
|
16884
17114
|
function emitSignal(lines, plan) {
|
|
17115
|
+
const getterSlot = plan.getterElided ? "" : plan.getter;
|
|
16885
17116
|
if (plan.initializerOverride) {
|
|
16886
17117
|
if (plan.setter) {
|
|
16887
|
-
lines.push(` const [${
|
|
17118
|
+
lines.push(` const [${getterSlot}, ${plan.setter}] = ${plan.initializerOverride}`);
|
|
16888
17119
|
} else {
|
|
16889
17120
|
lines.push(` const [${plan.getter}] = ${plan.initializerOverride}`);
|
|
16890
17121
|
}
|
|
@@ -16893,9 +17124,9 @@ function emitSignal(lines, plan) {
|
|
|
16893
17124
|
const id = bfIdArg(plan.bfId);
|
|
16894
17125
|
if (plan.branchCondition) {
|
|
16895
17126
|
if (plan.setter) {
|
|
16896
|
-
lines.push(` let ${plan.getter}, ${plan.setter}`);
|
|
17127
|
+
lines.push(plan.getterElided ? ` let ${plan.setter}` : ` let ${plan.getter}, ${plan.setter}`);
|
|
16897
17128
|
lines.push(` if (${plan.branchCondition}) {`);
|
|
16898
|
-
lines.push(` ;[${
|
|
17129
|
+
lines.push(` ;[${getterSlot}, ${plan.setter}] = createSignal(${plan.initialValueExpr}${id})`);
|
|
16899
17130
|
lines.push(` }`);
|
|
16900
17131
|
} else {
|
|
16901
17132
|
lines.push(` let ${plan.getter}`);
|
|
@@ -16906,7 +17137,7 @@ function emitSignal(lines, plan) {
|
|
|
16906
17137
|
return;
|
|
16907
17138
|
}
|
|
16908
17139
|
if (plan.setter) {
|
|
16909
|
-
lines.push(` const [${
|
|
17140
|
+
lines.push(` const [${getterSlot}, ${plan.setter}] = createSignal(${plan.initialValueExpr}${id})`);
|
|
16910
17141
|
} else {
|
|
16911
17142
|
lines.push(` const [${plan.getter}] = createSignal(${plan.initialValueExpr}${id})`);
|
|
16912
17143
|
}
|
|
@@ -17485,7 +17716,7 @@ function emitComponentAndEventSetup(ls, indent, elVar, comps, events, loopParam,
|
|
|
17485
17716
|
// src/ir-to-client-js/plan/build-static-array-child-init.ts
|
|
17486
17717
|
function staticPreludeStatements(preamble) {
|
|
17487
17718
|
return preamble ? [renderPreamble(preamble, {
|
|
17488
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined
|
|
17719
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
|
|
17489
17720
|
})] : [];
|
|
17490
17721
|
}
|
|
17491
17722
|
function buildStaticArrayChildInitsPlan(ctx) {
|
|
@@ -18040,7 +18271,8 @@ function buildReactiveEffectsPlan(args) {
|
|
|
18040
18271
|
attrs: slotAttrs.map((attr) => ({
|
|
18041
18272
|
attrName: attr.attrName,
|
|
18042
18273
|
wrappedExpression: wrap(attr.expression),
|
|
18043
|
-
meta: pickAttrMeta(attr)
|
|
18274
|
+
meta: pickAttrMeta(attr),
|
|
18275
|
+
...attr.readsPreamble && { readsPreamble: true }
|
|
18044
18276
|
}))
|
|
18045
18277
|
});
|
|
18046
18278
|
}
|
|
@@ -18240,7 +18472,7 @@ function buildReactiveEmit(inner, level, wrapOuter, uidSuffix, outerLoopParam, o
|
|
|
18240
18472
|
] : [{ param: inner.param, bindings: inner.paramBindings }];
|
|
18241
18473
|
preludeStatements.push(renderPreamble(inner.preamble, {
|
|
18242
18474
|
transformJs: (t) => wrapInner(wrapOuter(t)),
|
|
18243
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, leafLoopParams, undefined
|
|
18475
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, leafLoopParams, undefined)
|
|
18244
18476
|
}));
|
|
18245
18477
|
}
|
|
18246
18478
|
const childRefs = buildChildRefBindings(inner.bindings.refs, inner.param, inner.paramBindings);
|
|
@@ -18266,7 +18498,7 @@ function buildStaticEmit(inner, level, uidSuffix) {
|
|
|
18266
18498
|
preludeStatements.push(indexAlias);
|
|
18267
18499
|
if (inner.preamble) {
|
|
18268
18500
|
preludeStatements.push(renderPreamble(inner.preamble, {
|
|
18269
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined
|
|
18501
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
|
|
18270
18502
|
}));
|
|
18271
18503
|
}
|
|
18272
18504
|
return {
|
|
@@ -18298,7 +18530,7 @@ function buildTopLevelCompositePlan(elem, profileComponentName) {
|
|
|
18298
18530
|
indexParam: elem.index || "__idx",
|
|
18299
18531
|
mapPreambleWrapped: elem.preamble ? renderPreamble(elem.preamble, {
|
|
18300
18532
|
transformJs: wrap,
|
|
18301
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined
|
|
18533
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined)
|
|
18302
18534
|
}) : "",
|
|
18303
18535
|
template: elem.template,
|
|
18304
18536
|
outerComps: filterCondCompsOut(outerCompsByDepth, elem.bindings.conditionals),
|
|
@@ -18348,7 +18580,7 @@ function buildBranchCompositePlan(loop, cv, profileComponentName) {
|
|
|
18348
18580
|
indexParam: loop.index || "__idx",
|
|
18349
18581
|
mapPreambleWrapped: loop.preamble ? renderPreamble(loop.preamble, {
|
|
18350
18582
|
transformJs: wrap,
|
|
18351
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined
|
|
18583
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined)
|
|
18352
18584
|
}) : "",
|
|
18353
18585
|
template: loop.template,
|
|
18354
18586
|
outerComps: filterCondCompsOut(outerCompsByDepth, loop.bindings.conditionals),
|
|
@@ -18413,7 +18645,7 @@ function buildDynamicLoopDelegationPlan(elem, profileComponentName) {
|
|
|
18413
18645
|
key: elem.key,
|
|
18414
18646
|
index: elem.index,
|
|
18415
18647
|
mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
|
|
18416
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined
|
|
18648
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
|
|
18417
18649
|
}) : null,
|
|
18418
18650
|
mapPreambleDeclaredNames: elem.preamble?.declaredNames ?? []
|
|
18419
18651
|
})
|
|
@@ -18432,7 +18664,7 @@ function buildBranchLoopDelegationPlan(loop, cv, profileComponentName) {
|
|
|
18432
18664
|
key: loop.key,
|
|
18433
18665
|
index: loop.index,
|
|
18434
18666
|
mapPreamble: loop.preamble ? renderPreamble(loop.preamble, {
|
|
18435
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined
|
|
18667
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
|
|
18436
18668
|
}) : null,
|
|
18437
18669
|
mapPreambleDeclaredNames: loop.preamble?.declaredNames ?? []
|
|
18438
18670
|
})
|
|
@@ -18449,7 +18681,7 @@ function buildStaticArrayDelegationPlan(elem, profileComponentName) {
|
|
|
18449
18681
|
arrayExpr: buildChainedArrayExpr(elem),
|
|
18450
18682
|
param: elem.param,
|
|
18451
18683
|
mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
|
|
18452
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined
|
|
18684
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
|
|
18453
18685
|
}) : null,
|
|
18454
18686
|
mapPreambleDeclaredNames: elem.preamble?.declaredNames ?? [],
|
|
18455
18687
|
offset: elem.offset ?? null,
|
|
@@ -18484,6 +18716,181 @@ function buildKeyedOrIndexLookup(args) {
|
|
|
18484
18716
|
};
|
|
18485
18717
|
}
|
|
18486
18718
|
|
|
18719
|
+
// src/ir-to-client-js/control-flow/plan/lazy-conditional.ts
|
|
18720
|
+
var NO = (reason) => ({ lazySafe: false, reason });
|
|
18721
|
+
function wiringOn(branch) {
|
|
18722
|
+
const found = [];
|
|
18723
|
+
if (branch.childComponents.length > 0)
|
|
18724
|
+
found.push("child components");
|
|
18725
|
+
if (branch.innerLoops && branch.innerLoops.length > 0)
|
|
18726
|
+
found.push("an inner loop");
|
|
18727
|
+
if (branch.conditionals && branch.conditionals.length > 0)
|
|
18728
|
+
found.push("a nested conditional");
|
|
18729
|
+
if (branch.events && branch.events.length > 0)
|
|
18730
|
+
found.push("events");
|
|
18731
|
+
if (branch.reactiveAttrs && branch.reactiveAttrs.length > 0)
|
|
18732
|
+
found.push("reactive attrs");
|
|
18733
|
+
if (branch.reactiveTexts && branch.reactiveTexts.length > 0)
|
|
18734
|
+
found.push("reactive text");
|
|
18735
|
+
return found;
|
|
18736
|
+
}
|
|
18737
|
+
function analyzeLazyConditional(cond, indexParam, arms) {
|
|
18738
|
+
for (const [label, branch] of [["true", cond.whenTrue], ["false", cond.whenFalse]]) {
|
|
18739
|
+
const wiring = wiringOn(branch);
|
|
18740
|
+
if (wiring.length > 0) {
|
|
18741
|
+
return NO(`conditional on slot ${cond.slotId}: its ${label} arm owns ${wiring.join(" + ")}`);
|
|
18742
|
+
}
|
|
18743
|
+
}
|
|
18744
|
+
for (const [label, html] of [["true", arms.whenTrueHtml], ["false", arms.whenFalseHtml]]) {
|
|
18745
|
+
if (html.includes("bf-cond-start:")) {
|
|
18746
|
+
return NO(`conditional on slot ${cond.slotId}: its ${label} arm is a fragment conditional`);
|
|
18747
|
+
}
|
|
18748
|
+
if (!html.includes(`bf-c="${cond.slotId}"`)) {
|
|
18749
|
+
return NO(`conditional on slot ${cond.slotId}: its ${label} arm has no single bf-c root`);
|
|
18750
|
+
}
|
|
18751
|
+
if (html.includes("${")) {
|
|
18752
|
+
return NO(`conditional on slot ${cond.slotId}: its ${label} arm interpolates a value`);
|
|
18753
|
+
}
|
|
18754
|
+
}
|
|
18755
|
+
if (!cond.conditionFreeIdentifiers) {
|
|
18756
|
+
return NO(`conditional on slot ${cond.slotId}: condition has no analyzable identifier set`);
|
|
18757
|
+
}
|
|
18758
|
+
if (cond.conditionFreeIdentifiers.has(indexParam)) {
|
|
18759
|
+
return NO(`conditional on slot ${cond.slotId}: condition reads the loop index parameter '${indexParam}'`);
|
|
18760
|
+
}
|
|
18761
|
+
return {
|
|
18762
|
+
lazySafe: true,
|
|
18763
|
+
facts: {
|
|
18764
|
+
slotId: cond.slotId,
|
|
18765
|
+
condition: cond.condition,
|
|
18766
|
+
whenTrueHtml: arms.whenTrueHtml,
|
|
18767
|
+
whenFalseHtml: arms.whenFalseHtml
|
|
18768
|
+
}
|
|
18769
|
+
};
|
|
18770
|
+
}
|
|
18771
|
+
|
|
18772
|
+
// src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
|
|
18773
|
+
import ts15 from "typescript";
|
|
18774
|
+
var NO_PREAMBLE = {
|
|
18775
|
+
lazySafe: true,
|
|
18776
|
+
facts: { declaredNames: new Set, freeNames: new Set }
|
|
18777
|
+
};
|
|
18778
|
+
var NO2 = (reason) => ({ lazySafe: false, reason });
|
|
18779
|
+
function analyzeLazyPreamble(preamble, indexParam, primableNames) {
|
|
18780
|
+
if (!preamble)
|
|
18781
|
+
return NO_PREAMBLE;
|
|
18782
|
+
if (preamble.builderNames.length > 0) {
|
|
18783
|
+
return NO2(`map-callback preamble accumulates JSX leaves (${preamble.builderNames.join(", ")})`);
|
|
18784
|
+
}
|
|
18785
|
+
for (const seg of preamble.segments) {
|
|
18786
|
+
if (seg.kind !== "js")
|
|
18787
|
+
return NO2("map-callback preamble contains a JSX leaf");
|
|
18788
|
+
}
|
|
18789
|
+
const text = preambleAnalysisText(preamble);
|
|
18790
|
+
if (text.trim().length === 0)
|
|
18791
|
+
return NO_PREAMBLE;
|
|
18792
|
+
const declaredNames = new Set;
|
|
18793
|
+
const sf = ts15.createSourceFile("__lazy_preamble__.ts", text, ts15.ScriptTarget.Latest, true, ts15.ScriptKind.TS);
|
|
18794
|
+
for (const stmt of sf.statements) {
|
|
18795
|
+
if (!ts15.isVariableStatement(stmt)) {
|
|
18796
|
+
return NO2(`map-callback preamble has a non-declaration statement (${ts15.SyntaxKind[stmt.kind]})`);
|
|
18797
|
+
}
|
|
18798
|
+
const isConst = (stmt.declarationList.flags & ts15.NodeFlags.Const) !== 0;
|
|
18799
|
+
if (!isConst)
|
|
18800
|
+
return NO2("map-callback preamble declares a mutable binding (let/var)");
|
|
18801
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
18802
|
+
collectBindingNames2(decl.name, declaredNames);
|
|
18803
|
+
if (!decl.initializer) {
|
|
18804
|
+
return NO2("map-callback preamble has a declaration with no initializer");
|
|
18805
|
+
}
|
|
18806
|
+
const impure = findImpureNode(decl.initializer, primableNames);
|
|
18807
|
+
if (impure) {
|
|
18808
|
+
return NO2(`map-callback preamble initializer is not re-runnable (${impure})`);
|
|
18809
|
+
}
|
|
18810
|
+
}
|
|
18811
|
+
}
|
|
18812
|
+
for (const name of declaredNames) {
|
|
18813
|
+
if (primableNames.has(name)) {
|
|
18814
|
+
return NO2(`map-callback preamble shadows the signal/memo getter '${name}'`);
|
|
18815
|
+
}
|
|
18816
|
+
}
|
|
18817
|
+
const readNames = extractFreeIdentifiersFromStatementText(text);
|
|
18818
|
+
if (readNames.has(indexParam) && !declaredNames.has(indexParam)) {
|
|
18819
|
+
return NO2(`map-callback preamble reads the loop index parameter '${indexParam}'`);
|
|
18820
|
+
}
|
|
18821
|
+
const freeNames = new Set(readNames);
|
|
18822
|
+
for (const declared of declaredNames)
|
|
18823
|
+
freeNames.delete(declared);
|
|
18824
|
+
return { lazySafe: true, facts: { declaredNames, freeNames } };
|
|
18825
|
+
}
|
|
18826
|
+
function collectBindingNames2(name, out) {
|
|
18827
|
+
if (ts15.isIdentifier(name)) {
|
|
18828
|
+
out.add(name.text);
|
|
18829
|
+
return;
|
|
18830
|
+
}
|
|
18831
|
+
for (const element of name.elements) {
|
|
18832
|
+
if (ts15.isOmittedExpression(element))
|
|
18833
|
+
continue;
|
|
18834
|
+
collectBindingNames2(element.name, out);
|
|
18835
|
+
}
|
|
18836
|
+
}
|
|
18837
|
+
function findImpureNode(root, primableNames) {
|
|
18838
|
+
let found = null;
|
|
18839
|
+
const visit3 = (node) => {
|
|
18840
|
+
if (found)
|
|
18841
|
+
return;
|
|
18842
|
+
if (ts15.isCallExpression(node)) {
|
|
18843
|
+
const callee = node.expression;
|
|
18844
|
+
const isSignalRead = ts15.isIdentifier(callee) && primableNames.has(callee.text) && node.arguments.length === 0 && node.questionDotToken === undefined;
|
|
18845
|
+
if (!isSignalRead) {
|
|
18846
|
+
found = `call to ${callee.getText(callee.getSourceFile())}`;
|
|
18847
|
+
return;
|
|
18848
|
+
}
|
|
18849
|
+
}
|
|
18850
|
+
if (ts15.isNewExpression(node)) {
|
|
18851
|
+
found = "new expression";
|
|
18852
|
+
return;
|
|
18853
|
+
}
|
|
18854
|
+
if (ts15.isTaggedTemplateExpression(node)) {
|
|
18855
|
+
found = "tagged template";
|
|
18856
|
+
return;
|
|
18857
|
+
}
|
|
18858
|
+
if (ts15.isAwaitExpression(node)) {
|
|
18859
|
+
found = "await";
|
|
18860
|
+
return;
|
|
18861
|
+
}
|
|
18862
|
+
if (ts15.isYieldExpression(node)) {
|
|
18863
|
+
found = "yield";
|
|
18864
|
+
return;
|
|
18865
|
+
}
|
|
18866
|
+
if (ts15.isPrefixUnaryExpression(node) || ts15.isPostfixUnaryExpression(node)) {
|
|
18867
|
+
const op = node.operator;
|
|
18868
|
+
if (op === ts15.SyntaxKind.PlusPlusToken || op === ts15.SyntaxKind.MinusMinusToken) {
|
|
18869
|
+
found = "increment/decrement";
|
|
18870
|
+
return;
|
|
18871
|
+
}
|
|
18872
|
+
}
|
|
18873
|
+
if (ts15.isDeleteExpression(node)) {
|
|
18874
|
+
found = "delete";
|
|
18875
|
+
return;
|
|
18876
|
+
}
|
|
18877
|
+
if (ts15.isFunctionExpression(node) || ts15.isArrowFunction(node) || ts15.isClassExpression(node)) {
|
|
18878
|
+
found = "function or class expression";
|
|
18879
|
+
return;
|
|
18880
|
+
}
|
|
18881
|
+
if (ts15.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
|
|
18882
|
+
found = "assignment";
|
|
18883
|
+
return;
|
|
18884
|
+
}
|
|
18885
|
+
ts15.forEachChild(node, visit3);
|
|
18886
|
+
};
|
|
18887
|
+
visit3(root);
|
|
18888
|
+
return found;
|
|
18889
|
+
}
|
|
18890
|
+
function isAssignmentOperator(kind) {
|
|
18891
|
+
return kind >= ts15.SyntaxKind.FirstAssignment && kind <= ts15.SyntaxKind.LastAssignment;
|
|
18892
|
+
}
|
|
18893
|
+
|
|
18487
18894
|
// src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts
|
|
18488
18895
|
var PURE_SOURCE_GLOBALS = new Set([
|
|
18489
18896
|
"Object",
|
|
@@ -18527,51 +18934,51 @@ var INERT_BINDING_GLOBALS = new Set([
|
|
|
18527
18934
|
"decodeURI"
|
|
18528
18935
|
]);
|
|
18529
18936
|
var UNKNOWN_IDENTIFIERS = "<unknown>";
|
|
18530
|
-
var
|
|
18937
|
+
var NO3 = (reason) => ({ eligible: false, reason });
|
|
18531
18938
|
function lazyRowEligibility(args) {
|
|
18532
18939
|
const { shape, bindings, arraySourceIdentifiers, scope } = args;
|
|
18533
18940
|
if (scope.profile)
|
|
18534
|
-
return
|
|
18941
|
+
return NO3("profile mode keeps the granular eager emission");
|
|
18535
18942
|
if (shape.callSite !== "plain" && shape.callSite !== "branch-plain") {
|
|
18536
|
-
return
|
|
18943
|
+
return NO3(`call site '${shape.callSite}' is not a plain loop row`);
|
|
18537
18944
|
}
|
|
18538
18945
|
if (shape.flatMapLeafItem)
|
|
18539
|
-
return
|
|
18946
|
+
return NO3("flatMap descriptor loop (build-or-patch renderItem)");
|
|
18540
18947
|
if (shape.anchored)
|
|
18541
|
-
return
|
|
18948
|
+
return NO3("anchored whole-item-conditional loop");
|
|
18542
18949
|
if (shape.bodyIsMultiRoot)
|
|
18543
|
-
return
|
|
18950
|
+
return NO3("multi-root (Fragment) row");
|
|
18544
18951
|
if (!shape.hasExplicitKey)
|
|
18545
|
-
return
|
|
18546
|
-
if (shape.
|
|
18547
|
-
return
|
|
18952
|
+
return NO3("index-keyed loop (no explicit key)");
|
|
18953
|
+
if (shape.conditionalRefusal)
|
|
18954
|
+
return NO3(shape.conditionalRefusal);
|
|
18548
18955
|
if (shape.childRefCount > 0)
|
|
18549
|
-
return
|
|
18956
|
+
return NO3("row has imperative child refs");
|
|
18550
18957
|
if (shape.hasChildComponent)
|
|
18551
|
-
return
|
|
18958
|
+
return NO3("row body is a child component");
|
|
18552
18959
|
if (shape.nestedComponentCount > 0)
|
|
18553
|
-
return
|
|
18960
|
+
return NO3("row contains nested child components");
|
|
18554
18961
|
if (shape.innerLoopCount > 0)
|
|
18555
|
-
return
|
|
18556
|
-
if (shape.
|
|
18557
|
-
return
|
|
18962
|
+
return NO3("row contains an inner loop");
|
|
18963
|
+
if (shape.mapPreambleRefusal)
|
|
18964
|
+
return NO3(shape.mapPreambleRefusal);
|
|
18558
18965
|
if (shape.preambleRegionCount > 0)
|
|
18559
|
-
return
|
|
18966
|
+
return NO3("row has preamble-patched regions");
|
|
18560
18967
|
if (shape.hasParamUnwrap)
|
|
18561
|
-
return
|
|
18968
|
+
return NO3("destructured loop param without param bindings");
|
|
18562
18969
|
for (const b of bindings) {
|
|
18563
18970
|
if (b.referencesIndex) {
|
|
18564
|
-
return
|
|
18971
|
+
return NO3(`binding on slot ${b.slotId} references the loop index parameter`);
|
|
18565
18972
|
}
|
|
18566
18973
|
if (b.opaqueOuterNames.includes(UNKNOWN_IDENTIFIERS)) {
|
|
18567
|
-
return
|
|
18974
|
+
return NO3(`binding on slot ${b.slotId} has no analyzable identifier set`);
|
|
18568
18975
|
}
|
|
18569
18976
|
}
|
|
18570
18977
|
if (!arraySourceIdentifiers)
|
|
18571
|
-
return
|
|
18978
|
+
return NO3("loop source free identifiers unavailable");
|
|
18572
18979
|
const sourceGate = checkSourceConsistency(arraySourceIdentifiers, scope);
|
|
18573
18980
|
if (sourceGate)
|
|
18574
|
-
return
|
|
18981
|
+
return NO3(`loop source is not provably hydration-consistent: ${sourceGate}`);
|
|
18575
18982
|
return { eligible: true };
|
|
18576
18983
|
}
|
|
18577
18984
|
function checkSourceConsistency(names, scope) {
|
|
@@ -18622,6 +19029,7 @@ function checkSourceConsistency(names, scope) {
|
|
|
18622
19029
|
}
|
|
18623
19030
|
function classifyLazyBinding(args) {
|
|
18624
19031
|
const { kind, slotId, free, rowLocalNames, indexParam, scope } = args;
|
|
19032
|
+
const preamble = args.preamble;
|
|
18625
19033
|
if (free === null) {
|
|
18626
19034
|
return {
|
|
18627
19035
|
kind,
|
|
@@ -18630,33 +19038,44 @@ function classifyLazyBinding(args) {
|
|
|
18630
19038
|
readsOuter: true,
|
|
18631
19039
|
reactiveOuterNames: [],
|
|
18632
19040
|
opaqueOuterNames: [UNKNOWN_IDENTIFIERS],
|
|
18633
|
-
referencesIndex: false
|
|
19041
|
+
referencesIndex: false,
|
|
19042
|
+
readsPreamble: preamble != null && preamble.declaredNames.size > 0
|
|
18634
19043
|
};
|
|
18635
19044
|
}
|
|
18636
19045
|
let readsItem = false;
|
|
18637
19046
|
let referencesIndex = false;
|
|
19047
|
+
let readsPreamble = false;
|
|
18638
19048
|
const reactiveOuterNames = [];
|
|
18639
19049
|
const opaqueOuterNames = [];
|
|
18640
|
-
|
|
19050
|
+
const classifyName = (name) => {
|
|
18641
19051
|
if (rowLocalNames.has(name)) {
|
|
18642
19052
|
readsItem = true;
|
|
18643
|
-
|
|
19053
|
+
return;
|
|
18644
19054
|
}
|
|
18645
19055
|
if (name === indexParam) {
|
|
18646
19056
|
referencesIndex = true;
|
|
18647
|
-
|
|
19057
|
+
return;
|
|
18648
19058
|
}
|
|
18649
19059
|
if (INERT_BINDING_GLOBALS.has(name))
|
|
18650
|
-
|
|
19060
|
+
return;
|
|
18651
19061
|
if (scope.signals.has(name) || scope.memos.has(name)) {
|
|
18652
19062
|
if (!reactiveOuterNames.includes(name))
|
|
18653
19063
|
reactiveOuterNames.push(name);
|
|
18654
|
-
|
|
19064
|
+
return;
|
|
18655
19065
|
}
|
|
18656
19066
|
const constFree = scope.constants.get(name);
|
|
18657
19067
|
if (constFree !== undefined && constFree !== null && constFree.size === 0)
|
|
18658
|
-
|
|
19068
|
+
return;
|
|
18659
19069
|
opaqueOuterNames.push(name);
|
|
19070
|
+
};
|
|
19071
|
+
for (const name of free) {
|
|
19072
|
+
if (preamble?.declaredNames.has(name)) {
|
|
19073
|
+
readsPreamble = true;
|
|
19074
|
+
for (const dep of preamble.freeNames)
|
|
19075
|
+
classifyName(dep);
|
|
19076
|
+
continue;
|
|
19077
|
+
}
|
|
19078
|
+
classifyName(name);
|
|
18660
19079
|
}
|
|
18661
19080
|
return {
|
|
18662
19081
|
kind,
|
|
@@ -18665,7 +19084,8 @@ function classifyLazyBinding(args) {
|
|
|
18665
19084
|
readsOuter: reactiveOuterNames.length > 0 || opaqueOuterNames.length > 0,
|
|
18666
19085
|
reactiveOuterNames,
|
|
18667
19086
|
opaqueOuterNames,
|
|
18668
|
-
referencesIndex
|
|
19087
|
+
referencesIndex,
|
|
19088
|
+
readsPreamble
|
|
18669
19089
|
};
|
|
18670
19090
|
}
|
|
18671
19091
|
|
|
@@ -18682,6 +19102,23 @@ function decideLazyRow(args) {
|
|
|
18682
19102
|
const rowLocalNames = new Set([loop.param]);
|
|
18683
19103
|
for (const b of loop.paramBindings ?? [])
|
|
18684
19104
|
rowLocalNames.add(b.name);
|
|
19105
|
+
const primableNames = new Set([...scope.signals.keys(), ...scope.memos]);
|
|
19106
|
+
const preambleAnalysis = analyzeLazyPreamble(loop.preamble, args.indexParam, primableNames);
|
|
19107
|
+
const rawConditionals = loop.bindings.conditionals ?? [];
|
|
19108
|
+
const condFacts = [];
|
|
19109
|
+
let conditionalRefusal = null;
|
|
19110
|
+
for (const cond of rawConditionals) {
|
|
19111
|
+
const verdict = analyzeLazyConditional(cond, args.indexParam, {
|
|
19112
|
+
whenTrueHtml: addCondAttrToTemplate(wrap(cond.whenTrueHtml), cond.slotId),
|
|
19113
|
+
whenFalseHtml: addCondAttrToTemplate(wrap(cond.whenFalseHtml), cond.slotId)
|
|
19114
|
+
});
|
|
19115
|
+
if (!verdict.lazySafe) {
|
|
19116
|
+
conditionalRefusal = verdict.reason;
|
|
19117
|
+
break;
|
|
19118
|
+
}
|
|
19119
|
+
condFacts.push(verdict.facts);
|
|
19120
|
+
}
|
|
19121
|
+
const preambleFacts = preambleAnalysis.lazySafe ? preambleAnalysis.facts : undefined;
|
|
18685
19122
|
const classified = [];
|
|
18686
19123
|
const attrClass = new Map;
|
|
18687
19124
|
loop.bindings.reactiveAttrs.forEach((attr, i) => {
|
|
@@ -18691,7 +19128,8 @@ function decideLazyRow(args) {
|
|
|
18691
19128
|
free: attrFreeIdentifiers2(attr.expression),
|
|
18692
19129
|
rowLocalNames,
|
|
18693
19130
|
indexParam: args.indexParam,
|
|
18694
|
-
scope
|
|
19131
|
+
scope,
|
|
19132
|
+
preamble: preambleFacts
|
|
18695
19133
|
});
|
|
18696
19134
|
attrClass.set(i, c);
|
|
18697
19135
|
classified.push(c);
|
|
@@ -18704,23 +19142,38 @@ function decideLazyRow(args) {
|
|
|
18704
19142
|
free: text.freeIdentifiers ?? null,
|
|
18705
19143
|
rowLocalNames,
|
|
18706
19144
|
indexParam: args.indexParam,
|
|
18707
|
-
scope
|
|
19145
|
+
scope,
|
|
19146
|
+
preamble: preambleFacts
|
|
18708
19147
|
});
|
|
18709
19148
|
textClass.set(i, c);
|
|
18710
19149
|
classified.push(c);
|
|
18711
19150
|
});
|
|
19151
|
+
const condClass = new Map;
|
|
19152
|
+
condFacts.forEach((c, i) => {
|
|
19153
|
+
const k = classifyLazyBinding({
|
|
19154
|
+
kind: "attr",
|
|
19155
|
+
slotId: c.slotId,
|
|
19156
|
+
free: rawConditionals[i].conditionFreeIdentifiers ?? null,
|
|
19157
|
+
rowLocalNames,
|
|
19158
|
+
indexParam: args.indexParam,
|
|
19159
|
+
scope,
|
|
19160
|
+
preamble: preambleFacts
|
|
19161
|
+
});
|
|
19162
|
+
condClass.set(i, k);
|
|
19163
|
+
classified.push(k);
|
|
19164
|
+
});
|
|
18712
19165
|
const shape = {
|
|
18713
19166
|
callSite: args.callSite,
|
|
18714
19167
|
flatMapLeafItem: args.flatMapLeafItem,
|
|
18715
19168
|
anchored: args.anchored,
|
|
18716
19169
|
bodyIsMultiRoot: loop.bodyIsMultiRoot ?? false,
|
|
18717
19170
|
hasExplicitKey: loop.key != null,
|
|
18718
|
-
|
|
19171
|
+
conditionalRefusal,
|
|
18719
19172
|
childRefCount: loop.bindings.refs?.length ?? 0,
|
|
18720
19173
|
nestedComponentCount: loop.nestedComponents?.length ?? 0,
|
|
18721
19174
|
innerLoopCount: loop.innerLoops?.length ?? 0,
|
|
18722
19175
|
hasChildComponent: "childComponent" in loop && loop.childComponent != null,
|
|
18723
|
-
|
|
19176
|
+
mapPreambleRefusal: preambleAnalysis.lazySafe ? null : preambleAnalysis.reason,
|
|
18724
19177
|
preambleRegionCount: args.preambleRegionCount,
|
|
18725
19178
|
hasParamUnwrap: args.paramUnwrap.length > 0
|
|
18726
19179
|
};
|
|
@@ -18748,7 +19201,8 @@ function decideLazyRow(args) {
|
|
|
18748
19201
|
refIndex: attrSlotIds.indexOf(attr.childSlotId),
|
|
18749
19202
|
ordinal: ordinal++,
|
|
18750
19203
|
readsItem: c.readsItem,
|
|
18751
|
-
readsOuter: c.readsOuter
|
|
19204
|
+
readsOuter: c.readsOuter,
|
|
19205
|
+
readsPreamble: c.readsPreamble
|
|
18752
19206
|
};
|
|
18753
19207
|
});
|
|
18754
19208
|
const texts = loop.bindings.reactiveTexts.map((text, i) => {
|
|
@@ -18758,7 +19212,8 @@ function decideLazyRow(args) {
|
|
|
18758
19212
|
wrappedExpression: wrap(text.expression),
|
|
18759
19213
|
ordinal: ordinal++,
|
|
18760
19214
|
readsItem: c.readsItem || !c.readsOuter,
|
|
18761
|
-
readsOuter: c.readsOuter
|
|
19215
|
+
readsOuter: c.readsOuter,
|
|
19216
|
+
readsPreamble: c.readsPreamble
|
|
18762
19217
|
};
|
|
18763
19218
|
});
|
|
18764
19219
|
const outerPrimeGetters = [];
|
|
@@ -18768,6 +19223,21 @@ function decideLazyRow(args) {
|
|
|
18768
19223
|
outerPrimeGetters.push(name);
|
|
18769
19224
|
}
|
|
18770
19225
|
}
|
|
19226
|
+
const condRefBase = attrSlotIds.length + (texts.length > 0 ? 1 : 0);
|
|
19227
|
+
const conditionals = condFacts.map((c, i) => {
|
|
19228
|
+
const klass = condClass.get(i);
|
|
19229
|
+
return {
|
|
19230
|
+
slotId: c.slotId,
|
|
19231
|
+
wrappedCondition: wrap(c.condition),
|
|
19232
|
+
whenTrueHtml: c.whenTrueHtml,
|
|
19233
|
+
whenFalseHtml: c.whenFalseHtml,
|
|
19234
|
+
refIndex: condRefBase + i,
|
|
19235
|
+
ordinal: ordinal++,
|
|
19236
|
+
readsItem: klass.readsItem || !klass.readsOuter,
|
|
19237
|
+
readsOuter: klass.readsOuter,
|
|
19238
|
+
readsPreamble: klass.readsPreamble
|
|
19239
|
+
};
|
|
19240
|
+
});
|
|
18771
19241
|
return {
|
|
18772
19242
|
plan: {
|
|
18773
19243
|
attrSlotIds,
|
|
@@ -18777,7 +19247,10 @@ function decideLazyRow(args) {
|
|
|
18777
19247
|
textNeedsRead: texts.some((t) => t.readsOuter),
|
|
18778
19248
|
lastCount: ordinal,
|
|
18779
19249
|
outerPrimeGetters,
|
|
18780
|
-
|
|
19250
|
+
preambleStatements: args.mapPreambleWrapped,
|
|
19251
|
+
itemNeedsPreamble: [...attrs, ...texts, ...conditionals].some((b) => b.readsItem && b.readsPreamble),
|
|
19252
|
+
outerNeedsPreamble: [...attrs, ...texts, ...conditionals].some((b) => b.readsOuter && b.readsPreamble),
|
|
19253
|
+
conditionals
|
|
18781
19254
|
},
|
|
18782
19255
|
decision
|
|
18783
19256
|
};
|
|
@@ -18849,7 +19322,7 @@ function buildBranchLoopPlan(loop, profileComponentName, lazyScope) {
|
|
|
18849
19322
|
const indexParam = loop.index || "__idx";
|
|
18850
19323
|
const mapPreambleWrapped = loop.preamble ? renderPreamble(loop.preamble, {
|
|
18851
19324
|
transformJs: (t) => wrapLoopParamAsAccessor(t, loop.param, loop.paramBindings),
|
|
18852
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined
|
|
19325
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined)
|
|
18853
19326
|
}) : "";
|
|
18854
19327
|
const preambleRegions = buildPreambleRegionPlans(loop.preambleRegions, loop.param, loop.paramBindings);
|
|
18855
19328
|
const plan = {
|
|
@@ -18945,7 +19418,7 @@ function buildArmBody(branch, options) {
|
|
|
18945
19418
|
}
|
|
18946
19419
|
|
|
18947
19420
|
// src/ir-to-client-js/emit-reactive.ts
|
|
18948
|
-
import
|
|
19421
|
+
import ts16 from "typescript";
|
|
18949
19422
|
|
|
18950
19423
|
// src/ir-to-client-js/control-flow/stringify/claim-plan.ts
|
|
18951
19424
|
function slotSpecLiteral(slot) {
|
|
@@ -19048,20 +19521,20 @@ function lowerToLocaleCallsInReactiveExpr(expr, matcher) {
|
|
|
19048
19521
|
return expr;
|
|
19049
19522
|
let sourceFile;
|
|
19050
19523
|
try {
|
|
19051
|
-
sourceFile =
|
|
19524
|
+
sourceFile = ts16.createSourceFile("__reactive_expr__.ts", `(${expr});`, ts16.ScriptTarget.Latest, true, ts16.ScriptKind.TS);
|
|
19052
19525
|
} catch {
|
|
19053
19526
|
return expr;
|
|
19054
19527
|
}
|
|
19055
19528
|
const stmt = sourceFile.statements[0];
|
|
19056
|
-
if (!stmt || !
|
|
19529
|
+
if (!stmt || !ts16.isExpressionStatement(stmt))
|
|
19057
19530
|
return expr;
|
|
19058
|
-
const root =
|
|
19531
|
+
const root = ts16.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
|
|
19059
19532
|
const candidates = [];
|
|
19060
19533
|
const visit3 = (n) => {
|
|
19061
|
-
if (
|
|
19534
|
+
if (ts16.isCallExpression(n) && n.arguments.length === 2 && ts16.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && n.expression.name.text === "toLocaleDateString") {
|
|
19062
19535
|
candidates.push(n);
|
|
19063
19536
|
}
|
|
19064
|
-
|
|
19537
|
+
ts16.forEachChild(n, visit3);
|
|
19065
19538
|
};
|
|
19066
19539
|
visit3(root);
|
|
19067
19540
|
if (candidates.length === 0)
|
|
@@ -19097,20 +19570,20 @@ function lowerDateCallsInReactiveExpr(expr, matcher) {
|
|
|
19097
19570
|
return expr;
|
|
19098
19571
|
let sourceFile;
|
|
19099
19572
|
try {
|
|
19100
|
-
sourceFile =
|
|
19573
|
+
sourceFile = ts16.createSourceFile("__reactive_expr__.ts", `(${expr});`, ts16.ScriptTarget.Latest, true, ts16.ScriptKind.TS);
|
|
19101
19574
|
} catch {
|
|
19102
19575
|
return expr;
|
|
19103
19576
|
}
|
|
19104
19577
|
const stmt = sourceFile.statements[0];
|
|
19105
|
-
if (!stmt || !
|
|
19578
|
+
if (!stmt || !ts16.isExpressionStatement(stmt))
|
|
19106
19579
|
return expr;
|
|
19107
|
-
const root =
|
|
19580
|
+
const root = ts16.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
|
|
19108
19581
|
const candidates = [];
|
|
19109
19582
|
const visit3 = (n) => {
|
|
19110
|
-
if (
|
|
19583
|
+
if (ts16.isCallExpression(n) && n.arguments.length === 0 && ts16.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && DATE_METHODS.has(n.expression.name.text)) {
|
|
19111
19584
|
candidates.push(n);
|
|
19112
19585
|
}
|
|
19113
|
-
|
|
19586
|
+
ts16.forEachChild(n, visit3);
|
|
19114
19587
|
};
|
|
19115
19588
|
visit3(root);
|
|
19116
19589
|
if (candidates.length === 0)
|
|
@@ -19418,7 +19891,7 @@ function stringifyReactiveEffects(lines, plan, opts) {
|
|
|
19418
19891
|
const outerTexts = plan?.outerTexts ?? [];
|
|
19419
19892
|
const conditionals = plan?.conditionals ?? [];
|
|
19420
19893
|
if (pc) {
|
|
19421
|
-
emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId);
|
|
19894
|
+
emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId, mapPreambleWrapped);
|
|
19422
19895
|
emitOuterTexts(lines, indent, elVar, outerTexts, bindingBfId, textClaimPathExprs);
|
|
19423
19896
|
emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPreambleWrapped);
|
|
19424
19897
|
} else {
|
|
@@ -19428,7 +19901,7 @@ function stringifyReactiveEffects(lines, plan, opts) {
|
|
|
19428
19901
|
emitOuterConditional(lines, indent, elVar, cond, pc);
|
|
19429
19902
|
}
|
|
19430
19903
|
}
|
|
19431
|
-
function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId) {
|
|
19904
|
+
function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId, mapPreambleWrapped) {
|
|
19432
19905
|
for (const slot of attrSlots) {
|
|
19433
19906
|
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19434
19907
|
const lookupExpr = attrLookupExpr(slot.slotId, varName, elVar, lookup, elementIndexBySlot);
|
|
@@ -19436,6 +19909,9 @@ function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementI
|
|
|
19436
19909
|
lines.push(`${indent}if (${varName}) {`);
|
|
19437
19910
|
for (const attr of slot.attrs) {
|
|
19438
19911
|
lines.push(`${indent} createEffect(() => {`);
|
|
19912
|
+
if (attr.readsPreamble && mapPreambleWrapped) {
|
|
19913
|
+
lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19914
|
+
}
|
|
19439
19915
|
for (const stmt of emitAttrUpdate(varName, attr.attrName, attr.wrappedExpression, attr.meta)) {
|
|
19440
19916
|
lines.push(`${indent} ${stmt}`);
|
|
19441
19917
|
}
|
|
@@ -19458,6 +19934,9 @@ function emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPre
|
|
|
19458
19934
|
}
|
|
19459
19935
|
lines.push(`${indent}})`);
|
|
19460
19936
|
}
|
|
19937
|
+
function attrsReadPreamble(attrSlots) {
|
|
19938
|
+
return attrSlots.some((slot) => slot.attrs.some((a) => a.readsPreamble));
|
|
19939
|
+
}
|
|
19461
19940
|
function attrLookupExpr(slotId, varName, elVar, lookup, elementIndexBySlot) {
|
|
19462
19941
|
const pIdx = elementIndexBySlot?.get(slotId);
|
|
19463
19942
|
return pIdx !== undefined ? `__p ? __p[${pIdx}] : ${lookup}(${elVar}, '[bf="${slotId}"]')` : `${lookup}(${elVar}, '[bf="${slotId}"]')`;
|
|
@@ -19483,6 +19962,9 @@ function emitConsolidatedRowEffect(lines, indent, elVar, lookup, attrSlots, oute
|
|
|
19483
19962
|
return;
|
|
19484
19963
|
}
|
|
19485
19964
|
lines.push(`${indent}createEffect(() => {`);
|
|
19965
|
+
if (mapPreambleWrapped && (preambleRegions.length > 0 || attrsReadPreamble(attrSlots))) {
|
|
19966
|
+
lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19967
|
+
}
|
|
19486
19968
|
for (const slot of attrSlots) {
|
|
19487
19969
|
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19488
19970
|
lines.push(`${indent} if (${varName}) {`);
|
|
@@ -19495,9 +19977,6 @@ function emitConsolidatedRowEffect(lines, indent, elVar, lookup, attrSlots, oute
|
|
|
19495
19977
|
}
|
|
19496
19978
|
lines.push(`${indent} }`);
|
|
19497
19979
|
}
|
|
19498
|
-
if (preambleRegions.length > 0 && mapPreambleWrapped) {
|
|
19499
|
-
lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19500
|
-
}
|
|
19501
19980
|
for (const text of outerTexts) {
|
|
19502
19981
|
lines.push(`${indent} ${writer}('${text.slotId}', String(${text.wrappedExpression}))`);
|
|
19503
19982
|
}
|
|
@@ -19631,9 +20110,8 @@ function stringifyLazyRowLoop(lines, o) {
|
|
|
19631
20110
|
const { indent, lazyRow, paramHead } = o;
|
|
19632
20111
|
const mid = o.markerId.replace(/[^A-Za-z0-9_$]/g, "_");
|
|
19633
20112
|
const tplVar = `__tpl_${mid}`;
|
|
19634
|
-
const claimVar = `__lzc_${mid}`;
|
|
19635
20113
|
const hasRefs = lazyRow.attrSlotIds.length > 0 || lazyRow.texts.length > 0;
|
|
19636
|
-
const hasBindings = lazyRow.attrs.length > 0 || lazyRow.texts.length > 0;
|
|
20114
|
+
const hasBindings = lazyRow.attrs.length > 0 || lazyRow.texts.length > 0 || lazyRow.conditionals.length > 0;
|
|
19637
20115
|
const rwDoor = lazyRow.textNeedsRead;
|
|
19638
20116
|
const paths = o.skeletonPaths;
|
|
19639
20117
|
const useHoisted = Boolean(o.skeletonTemplate);
|
|
@@ -19663,13 +20141,10 @@ function stringifyLazyRowLoop(lines, o) {
|
|
|
19663
20141
|
freshPlanVar = adoptedPlanVar;
|
|
19664
20142
|
}
|
|
19665
20143
|
}
|
|
19666
|
-
|
|
19667
|
-
const
|
|
19668
|
-
lines
|
|
19669
|
-
|
|
19670
|
-
lines.push(`${indent} const __el = __e.primaryEl`);
|
|
19671
|
-
lines.push(`${indent} return [${parts.join(", ")}]`);
|
|
19672
|
-
lines.push(`${indent}}`);
|
|
20144
|
+
for (const c of lazyRow.conditionals) {
|
|
20145
|
+
const v = condVars(mid, c.slotId);
|
|
20146
|
+
emitHoistedTemplateDecl(lines, indent, v.trueTpl, c.whenTrueHtml);
|
|
20147
|
+
emitHoistedTemplateDecl(lines, indent, v.falseTpl, c.whenFalseHtml);
|
|
19673
20148
|
}
|
|
19674
20149
|
const call = `mapArrayLazy(() => ${o.arrayExpr}, ${o.containerVar}, ${o.keyFn}, {`;
|
|
19675
20150
|
lines.push(`${indent}${o.guardContainer ? `if (${o.containerVar}) ` : ""}${call}`);
|
|
@@ -19677,6 +20152,8 @@ function stringifyLazyRowLoop(lines, o) {
|
|
|
19677
20152
|
const b2 = `${indent} `;
|
|
19678
20153
|
lines.push(`${b1}createRow: (__e, ${o.indexParam}) => {`);
|
|
19679
20154
|
lines.push(`${b2}const ${paramHead} = () => __e.item`);
|
|
20155
|
+
if (lazyRow.preambleStatements)
|
|
20156
|
+
lines.push(`${b2}${lazyRow.preambleStatements}`);
|
|
19680
20157
|
const cloneExpr = useHoisted ? hoistedCloneExpr(tplVar, o.skeletonTemplate) : `(() => { ${emitTemplateCloneInline(o.template)} })()`;
|
|
19681
20158
|
lines.push(`${b2}const __el = ${cloneExpr}`);
|
|
19682
20159
|
if (hasRefs) {
|
|
@@ -19690,17 +20167,23 @@ function stringifyLazyRowLoop(lines, o) {
|
|
|
19690
20167
|
for (const t of lazyRow.texts)
|
|
19691
20168
|
emitTextBinding(lines, b2, t, createDoor, "create", rwDoor);
|
|
19692
20169
|
}
|
|
20170
|
+
for (const c of lazyRow.conditionals)
|
|
20171
|
+
emitConditional(lines, b2, mid, c, "create");
|
|
19693
20172
|
lines.push(`${b2}return __el`);
|
|
19694
20173
|
lines.push(`${b1}},`);
|
|
19695
20174
|
const itemAttrs = lazyRow.attrs.filter((a) => a.readsItem);
|
|
19696
20175
|
const itemTexts = lazyRow.texts.filter((t) => t.readsItem);
|
|
19697
|
-
|
|
20176
|
+
const itemConds = lazyRow.conditionals.filter((c) => c.readsItem);
|
|
20177
|
+
if (itemAttrs.length === 0 && itemTexts.length === 0 && itemConds.length === 0) {
|
|
19698
20178
|
lines.push(`${b1}applyItem: () => {},`);
|
|
19699
20179
|
} else {
|
|
19700
20180
|
lines.push(`${b1}applyItem: (__e) => {`);
|
|
19701
20181
|
lines.push(`${b2}const ${paramHead} = () => __e.item`);
|
|
19702
|
-
lines.push(`${b2}const __r = __e.refs ?? (__e.refs =
|
|
20182
|
+
lines.push(`${b2}const __r = __e.refs ?? (__e.refs = [])`);
|
|
19703
20183
|
lines.push(`${b2}const __l = __e.last ?? (__e.last = [])`);
|
|
20184
|
+
if (lazyRow.itemNeedsPreamble && lazyRow.preambleStatements) {
|
|
20185
|
+
lines.push(`${b2}${lazyRow.preambleStatements}`);
|
|
20186
|
+
}
|
|
19704
20187
|
for (const a of itemAttrs)
|
|
19705
20188
|
emitAttrBinding(lines, b2, a, "item");
|
|
19706
20189
|
if (itemTexts.length > 0) {
|
|
@@ -19708,19 +20191,25 @@ function stringifyLazyRowLoop(lines, o) {
|
|
|
19708
20191
|
for (const t of itemTexts)
|
|
19709
20192
|
emitTextBinding(lines, b2, t, "__d", "item", rwDoor);
|
|
19710
20193
|
}
|
|
20194
|
+
for (const c of itemConds)
|
|
20195
|
+
emitConditional(lines, b2, mid, c, "item");
|
|
19711
20196
|
lines.push(`${b1}},`);
|
|
19712
20197
|
}
|
|
19713
20198
|
const outerAttrs = lazyRow.attrs.filter((a) => a.readsOuter);
|
|
19714
20199
|
const outerTexts = lazyRow.texts.filter((t) => t.readsOuter);
|
|
19715
|
-
|
|
20200
|
+
const outerConds = lazyRow.conditionals.filter((c) => c.readsOuter);
|
|
20201
|
+
if (outerAttrs.length > 0 || outerTexts.length > 0 || outerConds.length > 0) {
|
|
19716
20202
|
const b3 = `${indent} `;
|
|
19717
20203
|
lines.push(`${b1}applyOuter: (__es, __seed) => {`);
|
|
19718
20204
|
for (const g of lazyRow.outerPrimeGetters)
|
|
19719
20205
|
lines.push(`${b2}${g}()`);
|
|
19720
20206
|
lines.push(`${b2}for (const __e of __es) {`);
|
|
19721
20207
|
lines.push(`${b3}const ${paramHead} = () => __e.item`);
|
|
19722
|
-
lines.push(`${b3}const __r = __e.refs ?? (__e.refs =
|
|
20208
|
+
lines.push(`${b3}const __r = __e.refs ?? (__e.refs = [])`);
|
|
19723
20209
|
lines.push(`${b3}const __l = __e.last ?? (__e.last = [])`);
|
|
20210
|
+
if (lazyRow.outerNeedsPreamble && lazyRow.preambleStatements) {
|
|
20211
|
+
lines.push(`${b3}${lazyRow.preambleStatements}`);
|
|
20212
|
+
}
|
|
19724
20213
|
for (const a of outerAttrs)
|
|
19725
20214
|
emitAttrBinding(lines, b3, a, "outer");
|
|
19726
20215
|
if (outerTexts.length > 0) {
|
|
@@ -19728,22 +20217,28 @@ function stringifyLazyRowLoop(lines, o) {
|
|
|
19728
20217
|
for (const t of outerTexts)
|
|
19729
20218
|
emitTextBinding(lines, b3, t, "__d", "outer", rwDoor);
|
|
19730
20219
|
}
|
|
20220
|
+
for (const c of outerConds)
|
|
20221
|
+
emitConditional(lines, b3, mid, c, "outer");
|
|
19731
20222
|
lines.push(`${b2}}`);
|
|
19732
20223
|
lines.push(`${b1}},`);
|
|
19733
20224
|
}
|
|
19734
20225
|
lines.push(`${indent}}, '${o.markerId}')`);
|
|
19735
20226
|
}
|
|
19736
|
-
function refParts(lazyRow, elVar, skeletonPaths, planVar
|
|
20227
|
+
function refParts(lazyRow, elVar, skeletonPaths, planVar) {
|
|
19737
20228
|
const parts = [];
|
|
19738
20229
|
for (const slotId of lazyRow.attrSlotIds) {
|
|
19739
20230
|
const path = skeletonPaths?.elementPaths.get(slotId);
|
|
19740
20231
|
parts.push(path ? pathExpr(elVar, path) : `qsa(${elVar}, '[bf="${slotId}"]')`);
|
|
19741
20232
|
}
|
|
19742
20233
|
if (lazyRow.texts.length > 0) {
|
|
19743
|
-
parts.push(
|
|
20234
|
+
parts.push(`${doorCtor(lazyRow)}(${elVar}, ${planVar})`);
|
|
19744
20235
|
}
|
|
19745
20236
|
return parts;
|
|
19746
20237
|
}
|
|
20238
|
+
function elementAccess(a) {
|
|
20239
|
+
const slot = `__r[${a.refIndex}]`;
|
|
20240
|
+
return `${a.refIndex} in __r ? ${slot} : (${slot} = qsa(__e.primaryEl, '[bf="${a.slotId}"]'))`;
|
|
20241
|
+
}
|
|
19747
20242
|
function doorCtor(lazyRow) {
|
|
19748
20243
|
return lazyRow.textNeedsRead ? "lazyClaimSlots" : "lazySlots";
|
|
19749
20244
|
}
|
|
@@ -19751,11 +20246,36 @@ function doorAccess(lazyRow, writerIndex, adoptedPlanVar) {
|
|
|
19751
20246
|
const slot = `__r[${writerIndex}]`;
|
|
19752
20247
|
return `${slot} ?? (${slot} = ${doorCtor(lazyRow)}(__e.primaryEl, ${adoptedPlanVar}))`;
|
|
19753
20248
|
}
|
|
20249
|
+
function condVars(mid, slotId) {
|
|
20250
|
+
const key = `${mid}_${slotId.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
20251
|
+
return { trueTpl: `__cbt_${key}`, falseTpl: `__cbf_${key}` };
|
|
20252
|
+
}
|
|
20253
|
+
function emitConditional(lines, ind, mid, c, mode) {
|
|
20254
|
+
const v = condVars(mid, c.slotId);
|
|
20255
|
+
if (mode === "create") {
|
|
20256
|
+
lines.push(`${ind}__l[${c.ordinal}] = !!(${c.wrappedCondition})`);
|
|
20257
|
+
return;
|
|
20258
|
+
}
|
|
20259
|
+
const slot = `__r[${c.refIndex}]`;
|
|
20260
|
+
lines.push(`${ind}{ const __c = ${c.refIndex} in __r ? ${slot} : (${slot} = qsa(__e.primaryEl, '[bf-c="${c.slotId}"]'))`);
|
|
20261
|
+
lines.push(`${ind}if (__c) {`);
|
|
20262
|
+
lines.push(`${ind} const __x = !!(${c.wrappedCondition})`);
|
|
20263
|
+
lines.push(`${ind} const __w = (__x ? ${v.trueTpl} : ${v.falseTpl}).content.firstElementChild`);
|
|
20264
|
+
const guard = mode === "item" ? dedupGuard(c.ordinal) : `__seed ? (__c.outerHTML !== __w.outerHTML) : (${dedupGuard(c.ordinal)})`;
|
|
20265
|
+
lines.push(`${ind} if (${guard}) {`);
|
|
20266
|
+
lines.push(`${ind} const __n = __w.cloneNode(true)`);
|
|
20267
|
+
lines.push(`${ind} __c.replaceWith(__n)`);
|
|
20268
|
+
lines.push(`${ind} ${slot} = __n`);
|
|
20269
|
+
lines.push(`${ind} }`);
|
|
20270
|
+
lines.push(`${ind} __l[${c.ordinal}] = __x`);
|
|
20271
|
+
lines.push(`${ind}} }`);
|
|
20272
|
+
}
|
|
19754
20273
|
function dedupGuard(ordinal) {
|
|
19755
20274
|
return `!(${ordinal} in __l) || !Object.is(__l[${ordinal}], __x)`;
|
|
19756
20275
|
}
|
|
19757
20276
|
function emitAttrBinding(lines, ind, a, mode) {
|
|
19758
|
-
|
|
20277
|
+
const target = mode === "create" ? `__r[${a.refIndex}]` : elementAccess(a);
|
|
20278
|
+
lines.push(`${ind}{ const __t = ${target}`);
|
|
19759
20279
|
lines.push(`${ind}if (__t) {`);
|
|
19760
20280
|
lines.push(`${ind} const __x = ${a.wrappedExpression}`);
|
|
19761
20281
|
const guard = mode === "create" ? null : mode === "item" ? dedupGuard(a.ordinal) : `__seed ? (${seedDiffersExpr("__t", a)}) : (${dedupGuard(a.ordinal)})`;
|
|
@@ -20752,7 +21272,7 @@ function buildPlainLoopPlan(elem, profileComponentName, lazyScope) {
|
|
|
20752
21272
|
const indexParam = elem.index || "__idx";
|
|
20753
21273
|
const mapPreambleWrapped = elem.preamble ? renderPreamble(elem.preamble, {
|
|
20754
21274
|
transformJs: wrap,
|
|
20755
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined
|
|
21275
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined)
|
|
20756
21276
|
}) : "";
|
|
20757
21277
|
const preambleRegions = buildPreambleRegionPlans(elem.preambleRegions, elem.param, elem.paramBindings);
|
|
20758
21278
|
return {
|
|
@@ -20829,7 +21349,7 @@ function buildStaticLoopMaterialize(elem, unsafeLocalNames) {
|
|
|
20829
21349
|
return {
|
|
20830
21350
|
itemTemplate: elem.staticItemTemplate,
|
|
20831
21351
|
mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
|
|
20832
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined
|
|
21352
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined)
|
|
20833
21353
|
}) : "",
|
|
20834
21354
|
bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false
|
|
20835
21355
|
};
|
|
@@ -21066,20 +21586,20 @@ var PHASES = [
|
|
|
21066
21586
|
];
|
|
21067
21587
|
|
|
21068
21588
|
// src/ir-to-client-js/rewrite-props-object.ts
|
|
21069
|
-
import
|
|
21589
|
+
import ts17 from "typescript";
|
|
21070
21590
|
function rewritePropsObjectRef(code, propsObjectName) {
|
|
21071
21591
|
const srcPropsName = propsObjectName ?? "props";
|
|
21072
21592
|
if (srcPropsName === PROPS_PARAM)
|
|
21073
21593
|
return code;
|
|
21074
21594
|
if (!new RegExp(`\\b${srcPropsName}\\b`).test(code))
|
|
21075
21595
|
return code;
|
|
21076
|
-
const sourceFile =
|
|
21596
|
+
const sourceFile = ts17.createSourceFile("init-body.ts", code, ts17.ScriptTarget.Latest, true, ts17.ScriptKind.TS);
|
|
21077
21597
|
const spans = [];
|
|
21078
21598
|
function visit3(node) {
|
|
21079
|
-
if (
|
|
21599
|
+
if (ts17.isIdentifier(node) && node.text === srcPropsName && shouldRewrite(node)) {
|
|
21080
21600
|
spans.push([node.getStart(sourceFile), node.getEnd()]);
|
|
21081
21601
|
}
|
|
21082
|
-
|
|
21602
|
+
ts17.forEachChild(node, visit3);
|
|
21083
21603
|
}
|
|
21084
21604
|
visit3(sourceFile);
|
|
21085
21605
|
if (spans.length === 0)
|
|
@@ -21095,17 +21615,17 @@ function shouldRewrite(node) {
|
|
|
21095
21615
|
const parent = node.parent;
|
|
21096
21616
|
if (!parent)
|
|
21097
21617
|
return true;
|
|
21098
|
-
if (
|
|
21618
|
+
if (ts17.isPropertyAccessExpression(parent) && parent.name === node)
|
|
21099
21619
|
return false;
|
|
21100
|
-
if (
|
|
21620
|
+
if (ts17.isPropertyAssignment(parent) && parent.name === node)
|
|
21101
21621
|
return false;
|
|
21102
|
-
if (
|
|
21622
|
+
if (ts17.isShorthandPropertyAssignment(parent) && parent.name === node)
|
|
21103
21623
|
return false;
|
|
21104
|
-
if (
|
|
21624
|
+
if (ts17.isPropertySignature(parent) && parent.name === node)
|
|
21105
21625
|
return false;
|
|
21106
|
-
if (
|
|
21626
|
+
if (ts17.isPropertyDeclaration(parent) && parent.name === node)
|
|
21107
21627
|
return false;
|
|
21108
|
-
if (
|
|
21628
|
+
if (ts17.isBindingElement(parent) && parent.name === node)
|
|
21109
21629
|
return false;
|
|
21110
21630
|
return true;
|
|
21111
21631
|
}
|
|
@@ -21449,7 +21969,7 @@ function generateTemplateOnlyMount(ir, ctx) {
|
|
|
21449
21969
|
}
|
|
21450
21970
|
if (!templateHtml) {
|
|
21451
21971
|
const csrInlinableConstants = csrInlinableConstantsFromCtx(ctx);
|
|
21452
|
-
templateHtml = generateCsrTemplate(ir.root, csrInlinableConstants, ctx,
|
|
21972
|
+
templateHtml = generateCsrTemplate(ir.root, csrInlinableConstants, ctx, restSpreadNames, ctx.propsObjectName, unsafeLocalNames);
|
|
21453
21973
|
}
|
|
21454
21974
|
if (!templateHtml) {
|
|
21455
21975
|
return "";
|
|
@@ -21735,7 +22255,7 @@ function walkIR2(node, visitor) {
|
|
|
21735
22255
|
}
|
|
21736
22256
|
|
|
21737
22257
|
// src/preprocess-inline-jsx-callbacks.ts
|
|
21738
|
-
import
|
|
22258
|
+
import ts18 from "typescript";
|
|
21739
22259
|
var SYNTHETIC_PREFIX = "BFInlineJsxCallback";
|
|
21740
22260
|
var MAX_FIXPOINT_ITERATIONS = 16;
|
|
21741
22261
|
function preprocessInlineJsxCallbacks(source, filePath) {
|
|
@@ -21757,8 +22277,8 @@ function preprocessInlineJsxCallbacks(source, filePath) {
|
|
|
21757
22277
|
return { source: current, errors, syntheticNames };
|
|
21758
22278
|
}
|
|
21759
22279
|
function runSinglePass(source, filePath, startingCounter) {
|
|
21760
|
-
const sourceFile =
|
|
21761
|
-
const hasUseClient = sourceFile.statements.some((stmt) =>
|
|
22280
|
+
const sourceFile = ts18.createSourceFile(filePath, source, ts18.ScriptTarget.Latest, true, ts18.ScriptKind.TSX);
|
|
22281
|
+
const hasUseClient = sourceFile.statements.some((stmt) => ts18.isExpressionStatement(stmt) && ts18.isStringLiteral(stmt.expression) && (stmt.expression.text === "use client" || stmt.expression.text === "'use client'"));
|
|
21762
22282
|
if (!hasUseClient) {
|
|
21763
22283
|
return { source, errors: [], syntheticNames: [], counterAfter: startingCounter };
|
|
21764
22284
|
}
|
|
@@ -21780,22 +22300,22 @@ function runSinglePass(source, filePath, startingCounter) {
|
|
|
21780
22300
|
}
|
|
21781
22301
|
}
|
|
21782
22302
|
function visit3(node) {
|
|
21783
|
-
if (
|
|
22303
|
+
if (ts18.isJsxAttribute(node) && node.initializer && ts18.isJsxExpression(node.initializer) && node.initializer.expression) {
|
|
21784
22304
|
if (tryHandleArrowValue(node.initializer.expression)) {
|
|
21785
22305
|
return;
|
|
21786
22306
|
}
|
|
21787
22307
|
}
|
|
21788
|
-
if (
|
|
22308
|
+
if (ts18.isPropertyAssignment(node) && node.initializer) {
|
|
21789
22309
|
if (tryHandleArrowValue(node.initializer))
|
|
21790
22310
|
return;
|
|
21791
22311
|
}
|
|
21792
|
-
|
|
22312
|
+
ts18.forEachChild(node, visit3);
|
|
21793
22313
|
}
|
|
21794
22314
|
function tryHandleArrowValue(initializer) {
|
|
21795
22315
|
let expr = initializer;
|
|
21796
|
-
while (
|
|
22316
|
+
while (ts18.isParenthesizedExpression(expr))
|
|
21797
22317
|
expr = expr.expression;
|
|
21798
|
-
if (
|
|
22318
|
+
if (ts18.isArrowFunction(expr) && arrowBodyContainsJsx(expr)) {
|
|
21799
22319
|
return handleInlineArrow(expr);
|
|
21800
22320
|
}
|
|
21801
22321
|
return false;
|
|
@@ -21832,7 +22352,7 @@ function runSinglePass(source, filePath, startingCounter) {
|
|
|
21832
22352
|
replacements.push({ start: arrowStart, end: arrowEnd, text: name });
|
|
21833
22353
|
return true;
|
|
21834
22354
|
}
|
|
21835
|
-
|
|
22355
|
+
ts18.forEachChild(sourceFile, visit3);
|
|
21836
22356
|
if (replacements.length === 0) {
|
|
21837
22357
|
return { source, errors, syntheticNames, counterAfter: counter };
|
|
21838
22358
|
}
|
|
@@ -21855,11 +22375,11 @@ function errorMessageForCapture(captures) {
|
|
|
21855
22375
|
return `Inline JSX-returning arrow function captures non-module identifier(s): ` + `${captures.sort().join(", ")}. ` + `Extract the callback into a top-level '\\'use client\\'' component (e.g. ` + `\`function MyNode(n) { return <div/> }\` then \`renderNode={MyNode}\`) ` + `or pass captured values via component props.`;
|
|
21856
22376
|
}
|
|
21857
22377
|
function arrowBodyContainsJsx(arrow) {
|
|
21858
|
-
if (
|
|
22378
|
+
if (ts18.isBlock(arrow.body)) {
|
|
21859
22379
|
return blockReturnsJsx(arrow.body);
|
|
21860
22380
|
}
|
|
21861
22381
|
let body = arrow.body;
|
|
21862
|
-
while (
|
|
22382
|
+
while (ts18.isParenthesizedExpression(body))
|
|
21863
22383
|
body = body.expression;
|
|
21864
22384
|
return isJsxLike(body);
|
|
21865
22385
|
}
|
|
@@ -21868,41 +22388,41 @@ function blockReturnsJsx(block) {
|
|
|
21868
22388
|
function visit3(n) {
|
|
21869
22389
|
if (found)
|
|
21870
22390
|
return;
|
|
21871
|
-
if (
|
|
22391
|
+
if (ts18.isReturnStatement(n) && n.expression) {
|
|
21872
22392
|
let e = n.expression;
|
|
21873
|
-
while (
|
|
22393
|
+
while (ts18.isParenthesizedExpression(e))
|
|
21874
22394
|
e = e.expression;
|
|
21875
22395
|
if (isJsxLike(e)) {
|
|
21876
22396
|
found = true;
|
|
21877
22397
|
return;
|
|
21878
22398
|
}
|
|
21879
22399
|
}
|
|
21880
|
-
if (
|
|
22400
|
+
if (ts18.isArrowFunction(n) || ts18.isFunctionDeclaration(n) || ts18.isFunctionExpression(n))
|
|
21881
22401
|
return;
|
|
21882
|
-
|
|
22402
|
+
ts18.forEachChild(n, visit3);
|
|
21883
22403
|
}
|
|
21884
|
-
|
|
22404
|
+
ts18.forEachChild(block, visit3);
|
|
21885
22405
|
return found;
|
|
21886
22406
|
}
|
|
21887
22407
|
function isJsxLike(expr) {
|
|
21888
|
-
return
|
|
22408
|
+
return ts18.isJsxElement(expr) || ts18.isJsxSelfClosingElement(expr) || ts18.isJsxFragment(expr);
|
|
21889
22409
|
}
|
|
21890
22410
|
function collectArrowParamNames(arrow) {
|
|
21891
22411
|
const names = new Set;
|
|
21892
22412
|
for (const p of arrow.parameters)
|
|
21893
|
-
|
|
22413
|
+
collectBindingNames3(p.name, names);
|
|
21894
22414
|
return names;
|
|
21895
22415
|
}
|
|
21896
|
-
function
|
|
22416
|
+
function collectBindingNames3(name, out) {
|
|
21897
22417
|
const push = Array.isArray(out) ? (n) => out.push(n) : (n) => out.add(n);
|
|
21898
|
-
if (
|
|
22418
|
+
if (ts18.isIdentifier(name)) {
|
|
21899
22419
|
push(name.text);
|
|
21900
|
-
} else if (
|
|
21901
|
-
name.elements.forEach((el) =>
|
|
21902
|
-
} else if (
|
|
22420
|
+
} else if (ts18.isObjectBindingPattern(name)) {
|
|
22421
|
+
name.elements.forEach((el) => collectBindingNames3(el.name, out));
|
|
22422
|
+
} else if (ts18.isArrayBindingPattern(name)) {
|
|
21903
22423
|
name.elements.forEach((el) => {
|
|
21904
|
-
if (!
|
|
21905
|
-
|
|
22424
|
+
if (!ts18.isOmittedExpression(el))
|
|
22425
|
+
collectBindingNames3(el.name, out);
|
|
21906
22426
|
});
|
|
21907
22427
|
}
|
|
21908
22428
|
}
|
|
@@ -21911,12 +22431,12 @@ function collectFreeIdentifiers(arrow) {
|
|
|
21911
22431
|
const bound = [];
|
|
21912
22432
|
for (const p of arrow.parameters) {
|
|
21913
22433
|
const names = [];
|
|
21914
|
-
|
|
22434
|
+
collectBindingNames3(p.name, names);
|
|
21915
22435
|
bound.push(...names);
|
|
21916
22436
|
}
|
|
21917
22437
|
function pushBindings(name) {
|
|
21918
22438
|
const names = [];
|
|
21919
|
-
|
|
22439
|
+
collectBindingNames3(name, names);
|
|
21920
22440
|
bound.push(...names);
|
|
21921
22441
|
return names;
|
|
21922
22442
|
}
|
|
@@ -21928,48 +22448,48 @@ function collectFreeIdentifiers(arrow) {
|
|
|
21928
22448
|
return bound.includes(name);
|
|
21929
22449
|
}
|
|
21930
22450
|
function visit3(node) {
|
|
21931
|
-
if (
|
|
22451
|
+
if (ts18.isIdentifier(node)) {
|
|
21932
22452
|
const parent = node.parent;
|
|
21933
|
-
if (parent &&
|
|
22453
|
+
if (parent && ts18.isPropertyAccessExpression(parent) && parent.name === node)
|
|
21934
22454
|
return;
|
|
21935
|
-
if (parent &&
|
|
22455
|
+
if (parent && ts18.isPropertyAssignment(parent) && parent.name === node)
|
|
21936
22456
|
return;
|
|
21937
|
-
if (parent &&
|
|
22457
|
+
if (parent && ts18.isPropertySignature(parent) && parent.name === node)
|
|
21938
22458
|
return;
|
|
21939
|
-
if (parent &&
|
|
22459
|
+
if (parent && ts18.isPropertyDeclaration(parent) && parent.name === node)
|
|
21940
22460
|
return;
|
|
21941
|
-
if (parent &&
|
|
22461
|
+
if (parent && ts18.isMethodDeclaration(parent) && parent.name === node)
|
|
21942
22462
|
return;
|
|
21943
|
-
if (parent &&
|
|
22463
|
+
if (parent && ts18.isMethodSignature(parent) && parent.name === node)
|
|
21944
22464
|
return;
|
|
21945
|
-
if (parent &&
|
|
22465
|
+
if (parent && ts18.isGetAccessorDeclaration(parent) && parent.name === node)
|
|
21946
22466
|
return;
|
|
21947
|
-
if (parent &&
|
|
22467
|
+
if (parent && ts18.isSetAccessorDeclaration(parent) && parent.name === node)
|
|
21948
22468
|
return;
|
|
21949
|
-
if (parent &&
|
|
22469
|
+
if (parent && ts18.isEnumMember(parent) && parent.name === node)
|
|
21950
22470
|
return;
|
|
21951
|
-
if (parent &&
|
|
22471
|
+
if (parent && ts18.isBindingElement(parent) && parent.propertyName === node)
|
|
21952
22472
|
return;
|
|
21953
|
-
if (parent &&
|
|
22473
|
+
if (parent && ts18.isShorthandPropertyAssignment(parent) && parent.name === node) {
|
|
21954
22474
|
if (!isBound(node.text))
|
|
21955
22475
|
ids.add(node.text);
|
|
21956
22476
|
return;
|
|
21957
22477
|
}
|
|
21958
|
-
if (parent &&
|
|
22478
|
+
if (parent && ts18.isParameter(parent) && parent.name === node)
|
|
21959
22479
|
return;
|
|
21960
|
-
if (parent &&
|
|
22480
|
+
if (parent && ts18.isVariableDeclaration(parent) && parent.name === node)
|
|
21961
22481
|
return;
|
|
21962
|
-
if (parent &&
|
|
22482
|
+
if (parent && ts18.isFunctionDeclaration(parent) && parent.name === node)
|
|
21963
22483
|
return;
|
|
21964
|
-
if (parent &&
|
|
22484
|
+
if (parent && ts18.isClassDeclaration(parent) && parent.name === node)
|
|
21965
22485
|
return;
|
|
21966
|
-
if (parent &&
|
|
22486
|
+
if (parent && ts18.isJsxAttribute(parent) && parent.name === node)
|
|
21967
22487
|
return;
|
|
21968
|
-
if (parent &&
|
|
22488
|
+
if (parent && ts18.isJsxOpeningElement(parent) && parent.tagName === node) {
|
|
21969
22489
|
if (/^[a-z]/.test(node.text))
|
|
21970
22490
|
return;
|
|
21971
22491
|
}
|
|
21972
|
-
if (parent &&
|
|
22492
|
+
if (parent && ts18.isJsxClosingElement(parent) && parent.tagName === node) {
|
|
21973
22493
|
if (/^[a-z]/.test(node.text))
|
|
21974
22494
|
return;
|
|
21975
22495
|
}
|
|
@@ -21978,43 +22498,43 @@ function collectFreeIdentifiers(arrow) {
|
|
|
21978
22498
|
ids.add(node.text);
|
|
21979
22499
|
return;
|
|
21980
22500
|
}
|
|
21981
|
-
if (
|
|
22501
|
+
if (ts18.isVariableDeclaration(node)) {
|
|
21982
22502
|
const declared = pushBindings(node.name);
|
|
21983
22503
|
if (node.initializer)
|
|
21984
22504
|
visit3(node.initializer);
|
|
21985
22505
|
return;
|
|
21986
22506
|
}
|
|
21987
|
-
if (
|
|
22507
|
+
if (ts18.isFunctionDeclaration(node)) {
|
|
21988
22508
|
if (node.name)
|
|
21989
22509
|
bound.push(node.name.text);
|
|
21990
22510
|
visitInsideNewScope(node);
|
|
21991
22511
|
return;
|
|
21992
22512
|
}
|
|
21993
|
-
if (
|
|
22513
|
+
if (ts18.isClassDeclaration(node)) {
|
|
21994
22514
|
if (node.name)
|
|
21995
22515
|
bound.push(node.name.text);
|
|
21996
|
-
|
|
22516
|
+
ts18.forEachChild(node, visit3);
|
|
21997
22517
|
return;
|
|
21998
22518
|
}
|
|
21999
|
-
if (
|
|
22519
|
+
if (ts18.isArrowFunction(node) || ts18.isFunctionExpression(node)) {
|
|
22000
22520
|
visitInsideNewScope(node);
|
|
22001
22521
|
return;
|
|
22002
22522
|
}
|
|
22003
|
-
if (
|
|
22523
|
+
if (ts18.isCatchClause(node)) {
|
|
22004
22524
|
const before = bound.length;
|
|
22005
22525
|
if (node.variableDeclaration)
|
|
22006
22526
|
pushBindings(node.variableDeclaration.name);
|
|
22007
|
-
|
|
22527
|
+
ts18.forEachChild(node, visit3);
|
|
22008
22528
|
popN(bound.length - before);
|
|
22009
22529
|
return;
|
|
22010
22530
|
}
|
|
22011
|
-
if (
|
|
22531
|
+
if (ts18.isBlock(node)) {
|
|
22012
22532
|
const before = bound.length;
|
|
22013
|
-
|
|
22533
|
+
ts18.forEachChild(node, visit3);
|
|
22014
22534
|
popN(bound.length - before);
|
|
22015
22535
|
return;
|
|
22016
22536
|
}
|
|
22017
|
-
|
|
22537
|
+
ts18.forEachChild(node, visit3);
|
|
22018
22538
|
}
|
|
22019
22539
|
function visitInsideNewScope(fn) {
|
|
22020
22540
|
const before = bound.length;
|
|
@@ -22037,29 +22557,29 @@ function collectFreeIdentifiers(arrow) {
|
|
|
22037
22557
|
function collectModuleScopeNames(sourceFile) {
|
|
22038
22558
|
const names = new Set;
|
|
22039
22559
|
for (const stmt of sourceFile.statements) {
|
|
22040
|
-
if (
|
|
22560
|
+
if (ts18.isFunctionDeclaration(stmt) && stmt.name)
|
|
22041
22561
|
names.add(stmt.name.text);
|
|
22042
|
-
else if (
|
|
22562
|
+
else if (ts18.isClassDeclaration(stmt) && stmt.name)
|
|
22043
22563
|
names.add(stmt.name.text);
|
|
22044
|
-
else if (
|
|
22564
|
+
else if (ts18.isVariableStatement(stmt)) {
|
|
22045
22565
|
for (const decl of stmt.declarationList.declarations)
|
|
22046
|
-
|
|
22047
|
-
} else if (
|
|
22566
|
+
collectBindingNames3(decl.name, names);
|
|
22567
|
+
} else if (ts18.isImportDeclaration(stmt) && stmt.importClause) {
|
|
22048
22568
|
const ic = stmt.importClause;
|
|
22049
22569
|
if (ic.name)
|
|
22050
22570
|
names.add(ic.name.text);
|
|
22051
22571
|
if (ic.namedBindings) {
|
|
22052
|
-
if (
|
|
22572
|
+
if (ts18.isNamespaceImport(ic.namedBindings))
|
|
22053
22573
|
names.add(ic.namedBindings.name.text);
|
|
22054
22574
|
else
|
|
22055
22575
|
for (const e of ic.namedBindings.elements)
|
|
22056
22576
|
names.add(e.name.text);
|
|
22057
22577
|
}
|
|
22058
|
-
} else if (
|
|
22578
|
+
} else if (ts18.isTypeAliasDeclaration(stmt))
|
|
22059
22579
|
names.add(stmt.name.text);
|
|
22060
|
-
else if (
|
|
22580
|
+
else if (ts18.isInterfaceDeclaration(stmt))
|
|
22061
22581
|
names.add(stmt.name.text);
|
|
22062
|
-
else if (
|
|
22582
|
+
else if (ts18.isEnumDeclaration(stmt))
|
|
22063
22583
|
names.add(stmt.name.text);
|
|
22064
22584
|
}
|
|
22065
22585
|
return names;
|
|
@@ -22067,7 +22587,7 @@ function collectModuleScopeNames(sourceFile) {
|
|
|
22067
22587
|
function buildSyntheticDeclaration(name, arrow, sourceFile) {
|
|
22068
22588
|
const paramsText = arrow.parameters.length === 0 ? "" : arrow.parameters.map((p) => p.getText(sourceFile)).join(", ");
|
|
22069
22589
|
let bodyText;
|
|
22070
|
-
if (
|
|
22590
|
+
if (ts18.isBlock(arrow.body)) {
|
|
22071
22591
|
bodyText = arrow.body.getText(sourceFile);
|
|
22072
22592
|
} else {
|
|
22073
22593
|
const expr = arrow.body.getText(sourceFile);
|
|
@@ -22077,7 +22597,7 @@ function buildSyntheticDeclaration(name, arrow, sourceFile) {
|
|
|
22077
22597
|
}
|
|
22078
22598
|
|
|
22079
22599
|
// src/ssr-defaults.ts
|
|
22080
|
-
import
|
|
22600
|
+
import ts19 from "typescript";
|
|
22081
22601
|
var UNRESOLVED = Symbol("unresolved");
|
|
22082
22602
|
var NO_RETURN = Symbol("no-return");
|
|
22083
22603
|
function extractSsrDefaults(metadata) {
|
|
@@ -22090,11 +22610,12 @@ function extractSsrDefaults(metadata) {
|
|
|
22090
22610
|
for (const p of metadata.propsParams) {
|
|
22091
22611
|
if (p.isRest)
|
|
22092
22612
|
continue;
|
|
22613
|
+
const callerPropName = p.sourceName ?? p.name;
|
|
22093
22614
|
if (metadata.propsObjectName === null && p.defaultValue !== undefined) {
|
|
22094
22615
|
const value = tryStaticEval(p.defaultValue, { bindings: {}, propsLike });
|
|
22095
|
-
out[p.name] = { propName:
|
|
22616
|
+
out[p.name] = { propName: callerPropName, value: resultToJsonable(value) };
|
|
22096
22617
|
} else {
|
|
22097
|
-
out[p.name] = { propName:
|
|
22618
|
+
out[p.name] = { propName: callerPropName, value: null };
|
|
22098
22619
|
}
|
|
22099
22620
|
}
|
|
22100
22621
|
if (metadata.restPropsName) {
|
|
@@ -22153,11 +22674,11 @@ function collectPropRefs(expr, propsObjectName, out) {
|
|
|
22153
22674
|
if (!node)
|
|
22154
22675
|
return;
|
|
22155
22676
|
const visit3 = (n) => {
|
|
22156
|
-
if (
|
|
22677
|
+
if (ts19.isPropertyAccessExpression(n) && ts19.isIdentifier(n.expression) && n.expression.text === propsObjectName && ts19.isIdentifier(n.name)) {
|
|
22157
22678
|
out.add(n.name.text);
|
|
22158
22679
|
return;
|
|
22159
22680
|
}
|
|
22160
|
-
|
|
22681
|
+
ts19.forEachChild(n, visit3);
|
|
22161
22682
|
};
|
|
22162
22683
|
visit3(node);
|
|
22163
22684
|
}
|
|
@@ -22178,23 +22699,23 @@ function tryStaticEval(expr, ctx) {
|
|
|
22178
22699
|
}
|
|
22179
22700
|
function evalStatementsForReturn(statements, ctx) {
|
|
22180
22701
|
for (const stmt of statements) {
|
|
22181
|
-
if (
|
|
22702
|
+
if (ts19.isVariableStatement(stmt)) {
|
|
22182
22703
|
for (const d of stmt.declarationList.declarations) {
|
|
22183
|
-
if (!
|
|
22704
|
+
if (!ts19.isIdentifier(d.name) || !d.initializer)
|
|
22184
22705
|
continue;
|
|
22185
22706
|
const v = evalNode(d.initializer, ctx);
|
|
22186
22707
|
if (v !== UNRESOLVED)
|
|
22187
22708
|
ctx.bindings[d.name.text] = v;
|
|
22188
22709
|
}
|
|
22189
|
-
} else if (
|
|
22710
|
+
} else if (ts19.isReturnStatement(stmt)) {
|
|
22190
22711
|
return stmt.expression ? evalNode(stmt.expression, ctx) : UNRESOLVED;
|
|
22191
|
-
} else if (
|
|
22712
|
+
} else if (ts19.isIfStatement(stmt)) {
|
|
22192
22713
|
const cond = evalNode(stmt.expression, ctx);
|
|
22193
22714
|
if (cond === UNRESOLVED)
|
|
22194
22715
|
return UNRESOLVED;
|
|
22195
22716
|
const branch = cond ? stmt.thenStatement : stmt.elseStatement;
|
|
22196
22717
|
if (branch) {
|
|
22197
|
-
const taken = evalStatementsForReturn(
|
|
22718
|
+
const taken = evalStatementsForReturn(ts19.isBlock(branch) ? branch.statements : [branch], ctx);
|
|
22198
22719
|
if (taken !== NO_RETURN)
|
|
22199
22720
|
return taken;
|
|
22200
22721
|
}
|
|
@@ -22205,45 +22726,45 @@ function evalStatementsForReturn(statements, ctx) {
|
|
|
22205
22726
|
return NO_RETURN;
|
|
22206
22727
|
}
|
|
22207
22728
|
function parseExpression2(expr) {
|
|
22208
|
-
const sf =
|
|
22729
|
+
const sf = ts19.createSourceFile("__ssr_default__.ts", `(${expr})`, ts19.ScriptTarget.Latest, false, ts19.ScriptKind.TS);
|
|
22209
22730
|
const stmt = sf.statements[0];
|
|
22210
|
-
if (!stmt || !
|
|
22731
|
+
if (!stmt || !ts19.isExpressionStatement(stmt))
|
|
22211
22732
|
return null;
|
|
22212
|
-
const inner =
|
|
22733
|
+
const inner = ts19.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
|
|
22213
22734
|
return inner;
|
|
22214
22735
|
}
|
|
22215
22736
|
function evalNode(node, ctx) {
|
|
22216
|
-
if (
|
|
22737
|
+
if (ts19.isParenthesizedExpression(node))
|
|
22217
22738
|
return evalNode(node.expression, ctx);
|
|
22218
|
-
if (
|
|
22739
|
+
if (ts19.isAsExpression(node))
|
|
22219
22740
|
return evalNode(node.expression, ctx);
|
|
22220
|
-
if (
|
|
22741
|
+
if (ts19.isSatisfiesExpression(node))
|
|
22221
22742
|
return evalNode(node.expression, ctx);
|
|
22222
|
-
if (
|
|
22743
|
+
if (ts19.isTypeAssertionExpression(node))
|
|
22223
22744
|
return evalNode(node.expression, ctx);
|
|
22224
|
-
if (
|
|
22745
|
+
if (ts19.isNonNullExpression(node))
|
|
22225
22746
|
return evalNode(node.expression, ctx);
|
|
22226
|
-
if (
|
|
22747
|
+
if (ts19.isArrowFunction(node)) {
|
|
22227
22748
|
if (node.parameters.length !== 0)
|
|
22228
22749
|
return UNRESOLVED;
|
|
22229
|
-
if (!
|
|
22750
|
+
if (!ts19.isBlock(node.body))
|
|
22230
22751
|
return evalNode(node.body, ctx);
|
|
22231
22752
|
const localBindings = { ...ctx.bindings };
|
|
22232
22753
|
const localCtx = { ...ctx, bindings: localBindings };
|
|
22233
22754
|
const result = evalStatementsForReturn(node.body.statements, localCtx);
|
|
22234
22755
|
return result === NO_RETURN ? UNRESOLVED : result;
|
|
22235
22756
|
}
|
|
22236
|
-
if (
|
|
22757
|
+
if (ts19.isNumericLiteral(node))
|
|
22237
22758
|
return Number(node.text);
|
|
22238
|
-
if (
|
|
22759
|
+
if (ts19.isStringLiteralLike(node))
|
|
22239
22760
|
return node.text;
|
|
22240
|
-
if (node.kind ===
|
|
22761
|
+
if (node.kind === ts19.SyntaxKind.TrueKeyword)
|
|
22241
22762
|
return true;
|
|
22242
|
-
if (node.kind ===
|
|
22763
|
+
if (node.kind === ts19.SyntaxKind.FalseKeyword)
|
|
22243
22764
|
return false;
|
|
22244
|
-
if (node.kind ===
|
|
22765
|
+
if (node.kind === ts19.SyntaxKind.NullKeyword)
|
|
22245
22766
|
return null;
|
|
22246
|
-
if (
|
|
22767
|
+
if (ts19.isIdentifier(node)) {
|
|
22247
22768
|
if (node.text === "undefined")
|
|
22248
22769
|
return;
|
|
22249
22770
|
if (node.text in ctx.bindings)
|
|
@@ -22252,29 +22773,29 @@ function evalNode(node, ctx) {
|
|
|
22252
22773
|
return;
|
|
22253
22774
|
return UNRESOLVED;
|
|
22254
22775
|
}
|
|
22255
|
-
if (
|
|
22776
|
+
if (ts19.isPrefixUnaryExpression(node)) {
|
|
22256
22777
|
const arg = evalNode(node.operand, ctx);
|
|
22257
22778
|
if (arg === UNRESOLVED)
|
|
22258
22779
|
return UNRESOLVED;
|
|
22259
22780
|
switch (node.operator) {
|
|
22260
|
-
case
|
|
22781
|
+
case ts19.SyntaxKind.MinusToken:
|
|
22261
22782
|
return typeof arg === "number" ? -arg : UNRESOLVED;
|
|
22262
|
-
case
|
|
22783
|
+
case ts19.SyntaxKind.PlusToken:
|
|
22263
22784
|
return typeof arg === "number" ? +arg : UNRESOLVED;
|
|
22264
|
-
case
|
|
22785
|
+
case ts19.SyntaxKind.ExclamationToken:
|
|
22265
22786
|
return !arg;
|
|
22266
22787
|
}
|
|
22267
22788
|
return UNRESOLVED;
|
|
22268
22789
|
}
|
|
22269
|
-
if (
|
|
22790
|
+
if (ts19.isObjectLiteralExpression(node)) {
|
|
22270
22791
|
const obj = {};
|
|
22271
22792
|
for (const prop of node.properties) {
|
|
22272
|
-
if (!
|
|
22793
|
+
if (!ts19.isPropertyAssignment(prop))
|
|
22273
22794
|
return UNRESOLVED;
|
|
22274
22795
|
let key;
|
|
22275
|
-
if (
|
|
22796
|
+
if (ts19.isIdentifier(prop.name) || ts19.isStringLiteralLike(prop.name)) {
|
|
22276
22797
|
key = prop.name.text;
|
|
22277
|
-
} else if (
|
|
22798
|
+
} else if (ts19.isNumericLiteral(prop.name)) {
|
|
22278
22799
|
key = prop.name.text;
|
|
22279
22800
|
} else {
|
|
22280
22801
|
return UNRESOLVED;
|
|
@@ -22286,10 +22807,10 @@ function evalNode(node, ctx) {
|
|
|
22286
22807
|
}
|
|
22287
22808
|
return obj;
|
|
22288
22809
|
}
|
|
22289
|
-
if (
|
|
22810
|
+
if (ts19.isArrayLiteralExpression(node)) {
|
|
22290
22811
|
const arr = [];
|
|
22291
22812
|
for (const elem of node.elements) {
|
|
22292
|
-
if (
|
|
22813
|
+
if (ts19.isOmittedExpression(elem))
|
|
22293
22814
|
return UNRESOLVED;
|
|
22294
22815
|
const v = evalNode(elem, ctx);
|
|
22295
22816
|
if (v === UNRESOLVED)
|
|
@@ -22298,7 +22819,7 @@ function evalNode(node, ctx) {
|
|
|
22298
22819
|
}
|
|
22299
22820
|
return arr;
|
|
22300
22821
|
}
|
|
22301
|
-
if (
|
|
22822
|
+
if (ts19.isElementAccessExpression(node)) {
|
|
22302
22823
|
const base = evalNode(node.expression, ctx);
|
|
22303
22824
|
if (base === undefined)
|
|
22304
22825
|
return;
|
|
@@ -22312,17 +22833,17 @@ function evalNode(node, ctx) {
|
|
|
22312
22833
|
const k = String(key);
|
|
22313
22834
|
return Object.prototype.hasOwnProperty.call(base, k) ? base[k] : undefined;
|
|
22314
22835
|
}
|
|
22315
|
-
if (
|
|
22836
|
+
if (ts19.isPropertyAccessExpression(node)) {
|
|
22316
22837
|
const baseResult = evalNode(node.expression, ctx);
|
|
22317
22838
|
if (baseResult === undefined)
|
|
22318
22839
|
return;
|
|
22319
22840
|
return UNRESOLVED;
|
|
22320
22841
|
}
|
|
22321
|
-
if (
|
|
22322
|
-
if (node.arguments.length === 0 &&
|
|
22842
|
+
if (ts19.isCallExpression(node)) {
|
|
22843
|
+
if (node.arguments.length === 0 && ts19.isIdentifier(node.expression) && node.expression.text in ctx.bindings) {
|
|
22323
22844
|
return ctx.bindings[node.expression.text];
|
|
22324
22845
|
}
|
|
22325
|
-
if (
|
|
22846
|
+
if (ts19.isPropertyAccessExpression(node.expression) && node.expression.name.text === "join") {
|
|
22326
22847
|
const recv = evalNode(node.expression.expression, ctx);
|
|
22327
22848
|
if (Array.isArray(recv)) {
|
|
22328
22849
|
let sep2 = ",";
|
|
@@ -22338,27 +22859,27 @@ function evalNode(node, ctx) {
|
|
|
22338
22859
|
}
|
|
22339
22860
|
return UNRESOLVED;
|
|
22340
22861
|
}
|
|
22341
|
-
if (
|
|
22862
|
+
if (ts19.isConditionalExpression(node)) {
|
|
22342
22863
|
const cond = evalNode(node.condition, ctx);
|
|
22343
22864
|
if (cond === UNRESOLVED)
|
|
22344
22865
|
return UNRESOLVED;
|
|
22345
22866
|
return cond ? evalNode(node.whenTrue, ctx) : evalNode(node.whenFalse, ctx);
|
|
22346
22867
|
}
|
|
22347
|
-
if (
|
|
22868
|
+
if (ts19.isBinaryExpression(node)) {
|
|
22348
22869
|
const op = node.operatorToken.kind;
|
|
22349
|
-
if (op ===
|
|
22870
|
+
if (op === ts19.SyntaxKind.QuestionQuestionToken) {
|
|
22350
22871
|
const l2 = evalNode(node.left, ctx);
|
|
22351
22872
|
if (l2 !== UNRESOLVED && l2 !== null && l2 !== undefined)
|
|
22352
22873
|
return l2;
|
|
22353
22874
|
return evalNode(node.right, ctx);
|
|
22354
22875
|
}
|
|
22355
|
-
if (op ===
|
|
22876
|
+
if (op === ts19.SyntaxKind.BarBarToken) {
|
|
22356
22877
|
const l2 = evalNode(node.left, ctx);
|
|
22357
22878
|
if (l2 !== UNRESOLVED && l2)
|
|
22358
22879
|
return l2;
|
|
22359
22880
|
return evalNode(node.right, ctx);
|
|
22360
22881
|
}
|
|
22361
|
-
if (op ===
|
|
22882
|
+
if (op === ts19.SyntaxKind.AmpersandAmpersandToken) {
|
|
22362
22883
|
const l2 = evalNode(node.left, ctx);
|
|
22363
22884
|
if (l2 === UNRESOLVED)
|
|
22364
22885
|
return UNRESOLVED;
|
|
@@ -22371,30 +22892,30 @@ function evalNode(node, ctx) {
|
|
|
22371
22892
|
if (l === UNRESOLVED || r === UNRESOLVED)
|
|
22372
22893
|
return UNRESOLVED;
|
|
22373
22894
|
switch (op) {
|
|
22374
|
-
case
|
|
22895
|
+
case ts19.SyntaxKind.PlusToken:
|
|
22375
22896
|
if (typeof l === "string" || typeof r === "string")
|
|
22376
22897
|
return `${l}${r}`;
|
|
22377
22898
|
if (typeof l === "number" && typeof r === "number")
|
|
22378
22899
|
return l + r;
|
|
22379
22900
|
return UNRESOLVED;
|
|
22380
|
-
case
|
|
22901
|
+
case ts19.SyntaxKind.MinusToken:
|
|
22381
22902
|
return typeof l === "number" && typeof r === "number" ? l - r : UNRESOLVED;
|
|
22382
|
-
case
|
|
22903
|
+
case ts19.SyntaxKind.AsteriskToken:
|
|
22383
22904
|
return typeof l === "number" && typeof r === "number" ? l * r : UNRESOLVED;
|
|
22384
|
-
case
|
|
22905
|
+
case ts19.SyntaxKind.SlashToken:
|
|
22385
22906
|
return typeof l === "number" && typeof r === "number" && r !== 0 ? l / r : UNRESOLVED;
|
|
22386
|
-
case
|
|
22907
|
+
case ts19.SyntaxKind.PercentToken:
|
|
22387
22908
|
return typeof l === "number" && typeof r === "number" && r !== 0 ? l % r : UNRESOLVED;
|
|
22388
|
-
case
|
|
22389
|
-
case
|
|
22909
|
+
case ts19.SyntaxKind.EqualsEqualsEqualsToken:
|
|
22910
|
+
case ts19.SyntaxKind.EqualsEqualsToken:
|
|
22390
22911
|
return l === r;
|
|
22391
|
-
case
|
|
22392
|
-
case
|
|
22912
|
+
case ts19.SyntaxKind.ExclamationEqualsEqualsToken:
|
|
22913
|
+
case ts19.SyntaxKind.ExclamationEqualsToken:
|
|
22393
22914
|
return l !== r;
|
|
22394
22915
|
}
|
|
22395
22916
|
return UNRESOLVED;
|
|
22396
22917
|
}
|
|
22397
|
-
if (
|
|
22918
|
+
if (ts19.isTemplateExpression(node)) {
|
|
22398
22919
|
if (node.templateSpans.length === 0)
|
|
22399
22920
|
return node.head.text;
|
|
22400
22921
|
let acc = node.head.text;
|
|
@@ -22406,13 +22927,13 @@ function evalNode(node, ctx) {
|
|
|
22406
22927
|
}
|
|
22407
22928
|
return acc;
|
|
22408
22929
|
}
|
|
22409
|
-
if (
|
|
22930
|
+
if (ts19.isNoSubstitutionTemplateLiteral(node))
|
|
22410
22931
|
return node.text;
|
|
22411
22932
|
return UNRESOLVED;
|
|
22412
22933
|
}
|
|
22413
22934
|
|
|
22414
22935
|
// src/augment-inherited-props.ts
|
|
22415
|
-
import
|
|
22936
|
+
import ts20 from "typescript";
|
|
22416
22937
|
function collectContextConsumers(metadata) {
|
|
22417
22938
|
const constants = metadata.localConstants ?? [];
|
|
22418
22939
|
const contextDefaults = new Map;
|
|
@@ -22444,47 +22965,47 @@ function collectContextConsumers(metadata) {
|
|
|
22444
22965
|
}
|
|
22445
22966
|
function parseUseContextArg(source) {
|
|
22446
22967
|
const expr = parseSingleExpression(source);
|
|
22447
|
-
if (!expr || !
|
|
22968
|
+
if (!expr || !ts20.isCallExpression(expr))
|
|
22448
22969
|
return null;
|
|
22449
|
-
if (!
|
|
22970
|
+
if (!ts20.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
|
|
22450
22971
|
return null;
|
|
22451
22972
|
if (expr.arguments.length !== 1)
|
|
22452
22973
|
return null;
|
|
22453
22974
|
const arg = expr.arguments[0];
|
|
22454
|
-
return
|
|
22975
|
+
return ts20.isIdentifier(arg) ? arg.text : null;
|
|
22455
22976
|
}
|
|
22456
22977
|
function parseCreateContextDefault(source) {
|
|
22457
22978
|
const expr = parseSingleExpression(source);
|
|
22458
|
-
if (!expr || !
|
|
22979
|
+
if (!expr || !ts20.isCallExpression(expr))
|
|
22459
22980
|
return null;
|
|
22460
22981
|
if (expr.arguments.length === 0)
|
|
22461
22982
|
return null;
|
|
22462
22983
|
const arg = expr.arguments[0];
|
|
22463
|
-
if (
|
|
22984
|
+
if (ts20.isStringLiteral(arg) || ts20.isNoSubstitutionTemplateLiteral(arg))
|
|
22464
22985
|
return arg.text;
|
|
22465
|
-
if (
|
|
22986
|
+
if (ts20.isNumericLiteral(arg))
|
|
22466
22987
|
return Number(arg.text);
|
|
22467
|
-
if (arg.kind ===
|
|
22988
|
+
if (arg.kind === ts20.SyntaxKind.TrueKeyword)
|
|
22468
22989
|
return true;
|
|
22469
|
-
if (arg.kind ===
|
|
22990
|
+
if (arg.kind === ts20.SyntaxKind.FalseKeyword)
|
|
22470
22991
|
return false;
|
|
22471
22992
|
return null;
|
|
22472
22993
|
}
|
|
22473
22994
|
function isObjectLiteralCreateContextDefault(source) {
|
|
22474
22995
|
const expr = parseSingleExpression(source);
|
|
22475
|
-
if (!expr || !
|
|
22996
|
+
if (!expr || !ts20.isCallExpression(expr))
|
|
22476
22997
|
return false;
|
|
22477
22998
|
if (expr.arguments.length === 0)
|
|
22478
22999
|
return false;
|
|
22479
|
-
return
|
|
23000
|
+
return ts20.isObjectLiteralExpression(expr.arguments[0]);
|
|
22480
23001
|
}
|
|
22481
23002
|
function parseSingleExpression(source) {
|
|
22482
|
-
const sf =
|
|
23003
|
+
const sf = ts20.createSourceFile("__ctx.ts", `(${source})`, ts20.ScriptTarget.Latest, false);
|
|
22483
23004
|
const stmt = sf.statements[0];
|
|
22484
|
-
if (!stmt || !
|
|
23005
|
+
if (!stmt || !ts20.isExpressionStatement(stmt))
|
|
22485
23006
|
return null;
|
|
22486
23007
|
let e = stmt.expression;
|
|
22487
|
-
while (
|
|
23008
|
+
while (ts20.isParenthesizedExpression(e))
|
|
22488
23009
|
e = e.expression;
|
|
22489
23010
|
return e;
|
|
22490
23011
|
}
|
|
@@ -22509,25 +23030,25 @@ function augmentInheritedPropAccesses(ir) {
|
|
|
22509
23030
|
const pinCoalesceLiterals = (s) => {
|
|
22510
23031
|
if (!s || !s.includes(propsObj))
|
|
22511
23032
|
return;
|
|
22512
|
-
const sf =
|
|
23033
|
+
const sf = ts20.createSourceFile("__aug.ts", `(${s})`, ts20.ScriptTarget.Latest, false);
|
|
22513
23034
|
const visit3 = (n) => {
|
|
22514
|
-
if (
|
|
23035
|
+
if (ts20.isBinaryExpression(n) && (n.operatorToken.kind === ts20.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts20.SyntaxKind.BarBarToken)) {
|
|
22515
23036
|
let left = n.left;
|
|
22516
|
-
while (
|
|
23037
|
+
while (ts20.isParenthesizedExpression(left))
|
|
22517
23038
|
left = left.expression;
|
|
22518
|
-
if (
|
|
23039
|
+
if (ts20.isPropertyAccessExpression(left) && ts20.isIdentifier(left.expression) && left.expression.text === propsObj) {
|
|
22519
23040
|
const name = left.name.text;
|
|
22520
23041
|
let right = n.right;
|
|
22521
|
-
while (
|
|
23042
|
+
while (ts20.isParenthesizedExpression(right))
|
|
22522
23043
|
right = right.expression;
|
|
22523
|
-
if (
|
|
23044
|
+
if (ts20.isPrefixUnaryExpression(right))
|
|
22524
23045
|
right = right.operand;
|
|
22525
|
-
const kind =
|
|
23046
|
+
const kind = ts20.isNumericLiteral(right) ? "number" : right.kind === ts20.SyntaxKind.TrueKeyword || right.kind === ts20.SyntaxKind.FalseKeyword ? "boolean" : ts20.isStringLiteralLike(right) ? "string" : null;
|
|
22526
23047
|
if (kind && !coalesceLiteralTypes.has(name))
|
|
22527
23048
|
coalesceLiteralTypes.set(name, kind);
|
|
22528
23049
|
}
|
|
22529
23050
|
}
|
|
22530
|
-
|
|
23051
|
+
ts20.forEachChild(n, visit3);
|
|
22531
23052
|
};
|
|
22532
23053
|
visit3(sf);
|
|
22533
23054
|
};
|
|
@@ -22638,33 +23159,33 @@ function augmentInheritedPropAccesses(ir) {
|
|
|
22638
23159
|
}
|
|
22639
23160
|
}
|
|
22640
23161
|
function parseStaticStringConst(source) {
|
|
22641
|
-
const sf =
|
|
23162
|
+
const sf = ts20.createSourceFile("__const.ts", `const __x = (${source});`, ts20.ScriptTarget.Latest, false);
|
|
22642
23163
|
const stmt = sf.statements[0];
|
|
22643
|
-
if (!stmt || !
|
|
23164
|
+
if (!stmt || !ts20.isVariableStatement(stmt))
|
|
22644
23165
|
return null;
|
|
22645
23166
|
let init = stmt.declarationList.declarations[0]?.initializer;
|
|
22646
|
-
while (init &&
|
|
23167
|
+
while (init && ts20.isParenthesizedExpression(init))
|
|
22647
23168
|
init = init.expression;
|
|
22648
23169
|
if (!init)
|
|
22649
23170
|
return null;
|
|
22650
|
-
if (
|
|
23171
|
+
if (ts20.isStringLiteral(init) || ts20.isNoSubstitutionTemplateLiteral(init)) {
|
|
22651
23172
|
return init.text;
|
|
22652
23173
|
}
|
|
22653
23174
|
return evalStringArrayJoin(source);
|
|
22654
23175
|
}
|
|
22655
23176
|
function evalTemplateOfStringConsts(source, resolved) {
|
|
22656
|
-
const sf =
|
|
23177
|
+
const sf = ts20.createSourceFile("__const.ts", `const __x = (${source});`, ts20.ScriptTarget.Latest, false);
|
|
22657
23178
|
const stmt = sf.statements[0];
|
|
22658
|
-
if (!stmt || !
|
|
23179
|
+
if (!stmt || !ts20.isVariableStatement(stmt))
|
|
22659
23180
|
return null;
|
|
22660
23181
|
let init = stmt.declarationList.declarations[0]?.initializer;
|
|
22661
|
-
while (init &&
|
|
23182
|
+
while (init && ts20.isParenthesizedExpression(init))
|
|
22662
23183
|
init = init.expression;
|
|
22663
|
-
if (!init || !
|
|
23184
|
+
if (!init || !ts20.isTemplateExpression(init))
|
|
22664
23185
|
return null;
|
|
22665
23186
|
let out = init.head.text;
|
|
22666
23187
|
for (const span of init.templateSpans) {
|
|
22667
|
-
if (!
|
|
23188
|
+
if (!ts20.isIdentifier(span.expression))
|
|
22668
23189
|
return null;
|
|
22669
23190
|
const value = resolved.get(span.expression.text);
|
|
22670
23191
|
if (value === undefined)
|
|
@@ -22695,30 +23216,30 @@ function lookupStaticRecordLiteral(objectName, key, constants) {
|
|
|
22695
23216
|
const constInfo = (constants ?? []).find((c) => c.name === objectName && c.isModule);
|
|
22696
23217
|
if (constInfo?.value === undefined)
|
|
22697
23218
|
return null;
|
|
22698
|
-
const sf =
|
|
23219
|
+
const sf = ts20.createSourceFile("__rec.ts", `(${constInfo.value})`, ts20.ScriptTarget.Latest, true);
|
|
22699
23220
|
if (sf.statements.length !== 1)
|
|
22700
23221
|
return null;
|
|
22701
23222
|
const stmt = sf.statements[0];
|
|
22702
|
-
if (!
|
|
23223
|
+
if (!ts20.isExpressionStatement(stmt))
|
|
22703
23224
|
return null;
|
|
22704
23225
|
let parsed = stmt.expression;
|
|
22705
|
-
while (
|
|
23226
|
+
while (ts20.isParenthesizedExpression(parsed))
|
|
22706
23227
|
parsed = parsed.expression;
|
|
22707
|
-
if (!
|
|
23228
|
+
if (!ts20.isObjectLiteralExpression(parsed))
|
|
22708
23229
|
return null;
|
|
22709
23230
|
for (const prop of parsed.properties) {
|
|
22710
|
-
if (!
|
|
23231
|
+
if (!ts20.isPropertyAssignment(prop))
|
|
22711
23232
|
continue;
|
|
22712
23233
|
const name = prop.name;
|
|
22713
|
-
const propKey =
|
|
23234
|
+
const propKey = ts20.isIdentifier(name) || ts20.isStringLiteral(name) || ts20.isNoSubstitutionTemplateLiteral(name) ? name.text : null;
|
|
22714
23235
|
if (propKey !== key)
|
|
22715
23236
|
continue;
|
|
22716
23237
|
let v = prop.initializer;
|
|
22717
|
-
while (
|
|
23238
|
+
while (ts20.isParenthesizedExpression(v))
|
|
22718
23239
|
v = v.expression;
|
|
22719
|
-
if (
|
|
23240
|
+
if (ts20.isNumericLiteral(v))
|
|
22720
23241
|
return { kind: "number", text: v.text };
|
|
22721
|
-
if (
|
|
23242
|
+
if (ts20.isStringLiteral(v) || ts20.isNoSubstitutionTemplateLiteral(v)) {
|
|
22722
23243
|
return { kind: "string", text: v.text };
|
|
22723
23244
|
}
|
|
22724
23245
|
return null;
|
|
@@ -22726,28 +23247,28 @@ function lookupStaticRecordLiteral(objectName, key, constants) {
|
|
|
22726
23247
|
return null;
|
|
22727
23248
|
}
|
|
22728
23249
|
function evalStringArrayJoin(source) {
|
|
22729
|
-
const sf =
|
|
23250
|
+
const sf = ts20.createSourceFile("__join.ts", `const __x = (${source});`, ts20.ScriptTarget.Latest, false);
|
|
22730
23251
|
const stmt = sf.statements[0];
|
|
22731
|
-
if (!stmt || !
|
|
23252
|
+
if (!stmt || !ts20.isVariableStatement(stmt))
|
|
22732
23253
|
return null;
|
|
22733
23254
|
let node = stmt.declarationList.declarations[0]?.initializer;
|
|
22734
|
-
while (node &&
|
|
23255
|
+
while (node && ts20.isParenthesizedExpression(node))
|
|
22735
23256
|
node = node.expression;
|
|
22736
|
-
if (!node || !
|
|
23257
|
+
if (!node || !ts20.isCallExpression(node))
|
|
22737
23258
|
return null;
|
|
22738
23259
|
const callee = node.expression;
|
|
22739
|
-
if (!
|
|
23260
|
+
if (!ts20.isPropertyAccessExpression(callee))
|
|
22740
23261
|
return null;
|
|
22741
23262
|
if (callee.name.text !== "join")
|
|
22742
23263
|
return null;
|
|
22743
23264
|
let recv = callee.expression;
|
|
22744
|
-
while (
|
|
23265
|
+
while (ts20.isParenthesizedExpression(recv))
|
|
22745
23266
|
recv = recv.expression;
|
|
22746
|
-
if (!
|
|
23267
|
+
if (!ts20.isArrayLiteralExpression(recv))
|
|
22747
23268
|
return null;
|
|
22748
23269
|
const parts = [];
|
|
22749
23270
|
for (const el of recv.elements) {
|
|
22750
|
-
if (
|
|
23271
|
+
if (ts20.isStringLiteral(el) || ts20.isNoSubstitutionTemplateLiteral(el)) {
|
|
22751
23272
|
parts.push(el.text);
|
|
22752
23273
|
} else {
|
|
22753
23274
|
return null;
|
|
@@ -22756,7 +23277,7 @@ function evalStringArrayJoin(source) {
|
|
|
22756
23277
|
let sep2 = ",";
|
|
22757
23278
|
if (node.arguments.length >= 1) {
|
|
22758
23279
|
const arg = node.arguments[0];
|
|
22759
|
-
if (
|
|
23280
|
+
if (ts20.isStringLiteral(arg) || ts20.isNoSubstitutionTemplateLiteral(arg))
|
|
22760
23281
|
sep2 = arg.text;
|
|
22761
23282
|
else
|
|
22762
23283
|
return null;
|
|
@@ -22764,11 +23285,11 @@ function evalStringArrayJoin(source) {
|
|
|
22764
23285
|
return parts.join(sep2);
|
|
22765
23286
|
}
|
|
22766
23287
|
function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
|
|
22767
|
-
if (!
|
|
23288
|
+
if (!ts20.isElementAccessExpression(val))
|
|
22768
23289
|
return null;
|
|
22769
23290
|
const obj = val.expression;
|
|
22770
23291
|
const arg = val.argumentExpression;
|
|
22771
|
-
if (!
|
|
23292
|
+
if (!ts20.isIdentifier(obj) || !ts20.isIdentifier(arg))
|
|
22772
23293
|
return null;
|
|
22773
23294
|
let indexPropName;
|
|
22774
23295
|
let defaultKey;
|
|
@@ -22784,35 +23305,35 @@ function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
|
|
|
22784
23305
|
const constInfo = localConstants.find((c) => c.name === obj.text && c.isModule);
|
|
22785
23306
|
if (constInfo?.value === undefined)
|
|
22786
23307
|
return null;
|
|
22787
|
-
const sf =
|
|
23308
|
+
const sf = ts20.createSourceFile("__rec.ts", `(${constInfo.value})`, ts20.ScriptTarget.Latest, true);
|
|
22788
23309
|
if (sf.statements.length !== 1)
|
|
22789
23310
|
return null;
|
|
22790
23311
|
const stmt = sf.statements[0];
|
|
22791
|
-
if (!
|
|
23312
|
+
if (!ts20.isExpressionStatement(stmt))
|
|
22792
23313
|
return null;
|
|
22793
23314
|
let parsed = stmt.expression;
|
|
22794
|
-
while (
|
|
23315
|
+
while (ts20.isParenthesizedExpression(parsed))
|
|
22795
23316
|
parsed = parsed.expression;
|
|
22796
|
-
if (!
|
|
23317
|
+
if (!ts20.isObjectLiteralExpression(parsed))
|
|
22797
23318
|
return null;
|
|
22798
23319
|
const entries = [];
|
|
22799
23320
|
for (const prop of parsed.properties) {
|
|
22800
|
-
if (!
|
|
23321
|
+
if (!ts20.isPropertyAssignment(prop))
|
|
22801
23322
|
return null;
|
|
22802
23323
|
let key;
|
|
22803
|
-
if (
|
|
23324
|
+
if (ts20.isIdentifier(prop.name)) {
|
|
22804
23325
|
key = prop.name.text;
|
|
22805
|
-
} else if (
|
|
23326
|
+
} else if (ts20.isStringLiteral(prop.name) || ts20.isNoSubstitutionTemplateLiteral(prop.name)) {
|
|
22806
23327
|
key = prop.name.text;
|
|
22807
23328
|
} else {
|
|
22808
23329
|
return null;
|
|
22809
23330
|
}
|
|
22810
23331
|
let v = prop.initializer;
|
|
22811
|
-
while (
|
|
23332
|
+
while (ts20.isParenthesizedExpression(v))
|
|
22812
23333
|
v = v.expression;
|
|
22813
|
-
if (
|
|
23334
|
+
if (ts20.isNumericLiteral(v)) {
|
|
22814
23335
|
entries.push({ key, value: { kind: "number", text: v.text } });
|
|
22815
|
-
} else if (
|
|
23336
|
+
} else if (ts20.isStringLiteral(v) || ts20.isNoSubstitutionTemplateLiteral(v)) {
|
|
22816
23337
|
entries.push({ key, value: { kind: "string", text: v.text } });
|
|
22817
23338
|
} else {
|
|
22818
23339
|
return null;
|
|
@@ -23595,7 +24116,7 @@ function compileJSX(source, filePath, options) {
|
|
|
23595
24116
|
return { files, errors };
|
|
23596
24117
|
}
|
|
23597
24118
|
// src/shared-program.ts
|
|
23598
|
-
import
|
|
24119
|
+
import ts21 from "typescript";
|
|
23599
24120
|
function commonParent(paths) {
|
|
23600
24121
|
if (paths.length === 0)
|
|
23601
24122
|
return process.cwd();
|
|
@@ -23616,10 +24137,10 @@ function commonParent(paths) {
|
|
|
23616
24137
|
function createProgramForCorpus(files, options = {}) {
|
|
23617
24138
|
const baseUrl = options.baseUrl ?? commonParent(files);
|
|
23618
24139
|
const compilerOptions = {
|
|
23619
|
-
target:
|
|
23620
|
-
module:
|
|
23621
|
-
moduleResolution:
|
|
23622
|
-
jsx:
|
|
24140
|
+
target: ts21.ScriptTarget.Latest,
|
|
24141
|
+
module: ts21.ModuleKind.ESNext,
|
|
24142
|
+
moduleResolution: ts21.ModuleResolutionKind.Bundler,
|
|
24143
|
+
jsx: ts21.JsxEmit.ReactJSX,
|
|
23623
24144
|
strict: true,
|
|
23624
24145
|
skipLibCheck: true,
|
|
23625
24146
|
noEmit: true,
|
|
@@ -23629,7 +24150,7 @@ function createProgramForCorpus(files, options = {}) {
|
|
|
23629
24150
|
...options.compilerOptions
|
|
23630
24151
|
};
|
|
23631
24152
|
const absolute = files.map((f) => path_default.resolve(f));
|
|
23632
|
-
return
|
|
24153
|
+
return ts21.createProgram(absolute, compilerOptions, undefined, options.oldProgram);
|
|
23633
24154
|
}
|
|
23634
24155
|
// src/adapters/interface.ts
|
|
23635
24156
|
class BaseAdapter {
|
|
@@ -24184,6 +24705,8 @@ function collectLoopBoundNames(ir) {
|
|
|
24184
24705
|
names.add(binding.name);
|
|
24185
24706
|
if (node.filterPredicate)
|
|
24186
24707
|
names.add(node.filterPredicate.param);
|
|
24708
|
+
for (const name of node.preamble?.declaredNames ?? [])
|
|
24709
|
+
names.add(name);
|
|
24187
24710
|
for (const child of node.children)
|
|
24188
24711
|
visit3(child);
|
|
24189
24712
|
if (node.childComponent) {
|
|
@@ -24611,7 +25134,7 @@ function dangerousInnerHtmlDiagnostic(expr, loc, reason) {
|
|
|
24611
25134
|
};
|
|
24612
25135
|
}
|
|
24613
25136
|
// src/combine-client-js.ts
|
|
24614
|
-
import
|
|
25137
|
+
import ts22 from "typescript";
|
|
24615
25138
|
var CHILD_PLACEHOLDER_RE = /import '\/\* @bf-child:(\w+) \*\/'/g;
|
|
24616
25139
|
function combineParentChildClientJs(files) {
|
|
24617
25140
|
const result = new Map;
|
|
@@ -24668,10 +25191,10 @@ function combineParentChildClientJs(files) {
|
|
|
24668
25191
|
return result;
|
|
24669
25192
|
}
|
|
24670
25193
|
function parseAndMerge(content, importsBySource, otherImports, codeSections) {
|
|
24671
|
-
const sourceFile =
|
|
25194
|
+
const sourceFile = ts22.createSourceFile("combine.js", content, ts22.ScriptTarget.Latest, false, ts22.ScriptKind.JS);
|
|
24672
25195
|
const importSpans = [];
|
|
24673
25196
|
for (const stmt of sourceFile.statements) {
|
|
24674
|
-
if (!
|
|
25197
|
+
if (!ts22.isImportDeclaration(stmt))
|
|
24675
25198
|
continue;
|
|
24676
25199
|
const start = stmt.getStart(sourceFile);
|
|
24677
25200
|
const end = stmt.getEnd();
|
|
@@ -24681,8 +25204,8 @@ function parseAndMerge(content, importsBySource, otherImports, codeSections) {
|
|
|
24681
25204
|
continue;
|
|
24682
25205
|
const clause = stmt.importClause;
|
|
24683
25206
|
const bindings = clause?.namedBindings;
|
|
24684
|
-
const specifier =
|
|
24685
|
-
if (clause && !clause.name && bindings &&
|
|
25207
|
+
const specifier = ts22.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : "";
|
|
25208
|
+
if (clause && !clause.name && bindings && ts22.isNamedImports(bindings)) {
|
|
24686
25209
|
if (!importsBySource.has(specifier)) {
|
|
24687
25210
|
importsBySource.set(specifier, new Set);
|
|
24688
25211
|
}
|
|
@@ -24849,7 +25372,7 @@ function escapeRe(s) {
|
|
|
24849
25372
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24850
25373
|
}
|
|
24851
25374
|
// src/debug.ts
|
|
24852
|
-
import
|
|
25375
|
+
import ts23 from "typescript";
|
|
24853
25376
|
function buildComponentGraph(source, filePath, componentName) {
|
|
24854
25377
|
const ctx = analyzeComponent(source, filePath, componentName);
|
|
24855
25378
|
if (!ctx.jsxReturn) {
|
|
@@ -26134,7 +26657,7 @@ function truncateExpr(expr, max = 40) {
|
|
|
26134
26657
|
function exprReadsPropMember(expr, propsObjectName) {
|
|
26135
26658
|
let sf;
|
|
26136
26659
|
try {
|
|
26137
|
-
sf =
|
|
26660
|
+
sf = ts23.createSourceFile("__attr.tsx", `(${expr})`, ts23.ScriptTarget.Latest, true, ts23.ScriptKind.TSX);
|
|
26138
26661
|
} catch {
|
|
26139
26662
|
return false;
|
|
26140
26663
|
}
|
|
@@ -26142,11 +26665,11 @@ function exprReadsPropMember(expr, propsObjectName) {
|
|
|
26142
26665
|
const visit3 = (n) => {
|
|
26143
26666
|
if (found)
|
|
26144
26667
|
return;
|
|
26145
|
-
if (
|
|
26668
|
+
if (ts23.isPropertyAccessExpression(n) && ts23.isIdentifier(n.expression) && n.expression.text === propsObjectName && n.name.text !== "children") {
|
|
26146
26669
|
found = true;
|
|
26147
26670
|
return;
|
|
26148
26671
|
}
|
|
26149
|
-
|
|
26672
|
+
ts23.forEachChild(n, visit3);
|
|
26150
26673
|
};
|
|
26151
26674
|
visit3(sf);
|
|
26152
26675
|
return found;
|
|
@@ -26216,7 +26739,7 @@ function findSourceFile2(meta) {
|
|
|
26216
26739
|
return null;
|
|
26217
26740
|
}
|
|
26218
26741
|
// src/profiler.ts
|
|
26219
|
-
import
|
|
26742
|
+
import ts24 from "typescript";
|
|
26220
26743
|
var PROFILE_SCHEMA_VERSION = 1;
|
|
26221
26744
|
var DEFAULT_FANOUT_THRESHOLD = 8;
|
|
26222
26745
|
function buildStaticBudget(source, filePath, componentName, options = {}) {
|
|
@@ -26486,15 +27009,15 @@ function joinProfilerEvents(events, index) {
|
|
|
26486
27009
|
return { joined, unattributed, diagnostics };
|
|
26487
27010
|
}
|
|
26488
27011
|
function findUninstrumentedEffects(source, filePath, instrumentedLines) {
|
|
26489
|
-
const sf =
|
|
27012
|
+
const sf = ts24.createSourceFile(filePath, source, ts24.ScriptTarget.Latest, true, ts24.ScriptKind.TSX);
|
|
26490
27013
|
const out = [];
|
|
26491
27014
|
const visit3 = (node) => {
|
|
26492
|
-
if (
|
|
27015
|
+
if (ts24.isCallExpression(node) && ts24.isIdentifier(node.expression) && node.expression.text === "createEffect") {
|
|
26493
27016
|
const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
|
|
26494
27017
|
if (!instrumentedLines.has(line))
|
|
26495
27018
|
out.push({ file: filePath, line });
|
|
26496
27019
|
}
|
|
26497
|
-
|
|
27020
|
+
ts24.forEachChild(node, visit3);
|
|
26498
27021
|
};
|
|
26499
27022
|
visit3(sf);
|
|
26500
27023
|
out.sort((a, b) => a.line - b.line);
|
|
@@ -26802,13 +27325,13 @@ function assessBatchSafety(args) {
|
|
|
26802
27325
|
const signalGetters = new Set(args.graph.signals.map((s) => s.name));
|
|
26803
27326
|
let sf;
|
|
26804
27327
|
try {
|
|
26805
|
-
sf =
|
|
27328
|
+
sf = ts24.createSourceFile("__h.ts", `const __h = ${args.handler}`, ts24.ScriptTarget.Latest, true);
|
|
26806
27329
|
} catch {
|
|
26807
27330
|
return "unverified";
|
|
26808
27331
|
}
|
|
26809
27332
|
const calls = [];
|
|
26810
27333
|
const visit3 = (node) => {
|
|
26811
|
-
if (
|
|
27334
|
+
if (ts24.isCallExpression(node) && ts24.isIdentifier(node.expression)) {
|
|
26812
27335
|
const name = node.expression.text;
|
|
26813
27336
|
if (setters.has(name))
|
|
26814
27337
|
calls.push({ pos: node.getStart(sf), kind: "write" });
|
|
@@ -26817,7 +27340,7 @@ function assessBatchSafety(args) {
|
|
|
26817
27340
|
else if (!signalGetters.has(name) && !memoNames.has(name))
|
|
26818
27341
|
calls.push({ pos: node.getStart(sf), kind: "risky" });
|
|
26819
27342
|
}
|
|
26820
|
-
|
|
27343
|
+
ts24.forEachChild(node, visit3);
|
|
26821
27344
|
};
|
|
26822
27345
|
visit3(sf);
|
|
26823
27346
|
calls.sort((a, b) => a.pos - b.pos);
|
|
@@ -27559,6 +28082,7 @@ export {
|
|
|
27559
28082
|
diffStaticBudget,
|
|
27560
28083
|
diffProfiles,
|
|
27561
28084
|
describeFallback,
|
|
28085
|
+
derivesScopeFromSlot,
|
|
27562
28086
|
decideClientOnlyElision,
|
|
27563
28087
|
dangerousInnerHtmlMetacharViolation,
|
|
27564
28088
|
dangerousInnerHtmlDiagnostic,
|