@barefootjs/jsx 0.29.0 → 0.30.2

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.
Files changed (90) hide show
  1. package/dist/adapters/child-scope.d.ts +17 -0
  2. package/dist/adapters/child-scope.d.ts.map +1 -0
  3. package/dist/adapters/loop-bound-names.d.ts.map +1 -1
  4. package/dist/analyzer-context.d.ts.map +1 -1
  5. package/dist/analyzer.d.ts.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +990 -367
  9. package/dist/ir-to-client-js/collect-elements.d.ts +5 -25
  10. package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
  11. package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts +66 -2
  12. package/dist/ir-to-client-js/control-flow/plan/build-lazy-row.d.ts.map +1 -1
  13. package/dist/ir-to-client-js/control-flow/plan/build-reactive-effects.d.ts.map +1 -1
  14. package/dist/ir-to-client-js/control-flow/plan/lazy-conditional.d.ts +92 -0
  15. package/dist/ir-to-client-js/control-flow/plan/lazy-conditional.d.ts.map +1 -0
  16. package/dist/ir-to-client-js/control-flow/plan/lazy-preamble.d.ts +134 -0
  17. package/dist/ir-to-client-js/control-flow/plan/lazy-preamble.d.ts.map +1 -0
  18. package/dist/ir-to-client-js/control-flow/plan/lazy-row-eligibility.d.ts +46 -11
  19. package/dist/ir-to-client-js/control-flow/plan/lazy-row-eligibility.d.ts.map +1 -1
  20. package/dist/ir-to-client-js/control-flow/plan/reactive-effects.d.ts +7 -0
  21. package/dist/ir-to-client-js/control-flow/plan/reactive-effects.d.ts.map +1 -1
  22. package/dist/ir-to-client-js/control-flow/stringify/lazy-row.d.ts.map +1 -1
  23. package/dist/ir-to-client-js/csr-substitute.d.ts.map +1 -1
  24. package/dist/ir-to-client-js/html-template.d.ts +2 -3
  25. package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
  26. package/dist/ir-to-client-js/plan/declaration-emit.d.ts +6 -0
  27. package/dist/ir-to-client-js/plan/declaration-emit.d.ts.map +1 -1
  28. package/dist/ir-to-client-js/reactivity.d.ts +1 -10
  29. package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
  30. package/dist/ir-to-client-js/types.d.ts +12 -0
  31. package/dist/ir-to-client-js/types.d.ts.map +1 -1
  32. package/dist/jsx-to-ir.d.ts.map +1 -1
  33. package/dist/prop-rewrite.d.ts +24 -7
  34. package/dist/prop-rewrite.d.ts.map +1 -1
  35. package/dist/rich-type-evidence.d.ts.map +1 -1
  36. package/dist/ssr-defaults.d.ts.map +1 -1
  37. package/dist/to-locale-date-lowering.d.ts.map +1 -1
  38. package/dist/types.d.ts +78 -0
  39. package/dist/types.d.ts.map +1 -1
  40. package/package.json +2 -2
  41. package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +6 -24
  42. package/src/__tests__/branch-loop-plain.test.ts +28 -45
  43. package/src/__tests__/csr-substitution-safety-divergence.test.ts +9 -3
  44. package/src/__tests__/csr-template-scope-soundness.test.ts +167 -0
  45. package/src/__tests__/early-return-branch-switch.test.ts +96 -0
  46. package/src/__tests__/form-control-value-ssr.test.ts +102 -0
  47. package/src/__tests__/lazy-conditional.test.ts +190 -0
  48. package/src/__tests__/lazy-preamble.test.ts +297 -0
  49. package/src/__tests__/lazy-row-eligibility.test.ts +97 -28
  50. package/src/__tests__/loop-item-root-scope.test.ts +213 -0
  51. package/src/__tests__/map-multi-return-body.test.ts +30 -3
  52. package/src/__tests__/nested-loop-conditional.test.ts +27 -6
  53. package/src/__tests__/preamble-attr-reactivity.test.ts +217 -0
  54. package/src/__tests__/preamble-declarations.test.ts +207 -0
  55. package/src/__tests__/ssr-defaults.test.ts +44 -0
  56. package/src/adapters/child-scope.ts +22 -0
  57. package/src/adapters/loop-bound-names.ts +6 -0
  58. package/src/analyzer-context.ts +43 -0
  59. package/src/analyzer.ts +33 -3
  60. package/src/index.ts +1 -0
  61. package/src/ir-to-client-js/collect-elements.ts +51 -10
  62. package/src/ir-to-client-js/control-flow/plan/build-branch-loop.ts +1 -1
  63. package/src/ir-to-client-js/control-flow/plan/build-composite-loop.ts +2 -2
  64. package/src/ir-to-client-js/control-flow/plan/build-event-delegation.ts +3 -3
  65. package/src/ir-to-client-js/control-flow/plan/build-inner-loop.ts +2 -2
  66. package/src/ir-to-client-js/control-flow/plan/build-lazy-row.ts +147 -5
  67. package/src/ir-to-client-js/control-flow/plan/build-loop.ts +2 -2
  68. package/src/ir-to-client-js/control-flow/plan/build-reactive-effects.ts +1 -0
  69. package/src/ir-to-client-js/control-flow/plan/lazy-conditional.ts +151 -0
  70. package/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts +287 -0
  71. package/src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts +85 -22
  72. package/src/ir-to-client-js/control-flow/plan/reactive-effects.ts +7 -0
  73. package/src/ir-to-client-js/control-flow/stringify/lazy-row.ts +133 -35
  74. package/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts +24 -4
  75. package/src/ir-to-client-js/csr-substitute.ts +6 -1
  76. package/src/ir-to-client-js/emit-registration.ts +1 -1
  77. package/src/ir-to-client-js/html-template.ts +51 -40
  78. package/src/ir-to-client-js/index.ts +1 -1
  79. package/src/ir-to-client-js/plan/build-declaration-emit.ts +2 -0
  80. package/src/ir-to-client-js/plan/build-static-array-child-init.ts +1 -1
  81. package/src/ir-to-client-js/plan/declaration-emit.ts +6 -0
  82. package/src/ir-to-client-js/reactivity.ts +25 -0
  83. package/src/ir-to-client-js/stringify/declaration-emit.ts +9 -4
  84. package/src/ir-to-client-js/types.ts +12 -0
  85. package/src/jsx-to-ir.ts +409 -24
  86. package/src/prop-rewrite.ts +149 -19
  87. package/src/rich-type-evidence.ts +6 -7
  88. package/src/ssr-defaults.ts +7 -2
  89. package/src/to-locale-date-lowering.ts +8 -2
  90. 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, true);
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, true)).join("");
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, insideLoop = false, inHoistedChildren = false) {
3465
- const recurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar, insideLoop, inHoistedChildren);
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, insideLoop, false);
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, insideLoop, true);
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 = !insideLoop && node.slotId ? `, '${node.slotId}'` : "";
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, insideLoop);
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, insideLoop)
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, insideLoop) });
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, insideLoop, restSpreadNames, propsObjectName, unsafeLocalNames, deferredChildSlots) {
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, insideLoop, unsafeLocalNames: effectiveUnsafeLocalNames, deferredChildSlots, loopDepth: -1 });
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, insideLoop, unsafeLocalNames, loopDepth = 0 } = opts;
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 = !insideLoop && node.slotId ? `, '${node.slotId}'` : "";
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,
@@ -4535,20 +4542,115 @@ function isSimplePropExpression(expr, propNames) {
4535
4542
  }
4536
4543
 
4537
4544
  // src/prop-rewrite.ts
4545
+ function collectBindingNames(name, out) {
4546
+ if (ts5.isIdentifier(name)) {
4547
+ out.add(name.text);
4548
+ return;
4549
+ }
4550
+ for (const el of name.elements) {
4551
+ if (ts5.isBindingElement(el))
4552
+ collectBindingNames(el.name, out);
4553
+ }
4554
+ }
4555
+ function scopeFrameOf(n) {
4556
+ if (ts5.isFunctionLike(n)) {
4557
+ const frame = new Set;
4558
+ for (const p of n.parameters)
4559
+ collectBindingNames(p.name, frame);
4560
+ if ((ts5.isFunctionExpression(n) || ts5.isFunctionDeclaration(n)) && n.name)
4561
+ frame.add(n.name.text);
4562
+ return frame.size > 0 ? frame : null;
4563
+ }
4564
+ if (ts5.isBlock(n)) {
4565
+ const frame = new Set;
4566
+ for (const st of n.statements) {
4567
+ if (ts5.isVariableStatement(st)) {
4568
+ for (const d of st.declarationList.declarations)
4569
+ collectBindingNames(d.name, frame);
4570
+ } else if (ts5.isFunctionDeclaration(st) && st.name) {
4571
+ frame.add(st.name.text);
4572
+ }
4573
+ }
4574
+ return frame.size > 0 ? frame : null;
4575
+ }
4576
+ if (ts5.isCatchClause(n) && n.variableDeclaration) {
4577
+ const frame = new Set;
4578
+ collectBindingNames(n.variableDeclaration.name, frame);
4579
+ return frame.size > 0 ? frame : null;
4580
+ }
4581
+ return null;
4582
+ }
4583
+ function walkWithScope(root, visit) {
4584
+ const scopeStack = [];
4585
+ const isShadowed = (name) => scopeStack.some((frame) => frame.has(name));
4586
+ function rec(n, parent) {
4587
+ const frame = scopeFrameOf(n);
4588
+ if (frame)
4589
+ scopeStack.push(frame);
4590
+ if (ts5.isIdentifier(n))
4591
+ visit(n, parent, isShadowed(n.text));
4592
+ ts5.forEachChild(n, (child) => rec(child, n));
4593
+ if (frame)
4594
+ scopeStack.pop();
4595
+ }
4596
+ rec(root);
4597
+ }
4598
+ function isNonValuePosition(n, parent) {
4599
+ if (!parent)
4600
+ return false;
4601
+ if (ts5.isPropertyAssignment(parent) && parent.name === n)
4602
+ return true;
4603
+ if (ts5.isPropertyAccessExpression(parent) && parent.name === n)
4604
+ return true;
4605
+ if (ts5.isQualifiedName(parent) && parent.right === n)
4606
+ return true;
4607
+ if ((ts5.isParameter(parent) || ts5.isVariableDeclaration(parent) || ts5.isBindingElement(parent)) && parent.name === n)
4608
+ return true;
4609
+ if (ts5.isTypeReferenceNode(parent))
4610
+ return true;
4611
+ return false;
4612
+ }
4538
4613
  function collectAstPropRefs(node, propNames, out) {
4539
- function visit(n, parent) {
4540
- if (ts5.isIdentifier(n) && propNames.has(n.text)) {
4541
- if (parent && ts5.isPropertyAssignment(parent) && parent.name === n)
4542
- return;
4543
- if (parent && ts5.isShorthandPropertyAssignment(parent) && parent.name === n)
4544
- return;
4545
- if (parent && ts5.isPropertyAccessExpression(parent) && parent.name === n)
4546
- return;
4547
- out.add(n.text);
4614
+ walkWithScope(node, (n, parent, shadowed) => {
4615
+ if (shadowed || !propNames.has(n.text))
4616
+ return;
4617
+ if (parent && ts5.isShorthandPropertyAssignment(parent) && parent.name === n)
4618
+ return;
4619
+ if (isNonValuePosition(n, parent))
4620
+ return;
4621
+ out.add(n.text);
4622
+ });
4623
+ }
4624
+ function applyScopedPropRefRewrite(text, propRefs) {
4625
+ const prefix = "(";
4626
+ const sf = ts5.createSourceFile("__bf_prop_rewrite.ts", `${prefix}${text}
4627
+ )`, ts5.ScriptTarget.Latest, true);
4628
+ const parseDiagnostics = sf.parseDiagnostics;
4629
+ if (parseDiagnostics && parseDiagnostics.length > 0)
4630
+ return null;
4631
+ const edits = [];
4632
+ walkWithScope(sf, (n, parent, shadowed) => {
4633
+ if (shadowed || !propRefs.has(n.text))
4634
+ return;
4635
+ if (isNonValuePosition(n, parent))
4636
+ return;
4637
+ const start = n.getStart(sf) - prefix.length;
4638
+ const end = n.getEnd() - prefix.length;
4639
+ if (start < 0 || end > text.length)
4640
+ return;
4641
+ if (parent && ts5.isShorthandPropertyAssignment(parent) && parent.name === n) {
4642
+ edits.push({ start, end, replacement: `${n.text}: ${PROPS_PARAM}.${n.text}` });
4643
+ return;
4548
4644
  }
4549
- ts5.forEachChild(n, (child) => visit(child, n));
4645
+ edits.push({ start, end, replacement: `${PROPS_PARAM}.${n.text}` });
4646
+ });
4647
+ if (edits.length === 0)
4648
+ return text;
4649
+ let result = text;
4650
+ for (const edit of edits.sort((a, b) => b.start - a.start)) {
4651
+ result = result.slice(0, edit.start) + edit.replacement + result.slice(edit.end);
4550
4652
  }
4551
- visit(node);
4653
+ return result;
4552
4654
  }
4553
4655
  function applyRegexPropRefRewrite(text, propRefs) {
4554
4656
  const { protect, restore } = createTemplateAwareStringProtector();
@@ -4578,7 +4680,7 @@ function rewriteBarePropRefs(text, node, propNames, extraPropRefs) {
4578
4680
  }
4579
4681
  if (foundPropRefs.size === 0)
4580
4682
  return;
4581
- return applyRegexPropRefRewrite(text, foundPropRefs);
4683
+ return applyScopedPropRefRewrite(text, foundPropRefs) ?? applyRegexPropRefRewrite(text, foundPropRefs);
4582
4684
  }
4583
4685
 
4584
4686
  // src/instrumentation.ts
@@ -4948,6 +5050,30 @@ function typeNodeToTypeInfo(typeNode, sourceFile, rawOf) {
4948
5050
  if (ts7.isArrayTypeNode(typeNode)) {
4949
5051
  return { kind: "array", raw, elementType: recurse(typeNode.elementType) };
4950
5052
  }
5053
+ if (ts7.isLiteralTypeNode(typeNode)) {
5054
+ const lit = typeNode.literal;
5055
+ if (ts7.isStringLiteral(lit) || ts7.isNoSubstitutionTemplateLiteral(lit)) {
5056
+ return { kind: "primitive", raw, primitive: "string", literalValue: lit.text };
5057
+ }
5058
+ if (ts7.isNumericLiteral(lit)) {
5059
+ return { kind: "primitive", raw, primitive: "number", literalValue: lit.text };
5060
+ }
5061
+ if (ts7.isPrefixUnaryExpression(lit) && lit.operator === ts7.SyntaxKind.MinusToken && ts7.isNumericLiteral(lit.operand)) {
5062
+ return { kind: "primitive", raw, primitive: "number", literalValue: `-${lit.operand.text}` };
5063
+ }
5064
+ if (lit.kind === ts7.SyntaxKind.TrueKeyword || lit.kind === ts7.SyntaxKind.FalseKeyword) {
5065
+ return {
5066
+ kind: "primitive",
5067
+ raw,
5068
+ primitive: "boolean",
5069
+ literalValue: lit.kind === ts7.SyntaxKind.TrueKeyword ? "true" : "false"
5070
+ };
5071
+ }
5072
+ if (lit.kind === ts7.SyntaxKind.NullKeyword) {
5073
+ return { kind: "primitive", raw, primitive: "null" };
5074
+ }
5075
+ return { kind: "unknown", raw };
5076
+ }
4951
5077
  if (ts7.isUnionTypeNode(typeNode)) {
4952
5078
  return { kind: "union", raw, unionTypes: typeNode.types.map(recurse) };
4953
5079
  }
@@ -5515,9 +5641,7 @@ function baseTypeName(raw) {
5515
5641
  return (idx === -1 ? raw : raw.slice(0, idx)).trim();
5516
5642
  }
5517
5643
  function isNullishArm(t) {
5518
- if (t.kind === "primitive" && (t.primitive === "null" || t.primitive === "undefined"))
5519
- return true;
5520
- return t.kind === "unknown" && (t.raw === "null" || t.raw === "undefined");
5644
+ return t.kind === "primitive" && (t.primitive === "null" || t.primitive === "undefined");
5521
5645
  }
5522
5646
  function stripUnion(type) {
5523
5647
  if (!type || type.kind !== "union" || !type.unionTypes)
@@ -6236,14 +6360,17 @@ function collectSignal(node, ctx) {
6236
6360
  const pattern = node.name;
6237
6361
  const callExpr = node.initializer;
6238
6362
  const elements = pattern.elements;
6239
- if (elements.length < 1 || elements.length > 2 || !ts8.isBindingElement(elements[0]) || !ts8.isIdentifier(elements[0].name)) {
6363
+ const getterElided = elements.length === 2 && ts8.isOmittedExpression(elements[0]);
6364
+ if (elements.length < 1 || elements.length > 2 || !getterElided && (!ts8.isBindingElement(elements[0]) || !ts8.isIdentifier(elements[0].name))) {
6240
6365
  return;
6241
6366
  }
6242
6367
  if (elements.length === 2 && (!ts8.isBindingElement(elements[1]) || !ts8.isIdentifier(elements[1].name))) {
6243
6368
  return;
6244
6369
  }
6245
- const getter = elements[0].name.text;
6246
6370
  const setter = elements.length === 2 && ts8.isBindingElement(elements[1]) && ts8.isIdentifier(elements[1].name) ? elements[1].name.text : null;
6371
+ if (getterElided && !setter)
6372
+ return;
6373
+ const getter = getterElided ? `__bfGet_${setter}` : elements[0].name.text;
6247
6374
  const initialValue = callExpr.arguments[0] ? ctx.getJS(callExpr.arguments[0]) : "";
6248
6375
  const typedInitialValue = callExpr.arguments[0] ? callExpr.arguments[0].getText(ctx.sourceFile) : undefined;
6249
6376
  let type = { kind: "unknown", raw: "unknown" };
@@ -6264,6 +6391,7 @@ function collectSignal(node, ctx) {
6264
6391
  ctx.signals.push({
6265
6392
  getter,
6266
6393
  setter,
6394
+ getterElided: getterElided || undefined,
6267
6395
  initialValue,
6268
6396
  typedInitialValue: typedInitialValue !== initialValue ? typedInitialValue : undefined,
6269
6397
  templateInitialValue,
@@ -6454,9 +6582,17 @@ function collectMemo(node, ctx) {
6454
6582
  const blockBody = arrowNode && ts8.isArrowFunction(arrowNode) && ts8.isBlock(arrowNode.body) ? arrowNode.body : undefined;
6455
6583
  const parsedBlock = blockBody ? parseBlockBodyTolerant(blockBody, ctx.sourceFile, (node2) => ctx.getJS(node2)) : undefined;
6456
6584
  const parsedBlockComplete = parsedBlock && blockBody ? parsedBlock.length === blockBody.statements.length : undefined;
6585
+ let templateComputation;
6586
+ if (!ctx.propsObjectName && callExpr.arguments[0]) {
6587
+ const propNames = new Set(ctx.propsParams.map((p) => p.name));
6588
+ if (propNames.size > 0) {
6589
+ templateComputation = rewriteBarePropRefs(computation, callExpr.arguments[0], propNames);
6590
+ }
6591
+ }
6457
6592
  ctx.memos.push({
6458
6593
  name,
6459
6594
  computation,
6595
+ templateComputation,
6460
6596
  parsedBlock,
6461
6597
  parsedBlockComplete,
6462
6598
  typedComputation: typedComputation !== computation ? typedComputation : undefined,
@@ -9677,8 +9813,10 @@ function deriveFormat(locale, probeOptions) {
9677
9813
  return { pattern, names };
9678
9814
  }
9679
9815
  function unionMemberLiteral(member) {
9680
- const m = /^'([^'\\]*)'$|^"([^"\\]*)"$/.exec(member.raw.trim());
9681
- return m ? m[1] ?? m[2] : null;
9816
+ if (member.kind === "primitive" && member.primitive === "string" && member.literalValue !== undefined) {
9817
+ return member.literalValue;
9818
+ }
9819
+ return null;
9682
9820
  }
9683
9821
  function resolveLocaleUnionMembers(locale, metadata) {
9684
9822
  let sourcePropName = null;
@@ -10284,6 +10422,13 @@ function jsxToIR(analyzer) {
10284
10422
  function buildIRRoot(analyzer) {
10285
10423
  if (analyzer.conditionalReturns.length > 0) {
10286
10424
  const ctx2 = createTransformContext(analyzer);
10425
+ const allReactiveNoLocals = analyzer.jsxReturn != null && analyzer.conditionalReturns.every((cr) => cr.scopeVariables.length === 0 && exprCallsReactiveGetters(cr.condition, ctx2));
10426
+ if (allReactiveNoLocals) {
10427
+ const chain = buildIfStatementChain(analyzer, ctx2, { asConditional: true });
10428
+ if (!chain)
10429
+ return null;
10430
+ return chain.type === "conditional" ? wrapInScopeElement(chain) : chain;
10431
+ }
10287
10432
  return buildIfStatementChain(analyzer, ctx2);
10288
10433
  }
10289
10434
  if (!analyzer.jsxReturn)
@@ -10439,11 +10584,52 @@ function transformJsxElement(node, ctx) {
10439
10584
  }
10440
10585
  return transformHtmlElement(node, ctx, tagName);
10441
10586
  }
10587
+ function lowerFormControlValueSsr(tagName, attrs, children) {
10588
+ if (tagName !== "textarea" && tagName !== "select")
10589
+ return;
10590
+ const valueAttr = attrs.find((a) => a.name === "value");
10591
+ if (!valueAttr || valueAttr.clientOnly || valueAttr.value.kind !== "expression")
10592
+ return;
10593
+ const { expr, templateExpr } = valueAttr.value;
10594
+ valueAttr.clientOnly = true;
10595
+ if (tagName === "textarea") {
10596
+ if (children.length > 0)
10597
+ return;
10598
+ children.push({
10599
+ type: "expression",
10600
+ expr,
10601
+ templateExpr: `escapeText(${templateExpr ?? expr})`,
10602
+ typeInfo: null,
10603
+ reactive: false,
10604
+ slotId: null,
10605
+ loc: valueAttr.loc,
10606
+ origin: { phase: "ssr", scope: "template", effect: "pure" }
10607
+ });
10608
+ return;
10609
+ }
10610
+ const selectedFor = (optValue) => AttrValueOf.expression(`(${expr}) === ${JSON.stringify(optValue)}`, templateExpr !== undefined ? { templateExpr: `(${templateExpr}) === ${JSON.stringify(optValue)}` } : undefined);
10611
+ const distribute = (nodes) => {
10612
+ for (const n of nodes) {
10613
+ if (n.type === "element" && n.tag === "option") {
10614
+ if (n.attrs.some((a) => a.name === "selected"))
10615
+ continue;
10616
+ const optValue = n.attrs.find((a) => a.name === "value");
10617
+ if (!optValue || optValue.value.kind !== "literal")
10618
+ continue;
10619
+ n.attrs.push({ name: "selected", value: selectedFor(optValue.value.value), loc: n.loc });
10620
+ } else if (n.type === "fragment" || n.type === "element" && n.tag === "optgroup") {
10621
+ distribute(n.children);
10622
+ }
10623
+ }
10624
+ };
10625
+ distribute(children);
10626
+ }
10442
10627
  function transformHtmlElement(node, ctx, tagName) {
10443
10628
  const { attrs, events, ref } = processAttributes(node.openingElement.attributes, ctx);
10444
10629
  const needsScope = ctx.isRoot;
10445
10630
  ctx.isRoot = false;
10446
10631
  const children = transformChildren(node.children, ctx);
10632
+ lowerFormControlValueSsr(tagName, attrs, children);
10447
10633
  const needsSlot = events.length > 0 || hasDynamicContent(children) || hasReactiveAttributes(attrs, ctx) || ref !== null;
10448
10634
  const slotId = needsSlot ? generateSlotId(ctx) : null;
10449
10635
  if (slotId) {
@@ -10475,6 +10661,8 @@ function transformSelfClosingElement(node, ctx) {
10475
10661
  return transformSelfClosingComponent(node, ctx, resolved ?? tagName);
10476
10662
  }
10477
10663
  const { attrs, events, ref } = processAttributes(node.attributes, ctx);
10664
+ const selfClosingChildren = [];
10665
+ lowerFormControlValueSsr(tagName, attrs, selfClosingChildren);
10478
10666
  const needsSlot = events.length > 0 || hasReactiveAttributes(attrs, ctx) || ref !== null;
10479
10667
  const slotId = needsSlot ? generateSlotId(ctx) : null;
10480
10668
  const needsScope = ctx.isRoot;
@@ -10485,7 +10673,7 @@ function transformSelfClosingElement(node, ctx) {
10485
10673
  attrs,
10486
10674
  events,
10487
10675
  ref,
10488
- children: [],
10676
+ children: selfClosingChildren,
10489
10677
  slotId,
10490
10678
  needsScope,
10491
10679
  loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
@@ -11868,6 +12056,15 @@ function branchHasNoElement(node) {
11868
12056
  }
11869
12057
  return true;
11870
12058
  }
12059
+ function tagLoopItemRootComponents(nodes) {
12060
+ for (const node of nodes) {
12061
+ if (node.type === "component") {
12062
+ node.loopItemRoot = true;
12063
+ } else if (node.type === "conditional") {
12064
+ tagLoopItemRootComponents([node.whenTrue, node.whenFalse]);
12065
+ }
12066
+ }
12067
+ }
11871
12068
  function loopBodyItemConditional(children) {
11872
12069
  const real = children.filter((c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim()));
11873
12070
  if (real.length !== 1)
@@ -12105,9 +12302,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
12105
12302
  const pre = multiReturn.preamble ?? [];
12106
12303
  if (pre.length > 0) {
12107
12304
  preamble = preambleFromValueStatements(pre, ctx);
12108
- if (!isClientOnly && !(ctx.analyzer.acceptsCallbackBody?.("map") ?? false)) {
12305
+ if (!preamble.declarations && !isClientOnly && !(ctx.analyzer.acceptsCallbackBody?.("map") ?? false)) {
12109
12306
  ctx.analyzer.errors.push(createError(ErrorCodes.UNSUPPORTED_JSX_PATTERN, loc, {
12110
- message: "A .map() callback body with a `const`/`let` preamble before its " + "branches cannot be lowered to a template: the loop-local binding " + "cannot be carried into a conditional branch on this backend.",
12307
+ 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
12308
  suggestion: {
12112
12309
  message: "Add /* @client */ to evaluate this expression on the client only"
12113
12310
  }
@@ -12174,6 +12371,14 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
12174
12371
  }
12175
12372
  if (valueStmts.length > 0) {
12176
12373
  preamble = preambleFromValueStatements(valueStmts, ctx);
12374
+ if (!preamble.declarations && !isClientOnly && !(ctx.analyzer.acceptsCallbackBody?.("map") ?? false)) {
12375
+ ctx.analyzer.errors.push(createError(ErrorCodes.UNSUPPORTED_JSX_PATTERN, getSourceLocation(body, ctx.sourceFile, ctx.filePath), {
12376
+ 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.",
12377
+ suggestion: {
12378
+ message: "Add /* @client */ to evaluate this expression on the client only"
12379
+ }
12380
+ }));
12381
+ }
12177
12382
  }
12178
12383
  }
12179
12384
  }
@@ -12259,6 +12464,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
12259
12464
  }));
12260
12465
  preamble = undefined;
12261
12466
  }
12467
+ tagLoopItemRootComponents(children);
12262
12468
  let childComponent;
12263
12469
  if (children.length === 1 && children[0].type === "component") {
12264
12470
  const comp = children[0];
@@ -12279,6 +12485,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
12279
12485
  const isDirectPropArray = method !== "flatMap" && isArrayExprDirectPropRef(arrayExpr, ctx);
12280
12486
  const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls && !objectIteration;
12281
12487
  const preambleRegions = preamble && !isStaticArray ? collectPreambleRegions(children, new Set(preamble.declaredNames), ctx) : undefined;
12488
+ if (preamble && !isStaticArray) {
12489
+ markPreambleAttrSlots(children, new Set(preamble.declaredNames), ctx);
12490
+ }
12282
12491
  const nestedComponents = collectNestedComponents(children).filter((c) => c.name !== childComponent?.name);
12283
12492
  return {
12284
12493
  type: "loop",
@@ -12503,20 +12712,66 @@ function collectPreambleRegions(nodes, declared, ctx) {
12503
12712
  visit2(nodes);
12504
12713
  return regions;
12505
12714
  }
12506
- function collectBindingNames(name, out) {
12715
+ function markPreambleAttrSlots(nodes, declared, ctx) {
12716
+ const readsDeclared = (attr) => {
12717
+ if (attr.name === "key")
12718
+ return false;
12719
+ const value = attr.value;
12720
+ if (value.kind !== "expression" && value.kind !== "template")
12721
+ return false;
12722
+ const refs = attr.freeIdentifiers ?? extractFreeIdentifiersFromText(attrValueText(value));
12723
+ for (const r of refs)
12724
+ if (declared.has(r))
12725
+ return true;
12726
+ return false;
12727
+ };
12728
+ const visit2 = (list) => {
12729
+ for (const node of list) {
12730
+ switch (node.type) {
12731
+ case "element":
12732
+ if (!node.slotId && node.attrs.some(readsDeclared))
12733
+ node.slotId = generateSlotId(ctx);
12734
+ visit2(node.children);
12735
+ break;
12736
+ case "fragment":
12737
+ visit2(node.children);
12738
+ break;
12739
+ case "conditional":
12740
+ visit2([node.whenTrue, ...node.whenFalse ? [node.whenFalse] : []]);
12741
+ break;
12742
+ }
12743
+ }
12744
+ };
12745
+ visit2(nodes);
12746
+ }
12747
+ function attrValueText(value) {
12748
+ if (value.kind === "expression")
12749
+ return value.expr;
12750
+ if (value.kind !== "template")
12751
+ return "";
12752
+ const out = [];
12753
+ for (const p of value.parts) {
12754
+ if (p.type === "ternary")
12755
+ out.push(p.condition, p.whenTrue, p.whenFalse);
12756
+ else if (p.type === "lookup")
12757
+ out.push(p.key);
12758
+ }
12759
+ return out.join(" ");
12760
+ }
12761
+ function collectBindingNames2(name, out) {
12507
12762
  if (ts11.isIdentifier(name)) {
12508
12763
  out.add(name.text);
12509
12764
  return;
12510
12765
  }
12511
12766
  for (const el of name.elements) {
12512
12767
  if (ts11.isBindingElement(el))
12513
- collectBindingNames(el.name, out);
12768
+ collectBindingNames2(el.name, out);
12514
12769
  }
12515
12770
  }
12516
12771
  function collectPreambleDeclaredNames(stmt, out) {
12517
12772
  if (ts11.isVariableStatement(stmt)) {
12518
12773
  for (const decl of stmt.declarationList.declarations) {
12519
- collectBindingNames(decl.name, out);
12774
+ collectBindingNames2(decl.name, out);
12520
12775
  }
12521
12776
  } else if (ts11.isFunctionDeclaration(stmt) && stmt.name) {
12522
12777
  out.add(stmt.name.text);
@@ -12540,9 +12795,32 @@ function preambleFromValueStatements(statements, ctx) {
12540
12795
  segments: trimPreambleSegments(segments),
12541
12796
  ssrText: tsxSourceText(typedParts.join(" ")),
12542
12797
  declaredNames: [...declared],
12543
- builderNames: []
12798
+ builderNames: [],
12799
+ declarations: neutralPreambleDeclarations(statements, ctx) ?? undefined
12544
12800
  };
12545
12801
  }
12802
+ function neutralPreambleDeclarations(statements, ctx) {
12803
+ const out = [];
12804
+ for (const stmt of statements) {
12805
+ if (!ts11.isVariableStatement(stmt))
12806
+ return null;
12807
+ for (const decl of stmt.declarationList.declarations) {
12808
+ if (!ts11.isIdentifier(decl.name))
12809
+ return null;
12810
+ if (!decl.initializer)
12811
+ return null;
12812
+ const valueParsed = tsNodeToParsedExpr(decl.initializer);
12813
+ if (!isSupported(valueParsed).supported)
12814
+ return null;
12815
+ out.push({
12816
+ name: decl.name.text,
12817
+ valueParsed,
12818
+ raw: decl.initializer.getText(ctx.sourceFile)
12819
+ });
12820
+ }
12821
+ }
12822
+ return out.length > 0 ? out : null;
12823
+ }
12546
12824
  function trimPreambleSegments(segments) {
12547
12825
  const last = segments[segments.length - 1];
12548
12826
  if (last?.kind === "js") {
@@ -12886,6 +13164,8 @@ function parseTemplateLiteral(expr, ctx) {
12886
13164
  }
12887
13165
  function tryResolveTemplateSpanFromConst(expr, ctx) {
12888
13166
  if (ts11.isIdentifier(expr)) {
13167
+ if (ctx.loopParams.has(expr.text))
13168
+ return null;
12889
13169
  const constInfo = findLocalConst(expr.text, ctx.analyzer);
12890
13170
  if (!constInfo)
12891
13171
  return null;
@@ -12900,6 +13180,8 @@ function tryResolveTemplateSpanFromConst(expr, ctx) {
12900
13180
  if (ts11.isElementAccessExpression(expr)) {
12901
13181
  if (!ts11.isIdentifier(expr.expression))
12902
13182
  return null;
13183
+ if (ctx.loopParams.has(expr.expression.text))
13184
+ return null;
12903
13185
  const constInfo = findLocalConst(expr.expression.text, ctx.analyzer);
12904
13186
  if (!constInfo)
12905
13187
  return null;
@@ -12988,6 +13270,9 @@ function tryResolveIdentifierAsTemplateLiteral(ident, ctx) {
12988
13270
  if (ts11.isNoSubstitutionTemplateLiteral(ast) || ts11.isStringLiteral(ast)) {
12989
13271
  return [{ type: "string", value: ast.text }];
12990
13272
  }
13273
+ if (ts11.isElementAccessExpression(ast) && !ts11.isStringLiteralLike(ast.argumentExpression) && !ts11.isNumericLiteral(ast.argumentExpression)) {
13274
+ return tryResolveTemplateSpanFromConst(ast, ctx);
13275
+ }
12991
13276
  if (!ts11.isTemplateExpression(ast))
12992
13277
  return null;
12993
13278
  let resolvedAny = false;
@@ -13235,8 +13520,11 @@ function processComponentProps(attributes, ctx) {
13235
13520
  }
13236
13521
  let value = getAttributeValue(attr, ctx);
13237
13522
  if (value.kind === "template") {
13238
- value = AttrValueOf.expression(templatePartsToJsString(value.parts), {
13239
- parts: value.parts
13523
+ const collapsed = templatePartsToJsString(value.parts);
13524
+ const collapsedTemplate = templatePartsToJsString(value.parts, { useTemplate: true });
13525
+ value = AttrValueOf.expression(collapsed, {
13526
+ parts: value.parts,
13527
+ ...collapsedTemplate !== collapsed && { templateExpr: collapsedTemplate }
13240
13528
  });
13241
13529
  } else if (value.kind === "boolean-attr") {
13242
13530
  value = AttrValueOf.booleanShorthand();
@@ -13265,16 +13553,18 @@ function processComponentProps(attributes, ctx) {
13265
13553
  }
13266
13554
  return props;
13267
13555
  }
13268
- function templatePartsToJsString(parts) {
13556
+ function templatePartsToJsString(parts, opts) {
13269
13557
  let result = "`";
13270
13558
  for (const part of parts) {
13271
13559
  if (part.type === "string") {
13272
- result += part.value;
13560
+ result += opts?.useTemplate && part.templateValue ? part.templateValue : part.value;
13273
13561
  } else if (part.type === "ternary") {
13274
- result += `\${${part.condition} ? '${part.whenTrue}' : '${part.whenFalse}'}`;
13562
+ const cond = opts?.useTemplate && part.templateCondition ? part.templateCondition : part.condition;
13563
+ result += `\${${cond} ? '${part.whenTrue}' : '${part.whenFalse}'}`;
13275
13564
  } else if (part.type === "lookup") {
13565
+ const key = opts?.useTemplate && part.templateKey ? part.templateKey : part.key;
13276
13566
  const obj = "{" + Object.entries(part.cases).map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(", ") + "}";
13277
- result += `\${(${obj})[${part.key}]}`;
13567
+ result += `\${(${obj})[${key}]}`;
13278
13568
  }
13279
13569
  }
13280
13570
  result += "`";
@@ -13485,11 +13775,12 @@ function replaceBranchLocalRefs(text, branchNames, resolve2) {
13485
13775
  const pattern = new RegExp(`(?<![\\w$])(${branchNames.join("|")})(?![\\w$])`, "g");
13486
13776
  return replaceInExprContexts(text, pattern, (_match, name) => resolve2(name));
13487
13777
  }
13488
- function buildIfStatementChain(analyzer, ctx) {
13778
+ function buildIfStatementChain(analyzer, ctx, opts) {
13489
13779
  const conditionalReturns = analyzer.conditionalReturns;
13780
+ const asConditional = opts?.asConditional === true;
13490
13781
  let alternate = null;
13491
13782
  if (analyzer.jsxReturn) {
13492
- ctx.isRoot = true;
13783
+ ctx.isRoot = !asConditional;
13493
13784
  alternate = transformNode(analyzer.jsxReturn, ctx);
13494
13785
  }
13495
13786
  for (let i = conditionalReturns.length - 1;i >= 0; i--) {
@@ -13558,7 +13849,7 @@ function buildIfStatementChain(analyzer, ctx) {
13558
13849
  ctx.getJS = substitutedGetJS;
13559
13850
  ctx.analyzer.getJS = substitutedGetJS;
13560
13851
  }
13561
- ctx.isRoot = true;
13852
+ ctx.isRoot = !asConditional;
13562
13853
  let consequent;
13563
13854
  try {
13564
13855
  consequent = transformNode(condReturn.jsxReturn, ctx);
@@ -13588,6 +13879,27 @@ function buildIfStatementChain(analyzer, ctx) {
13588
13879
  }
13589
13880
  }
13590
13881
  const loc = getSourceLocation(condReturn.ifStatement, analyzer.sourceFile, analyzer.filePath);
13882
+ if (asConditional && alternate) {
13883
+ const conditional = {
13884
+ type: "conditional",
13885
+ condition,
13886
+ templateCondition,
13887
+ conditionType: null,
13888
+ reactive: true,
13889
+ whenTrue: consequent,
13890
+ whenFalse: alternate,
13891
+ slotId: generateSlotId(ctx),
13892
+ loc,
13893
+ origin: {
13894
+ phase: "tick",
13895
+ scope: "template",
13896
+ effect: "pure",
13897
+ freeRefs: resolveFreeRefs(condReturn.condition, makeBindingEnv(ctx))
13898
+ }
13899
+ };
13900
+ alternate = conditional;
13901
+ continue;
13902
+ }
13591
13903
  const ifStmt = {
13592
13904
  type: "if-statement",
13593
13905
  condition,
@@ -13901,7 +14213,13 @@ function collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings,
13901
14213
  });
13902
14214
  return texts;
13903
14215
  }
13904
- function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false) {
14216
+ function anyNameIn(names, set) {
14217
+ for (const n of names)
14218
+ if (set.has(n))
14219
+ return true;
14220
+ return false;
14221
+ }
14222
+ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false, preambleNames) {
13905
14223
  const attrs = [];
13906
14224
  traverseElements(node, (el) => {
13907
14225
  if (el.slotId) {
@@ -13916,7 +14234,8 @@ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings,
13916
14234
  if (!valueStr)
13917
14235
  continue;
13918
14236
  const expanded = expandConstantForReactivity(valueStr, ctx, attr.freeIdentifiers);
13919
- const reactive = classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || attr.callsReactiveGetters || attr.hasFunctionCalls;
14237
+ const readsPreamble = preambleNames !== undefined && preambleNames.size > 0 && anyNameIn(expanded.freeIds ?? extractFreeIdentifiersFromText(expanded.expr), preambleNames);
14238
+ const reactive = classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || readsPreamble || attr.callsReactiveGetters || attr.hasFunctionCalls;
13920
14239
  if (!attr.clientOnly && !reactive)
13921
14240
  continue;
13922
14241
  attrs.push({
@@ -13924,7 +14243,8 @@ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings,
13924
14243
  attrName: attr.name,
13925
14244
  expression: expanded.expr,
13926
14245
  ...pickAttrMetaFromIR(attr),
13927
- ...expanded.freeIds !== undefined && { freeIdentifiers: expanded.freeIds }
14246
+ ...expanded.freeIds !== undefined && { freeIdentifiers: expanded.freeIds },
14247
+ ...readsPreamble && { readsPreamble: true }
13928
14248
  });
13929
14249
  }
13930
14250
  }
@@ -14220,10 +14540,11 @@ function collectInnerLoops(nodes, siblingOffsets, outerLoopParam, ctx, options)
14220
14540
  const template = n.children.map((c) => irToPlaceholderTemplate(c, undefined, emitDepth, loopParamsForTemplate)).join("");
14221
14541
  const refsOuter = outerLoopParam ? new RegExp(`\\b${outerLoopParam}\\b`).test(n.array) : false;
14222
14542
  const bindings = emptyLoopChildBindings();
14543
+ const innerPreambleNames = preambleNamesOf(n);
14223
14544
  if (ctx) {
14224
14545
  for (const child of n.children) {
14225
14546
  bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, n.param, n.paramBindings));
14226
- bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, n.param, n.paramBindings));
14547
+ bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, n.param, n.paramBindings, false, innerPreambleNames));
14227
14548
  bindings.refs.push(...collectLoopChildRefs(child));
14228
14549
  }
14229
14550
  }
@@ -14446,7 +14767,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
14446
14767
  return;
14447
14768
  const projectionInner = l.method === "flatMap" && l.children.length === 1 && l.children[0].type === "loop" ? l.children[0] : undefined;
14448
14769
  const childHandlers = [];
14449
- const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx, siblingOffsets, l.param, l.paramBindings);
14770
+ const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx, siblingOffsets, l.param, l.paramBindings, preambleNamesOf(l));
14450
14771
  if (!projectionInner) {
14451
14772
  for (const child of l.children) {
14452
14773
  childHandlers.push(...collectEventHandlersFromIR(child));
@@ -14469,7 +14790,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
14469
14790
  if (l.childComponent) {
14470
14791
  template = "";
14471
14792
  if (l.isStaticArray && l.children[0]) {
14472
- staticItemTemplate = irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx), 0, undefined, undefined, true);
14793
+ staticItemTemplate = irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx), 0, undefined, undefined);
14473
14794
  }
14474
14795
  } else if (l.children[0] && !projectionInner) {
14475
14796
  const loopParamSpec = [{ param: l.param, bindings: l.paramBindings }];
@@ -14701,7 +15022,7 @@ function collectBranchLoops(node, ctx, siblingOffsets) {
14701
15022
  } else {
14702
15023
  childTemplate = n.children.map((c) => irToHtmlTemplate(c, undefined, 0, branchLoopParamSpec)).join("");
14703
15024
  }
14704
- const branchBindings = ctx && !projectionInner ? collectLoopChildBindings(n.children, ctx, siblingOffsets, n.param, n.paramBindings) : emptyLoopChildBindings();
15025
+ const branchBindings = ctx && !projectionInner ? collectLoopChildBindings(n.children, ctx, siblingOffsets, n.param, n.paramBindings, preambleNamesOf(n)) : emptyLoopChildBindings();
14705
15026
  loops.push({
14706
15027
  kind: "branch",
14707
15028
  array: n.array,
@@ -14781,11 +15102,17 @@ function collectBranchConditionals(node, ctx, siblingOffsets) {
14781
15102
  });
14782
15103
  return result;
14783
15104
  }
14784
- function collectLoopChildBindings(children, ctx, siblingOffsets, loopParam, loopParamBindings) {
15105
+ function preambleNamesOf(loop) {
15106
+ if (loop.isStaticArray)
15107
+ return;
15108
+ const declared = loop.preamble?.declaredNames;
15109
+ return declared && declared.length > 0 ? new Set(declared) : undefined;
15110
+ }
15111
+ function collectLoopChildBindings(children, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames) {
14785
15112
  const bindings = emptyLoopChildBindings();
14786
15113
  for (const child of children) {
14787
15114
  bindings.events.push(...collectLoopChildEventsWithNesting(child));
14788
- bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, loopParam, loopParamBindings, true));
15115
+ bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, loopParam, loopParamBindings, true, preambleNames));
14789
15116
  bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, loopParam, loopParamBindings, true));
14790
15117
  bindings.refs.push(...collectLoopChildRefs(child));
14791
15118
  bindings.conditionals.push(...collectLoopChildConditionals(child, ctx, siblingOffsets, loopParam, loopParamBindings));
@@ -16399,7 +16726,7 @@ function emitRegistrationAndHydration(lines, ctx, _ir, graph, inlinability) {
16399
16726
  }
16400
16727
  } else {
16401
16728
  const csrInlinableConstants = csrInlinableConstantsFromCtx(ctx);
16402
- const templateHtml = generateCsrTemplate(_ir.root, csrInlinableConstants, ctx, undefined, restSpreadNames, ctx.propsObjectName, unsafeLocalNames, ctx.deferredChildSlots);
16729
+ const templateHtml = generateCsrTemplate(_ir.root, csrInlinableConstants, ctx, restSpreadNames, ctx.propsObjectName, unsafeLocalNames, ctx.deferredChildSlots);
16403
16730
  if (templateHtml) {
16404
16731
  defParts.push(`template: (${PROPS_PARAM}) => \`${templateHtml}\``);
16405
16732
  }
@@ -16797,6 +17124,7 @@ function buildSignalPlan(signal, ctx, lookups) {
16797
17124
  kind: "signal",
16798
17125
  getter: signal.getter,
16799
17126
  setter: signal.setter,
17127
+ getterElided: signal.getterElided,
16800
17128
  initialValueExpr: "",
16801
17129
  controlledEffect: null,
16802
17130
  initializerOverride: `${factory}()`
@@ -16811,6 +17139,7 @@ function buildSignalPlan(signal, ctx, lookups) {
16811
17139
  kind: "signal",
16812
17140
  getter: signal.getter,
16813
17141
  setter: signal.setter,
17142
+ getterElided: signal.getterElided,
16814
17143
  initialValueExpr: resolveSignalInitialValue(signal, ctx, lookups),
16815
17144
  controlledEffect,
16816
17145
  branchCondition: signal.branchCondition,
@@ -16882,9 +17211,10 @@ function bfIdArg(bfId) {
16882
17211
  return bfId ? `, ${JSON.stringify(bfId)}` : "";
16883
17212
  }
16884
17213
  function emitSignal(lines, plan) {
17214
+ const getterSlot = plan.getterElided ? "" : plan.getter;
16885
17215
  if (plan.initializerOverride) {
16886
17216
  if (plan.setter) {
16887
- lines.push(` const [${plan.getter}, ${plan.setter}] = ${plan.initializerOverride}`);
17217
+ lines.push(` const [${getterSlot}, ${plan.setter}] = ${plan.initializerOverride}`);
16888
17218
  } else {
16889
17219
  lines.push(` const [${plan.getter}] = ${plan.initializerOverride}`);
16890
17220
  }
@@ -16893,9 +17223,9 @@ function emitSignal(lines, plan) {
16893
17223
  const id = bfIdArg(plan.bfId);
16894
17224
  if (plan.branchCondition) {
16895
17225
  if (plan.setter) {
16896
- lines.push(` let ${plan.getter}, ${plan.setter}`);
17226
+ lines.push(plan.getterElided ? ` let ${plan.setter}` : ` let ${plan.getter}, ${plan.setter}`);
16897
17227
  lines.push(` if (${plan.branchCondition}) {`);
16898
- lines.push(` ;[${plan.getter}, ${plan.setter}] = createSignal(${plan.initialValueExpr}${id})`);
17228
+ lines.push(` ;[${getterSlot}, ${plan.setter}] = createSignal(${plan.initialValueExpr}${id})`);
16899
17229
  lines.push(` }`);
16900
17230
  } else {
16901
17231
  lines.push(` let ${plan.getter}`);
@@ -16906,7 +17236,7 @@ function emitSignal(lines, plan) {
16906
17236
  return;
16907
17237
  }
16908
17238
  if (plan.setter) {
16909
- lines.push(` const [${plan.getter}, ${plan.setter}] = createSignal(${plan.initialValueExpr}${id})`);
17239
+ lines.push(` const [${getterSlot}, ${plan.setter}] = createSignal(${plan.initialValueExpr}${id})`);
16910
17240
  } else {
16911
17241
  lines.push(` const [${plan.getter}] = createSignal(${plan.initialValueExpr}${id})`);
16912
17242
  }
@@ -17485,7 +17815,7 @@ function emitComponentAndEventSetup(ls, indent, elVar, comps, events, loopParam,
17485
17815
  // src/ir-to-client-js/plan/build-static-array-child-init.ts
17486
17816
  function staticPreludeStatements(preamble) {
17487
17817
  return preamble ? [renderPreamble(preamble, {
17488
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined, true)
17818
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
17489
17819
  })] : [];
17490
17820
  }
17491
17821
  function buildStaticArrayChildInitsPlan(ctx) {
@@ -18040,7 +18370,8 @@ function buildReactiveEffectsPlan(args) {
18040
18370
  attrs: slotAttrs.map((attr) => ({
18041
18371
  attrName: attr.attrName,
18042
18372
  wrappedExpression: wrap(attr.expression),
18043
- meta: pickAttrMeta(attr)
18373
+ meta: pickAttrMeta(attr),
18374
+ ...attr.readsPreamble && { readsPreamble: true }
18044
18375
  }))
18045
18376
  });
18046
18377
  }
@@ -18240,7 +18571,7 @@ function buildReactiveEmit(inner, level, wrapOuter, uidSuffix, outerLoopParam, o
18240
18571
  ] : [{ param: inner.param, bindings: inner.paramBindings }];
18241
18572
  preludeStatements.push(renderPreamble(inner.preamble, {
18242
18573
  transformJs: (t) => wrapInner(wrapOuter(t)),
18243
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, leafLoopParams, undefined, true)
18574
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, leafLoopParams, undefined)
18244
18575
  }));
18245
18576
  }
18246
18577
  const childRefs = buildChildRefBindings(inner.bindings.refs, inner.param, inner.paramBindings);
@@ -18266,7 +18597,7 @@ function buildStaticEmit(inner, level, uidSuffix) {
18266
18597
  preludeStatements.push(indexAlias);
18267
18598
  if (inner.preamble) {
18268
18599
  preludeStatements.push(renderPreamble(inner.preamble, {
18269
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined, true)
18600
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
18270
18601
  }));
18271
18602
  }
18272
18603
  return {
@@ -18298,7 +18629,7 @@ function buildTopLevelCompositePlan(elem, profileComponentName) {
18298
18629
  indexParam: elem.index || "__idx",
18299
18630
  mapPreambleWrapped: elem.preamble ? renderPreamble(elem.preamble, {
18300
18631
  transformJs: wrap,
18301
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined, true)
18632
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined)
18302
18633
  }) : "",
18303
18634
  template: elem.template,
18304
18635
  outerComps: filterCondCompsOut(outerCompsByDepth, elem.bindings.conditionals),
@@ -18348,7 +18679,7 @@ function buildBranchCompositePlan(loop, cv, profileComponentName) {
18348
18679
  indexParam: loop.index || "__idx",
18349
18680
  mapPreambleWrapped: loop.preamble ? renderPreamble(loop.preamble, {
18350
18681
  transformJs: wrap,
18351
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined, true)
18682
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined)
18352
18683
  }) : "",
18353
18684
  template: loop.template,
18354
18685
  outerComps: filterCondCompsOut(outerCompsByDepth, loop.bindings.conditionals),
@@ -18413,7 +18744,7 @@ function buildDynamicLoopDelegationPlan(elem, profileComponentName) {
18413
18744
  key: elem.key,
18414
18745
  index: elem.index,
18415
18746
  mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
18416
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined, true)
18747
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
18417
18748
  }) : null,
18418
18749
  mapPreambleDeclaredNames: elem.preamble?.declaredNames ?? []
18419
18750
  })
@@ -18432,7 +18763,7 @@ function buildBranchLoopDelegationPlan(loop, cv, profileComponentName) {
18432
18763
  key: loop.key,
18433
18764
  index: loop.index,
18434
18765
  mapPreamble: loop.preamble ? renderPreamble(loop.preamble, {
18435
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined, true)
18766
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
18436
18767
  }) : null,
18437
18768
  mapPreambleDeclaredNames: loop.preamble?.declaredNames ?? []
18438
18769
  })
@@ -18449,7 +18780,7 @@ function buildStaticArrayDelegationPlan(elem, profileComponentName) {
18449
18780
  arrayExpr: buildChainedArrayExpr(elem),
18450
18781
  param: elem.param,
18451
18782
  mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
18452
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined, true)
18783
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, undefined, undefined)
18453
18784
  }) : null,
18454
18785
  mapPreambleDeclaredNames: elem.preamble?.declaredNames ?? [],
18455
18786
  offset: elem.offset ?? null,
@@ -18484,6 +18815,181 @@ function buildKeyedOrIndexLookup(args) {
18484
18815
  };
18485
18816
  }
18486
18817
 
18818
+ // src/ir-to-client-js/control-flow/plan/lazy-conditional.ts
18819
+ var NO = (reason) => ({ lazySafe: false, reason });
18820
+ function wiringOn(branch) {
18821
+ const found = [];
18822
+ if (branch.childComponents.length > 0)
18823
+ found.push("child components");
18824
+ if (branch.innerLoops && branch.innerLoops.length > 0)
18825
+ found.push("an inner loop");
18826
+ if (branch.conditionals && branch.conditionals.length > 0)
18827
+ found.push("a nested conditional");
18828
+ if (branch.events && branch.events.length > 0)
18829
+ found.push("events");
18830
+ if (branch.reactiveAttrs && branch.reactiveAttrs.length > 0)
18831
+ found.push("reactive attrs");
18832
+ if (branch.reactiveTexts && branch.reactiveTexts.length > 0)
18833
+ found.push("reactive text");
18834
+ return found;
18835
+ }
18836
+ function analyzeLazyConditional(cond, indexParam, arms) {
18837
+ for (const [label, branch] of [["true", cond.whenTrue], ["false", cond.whenFalse]]) {
18838
+ const wiring = wiringOn(branch);
18839
+ if (wiring.length > 0) {
18840
+ return NO(`conditional on slot ${cond.slotId}: its ${label} arm owns ${wiring.join(" + ")}`);
18841
+ }
18842
+ }
18843
+ for (const [label, html] of [["true", arms.whenTrueHtml], ["false", arms.whenFalseHtml]]) {
18844
+ if (html.includes("bf-cond-start:")) {
18845
+ return NO(`conditional on slot ${cond.slotId}: its ${label} arm is a fragment conditional`);
18846
+ }
18847
+ if (!html.includes(`bf-c="${cond.slotId}"`)) {
18848
+ return NO(`conditional on slot ${cond.slotId}: its ${label} arm has no single bf-c root`);
18849
+ }
18850
+ if (html.includes("${")) {
18851
+ return NO(`conditional on slot ${cond.slotId}: its ${label} arm interpolates a value`);
18852
+ }
18853
+ }
18854
+ if (!cond.conditionFreeIdentifiers) {
18855
+ return NO(`conditional on slot ${cond.slotId}: condition has no analyzable identifier set`);
18856
+ }
18857
+ if (cond.conditionFreeIdentifiers.has(indexParam)) {
18858
+ return NO(`conditional on slot ${cond.slotId}: condition reads the loop index parameter '${indexParam}'`);
18859
+ }
18860
+ return {
18861
+ lazySafe: true,
18862
+ facts: {
18863
+ slotId: cond.slotId,
18864
+ condition: cond.condition,
18865
+ whenTrueHtml: arms.whenTrueHtml,
18866
+ whenFalseHtml: arms.whenFalseHtml
18867
+ }
18868
+ };
18869
+ }
18870
+
18871
+ // src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
18872
+ import ts15 from "typescript";
18873
+ var NO_PREAMBLE = {
18874
+ lazySafe: true,
18875
+ facts: { declaredNames: new Set, freeNames: new Set }
18876
+ };
18877
+ var NO2 = (reason) => ({ lazySafe: false, reason });
18878
+ function analyzeLazyPreamble(preamble, indexParam, primableNames) {
18879
+ if (!preamble)
18880
+ return NO_PREAMBLE;
18881
+ if (preamble.builderNames.length > 0) {
18882
+ return NO2(`map-callback preamble accumulates JSX leaves (${preamble.builderNames.join(", ")})`);
18883
+ }
18884
+ for (const seg of preamble.segments) {
18885
+ if (seg.kind !== "js")
18886
+ return NO2("map-callback preamble contains a JSX leaf");
18887
+ }
18888
+ const text = preambleAnalysisText(preamble);
18889
+ if (text.trim().length === 0)
18890
+ return NO_PREAMBLE;
18891
+ const declaredNames = new Set;
18892
+ const sf = ts15.createSourceFile("__lazy_preamble__.ts", text, ts15.ScriptTarget.Latest, true, ts15.ScriptKind.TS);
18893
+ for (const stmt of sf.statements) {
18894
+ if (!ts15.isVariableStatement(stmt)) {
18895
+ return NO2(`map-callback preamble has a non-declaration statement (${ts15.SyntaxKind[stmt.kind]})`);
18896
+ }
18897
+ const isConst = (stmt.declarationList.flags & ts15.NodeFlags.Const) !== 0;
18898
+ if (!isConst)
18899
+ return NO2("map-callback preamble declares a mutable binding (let/var)");
18900
+ for (const decl of stmt.declarationList.declarations) {
18901
+ collectBindingNames3(decl.name, declaredNames);
18902
+ if (!decl.initializer) {
18903
+ return NO2("map-callback preamble has a declaration with no initializer");
18904
+ }
18905
+ const impure = findImpureNode(decl.initializer, primableNames);
18906
+ if (impure) {
18907
+ return NO2(`map-callback preamble initializer is not re-runnable (${impure})`);
18908
+ }
18909
+ }
18910
+ }
18911
+ for (const name of declaredNames) {
18912
+ if (primableNames.has(name)) {
18913
+ return NO2(`map-callback preamble shadows the signal/memo getter '${name}'`);
18914
+ }
18915
+ }
18916
+ const readNames = extractFreeIdentifiersFromStatementText(text);
18917
+ if (readNames.has(indexParam) && !declaredNames.has(indexParam)) {
18918
+ return NO2(`map-callback preamble reads the loop index parameter '${indexParam}'`);
18919
+ }
18920
+ const freeNames = new Set(readNames);
18921
+ for (const declared of declaredNames)
18922
+ freeNames.delete(declared);
18923
+ return { lazySafe: true, facts: { declaredNames, freeNames } };
18924
+ }
18925
+ function collectBindingNames3(name, out) {
18926
+ if (ts15.isIdentifier(name)) {
18927
+ out.add(name.text);
18928
+ return;
18929
+ }
18930
+ for (const element of name.elements) {
18931
+ if (ts15.isOmittedExpression(element))
18932
+ continue;
18933
+ collectBindingNames3(element.name, out);
18934
+ }
18935
+ }
18936
+ function findImpureNode(root, primableNames) {
18937
+ let found = null;
18938
+ const visit3 = (node) => {
18939
+ if (found)
18940
+ return;
18941
+ if (ts15.isCallExpression(node)) {
18942
+ const callee = node.expression;
18943
+ const isSignalRead = ts15.isIdentifier(callee) && primableNames.has(callee.text) && node.arguments.length === 0 && node.questionDotToken === undefined;
18944
+ if (!isSignalRead) {
18945
+ found = `call to ${callee.getText(callee.getSourceFile())}`;
18946
+ return;
18947
+ }
18948
+ }
18949
+ if (ts15.isNewExpression(node)) {
18950
+ found = "new expression";
18951
+ return;
18952
+ }
18953
+ if (ts15.isTaggedTemplateExpression(node)) {
18954
+ found = "tagged template";
18955
+ return;
18956
+ }
18957
+ if (ts15.isAwaitExpression(node)) {
18958
+ found = "await";
18959
+ return;
18960
+ }
18961
+ if (ts15.isYieldExpression(node)) {
18962
+ found = "yield";
18963
+ return;
18964
+ }
18965
+ if (ts15.isPrefixUnaryExpression(node) || ts15.isPostfixUnaryExpression(node)) {
18966
+ const op = node.operator;
18967
+ if (op === ts15.SyntaxKind.PlusPlusToken || op === ts15.SyntaxKind.MinusMinusToken) {
18968
+ found = "increment/decrement";
18969
+ return;
18970
+ }
18971
+ }
18972
+ if (ts15.isDeleteExpression(node)) {
18973
+ found = "delete";
18974
+ return;
18975
+ }
18976
+ if (ts15.isFunctionExpression(node) || ts15.isArrowFunction(node) || ts15.isClassExpression(node)) {
18977
+ found = "function or class expression";
18978
+ return;
18979
+ }
18980
+ if (ts15.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
18981
+ found = "assignment";
18982
+ return;
18983
+ }
18984
+ ts15.forEachChild(node, visit3);
18985
+ };
18986
+ visit3(root);
18987
+ return found;
18988
+ }
18989
+ function isAssignmentOperator(kind) {
18990
+ return kind >= ts15.SyntaxKind.FirstAssignment && kind <= ts15.SyntaxKind.LastAssignment;
18991
+ }
18992
+
18487
18993
  // src/ir-to-client-js/control-flow/plan/lazy-row-eligibility.ts
18488
18994
  var PURE_SOURCE_GLOBALS = new Set([
18489
18995
  "Object",
@@ -18527,51 +19033,51 @@ var INERT_BINDING_GLOBALS = new Set([
18527
19033
  "decodeURI"
18528
19034
  ]);
18529
19035
  var UNKNOWN_IDENTIFIERS = "<unknown>";
18530
- var NO = (reason) => ({ eligible: false, reason });
19036
+ var NO3 = (reason) => ({ eligible: false, reason });
18531
19037
  function lazyRowEligibility(args) {
18532
19038
  const { shape, bindings, arraySourceIdentifiers, scope } = args;
18533
19039
  if (scope.profile)
18534
- return NO("profile mode keeps the granular eager emission");
19040
+ return NO3("profile mode keeps the granular eager emission");
18535
19041
  if (shape.callSite !== "plain" && shape.callSite !== "branch-plain") {
18536
- return NO(`call site '${shape.callSite}' is not a plain loop row`);
19042
+ return NO3(`call site '${shape.callSite}' is not a plain loop row`);
18537
19043
  }
18538
19044
  if (shape.flatMapLeafItem)
18539
- return NO("flatMap descriptor loop (build-or-patch renderItem)");
19045
+ return NO3("flatMap descriptor loop (build-or-patch renderItem)");
18540
19046
  if (shape.anchored)
18541
- return NO("anchored whole-item-conditional loop");
19047
+ return NO3("anchored whole-item-conditional loop");
18542
19048
  if (shape.bodyIsMultiRoot)
18543
- return NO("multi-root (Fragment) row");
19049
+ return NO3("multi-root (Fragment) row");
18544
19050
  if (!shape.hasExplicitKey)
18545
- return NO("index-keyed loop (no explicit key)");
18546
- if (shape.conditionalCount > 0)
18547
- return NO("row contains a reactive conditional");
19051
+ return NO3("index-keyed loop (no explicit key)");
19052
+ if (shape.conditionalRefusal)
19053
+ return NO3(shape.conditionalRefusal);
18548
19054
  if (shape.childRefCount > 0)
18549
- return NO("row has imperative child refs");
19055
+ return NO3("row has imperative child refs");
18550
19056
  if (shape.hasChildComponent)
18551
- return NO("row body is a child component");
19057
+ return NO3("row body is a child component");
18552
19058
  if (shape.nestedComponentCount > 0)
18553
- return NO("row contains nested child components");
19059
+ return NO3("row contains nested child components");
18554
19060
  if (shape.innerLoopCount > 0)
18555
- return NO("row contains an inner loop");
18556
- if (shape.hasMapPreamble)
18557
- return NO("row has a map-callback preamble (may declare row-local reactivity)");
19061
+ return NO3("row contains an inner loop");
19062
+ if (shape.mapPreambleRefusal)
19063
+ return NO3(shape.mapPreambleRefusal);
18558
19064
  if (shape.preambleRegionCount > 0)
18559
- return NO("row has preamble-patched regions");
19065
+ return NO3("row has preamble-patched regions");
18560
19066
  if (shape.hasParamUnwrap)
18561
- return NO("destructured loop param without param bindings");
19067
+ return NO3("destructured loop param without param bindings");
18562
19068
  for (const b of bindings) {
18563
19069
  if (b.referencesIndex) {
18564
- return NO(`binding on slot ${b.slotId} references the loop index parameter`);
19070
+ return NO3(`binding on slot ${b.slotId} references the loop index parameter`);
18565
19071
  }
18566
19072
  if (b.opaqueOuterNames.includes(UNKNOWN_IDENTIFIERS)) {
18567
- return NO(`binding on slot ${b.slotId} has no analyzable identifier set`);
19073
+ return NO3(`binding on slot ${b.slotId} has no analyzable identifier set`);
18568
19074
  }
18569
19075
  }
18570
19076
  if (!arraySourceIdentifiers)
18571
- return NO("loop source free identifiers unavailable");
19077
+ return NO3("loop source free identifiers unavailable");
18572
19078
  const sourceGate = checkSourceConsistency(arraySourceIdentifiers, scope);
18573
19079
  if (sourceGate)
18574
- return NO(`loop source is not provably hydration-consistent: ${sourceGate}`);
19080
+ return NO3(`loop source is not provably hydration-consistent: ${sourceGate}`);
18575
19081
  return { eligible: true };
18576
19082
  }
18577
19083
  function checkSourceConsistency(names, scope) {
@@ -18622,6 +19128,7 @@ function checkSourceConsistency(names, scope) {
18622
19128
  }
18623
19129
  function classifyLazyBinding(args) {
18624
19130
  const { kind, slotId, free, rowLocalNames, indexParam, scope } = args;
19131
+ const preamble = args.preamble;
18625
19132
  if (free === null) {
18626
19133
  return {
18627
19134
  kind,
@@ -18630,33 +19137,44 @@ function classifyLazyBinding(args) {
18630
19137
  readsOuter: true,
18631
19138
  reactiveOuterNames: [],
18632
19139
  opaqueOuterNames: [UNKNOWN_IDENTIFIERS],
18633
- referencesIndex: false
19140
+ referencesIndex: false,
19141
+ readsPreamble: preamble != null && preamble.declaredNames.size > 0
18634
19142
  };
18635
19143
  }
18636
19144
  let readsItem = false;
18637
19145
  let referencesIndex = false;
19146
+ let readsPreamble = false;
18638
19147
  const reactiveOuterNames = [];
18639
19148
  const opaqueOuterNames = [];
18640
- for (const name of free) {
19149
+ const classifyName = (name) => {
18641
19150
  if (rowLocalNames.has(name)) {
18642
19151
  readsItem = true;
18643
- continue;
19152
+ return;
18644
19153
  }
18645
19154
  if (name === indexParam) {
18646
19155
  referencesIndex = true;
18647
- continue;
19156
+ return;
18648
19157
  }
18649
19158
  if (INERT_BINDING_GLOBALS.has(name))
18650
- continue;
19159
+ return;
18651
19160
  if (scope.signals.has(name) || scope.memos.has(name)) {
18652
19161
  if (!reactiveOuterNames.includes(name))
18653
19162
  reactiveOuterNames.push(name);
18654
- continue;
19163
+ return;
18655
19164
  }
18656
19165
  const constFree = scope.constants.get(name);
18657
19166
  if (constFree !== undefined && constFree !== null && constFree.size === 0)
18658
- continue;
19167
+ return;
18659
19168
  opaqueOuterNames.push(name);
19169
+ };
19170
+ for (const name of free) {
19171
+ if (preamble?.declaredNames.has(name)) {
19172
+ readsPreamble = true;
19173
+ for (const dep of preamble.freeNames)
19174
+ classifyName(dep);
19175
+ continue;
19176
+ }
19177
+ classifyName(name);
18660
19178
  }
18661
19179
  return {
18662
19180
  kind,
@@ -18665,7 +19183,8 @@ function classifyLazyBinding(args) {
18665
19183
  readsOuter: reactiveOuterNames.length > 0 || opaqueOuterNames.length > 0,
18666
19184
  reactiveOuterNames,
18667
19185
  opaqueOuterNames,
18668
- referencesIndex
19186
+ referencesIndex,
19187
+ readsPreamble
18669
19188
  };
18670
19189
  }
18671
19190
 
@@ -18682,6 +19201,23 @@ function decideLazyRow(args) {
18682
19201
  const rowLocalNames = new Set([loop.param]);
18683
19202
  for (const b of loop.paramBindings ?? [])
18684
19203
  rowLocalNames.add(b.name);
19204
+ const primableNames = new Set([...scope.signals.keys(), ...scope.memos]);
19205
+ const preambleAnalysis = analyzeLazyPreamble(loop.preamble, args.indexParam, primableNames);
19206
+ const rawConditionals = loop.bindings.conditionals ?? [];
19207
+ const condFacts = [];
19208
+ let conditionalRefusal = null;
19209
+ for (const cond of rawConditionals) {
19210
+ const verdict = analyzeLazyConditional(cond, args.indexParam, {
19211
+ whenTrueHtml: addCondAttrToTemplate(wrap(cond.whenTrueHtml), cond.slotId),
19212
+ whenFalseHtml: addCondAttrToTemplate(wrap(cond.whenFalseHtml), cond.slotId)
19213
+ });
19214
+ if (!verdict.lazySafe) {
19215
+ conditionalRefusal = verdict.reason;
19216
+ break;
19217
+ }
19218
+ condFacts.push(verdict.facts);
19219
+ }
19220
+ const preambleFacts = preambleAnalysis.lazySafe ? preambleAnalysis.facts : undefined;
18685
19221
  const classified = [];
18686
19222
  const attrClass = new Map;
18687
19223
  loop.bindings.reactiveAttrs.forEach((attr, i) => {
@@ -18691,7 +19227,8 @@ function decideLazyRow(args) {
18691
19227
  free: attrFreeIdentifiers2(attr.expression),
18692
19228
  rowLocalNames,
18693
19229
  indexParam: args.indexParam,
18694
- scope
19230
+ scope,
19231
+ preamble: preambleFacts
18695
19232
  });
18696
19233
  attrClass.set(i, c);
18697
19234
  classified.push(c);
@@ -18704,23 +19241,38 @@ function decideLazyRow(args) {
18704
19241
  free: text.freeIdentifiers ?? null,
18705
19242
  rowLocalNames,
18706
19243
  indexParam: args.indexParam,
18707
- scope
19244
+ scope,
19245
+ preamble: preambleFacts
18708
19246
  });
18709
19247
  textClass.set(i, c);
18710
19248
  classified.push(c);
18711
19249
  });
19250
+ const condClass = new Map;
19251
+ condFacts.forEach((c, i) => {
19252
+ const k = classifyLazyBinding({
19253
+ kind: "attr",
19254
+ slotId: c.slotId,
19255
+ free: rawConditionals[i].conditionFreeIdentifiers ?? null,
19256
+ rowLocalNames,
19257
+ indexParam: args.indexParam,
19258
+ scope,
19259
+ preamble: preambleFacts
19260
+ });
19261
+ condClass.set(i, k);
19262
+ classified.push(k);
19263
+ });
18712
19264
  const shape = {
18713
19265
  callSite: args.callSite,
18714
19266
  flatMapLeafItem: args.flatMapLeafItem,
18715
19267
  anchored: args.anchored,
18716
19268
  bodyIsMultiRoot: loop.bodyIsMultiRoot ?? false,
18717
19269
  hasExplicitKey: loop.key != null,
18718
- conditionalCount: loop.bindings.conditionals?.length ?? 0,
19270
+ conditionalRefusal,
18719
19271
  childRefCount: loop.bindings.refs?.length ?? 0,
18720
19272
  nestedComponentCount: loop.nestedComponents?.length ?? 0,
18721
19273
  innerLoopCount: loop.innerLoops?.length ?? 0,
18722
19274
  hasChildComponent: "childComponent" in loop && loop.childComponent != null,
18723
- hasMapPreamble: args.mapPreambleWrapped.length > 0,
19275
+ mapPreambleRefusal: preambleAnalysis.lazySafe ? null : preambleAnalysis.reason,
18724
19276
  preambleRegionCount: args.preambleRegionCount,
18725
19277
  hasParamUnwrap: args.paramUnwrap.length > 0
18726
19278
  };
@@ -18748,7 +19300,8 @@ function decideLazyRow(args) {
18748
19300
  refIndex: attrSlotIds.indexOf(attr.childSlotId),
18749
19301
  ordinal: ordinal++,
18750
19302
  readsItem: c.readsItem,
18751
- readsOuter: c.readsOuter
19303
+ readsOuter: c.readsOuter,
19304
+ readsPreamble: c.readsPreamble
18752
19305
  };
18753
19306
  });
18754
19307
  const texts = loop.bindings.reactiveTexts.map((text, i) => {
@@ -18758,7 +19311,8 @@ function decideLazyRow(args) {
18758
19311
  wrappedExpression: wrap(text.expression),
18759
19312
  ordinal: ordinal++,
18760
19313
  readsItem: c.readsItem || !c.readsOuter,
18761
- readsOuter: c.readsOuter
19314
+ readsOuter: c.readsOuter,
19315
+ readsPreamble: c.readsPreamble
18762
19316
  };
18763
19317
  });
18764
19318
  const outerPrimeGetters = [];
@@ -18768,6 +19322,21 @@ function decideLazyRow(args) {
18768
19322
  outerPrimeGetters.push(name);
18769
19323
  }
18770
19324
  }
19325
+ const condRefBase = attrSlotIds.length + (texts.length > 0 ? 1 : 0);
19326
+ const conditionals = condFacts.map((c, i) => {
19327
+ const klass = condClass.get(i);
19328
+ return {
19329
+ slotId: c.slotId,
19330
+ wrappedCondition: wrap(c.condition),
19331
+ whenTrueHtml: c.whenTrueHtml,
19332
+ whenFalseHtml: c.whenFalseHtml,
19333
+ refIndex: condRefBase + i,
19334
+ ordinal: ordinal++,
19335
+ readsItem: klass.readsItem || !klass.readsOuter,
19336
+ readsOuter: klass.readsOuter,
19337
+ readsPreamble: klass.readsPreamble
19338
+ };
19339
+ });
18771
19340
  return {
18772
19341
  plan: {
18773
19342
  attrSlotIds,
@@ -18777,7 +19346,10 @@ function decideLazyRow(args) {
18777
19346
  textNeedsRead: texts.some((t) => t.readsOuter),
18778
19347
  lastCount: ordinal,
18779
19348
  outerPrimeGetters,
18780
- hasOuter: attrs.some((a) => a.readsOuter) || texts.some((t) => t.readsOuter)
19349
+ preambleStatements: args.mapPreambleWrapped,
19350
+ itemNeedsPreamble: [...attrs, ...texts, ...conditionals].some((b) => b.readsItem && b.readsPreamble),
19351
+ outerNeedsPreamble: [...attrs, ...texts, ...conditionals].some((b) => b.readsOuter && b.readsPreamble),
19352
+ conditionals
18781
19353
  },
18782
19354
  decision
18783
19355
  };
@@ -18849,7 +19421,7 @@ function buildBranchLoopPlan(loop, profileComponentName, lazyScope) {
18849
19421
  const indexParam = loop.index || "__idx";
18850
19422
  const mapPreambleWrapped = loop.preamble ? renderPreamble(loop.preamble, {
18851
19423
  transformJs: (t) => wrapLoopParamAsAccessor(t, loop.param, loop.paramBindings),
18852
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined, true)
19424
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: loop.param, bindings: loop.paramBindings }], undefined)
18853
19425
  }) : "";
18854
19426
  const preambleRegions = buildPreambleRegionPlans(loop.preambleRegions, loop.param, loop.paramBindings);
18855
19427
  const plan = {
@@ -18945,7 +19517,7 @@ function buildArmBody(branch, options) {
18945
19517
  }
18946
19518
 
18947
19519
  // src/ir-to-client-js/emit-reactive.ts
18948
- import ts15 from "typescript";
19520
+ import ts16 from "typescript";
18949
19521
 
18950
19522
  // src/ir-to-client-js/control-flow/stringify/claim-plan.ts
18951
19523
  function slotSpecLiteral(slot) {
@@ -19048,20 +19620,20 @@ function lowerToLocaleCallsInReactiveExpr(expr, matcher) {
19048
19620
  return expr;
19049
19621
  let sourceFile;
19050
19622
  try {
19051
- sourceFile = ts15.createSourceFile("__reactive_expr__.ts", `(${expr});`, ts15.ScriptTarget.Latest, true, ts15.ScriptKind.TS);
19623
+ sourceFile = ts16.createSourceFile("__reactive_expr__.ts", `(${expr});`, ts16.ScriptTarget.Latest, true, ts16.ScriptKind.TS);
19052
19624
  } catch {
19053
19625
  return expr;
19054
19626
  }
19055
19627
  const stmt = sourceFile.statements[0];
19056
- if (!stmt || !ts15.isExpressionStatement(stmt))
19628
+ if (!stmt || !ts16.isExpressionStatement(stmt))
19057
19629
  return expr;
19058
- const root = ts15.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
19630
+ const root = ts16.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
19059
19631
  const candidates = [];
19060
19632
  const visit3 = (n) => {
19061
- if (ts15.isCallExpression(n) && n.arguments.length === 2 && ts15.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && n.expression.name.text === "toLocaleDateString") {
19633
+ if (ts16.isCallExpression(n) && n.arguments.length === 2 && ts16.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && n.expression.name.text === "toLocaleDateString") {
19062
19634
  candidates.push(n);
19063
19635
  }
19064
- ts15.forEachChild(n, visit3);
19636
+ ts16.forEachChild(n, visit3);
19065
19637
  };
19066
19638
  visit3(root);
19067
19639
  if (candidates.length === 0)
@@ -19097,20 +19669,20 @@ function lowerDateCallsInReactiveExpr(expr, matcher) {
19097
19669
  return expr;
19098
19670
  let sourceFile;
19099
19671
  try {
19100
- sourceFile = ts15.createSourceFile("__reactive_expr__.ts", `(${expr});`, ts15.ScriptTarget.Latest, true, ts15.ScriptKind.TS);
19672
+ sourceFile = ts16.createSourceFile("__reactive_expr__.ts", `(${expr});`, ts16.ScriptTarget.Latest, true, ts16.ScriptKind.TS);
19101
19673
  } catch {
19102
19674
  return expr;
19103
19675
  }
19104
19676
  const stmt = sourceFile.statements[0];
19105
- if (!stmt || !ts15.isExpressionStatement(stmt))
19677
+ if (!stmt || !ts16.isExpressionStatement(stmt))
19106
19678
  return expr;
19107
- const root = ts15.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
19679
+ const root = ts16.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
19108
19680
  const candidates = [];
19109
19681
  const visit3 = (n) => {
19110
- if (ts15.isCallExpression(n) && n.arguments.length === 0 && ts15.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && DATE_METHODS.has(n.expression.name.text)) {
19682
+ if (ts16.isCallExpression(n) && n.arguments.length === 0 && ts16.isPropertyAccessExpression(n.expression) && !n.expression.questionDotToken && DATE_METHODS.has(n.expression.name.text)) {
19111
19683
  candidates.push(n);
19112
19684
  }
19113
- ts15.forEachChild(n, visit3);
19685
+ ts16.forEachChild(n, visit3);
19114
19686
  };
19115
19687
  visit3(root);
19116
19688
  if (candidates.length === 0)
@@ -19418,7 +19990,7 @@ function stringifyReactiveEffects(lines, plan, opts) {
19418
19990
  const outerTexts = plan?.outerTexts ?? [];
19419
19991
  const conditionals = plan?.conditionals ?? [];
19420
19992
  if (pc) {
19421
- emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId);
19993
+ emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId, mapPreambleWrapped);
19422
19994
  emitOuterTexts(lines, indent, elVar, outerTexts, bindingBfId, textClaimPathExprs);
19423
19995
  emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPreambleWrapped);
19424
19996
  } else {
@@ -19428,7 +20000,7 @@ function stringifyReactiveEffects(lines, plan, opts) {
19428
20000
  emitOuterConditional(lines, indent, elVar, cond, pc);
19429
20001
  }
19430
20002
  }
19431
- function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId) {
20003
+ function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId, mapPreambleWrapped) {
19432
20004
  for (const slot of attrSlots) {
19433
20005
  const varName = `__ra_${varSlotId(slot.slotId)}`;
19434
20006
  const lookupExpr = attrLookupExpr(slot.slotId, varName, elVar, lookup, elementIndexBySlot);
@@ -19436,6 +20008,9 @@ function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementI
19436
20008
  lines.push(`${indent}if (${varName}) {`);
19437
20009
  for (const attr of slot.attrs) {
19438
20010
  lines.push(`${indent} createEffect(() => {`);
20011
+ if (attr.readsPreamble && mapPreambleWrapped) {
20012
+ lines.push(`${indent} ${mapPreambleWrapped}`);
20013
+ }
19439
20014
  for (const stmt of emitAttrUpdate(varName, attr.attrName, attr.wrappedExpression, attr.meta)) {
19440
20015
  lines.push(`${indent} ${stmt}`);
19441
20016
  }
@@ -19458,6 +20033,9 @@ function emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPre
19458
20033
  }
19459
20034
  lines.push(`${indent}})`);
19460
20035
  }
20036
+ function attrsReadPreamble(attrSlots) {
20037
+ return attrSlots.some((slot) => slot.attrs.some((a) => a.readsPreamble));
20038
+ }
19461
20039
  function attrLookupExpr(slotId, varName, elVar, lookup, elementIndexBySlot) {
19462
20040
  const pIdx = elementIndexBySlot?.get(slotId);
19463
20041
  return pIdx !== undefined ? `__p ? __p[${pIdx}] : ${lookup}(${elVar}, '[bf="${slotId}"]')` : `${lookup}(${elVar}, '[bf="${slotId}"]')`;
@@ -19483,6 +20061,9 @@ function emitConsolidatedRowEffect(lines, indent, elVar, lookup, attrSlots, oute
19483
20061
  return;
19484
20062
  }
19485
20063
  lines.push(`${indent}createEffect(() => {`);
20064
+ if (mapPreambleWrapped && (preambleRegions.length > 0 || attrsReadPreamble(attrSlots))) {
20065
+ lines.push(`${indent} ${mapPreambleWrapped}`);
20066
+ }
19486
20067
  for (const slot of attrSlots) {
19487
20068
  const varName = `__ra_${varSlotId(slot.slotId)}`;
19488
20069
  lines.push(`${indent} if (${varName}) {`);
@@ -19495,9 +20076,6 @@ function emitConsolidatedRowEffect(lines, indent, elVar, lookup, attrSlots, oute
19495
20076
  }
19496
20077
  lines.push(`${indent} }`);
19497
20078
  }
19498
- if (preambleRegions.length > 0 && mapPreambleWrapped) {
19499
- lines.push(`${indent} ${mapPreambleWrapped}`);
19500
- }
19501
20079
  for (const text of outerTexts) {
19502
20080
  lines.push(`${indent} ${writer}('${text.slotId}', String(${text.wrappedExpression}))`);
19503
20081
  }
@@ -19631,9 +20209,8 @@ function stringifyLazyRowLoop(lines, o) {
19631
20209
  const { indent, lazyRow, paramHead } = o;
19632
20210
  const mid = o.markerId.replace(/[^A-Za-z0-9_$]/g, "_");
19633
20211
  const tplVar = `__tpl_${mid}`;
19634
- const claimVar = `__lzc_${mid}`;
19635
20212
  const hasRefs = lazyRow.attrSlotIds.length > 0 || lazyRow.texts.length > 0;
19636
- const hasBindings = lazyRow.attrs.length > 0 || lazyRow.texts.length > 0;
20213
+ const hasBindings = lazyRow.attrs.length > 0 || lazyRow.texts.length > 0 || lazyRow.conditionals.length > 0;
19637
20214
  const rwDoor = lazyRow.textNeedsRead;
19638
20215
  const paths = o.skeletonPaths;
19639
20216
  const useHoisted = Boolean(o.skeletonTemplate);
@@ -19663,13 +20240,10 @@ function stringifyLazyRowLoop(lines, o) {
19663
20240
  freshPlanVar = adoptedPlanVar;
19664
20241
  }
19665
20242
  }
19666
- if (hasRefs) {
19667
- const parts = refParts(lazyRow, "__el", null, adoptedPlanVar, true);
19668
- lines.push(`${indent}const ${claimVar} = (__e) => {`);
19669
- if (parts.some((p) => p.includes("__el")))
19670
- lines.push(`${indent} const __el = __e.primaryEl`);
19671
- lines.push(`${indent} return [${parts.join(", ")}]`);
19672
- lines.push(`${indent}}`);
20243
+ for (const c of lazyRow.conditionals) {
20244
+ const v = condVars(mid, c.slotId);
20245
+ emitHoistedTemplateDecl(lines, indent, v.trueTpl, c.whenTrueHtml);
20246
+ emitHoistedTemplateDecl(lines, indent, v.falseTpl, c.whenFalseHtml);
19673
20247
  }
19674
20248
  const call = `mapArrayLazy(() => ${o.arrayExpr}, ${o.containerVar}, ${o.keyFn}, {`;
19675
20249
  lines.push(`${indent}${o.guardContainer ? `if (${o.containerVar}) ` : ""}${call}`);
@@ -19677,6 +20251,8 @@ function stringifyLazyRowLoop(lines, o) {
19677
20251
  const b2 = `${indent} `;
19678
20252
  lines.push(`${b1}createRow: (__e, ${o.indexParam}) => {`);
19679
20253
  lines.push(`${b2}const ${paramHead} = () => __e.item`);
20254
+ if (lazyRow.preambleStatements)
20255
+ lines.push(`${b2}${lazyRow.preambleStatements}`);
19680
20256
  const cloneExpr = useHoisted ? hoistedCloneExpr(tplVar, o.skeletonTemplate) : `(() => { ${emitTemplateCloneInline(o.template)} })()`;
19681
20257
  lines.push(`${b2}const __el = ${cloneExpr}`);
19682
20258
  if (hasRefs) {
@@ -19690,17 +20266,23 @@ function stringifyLazyRowLoop(lines, o) {
19690
20266
  for (const t of lazyRow.texts)
19691
20267
  emitTextBinding(lines, b2, t, createDoor, "create", rwDoor);
19692
20268
  }
20269
+ for (const c of lazyRow.conditionals)
20270
+ emitConditional(lines, b2, mid, c, "create");
19693
20271
  lines.push(`${b2}return __el`);
19694
20272
  lines.push(`${b1}},`);
19695
20273
  const itemAttrs = lazyRow.attrs.filter((a) => a.readsItem);
19696
20274
  const itemTexts = lazyRow.texts.filter((t) => t.readsItem);
19697
- if (itemAttrs.length === 0 && itemTexts.length === 0) {
20275
+ const itemConds = lazyRow.conditionals.filter((c) => c.readsItem);
20276
+ if (itemAttrs.length === 0 && itemTexts.length === 0 && itemConds.length === 0) {
19698
20277
  lines.push(`${b1}applyItem: () => {},`);
19699
20278
  } else {
19700
20279
  lines.push(`${b1}applyItem: (__e) => {`);
19701
20280
  lines.push(`${b2}const ${paramHead} = () => __e.item`);
19702
- lines.push(`${b2}const __r = __e.refs ?? (__e.refs = ${claimVar}(__e))`);
20281
+ lines.push(`${b2}const __r = __e.refs ?? (__e.refs = [])`);
19703
20282
  lines.push(`${b2}const __l = __e.last ?? (__e.last = [])`);
20283
+ if (lazyRow.itemNeedsPreamble && lazyRow.preambleStatements) {
20284
+ lines.push(`${b2}${lazyRow.preambleStatements}`);
20285
+ }
19704
20286
  for (const a of itemAttrs)
19705
20287
  emitAttrBinding(lines, b2, a, "item");
19706
20288
  if (itemTexts.length > 0) {
@@ -19708,19 +20290,25 @@ function stringifyLazyRowLoop(lines, o) {
19708
20290
  for (const t of itemTexts)
19709
20291
  emitTextBinding(lines, b2, t, "__d", "item", rwDoor);
19710
20292
  }
20293
+ for (const c of itemConds)
20294
+ emitConditional(lines, b2, mid, c, "item");
19711
20295
  lines.push(`${b1}},`);
19712
20296
  }
19713
20297
  const outerAttrs = lazyRow.attrs.filter((a) => a.readsOuter);
19714
20298
  const outerTexts = lazyRow.texts.filter((t) => t.readsOuter);
19715
- if (outerAttrs.length > 0 || outerTexts.length > 0) {
20299
+ const outerConds = lazyRow.conditionals.filter((c) => c.readsOuter);
20300
+ if (outerAttrs.length > 0 || outerTexts.length > 0 || outerConds.length > 0) {
19716
20301
  const b3 = `${indent} `;
19717
20302
  lines.push(`${b1}applyOuter: (__es, __seed) => {`);
19718
20303
  for (const g of lazyRow.outerPrimeGetters)
19719
20304
  lines.push(`${b2}${g}()`);
19720
20305
  lines.push(`${b2}for (const __e of __es) {`);
19721
20306
  lines.push(`${b3}const ${paramHead} = () => __e.item`);
19722
- lines.push(`${b3}const __r = __e.refs ?? (__e.refs = ${claimVar}(__e))`);
20307
+ lines.push(`${b3}const __r = __e.refs ?? (__e.refs = [])`);
19723
20308
  lines.push(`${b3}const __l = __e.last ?? (__e.last = [])`);
20309
+ if (lazyRow.outerNeedsPreamble && lazyRow.preambleStatements) {
20310
+ lines.push(`${b3}${lazyRow.preambleStatements}`);
20311
+ }
19724
20312
  for (const a of outerAttrs)
19725
20313
  emitAttrBinding(lines, b3, a, "outer");
19726
20314
  if (outerTexts.length > 0) {
@@ -19728,22 +20316,28 @@ function stringifyLazyRowLoop(lines, o) {
19728
20316
  for (const t of outerTexts)
19729
20317
  emitTextBinding(lines, b3, t, "__d", "outer", rwDoor);
19730
20318
  }
20319
+ for (const c of outerConds)
20320
+ emitConditional(lines, b3, mid, c, "outer");
19731
20321
  lines.push(`${b2}}`);
19732
20322
  lines.push(`${b1}},`);
19733
20323
  }
19734
20324
  lines.push(`${indent}}, '${o.markerId}')`);
19735
20325
  }
19736
- function refParts(lazyRow, elVar, skeletonPaths, planVar, deferDoor = false) {
20326
+ function refParts(lazyRow, elVar, skeletonPaths, planVar) {
19737
20327
  const parts = [];
19738
20328
  for (const slotId of lazyRow.attrSlotIds) {
19739
20329
  const path = skeletonPaths?.elementPaths.get(slotId);
19740
20330
  parts.push(path ? pathExpr(elVar, path) : `qsa(${elVar}, '[bf="${slotId}"]')`);
19741
20331
  }
19742
20332
  if (lazyRow.texts.length > 0) {
19743
- parts.push(deferDoor ? "null" : `${doorCtor(lazyRow)}(${elVar}, ${planVar})`);
20333
+ parts.push(`${doorCtor(lazyRow)}(${elVar}, ${planVar})`);
19744
20334
  }
19745
20335
  return parts;
19746
20336
  }
20337
+ function elementAccess(a) {
20338
+ const slot = `__r[${a.refIndex}]`;
20339
+ return `${a.refIndex} in __r ? ${slot} : (${slot} = qsa(__e.primaryEl, '[bf="${a.slotId}"]'))`;
20340
+ }
19747
20341
  function doorCtor(lazyRow) {
19748
20342
  return lazyRow.textNeedsRead ? "lazyClaimSlots" : "lazySlots";
19749
20343
  }
@@ -19751,11 +20345,36 @@ function doorAccess(lazyRow, writerIndex, adoptedPlanVar) {
19751
20345
  const slot = `__r[${writerIndex}]`;
19752
20346
  return `${slot} ?? (${slot} = ${doorCtor(lazyRow)}(__e.primaryEl, ${adoptedPlanVar}))`;
19753
20347
  }
20348
+ function condVars(mid, slotId) {
20349
+ const key = `${mid}_${slotId.replace(/[^A-Za-z0-9_$]/g, "_")}`;
20350
+ return { trueTpl: `__cbt_${key}`, falseTpl: `__cbf_${key}` };
20351
+ }
20352
+ function emitConditional(lines, ind, mid, c, mode) {
20353
+ const v = condVars(mid, c.slotId);
20354
+ if (mode === "create") {
20355
+ lines.push(`${ind}__l[${c.ordinal}] = !!(${c.wrappedCondition})`);
20356
+ return;
20357
+ }
20358
+ const slot = `__r[${c.refIndex}]`;
20359
+ lines.push(`${ind}{ const __c = ${c.refIndex} in __r ? ${slot} : (${slot} = qsa(__e.primaryEl, '[bf-c="${c.slotId}"]'))`);
20360
+ lines.push(`${ind}if (__c) {`);
20361
+ lines.push(`${ind} const __x = !!(${c.wrappedCondition})`);
20362
+ lines.push(`${ind} const __w = (__x ? ${v.trueTpl} : ${v.falseTpl}).content.firstElementChild`);
20363
+ const guard = mode === "item" ? dedupGuard(c.ordinal) : `__seed ? (__c.outerHTML !== __w.outerHTML) : (${dedupGuard(c.ordinal)})`;
20364
+ lines.push(`${ind} if (${guard}) {`);
20365
+ lines.push(`${ind} const __n = __w.cloneNode(true)`);
20366
+ lines.push(`${ind} __c.replaceWith(__n)`);
20367
+ lines.push(`${ind} ${slot} = __n`);
20368
+ lines.push(`${ind} }`);
20369
+ lines.push(`${ind} __l[${c.ordinal}] = __x`);
20370
+ lines.push(`${ind}} }`);
20371
+ }
19754
20372
  function dedupGuard(ordinal) {
19755
20373
  return `!(${ordinal} in __l) || !Object.is(__l[${ordinal}], __x)`;
19756
20374
  }
19757
20375
  function emitAttrBinding(lines, ind, a, mode) {
19758
- lines.push(`${ind}{ const __t = __r[${a.refIndex}]`);
20376
+ const target = mode === "create" ? `__r[${a.refIndex}]` : elementAccess(a);
20377
+ lines.push(`${ind}{ const __t = ${target}`);
19759
20378
  lines.push(`${ind}if (__t) {`);
19760
20379
  lines.push(`${ind} const __x = ${a.wrappedExpression}`);
19761
20380
  const guard = mode === "create" ? null : mode === "item" ? dedupGuard(a.ordinal) : `__seed ? (${seedDiffersExpr("__t", a)}) : (${dedupGuard(a.ordinal)})`;
@@ -20752,7 +21371,7 @@ function buildPlainLoopPlan(elem, profileComponentName, lazyScope) {
20752
21371
  const indexParam = elem.index || "__idx";
20753
21372
  const mapPreambleWrapped = elem.preamble ? renderPreamble(elem.preamble, {
20754
21373
  transformJs: wrap,
20755
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined, true)
21374
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined)
20756
21375
  }) : "";
20757
21376
  const preambleRegions = buildPreambleRegionPlans(elem.preambleRegions, elem.param, elem.paramBindings);
20758
21377
  return {
@@ -20829,7 +21448,7 @@ function buildStaticLoopMaterialize(elem, unsafeLocalNames) {
20829
21448
  return {
20830
21449
  itemTemplate: elem.staticItemTemplate,
20831
21450
  mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
20832
- renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined, true)
21451
+ renderLeaf: (ir) => irToHtmlTemplate(ir, undefined, 1, [{ param: elem.param, bindings: elem.paramBindings }], undefined)
20833
21452
  }) : "",
20834
21453
  bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false
20835
21454
  };
@@ -21066,20 +21685,20 @@ var PHASES = [
21066
21685
  ];
21067
21686
 
21068
21687
  // src/ir-to-client-js/rewrite-props-object.ts
21069
- import ts16 from "typescript";
21688
+ import ts17 from "typescript";
21070
21689
  function rewritePropsObjectRef(code, propsObjectName) {
21071
21690
  const srcPropsName = propsObjectName ?? "props";
21072
21691
  if (srcPropsName === PROPS_PARAM)
21073
21692
  return code;
21074
21693
  if (!new RegExp(`\\b${srcPropsName}\\b`).test(code))
21075
21694
  return code;
21076
- const sourceFile = ts16.createSourceFile("init-body.ts", code, ts16.ScriptTarget.Latest, true, ts16.ScriptKind.TS);
21695
+ const sourceFile = ts17.createSourceFile("init-body.ts", code, ts17.ScriptTarget.Latest, true, ts17.ScriptKind.TS);
21077
21696
  const spans = [];
21078
21697
  function visit3(node) {
21079
- if (ts16.isIdentifier(node) && node.text === srcPropsName && shouldRewrite(node)) {
21698
+ if (ts17.isIdentifier(node) && node.text === srcPropsName && shouldRewrite(node)) {
21080
21699
  spans.push([node.getStart(sourceFile), node.getEnd()]);
21081
21700
  }
21082
- ts16.forEachChild(node, visit3);
21701
+ ts17.forEachChild(node, visit3);
21083
21702
  }
21084
21703
  visit3(sourceFile);
21085
21704
  if (spans.length === 0)
@@ -21095,17 +21714,17 @@ function shouldRewrite(node) {
21095
21714
  const parent = node.parent;
21096
21715
  if (!parent)
21097
21716
  return true;
21098
- if (ts16.isPropertyAccessExpression(parent) && parent.name === node)
21717
+ if (ts17.isPropertyAccessExpression(parent) && parent.name === node)
21099
21718
  return false;
21100
- if (ts16.isPropertyAssignment(parent) && parent.name === node)
21719
+ if (ts17.isPropertyAssignment(parent) && parent.name === node)
21101
21720
  return false;
21102
- if (ts16.isShorthandPropertyAssignment(parent) && parent.name === node)
21721
+ if (ts17.isShorthandPropertyAssignment(parent) && parent.name === node)
21103
21722
  return false;
21104
- if (ts16.isPropertySignature(parent) && parent.name === node)
21723
+ if (ts17.isPropertySignature(parent) && parent.name === node)
21105
21724
  return false;
21106
- if (ts16.isPropertyDeclaration(parent) && parent.name === node)
21725
+ if (ts17.isPropertyDeclaration(parent) && parent.name === node)
21107
21726
  return false;
21108
- if (ts16.isBindingElement(parent) && parent.name === node)
21727
+ if (ts17.isBindingElement(parent) && parent.name === node)
21109
21728
  return false;
21110
21729
  return true;
21111
21730
  }
@@ -21449,7 +22068,7 @@ function generateTemplateOnlyMount(ir, ctx) {
21449
22068
  }
21450
22069
  if (!templateHtml) {
21451
22070
  const csrInlinableConstants = csrInlinableConstantsFromCtx(ctx);
21452
- templateHtml = generateCsrTemplate(ir.root, csrInlinableConstants, ctx, undefined, restSpreadNames, ctx.propsObjectName, unsafeLocalNames);
22071
+ templateHtml = generateCsrTemplate(ir.root, csrInlinableConstants, ctx, restSpreadNames, ctx.propsObjectName, unsafeLocalNames);
21453
22072
  }
21454
22073
  if (!templateHtml) {
21455
22074
  return "";
@@ -21735,7 +22354,7 @@ function walkIR2(node, visitor) {
21735
22354
  }
21736
22355
 
21737
22356
  // src/preprocess-inline-jsx-callbacks.ts
21738
- import ts17 from "typescript";
22357
+ import ts18 from "typescript";
21739
22358
  var SYNTHETIC_PREFIX = "BFInlineJsxCallback";
21740
22359
  var MAX_FIXPOINT_ITERATIONS = 16;
21741
22360
  function preprocessInlineJsxCallbacks(source, filePath) {
@@ -21757,8 +22376,8 @@ function preprocessInlineJsxCallbacks(source, filePath) {
21757
22376
  return { source: current, errors, syntheticNames };
21758
22377
  }
21759
22378
  function runSinglePass(source, filePath, startingCounter) {
21760
- const sourceFile = ts17.createSourceFile(filePath, source, ts17.ScriptTarget.Latest, true, ts17.ScriptKind.TSX);
21761
- const hasUseClient = sourceFile.statements.some((stmt) => ts17.isExpressionStatement(stmt) && ts17.isStringLiteral(stmt.expression) && (stmt.expression.text === "use client" || stmt.expression.text === "'use client'"));
22379
+ const sourceFile = ts18.createSourceFile(filePath, source, ts18.ScriptTarget.Latest, true, ts18.ScriptKind.TSX);
22380
+ const hasUseClient = sourceFile.statements.some((stmt) => ts18.isExpressionStatement(stmt) && ts18.isStringLiteral(stmt.expression) && (stmt.expression.text === "use client" || stmt.expression.text === "'use client'"));
21762
22381
  if (!hasUseClient) {
21763
22382
  return { source, errors: [], syntheticNames: [], counterAfter: startingCounter };
21764
22383
  }
@@ -21780,22 +22399,22 @@ function runSinglePass(source, filePath, startingCounter) {
21780
22399
  }
21781
22400
  }
21782
22401
  function visit3(node) {
21783
- if (ts17.isJsxAttribute(node) && node.initializer && ts17.isJsxExpression(node.initializer) && node.initializer.expression) {
22402
+ if (ts18.isJsxAttribute(node) && node.initializer && ts18.isJsxExpression(node.initializer) && node.initializer.expression) {
21784
22403
  if (tryHandleArrowValue(node.initializer.expression)) {
21785
22404
  return;
21786
22405
  }
21787
22406
  }
21788
- if (ts17.isPropertyAssignment(node) && node.initializer) {
22407
+ if (ts18.isPropertyAssignment(node) && node.initializer) {
21789
22408
  if (tryHandleArrowValue(node.initializer))
21790
22409
  return;
21791
22410
  }
21792
- ts17.forEachChild(node, visit3);
22411
+ ts18.forEachChild(node, visit3);
21793
22412
  }
21794
22413
  function tryHandleArrowValue(initializer) {
21795
22414
  let expr = initializer;
21796
- while (ts17.isParenthesizedExpression(expr))
22415
+ while (ts18.isParenthesizedExpression(expr))
21797
22416
  expr = expr.expression;
21798
- if (ts17.isArrowFunction(expr) && arrowBodyContainsJsx(expr)) {
22417
+ if (ts18.isArrowFunction(expr) && arrowBodyContainsJsx(expr)) {
21799
22418
  return handleInlineArrow(expr);
21800
22419
  }
21801
22420
  return false;
@@ -21832,7 +22451,7 @@ function runSinglePass(source, filePath, startingCounter) {
21832
22451
  replacements.push({ start: arrowStart, end: arrowEnd, text: name });
21833
22452
  return true;
21834
22453
  }
21835
- ts17.forEachChild(sourceFile, visit3);
22454
+ ts18.forEachChild(sourceFile, visit3);
21836
22455
  if (replacements.length === 0) {
21837
22456
  return { source, errors, syntheticNames, counterAfter: counter };
21838
22457
  }
@@ -21855,11 +22474,11 @@ function errorMessageForCapture(captures) {
21855
22474
  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
22475
  }
21857
22476
  function arrowBodyContainsJsx(arrow) {
21858
- if (ts17.isBlock(arrow.body)) {
22477
+ if (ts18.isBlock(arrow.body)) {
21859
22478
  return blockReturnsJsx(arrow.body);
21860
22479
  }
21861
22480
  let body = arrow.body;
21862
- while (ts17.isParenthesizedExpression(body))
22481
+ while (ts18.isParenthesizedExpression(body))
21863
22482
  body = body.expression;
21864
22483
  return isJsxLike(body);
21865
22484
  }
@@ -21868,41 +22487,41 @@ function blockReturnsJsx(block) {
21868
22487
  function visit3(n) {
21869
22488
  if (found)
21870
22489
  return;
21871
- if (ts17.isReturnStatement(n) && n.expression) {
22490
+ if (ts18.isReturnStatement(n) && n.expression) {
21872
22491
  let e = n.expression;
21873
- while (ts17.isParenthesizedExpression(e))
22492
+ while (ts18.isParenthesizedExpression(e))
21874
22493
  e = e.expression;
21875
22494
  if (isJsxLike(e)) {
21876
22495
  found = true;
21877
22496
  return;
21878
22497
  }
21879
22498
  }
21880
- if (ts17.isArrowFunction(n) || ts17.isFunctionDeclaration(n) || ts17.isFunctionExpression(n))
22499
+ if (ts18.isArrowFunction(n) || ts18.isFunctionDeclaration(n) || ts18.isFunctionExpression(n))
21881
22500
  return;
21882
- ts17.forEachChild(n, visit3);
22501
+ ts18.forEachChild(n, visit3);
21883
22502
  }
21884
- ts17.forEachChild(block, visit3);
22503
+ ts18.forEachChild(block, visit3);
21885
22504
  return found;
21886
22505
  }
21887
22506
  function isJsxLike(expr) {
21888
- return ts17.isJsxElement(expr) || ts17.isJsxSelfClosingElement(expr) || ts17.isJsxFragment(expr);
22507
+ return ts18.isJsxElement(expr) || ts18.isJsxSelfClosingElement(expr) || ts18.isJsxFragment(expr);
21889
22508
  }
21890
22509
  function collectArrowParamNames(arrow) {
21891
22510
  const names = new Set;
21892
22511
  for (const p of arrow.parameters)
21893
- collectBindingNames2(p.name, names);
22512
+ collectBindingNames4(p.name, names);
21894
22513
  return names;
21895
22514
  }
21896
- function collectBindingNames2(name, out) {
22515
+ function collectBindingNames4(name, out) {
21897
22516
  const push = Array.isArray(out) ? (n) => out.push(n) : (n) => out.add(n);
21898
- if (ts17.isIdentifier(name)) {
22517
+ if (ts18.isIdentifier(name)) {
21899
22518
  push(name.text);
21900
- } else if (ts17.isObjectBindingPattern(name)) {
21901
- name.elements.forEach((el) => collectBindingNames2(el.name, out));
21902
- } else if (ts17.isArrayBindingPattern(name)) {
22519
+ } else if (ts18.isObjectBindingPattern(name)) {
22520
+ name.elements.forEach((el) => collectBindingNames4(el.name, out));
22521
+ } else if (ts18.isArrayBindingPattern(name)) {
21903
22522
  name.elements.forEach((el) => {
21904
- if (!ts17.isOmittedExpression(el))
21905
- collectBindingNames2(el.name, out);
22523
+ if (!ts18.isOmittedExpression(el))
22524
+ collectBindingNames4(el.name, out);
21906
22525
  });
21907
22526
  }
21908
22527
  }
@@ -21911,12 +22530,12 @@ function collectFreeIdentifiers(arrow) {
21911
22530
  const bound = [];
21912
22531
  for (const p of arrow.parameters) {
21913
22532
  const names = [];
21914
- collectBindingNames2(p.name, names);
22533
+ collectBindingNames4(p.name, names);
21915
22534
  bound.push(...names);
21916
22535
  }
21917
22536
  function pushBindings(name) {
21918
22537
  const names = [];
21919
- collectBindingNames2(name, names);
22538
+ collectBindingNames4(name, names);
21920
22539
  bound.push(...names);
21921
22540
  return names;
21922
22541
  }
@@ -21928,48 +22547,48 @@ function collectFreeIdentifiers(arrow) {
21928
22547
  return bound.includes(name);
21929
22548
  }
21930
22549
  function visit3(node) {
21931
- if (ts17.isIdentifier(node)) {
22550
+ if (ts18.isIdentifier(node)) {
21932
22551
  const parent = node.parent;
21933
- if (parent && ts17.isPropertyAccessExpression(parent) && parent.name === node)
22552
+ if (parent && ts18.isPropertyAccessExpression(parent) && parent.name === node)
21934
22553
  return;
21935
- if (parent && ts17.isPropertyAssignment(parent) && parent.name === node)
22554
+ if (parent && ts18.isPropertyAssignment(parent) && parent.name === node)
21936
22555
  return;
21937
- if (parent && ts17.isPropertySignature(parent) && parent.name === node)
22556
+ if (parent && ts18.isPropertySignature(parent) && parent.name === node)
21938
22557
  return;
21939
- if (parent && ts17.isPropertyDeclaration(parent) && parent.name === node)
22558
+ if (parent && ts18.isPropertyDeclaration(parent) && parent.name === node)
21940
22559
  return;
21941
- if (parent && ts17.isMethodDeclaration(parent) && parent.name === node)
22560
+ if (parent && ts18.isMethodDeclaration(parent) && parent.name === node)
21942
22561
  return;
21943
- if (parent && ts17.isMethodSignature(parent) && parent.name === node)
22562
+ if (parent && ts18.isMethodSignature(parent) && parent.name === node)
21944
22563
  return;
21945
- if (parent && ts17.isGetAccessorDeclaration(parent) && parent.name === node)
22564
+ if (parent && ts18.isGetAccessorDeclaration(parent) && parent.name === node)
21946
22565
  return;
21947
- if (parent && ts17.isSetAccessorDeclaration(parent) && parent.name === node)
22566
+ if (parent && ts18.isSetAccessorDeclaration(parent) && parent.name === node)
21948
22567
  return;
21949
- if (parent && ts17.isEnumMember(parent) && parent.name === node)
22568
+ if (parent && ts18.isEnumMember(parent) && parent.name === node)
21950
22569
  return;
21951
- if (parent && ts17.isBindingElement(parent) && parent.propertyName === node)
22570
+ if (parent && ts18.isBindingElement(parent) && parent.propertyName === node)
21952
22571
  return;
21953
- if (parent && ts17.isShorthandPropertyAssignment(parent) && parent.name === node) {
22572
+ if (parent && ts18.isShorthandPropertyAssignment(parent) && parent.name === node) {
21954
22573
  if (!isBound(node.text))
21955
22574
  ids.add(node.text);
21956
22575
  return;
21957
22576
  }
21958
- if (parent && ts17.isParameter(parent) && parent.name === node)
22577
+ if (parent && ts18.isParameter(parent) && parent.name === node)
21959
22578
  return;
21960
- if (parent && ts17.isVariableDeclaration(parent) && parent.name === node)
22579
+ if (parent && ts18.isVariableDeclaration(parent) && parent.name === node)
21961
22580
  return;
21962
- if (parent && ts17.isFunctionDeclaration(parent) && parent.name === node)
22581
+ if (parent && ts18.isFunctionDeclaration(parent) && parent.name === node)
21963
22582
  return;
21964
- if (parent && ts17.isClassDeclaration(parent) && parent.name === node)
22583
+ if (parent && ts18.isClassDeclaration(parent) && parent.name === node)
21965
22584
  return;
21966
- if (parent && ts17.isJsxAttribute(parent) && parent.name === node)
22585
+ if (parent && ts18.isJsxAttribute(parent) && parent.name === node)
21967
22586
  return;
21968
- if (parent && ts17.isJsxOpeningElement(parent) && parent.tagName === node) {
22587
+ if (parent && ts18.isJsxOpeningElement(parent) && parent.tagName === node) {
21969
22588
  if (/^[a-z]/.test(node.text))
21970
22589
  return;
21971
22590
  }
21972
- if (parent && ts17.isJsxClosingElement(parent) && parent.tagName === node) {
22591
+ if (parent && ts18.isJsxClosingElement(parent) && parent.tagName === node) {
21973
22592
  if (/^[a-z]/.test(node.text))
21974
22593
  return;
21975
22594
  }
@@ -21978,43 +22597,43 @@ function collectFreeIdentifiers(arrow) {
21978
22597
  ids.add(node.text);
21979
22598
  return;
21980
22599
  }
21981
- if (ts17.isVariableDeclaration(node)) {
22600
+ if (ts18.isVariableDeclaration(node)) {
21982
22601
  const declared = pushBindings(node.name);
21983
22602
  if (node.initializer)
21984
22603
  visit3(node.initializer);
21985
22604
  return;
21986
22605
  }
21987
- if (ts17.isFunctionDeclaration(node)) {
22606
+ if (ts18.isFunctionDeclaration(node)) {
21988
22607
  if (node.name)
21989
22608
  bound.push(node.name.text);
21990
22609
  visitInsideNewScope(node);
21991
22610
  return;
21992
22611
  }
21993
- if (ts17.isClassDeclaration(node)) {
22612
+ if (ts18.isClassDeclaration(node)) {
21994
22613
  if (node.name)
21995
22614
  bound.push(node.name.text);
21996
- ts17.forEachChild(node, visit3);
22615
+ ts18.forEachChild(node, visit3);
21997
22616
  return;
21998
22617
  }
21999
- if (ts17.isArrowFunction(node) || ts17.isFunctionExpression(node)) {
22618
+ if (ts18.isArrowFunction(node) || ts18.isFunctionExpression(node)) {
22000
22619
  visitInsideNewScope(node);
22001
22620
  return;
22002
22621
  }
22003
- if (ts17.isCatchClause(node)) {
22622
+ if (ts18.isCatchClause(node)) {
22004
22623
  const before = bound.length;
22005
22624
  if (node.variableDeclaration)
22006
22625
  pushBindings(node.variableDeclaration.name);
22007
- ts17.forEachChild(node, visit3);
22626
+ ts18.forEachChild(node, visit3);
22008
22627
  popN(bound.length - before);
22009
22628
  return;
22010
22629
  }
22011
- if (ts17.isBlock(node)) {
22630
+ if (ts18.isBlock(node)) {
22012
22631
  const before = bound.length;
22013
- ts17.forEachChild(node, visit3);
22632
+ ts18.forEachChild(node, visit3);
22014
22633
  popN(bound.length - before);
22015
22634
  return;
22016
22635
  }
22017
- ts17.forEachChild(node, visit3);
22636
+ ts18.forEachChild(node, visit3);
22018
22637
  }
22019
22638
  function visitInsideNewScope(fn) {
22020
22639
  const before = bound.length;
@@ -22037,29 +22656,29 @@ function collectFreeIdentifiers(arrow) {
22037
22656
  function collectModuleScopeNames(sourceFile) {
22038
22657
  const names = new Set;
22039
22658
  for (const stmt of sourceFile.statements) {
22040
- if (ts17.isFunctionDeclaration(stmt) && stmt.name)
22659
+ if (ts18.isFunctionDeclaration(stmt) && stmt.name)
22041
22660
  names.add(stmt.name.text);
22042
- else if (ts17.isClassDeclaration(stmt) && stmt.name)
22661
+ else if (ts18.isClassDeclaration(stmt) && stmt.name)
22043
22662
  names.add(stmt.name.text);
22044
- else if (ts17.isVariableStatement(stmt)) {
22663
+ else if (ts18.isVariableStatement(stmt)) {
22045
22664
  for (const decl of stmt.declarationList.declarations)
22046
- collectBindingNames2(decl.name, names);
22047
- } else if (ts17.isImportDeclaration(stmt) && stmt.importClause) {
22665
+ collectBindingNames4(decl.name, names);
22666
+ } else if (ts18.isImportDeclaration(stmt) && stmt.importClause) {
22048
22667
  const ic = stmt.importClause;
22049
22668
  if (ic.name)
22050
22669
  names.add(ic.name.text);
22051
22670
  if (ic.namedBindings) {
22052
- if (ts17.isNamespaceImport(ic.namedBindings))
22671
+ if (ts18.isNamespaceImport(ic.namedBindings))
22053
22672
  names.add(ic.namedBindings.name.text);
22054
22673
  else
22055
22674
  for (const e of ic.namedBindings.elements)
22056
22675
  names.add(e.name.text);
22057
22676
  }
22058
- } else if (ts17.isTypeAliasDeclaration(stmt))
22677
+ } else if (ts18.isTypeAliasDeclaration(stmt))
22059
22678
  names.add(stmt.name.text);
22060
- else if (ts17.isInterfaceDeclaration(stmt))
22679
+ else if (ts18.isInterfaceDeclaration(stmt))
22061
22680
  names.add(stmt.name.text);
22062
- else if (ts17.isEnumDeclaration(stmt))
22681
+ else if (ts18.isEnumDeclaration(stmt))
22063
22682
  names.add(stmt.name.text);
22064
22683
  }
22065
22684
  return names;
@@ -22067,7 +22686,7 @@ function collectModuleScopeNames(sourceFile) {
22067
22686
  function buildSyntheticDeclaration(name, arrow, sourceFile) {
22068
22687
  const paramsText = arrow.parameters.length === 0 ? "" : arrow.parameters.map((p) => p.getText(sourceFile)).join(", ");
22069
22688
  let bodyText;
22070
- if (ts17.isBlock(arrow.body)) {
22689
+ if (ts18.isBlock(arrow.body)) {
22071
22690
  bodyText = arrow.body.getText(sourceFile);
22072
22691
  } else {
22073
22692
  const expr = arrow.body.getText(sourceFile);
@@ -22077,7 +22696,7 @@ function buildSyntheticDeclaration(name, arrow, sourceFile) {
22077
22696
  }
22078
22697
 
22079
22698
  // src/ssr-defaults.ts
22080
- import ts18 from "typescript";
22699
+ import ts19 from "typescript";
22081
22700
  var UNRESOLVED = Symbol("unresolved");
22082
22701
  var NO_RETURN = Symbol("no-return");
22083
22702
  function extractSsrDefaults(metadata) {
@@ -22090,11 +22709,12 @@ function extractSsrDefaults(metadata) {
22090
22709
  for (const p of metadata.propsParams) {
22091
22710
  if (p.isRest)
22092
22711
  continue;
22712
+ const callerPropName = p.sourceName ?? p.name;
22093
22713
  if (metadata.propsObjectName === null && p.defaultValue !== undefined) {
22094
22714
  const value = tryStaticEval(p.defaultValue, { bindings: {}, propsLike });
22095
- out[p.name] = { propName: p.name, value: resultToJsonable(value) };
22715
+ out[p.name] = { propName: callerPropName, value: resultToJsonable(value) };
22096
22716
  } else {
22097
- out[p.name] = { propName: p.name, value: null };
22717
+ out[p.name] = { propName: callerPropName, value: null };
22098
22718
  }
22099
22719
  }
22100
22720
  if (metadata.restPropsName) {
@@ -22153,11 +22773,11 @@ function collectPropRefs(expr, propsObjectName, out) {
22153
22773
  if (!node)
22154
22774
  return;
22155
22775
  const visit3 = (n) => {
22156
- if (ts18.isPropertyAccessExpression(n) && ts18.isIdentifier(n.expression) && n.expression.text === propsObjectName && ts18.isIdentifier(n.name)) {
22776
+ if (ts19.isPropertyAccessExpression(n) && ts19.isIdentifier(n.expression) && n.expression.text === propsObjectName && ts19.isIdentifier(n.name)) {
22157
22777
  out.add(n.name.text);
22158
22778
  return;
22159
22779
  }
22160
- ts18.forEachChild(n, visit3);
22780
+ ts19.forEachChild(n, visit3);
22161
22781
  };
22162
22782
  visit3(node);
22163
22783
  }
@@ -22178,23 +22798,23 @@ function tryStaticEval(expr, ctx) {
22178
22798
  }
22179
22799
  function evalStatementsForReturn(statements, ctx) {
22180
22800
  for (const stmt of statements) {
22181
- if (ts18.isVariableStatement(stmt)) {
22801
+ if (ts19.isVariableStatement(stmt)) {
22182
22802
  for (const d of stmt.declarationList.declarations) {
22183
- if (!ts18.isIdentifier(d.name) || !d.initializer)
22803
+ if (!ts19.isIdentifier(d.name) || !d.initializer)
22184
22804
  continue;
22185
22805
  const v = evalNode(d.initializer, ctx);
22186
22806
  if (v !== UNRESOLVED)
22187
22807
  ctx.bindings[d.name.text] = v;
22188
22808
  }
22189
- } else if (ts18.isReturnStatement(stmt)) {
22809
+ } else if (ts19.isReturnStatement(stmt)) {
22190
22810
  return stmt.expression ? evalNode(stmt.expression, ctx) : UNRESOLVED;
22191
- } else if (ts18.isIfStatement(stmt)) {
22811
+ } else if (ts19.isIfStatement(stmt)) {
22192
22812
  const cond = evalNode(stmt.expression, ctx);
22193
22813
  if (cond === UNRESOLVED)
22194
22814
  return UNRESOLVED;
22195
22815
  const branch = cond ? stmt.thenStatement : stmt.elseStatement;
22196
22816
  if (branch) {
22197
- const taken = evalStatementsForReturn(ts18.isBlock(branch) ? branch.statements : [branch], ctx);
22817
+ const taken = evalStatementsForReturn(ts19.isBlock(branch) ? branch.statements : [branch], ctx);
22198
22818
  if (taken !== NO_RETURN)
22199
22819
  return taken;
22200
22820
  }
@@ -22205,45 +22825,45 @@ function evalStatementsForReturn(statements, ctx) {
22205
22825
  return NO_RETURN;
22206
22826
  }
22207
22827
  function parseExpression2(expr) {
22208
- const sf = ts18.createSourceFile("__ssr_default__.ts", `(${expr})`, ts18.ScriptTarget.Latest, false, ts18.ScriptKind.TS);
22828
+ const sf = ts19.createSourceFile("__ssr_default__.ts", `(${expr})`, ts19.ScriptTarget.Latest, false, ts19.ScriptKind.TS);
22209
22829
  const stmt = sf.statements[0];
22210
- if (!stmt || !ts18.isExpressionStatement(stmt))
22830
+ if (!stmt || !ts19.isExpressionStatement(stmt))
22211
22831
  return null;
22212
- const inner = ts18.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
22832
+ const inner = ts19.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
22213
22833
  return inner;
22214
22834
  }
22215
22835
  function evalNode(node, ctx) {
22216
- if (ts18.isParenthesizedExpression(node))
22836
+ if (ts19.isParenthesizedExpression(node))
22217
22837
  return evalNode(node.expression, ctx);
22218
- if (ts18.isAsExpression(node))
22838
+ if (ts19.isAsExpression(node))
22219
22839
  return evalNode(node.expression, ctx);
22220
- if (ts18.isSatisfiesExpression(node))
22840
+ if (ts19.isSatisfiesExpression(node))
22221
22841
  return evalNode(node.expression, ctx);
22222
- if (ts18.isTypeAssertionExpression(node))
22842
+ if (ts19.isTypeAssertionExpression(node))
22223
22843
  return evalNode(node.expression, ctx);
22224
- if (ts18.isNonNullExpression(node))
22844
+ if (ts19.isNonNullExpression(node))
22225
22845
  return evalNode(node.expression, ctx);
22226
- if (ts18.isArrowFunction(node)) {
22846
+ if (ts19.isArrowFunction(node)) {
22227
22847
  if (node.parameters.length !== 0)
22228
22848
  return UNRESOLVED;
22229
- if (!ts18.isBlock(node.body))
22849
+ if (!ts19.isBlock(node.body))
22230
22850
  return evalNode(node.body, ctx);
22231
22851
  const localBindings = { ...ctx.bindings };
22232
22852
  const localCtx = { ...ctx, bindings: localBindings };
22233
22853
  const result = evalStatementsForReturn(node.body.statements, localCtx);
22234
22854
  return result === NO_RETURN ? UNRESOLVED : result;
22235
22855
  }
22236
- if (ts18.isNumericLiteral(node))
22856
+ if (ts19.isNumericLiteral(node))
22237
22857
  return Number(node.text);
22238
- if (ts18.isStringLiteralLike(node))
22858
+ if (ts19.isStringLiteralLike(node))
22239
22859
  return node.text;
22240
- if (node.kind === ts18.SyntaxKind.TrueKeyword)
22860
+ if (node.kind === ts19.SyntaxKind.TrueKeyword)
22241
22861
  return true;
22242
- if (node.kind === ts18.SyntaxKind.FalseKeyword)
22862
+ if (node.kind === ts19.SyntaxKind.FalseKeyword)
22243
22863
  return false;
22244
- if (node.kind === ts18.SyntaxKind.NullKeyword)
22864
+ if (node.kind === ts19.SyntaxKind.NullKeyword)
22245
22865
  return null;
22246
- if (ts18.isIdentifier(node)) {
22866
+ if (ts19.isIdentifier(node)) {
22247
22867
  if (node.text === "undefined")
22248
22868
  return;
22249
22869
  if (node.text in ctx.bindings)
@@ -22252,29 +22872,29 @@ function evalNode(node, ctx) {
22252
22872
  return;
22253
22873
  return UNRESOLVED;
22254
22874
  }
22255
- if (ts18.isPrefixUnaryExpression(node)) {
22875
+ if (ts19.isPrefixUnaryExpression(node)) {
22256
22876
  const arg = evalNode(node.operand, ctx);
22257
22877
  if (arg === UNRESOLVED)
22258
22878
  return UNRESOLVED;
22259
22879
  switch (node.operator) {
22260
- case ts18.SyntaxKind.MinusToken:
22880
+ case ts19.SyntaxKind.MinusToken:
22261
22881
  return typeof arg === "number" ? -arg : UNRESOLVED;
22262
- case ts18.SyntaxKind.PlusToken:
22882
+ case ts19.SyntaxKind.PlusToken:
22263
22883
  return typeof arg === "number" ? +arg : UNRESOLVED;
22264
- case ts18.SyntaxKind.ExclamationToken:
22884
+ case ts19.SyntaxKind.ExclamationToken:
22265
22885
  return !arg;
22266
22886
  }
22267
22887
  return UNRESOLVED;
22268
22888
  }
22269
- if (ts18.isObjectLiteralExpression(node)) {
22889
+ if (ts19.isObjectLiteralExpression(node)) {
22270
22890
  const obj = {};
22271
22891
  for (const prop of node.properties) {
22272
- if (!ts18.isPropertyAssignment(prop))
22892
+ if (!ts19.isPropertyAssignment(prop))
22273
22893
  return UNRESOLVED;
22274
22894
  let key;
22275
- if (ts18.isIdentifier(prop.name) || ts18.isStringLiteralLike(prop.name)) {
22895
+ if (ts19.isIdentifier(prop.name) || ts19.isStringLiteralLike(prop.name)) {
22276
22896
  key = prop.name.text;
22277
- } else if (ts18.isNumericLiteral(prop.name)) {
22897
+ } else if (ts19.isNumericLiteral(prop.name)) {
22278
22898
  key = prop.name.text;
22279
22899
  } else {
22280
22900
  return UNRESOLVED;
@@ -22286,10 +22906,10 @@ function evalNode(node, ctx) {
22286
22906
  }
22287
22907
  return obj;
22288
22908
  }
22289
- if (ts18.isArrayLiteralExpression(node)) {
22909
+ if (ts19.isArrayLiteralExpression(node)) {
22290
22910
  const arr = [];
22291
22911
  for (const elem of node.elements) {
22292
- if (ts18.isOmittedExpression(elem))
22912
+ if (ts19.isOmittedExpression(elem))
22293
22913
  return UNRESOLVED;
22294
22914
  const v = evalNode(elem, ctx);
22295
22915
  if (v === UNRESOLVED)
@@ -22298,7 +22918,7 @@ function evalNode(node, ctx) {
22298
22918
  }
22299
22919
  return arr;
22300
22920
  }
22301
- if (ts18.isElementAccessExpression(node)) {
22921
+ if (ts19.isElementAccessExpression(node)) {
22302
22922
  const base = evalNode(node.expression, ctx);
22303
22923
  if (base === undefined)
22304
22924
  return;
@@ -22312,17 +22932,17 @@ function evalNode(node, ctx) {
22312
22932
  const k = String(key);
22313
22933
  return Object.prototype.hasOwnProperty.call(base, k) ? base[k] : undefined;
22314
22934
  }
22315
- if (ts18.isPropertyAccessExpression(node)) {
22935
+ if (ts19.isPropertyAccessExpression(node)) {
22316
22936
  const baseResult = evalNode(node.expression, ctx);
22317
22937
  if (baseResult === undefined)
22318
22938
  return;
22319
22939
  return UNRESOLVED;
22320
22940
  }
22321
- if (ts18.isCallExpression(node)) {
22322
- if (node.arguments.length === 0 && ts18.isIdentifier(node.expression) && node.expression.text in ctx.bindings) {
22941
+ if (ts19.isCallExpression(node)) {
22942
+ if (node.arguments.length === 0 && ts19.isIdentifier(node.expression) && node.expression.text in ctx.bindings) {
22323
22943
  return ctx.bindings[node.expression.text];
22324
22944
  }
22325
- if (ts18.isPropertyAccessExpression(node.expression) && node.expression.name.text === "join") {
22945
+ if (ts19.isPropertyAccessExpression(node.expression) && node.expression.name.text === "join") {
22326
22946
  const recv = evalNode(node.expression.expression, ctx);
22327
22947
  if (Array.isArray(recv)) {
22328
22948
  let sep2 = ",";
@@ -22338,27 +22958,27 @@ function evalNode(node, ctx) {
22338
22958
  }
22339
22959
  return UNRESOLVED;
22340
22960
  }
22341
- if (ts18.isConditionalExpression(node)) {
22961
+ if (ts19.isConditionalExpression(node)) {
22342
22962
  const cond = evalNode(node.condition, ctx);
22343
22963
  if (cond === UNRESOLVED)
22344
22964
  return UNRESOLVED;
22345
22965
  return cond ? evalNode(node.whenTrue, ctx) : evalNode(node.whenFalse, ctx);
22346
22966
  }
22347
- if (ts18.isBinaryExpression(node)) {
22967
+ if (ts19.isBinaryExpression(node)) {
22348
22968
  const op = node.operatorToken.kind;
22349
- if (op === ts18.SyntaxKind.QuestionQuestionToken) {
22969
+ if (op === ts19.SyntaxKind.QuestionQuestionToken) {
22350
22970
  const l2 = evalNode(node.left, ctx);
22351
22971
  if (l2 !== UNRESOLVED && l2 !== null && l2 !== undefined)
22352
22972
  return l2;
22353
22973
  return evalNode(node.right, ctx);
22354
22974
  }
22355
- if (op === ts18.SyntaxKind.BarBarToken) {
22975
+ if (op === ts19.SyntaxKind.BarBarToken) {
22356
22976
  const l2 = evalNode(node.left, ctx);
22357
22977
  if (l2 !== UNRESOLVED && l2)
22358
22978
  return l2;
22359
22979
  return evalNode(node.right, ctx);
22360
22980
  }
22361
- if (op === ts18.SyntaxKind.AmpersandAmpersandToken) {
22981
+ if (op === ts19.SyntaxKind.AmpersandAmpersandToken) {
22362
22982
  const l2 = evalNode(node.left, ctx);
22363
22983
  if (l2 === UNRESOLVED)
22364
22984
  return UNRESOLVED;
@@ -22371,30 +22991,30 @@ function evalNode(node, ctx) {
22371
22991
  if (l === UNRESOLVED || r === UNRESOLVED)
22372
22992
  return UNRESOLVED;
22373
22993
  switch (op) {
22374
- case ts18.SyntaxKind.PlusToken:
22994
+ case ts19.SyntaxKind.PlusToken:
22375
22995
  if (typeof l === "string" || typeof r === "string")
22376
22996
  return `${l}${r}`;
22377
22997
  if (typeof l === "number" && typeof r === "number")
22378
22998
  return l + r;
22379
22999
  return UNRESOLVED;
22380
- case ts18.SyntaxKind.MinusToken:
23000
+ case ts19.SyntaxKind.MinusToken:
22381
23001
  return typeof l === "number" && typeof r === "number" ? l - r : UNRESOLVED;
22382
- case ts18.SyntaxKind.AsteriskToken:
23002
+ case ts19.SyntaxKind.AsteriskToken:
22383
23003
  return typeof l === "number" && typeof r === "number" ? l * r : UNRESOLVED;
22384
- case ts18.SyntaxKind.SlashToken:
23004
+ case ts19.SyntaxKind.SlashToken:
22385
23005
  return typeof l === "number" && typeof r === "number" && r !== 0 ? l / r : UNRESOLVED;
22386
- case ts18.SyntaxKind.PercentToken:
23006
+ case ts19.SyntaxKind.PercentToken:
22387
23007
  return typeof l === "number" && typeof r === "number" && r !== 0 ? l % r : UNRESOLVED;
22388
- case ts18.SyntaxKind.EqualsEqualsEqualsToken:
22389
- case ts18.SyntaxKind.EqualsEqualsToken:
23008
+ case ts19.SyntaxKind.EqualsEqualsEqualsToken:
23009
+ case ts19.SyntaxKind.EqualsEqualsToken:
22390
23010
  return l === r;
22391
- case ts18.SyntaxKind.ExclamationEqualsEqualsToken:
22392
- case ts18.SyntaxKind.ExclamationEqualsToken:
23011
+ case ts19.SyntaxKind.ExclamationEqualsEqualsToken:
23012
+ case ts19.SyntaxKind.ExclamationEqualsToken:
22393
23013
  return l !== r;
22394
23014
  }
22395
23015
  return UNRESOLVED;
22396
23016
  }
22397
- if (ts18.isTemplateExpression(node)) {
23017
+ if (ts19.isTemplateExpression(node)) {
22398
23018
  if (node.templateSpans.length === 0)
22399
23019
  return node.head.text;
22400
23020
  let acc = node.head.text;
@@ -22406,13 +23026,13 @@ function evalNode(node, ctx) {
22406
23026
  }
22407
23027
  return acc;
22408
23028
  }
22409
- if (ts18.isNoSubstitutionTemplateLiteral(node))
23029
+ if (ts19.isNoSubstitutionTemplateLiteral(node))
22410
23030
  return node.text;
22411
23031
  return UNRESOLVED;
22412
23032
  }
22413
23033
 
22414
23034
  // src/augment-inherited-props.ts
22415
- import ts19 from "typescript";
23035
+ import ts20 from "typescript";
22416
23036
  function collectContextConsumers(metadata) {
22417
23037
  const constants = metadata.localConstants ?? [];
22418
23038
  const contextDefaults = new Map;
@@ -22444,47 +23064,47 @@ function collectContextConsumers(metadata) {
22444
23064
  }
22445
23065
  function parseUseContextArg(source) {
22446
23066
  const expr = parseSingleExpression(source);
22447
- if (!expr || !ts19.isCallExpression(expr))
23067
+ if (!expr || !ts20.isCallExpression(expr))
22448
23068
  return null;
22449
- if (!ts19.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
23069
+ if (!ts20.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
22450
23070
  return null;
22451
23071
  if (expr.arguments.length !== 1)
22452
23072
  return null;
22453
23073
  const arg = expr.arguments[0];
22454
- return ts19.isIdentifier(arg) ? arg.text : null;
23074
+ return ts20.isIdentifier(arg) ? arg.text : null;
22455
23075
  }
22456
23076
  function parseCreateContextDefault(source) {
22457
23077
  const expr = parseSingleExpression(source);
22458
- if (!expr || !ts19.isCallExpression(expr))
23078
+ if (!expr || !ts20.isCallExpression(expr))
22459
23079
  return null;
22460
23080
  if (expr.arguments.length === 0)
22461
23081
  return null;
22462
23082
  const arg = expr.arguments[0];
22463
- if (ts19.isStringLiteral(arg) || ts19.isNoSubstitutionTemplateLiteral(arg))
23083
+ if (ts20.isStringLiteral(arg) || ts20.isNoSubstitutionTemplateLiteral(arg))
22464
23084
  return arg.text;
22465
- if (ts19.isNumericLiteral(arg))
23085
+ if (ts20.isNumericLiteral(arg))
22466
23086
  return Number(arg.text);
22467
- if (arg.kind === ts19.SyntaxKind.TrueKeyword)
23087
+ if (arg.kind === ts20.SyntaxKind.TrueKeyword)
22468
23088
  return true;
22469
- if (arg.kind === ts19.SyntaxKind.FalseKeyword)
23089
+ if (arg.kind === ts20.SyntaxKind.FalseKeyword)
22470
23090
  return false;
22471
23091
  return null;
22472
23092
  }
22473
23093
  function isObjectLiteralCreateContextDefault(source) {
22474
23094
  const expr = parseSingleExpression(source);
22475
- if (!expr || !ts19.isCallExpression(expr))
23095
+ if (!expr || !ts20.isCallExpression(expr))
22476
23096
  return false;
22477
23097
  if (expr.arguments.length === 0)
22478
23098
  return false;
22479
- return ts19.isObjectLiteralExpression(expr.arguments[0]);
23099
+ return ts20.isObjectLiteralExpression(expr.arguments[0]);
22480
23100
  }
22481
23101
  function parseSingleExpression(source) {
22482
- const sf = ts19.createSourceFile("__ctx.ts", `(${source})`, ts19.ScriptTarget.Latest, false);
23102
+ const sf = ts20.createSourceFile("__ctx.ts", `(${source})`, ts20.ScriptTarget.Latest, false);
22483
23103
  const stmt = sf.statements[0];
22484
- if (!stmt || !ts19.isExpressionStatement(stmt))
23104
+ if (!stmt || !ts20.isExpressionStatement(stmt))
22485
23105
  return null;
22486
23106
  let e = stmt.expression;
22487
- while (ts19.isParenthesizedExpression(e))
23107
+ while (ts20.isParenthesizedExpression(e))
22488
23108
  e = e.expression;
22489
23109
  return e;
22490
23110
  }
@@ -22509,25 +23129,25 @@ function augmentInheritedPropAccesses(ir) {
22509
23129
  const pinCoalesceLiterals = (s) => {
22510
23130
  if (!s || !s.includes(propsObj))
22511
23131
  return;
22512
- const sf = ts19.createSourceFile("__aug.ts", `(${s})`, ts19.ScriptTarget.Latest, false);
23132
+ const sf = ts20.createSourceFile("__aug.ts", `(${s})`, ts20.ScriptTarget.Latest, false);
22513
23133
  const visit3 = (n) => {
22514
- if (ts19.isBinaryExpression(n) && (n.operatorToken.kind === ts19.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts19.SyntaxKind.BarBarToken)) {
23134
+ if (ts20.isBinaryExpression(n) && (n.operatorToken.kind === ts20.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts20.SyntaxKind.BarBarToken)) {
22515
23135
  let left = n.left;
22516
- while (ts19.isParenthesizedExpression(left))
23136
+ while (ts20.isParenthesizedExpression(left))
22517
23137
  left = left.expression;
22518
- if (ts19.isPropertyAccessExpression(left) && ts19.isIdentifier(left.expression) && left.expression.text === propsObj) {
23138
+ if (ts20.isPropertyAccessExpression(left) && ts20.isIdentifier(left.expression) && left.expression.text === propsObj) {
22519
23139
  const name = left.name.text;
22520
23140
  let right = n.right;
22521
- while (ts19.isParenthesizedExpression(right))
23141
+ while (ts20.isParenthesizedExpression(right))
22522
23142
  right = right.expression;
22523
- if (ts19.isPrefixUnaryExpression(right))
23143
+ if (ts20.isPrefixUnaryExpression(right))
22524
23144
  right = right.operand;
22525
- const kind = ts19.isNumericLiteral(right) ? "number" : right.kind === ts19.SyntaxKind.TrueKeyword || right.kind === ts19.SyntaxKind.FalseKeyword ? "boolean" : ts19.isStringLiteralLike(right) ? "string" : null;
23145
+ const kind = ts20.isNumericLiteral(right) ? "number" : right.kind === ts20.SyntaxKind.TrueKeyword || right.kind === ts20.SyntaxKind.FalseKeyword ? "boolean" : ts20.isStringLiteralLike(right) ? "string" : null;
22526
23146
  if (kind && !coalesceLiteralTypes.has(name))
22527
23147
  coalesceLiteralTypes.set(name, kind);
22528
23148
  }
22529
23149
  }
22530
- ts19.forEachChild(n, visit3);
23150
+ ts20.forEachChild(n, visit3);
22531
23151
  };
22532
23152
  visit3(sf);
22533
23153
  };
@@ -22638,33 +23258,33 @@ function augmentInheritedPropAccesses(ir) {
22638
23258
  }
22639
23259
  }
22640
23260
  function parseStaticStringConst(source) {
22641
- const sf = ts19.createSourceFile("__const.ts", `const __x = (${source});`, ts19.ScriptTarget.Latest, false);
23261
+ const sf = ts20.createSourceFile("__const.ts", `const __x = (${source});`, ts20.ScriptTarget.Latest, false);
22642
23262
  const stmt = sf.statements[0];
22643
- if (!stmt || !ts19.isVariableStatement(stmt))
23263
+ if (!stmt || !ts20.isVariableStatement(stmt))
22644
23264
  return null;
22645
23265
  let init = stmt.declarationList.declarations[0]?.initializer;
22646
- while (init && ts19.isParenthesizedExpression(init))
23266
+ while (init && ts20.isParenthesizedExpression(init))
22647
23267
  init = init.expression;
22648
23268
  if (!init)
22649
23269
  return null;
22650
- if (ts19.isStringLiteral(init) || ts19.isNoSubstitutionTemplateLiteral(init)) {
23270
+ if (ts20.isStringLiteral(init) || ts20.isNoSubstitutionTemplateLiteral(init)) {
22651
23271
  return init.text;
22652
23272
  }
22653
23273
  return evalStringArrayJoin(source);
22654
23274
  }
22655
23275
  function evalTemplateOfStringConsts(source, resolved) {
22656
- const sf = ts19.createSourceFile("__const.ts", `const __x = (${source});`, ts19.ScriptTarget.Latest, false);
23276
+ const sf = ts20.createSourceFile("__const.ts", `const __x = (${source});`, ts20.ScriptTarget.Latest, false);
22657
23277
  const stmt = sf.statements[0];
22658
- if (!stmt || !ts19.isVariableStatement(stmt))
23278
+ if (!stmt || !ts20.isVariableStatement(stmt))
22659
23279
  return null;
22660
23280
  let init = stmt.declarationList.declarations[0]?.initializer;
22661
- while (init && ts19.isParenthesizedExpression(init))
23281
+ while (init && ts20.isParenthesizedExpression(init))
22662
23282
  init = init.expression;
22663
- if (!init || !ts19.isTemplateExpression(init))
23283
+ if (!init || !ts20.isTemplateExpression(init))
22664
23284
  return null;
22665
23285
  let out = init.head.text;
22666
23286
  for (const span of init.templateSpans) {
22667
- if (!ts19.isIdentifier(span.expression))
23287
+ if (!ts20.isIdentifier(span.expression))
22668
23288
  return null;
22669
23289
  const value = resolved.get(span.expression.text);
22670
23290
  if (value === undefined)
@@ -22695,30 +23315,30 @@ function lookupStaticRecordLiteral(objectName, key, constants) {
22695
23315
  const constInfo = (constants ?? []).find((c) => c.name === objectName && c.isModule);
22696
23316
  if (constInfo?.value === undefined)
22697
23317
  return null;
22698
- const sf = ts19.createSourceFile("__rec.ts", `(${constInfo.value})`, ts19.ScriptTarget.Latest, true);
23318
+ const sf = ts20.createSourceFile("__rec.ts", `(${constInfo.value})`, ts20.ScriptTarget.Latest, true);
22699
23319
  if (sf.statements.length !== 1)
22700
23320
  return null;
22701
23321
  const stmt = sf.statements[0];
22702
- if (!ts19.isExpressionStatement(stmt))
23322
+ if (!ts20.isExpressionStatement(stmt))
22703
23323
  return null;
22704
23324
  let parsed = stmt.expression;
22705
- while (ts19.isParenthesizedExpression(parsed))
23325
+ while (ts20.isParenthesizedExpression(parsed))
22706
23326
  parsed = parsed.expression;
22707
- if (!ts19.isObjectLiteralExpression(parsed))
23327
+ if (!ts20.isObjectLiteralExpression(parsed))
22708
23328
  return null;
22709
23329
  for (const prop of parsed.properties) {
22710
- if (!ts19.isPropertyAssignment(prop))
23330
+ if (!ts20.isPropertyAssignment(prop))
22711
23331
  continue;
22712
23332
  const name = prop.name;
22713
- const propKey = ts19.isIdentifier(name) || ts19.isStringLiteral(name) || ts19.isNoSubstitutionTemplateLiteral(name) ? name.text : null;
23333
+ const propKey = ts20.isIdentifier(name) || ts20.isStringLiteral(name) || ts20.isNoSubstitutionTemplateLiteral(name) ? name.text : null;
22714
23334
  if (propKey !== key)
22715
23335
  continue;
22716
23336
  let v = prop.initializer;
22717
- while (ts19.isParenthesizedExpression(v))
23337
+ while (ts20.isParenthesizedExpression(v))
22718
23338
  v = v.expression;
22719
- if (ts19.isNumericLiteral(v))
23339
+ if (ts20.isNumericLiteral(v))
22720
23340
  return { kind: "number", text: v.text };
22721
- if (ts19.isStringLiteral(v) || ts19.isNoSubstitutionTemplateLiteral(v)) {
23341
+ if (ts20.isStringLiteral(v) || ts20.isNoSubstitutionTemplateLiteral(v)) {
22722
23342
  return { kind: "string", text: v.text };
22723
23343
  }
22724
23344
  return null;
@@ -22726,28 +23346,28 @@ function lookupStaticRecordLiteral(objectName, key, constants) {
22726
23346
  return null;
22727
23347
  }
22728
23348
  function evalStringArrayJoin(source) {
22729
- const sf = ts19.createSourceFile("__join.ts", `const __x = (${source});`, ts19.ScriptTarget.Latest, false);
23349
+ const sf = ts20.createSourceFile("__join.ts", `const __x = (${source});`, ts20.ScriptTarget.Latest, false);
22730
23350
  const stmt = sf.statements[0];
22731
- if (!stmt || !ts19.isVariableStatement(stmt))
23351
+ if (!stmt || !ts20.isVariableStatement(stmt))
22732
23352
  return null;
22733
23353
  let node = stmt.declarationList.declarations[0]?.initializer;
22734
- while (node && ts19.isParenthesizedExpression(node))
23354
+ while (node && ts20.isParenthesizedExpression(node))
22735
23355
  node = node.expression;
22736
- if (!node || !ts19.isCallExpression(node))
23356
+ if (!node || !ts20.isCallExpression(node))
22737
23357
  return null;
22738
23358
  const callee = node.expression;
22739
- if (!ts19.isPropertyAccessExpression(callee))
23359
+ if (!ts20.isPropertyAccessExpression(callee))
22740
23360
  return null;
22741
23361
  if (callee.name.text !== "join")
22742
23362
  return null;
22743
23363
  let recv = callee.expression;
22744
- while (ts19.isParenthesizedExpression(recv))
23364
+ while (ts20.isParenthesizedExpression(recv))
22745
23365
  recv = recv.expression;
22746
- if (!ts19.isArrayLiteralExpression(recv))
23366
+ if (!ts20.isArrayLiteralExpression(recv))
22747
23367
  return null;
22748
23368
  const parts = [];
22749
23369
  for (const el of recv.elements) {
22750
- if (ts19.isStringLiteral(el) || ts19.isNoSubstitutionTemplateLiteral(el)) {
23370
+ if (ts20.isStringLiteral(el) || ts20.isNoSubstitutionTemplateLiteral(el)) {
22751
23371
  parts.push(el.text);
22752
23372
  } else {
22753
23373
  return null;
@@ -22756,7 +23376,7 @@ function evalStringArrayJoin(source) {
22756
23376
  let sep2 = ",";
22757
23377
  if (node.arguments.length >= 1) {
22758
23378
  const arg = node.arguments[0];
22759
- if (ts19.isStringLiteral(arg) || ts19.isNoSubstitutionTemplateLiteral(arg))
23379
+ if (ts20.isStringLiteral(arg) || ts20.isNoSubstitutionTemplateLiteral(arg))
22760
23380
  sep2 = arg.text;
22761
23381
  else
22762
23382
  return null;
@@ -22764,11 +23384,11 @@ function evalStringArrayJoin(source) {
22764
23384
  return parts.join(sep2);
22765
23385
  }
22766
23386
  function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
22767
- if (!ts19.isElementAccessExpression(val))
23387
+ if (!ts20.isElementAccessExpression(val))
22768
23388
  return null;
22769
23389
  const obj = val.expression;
22770
23390
  const arg = val.argumentExpression;
22771
- if (!ts19.isIdentifier(obj) || !ts19.isIdentifier(arg))
23391
+ if (!ts20.isIdentifier(obj) || !ts20.isIdentifier(arg))
22772
23392
  return null;
22773
23393
  let indexPropName;
22774
23394
  let defaultKey;
@@ -22784,35 +23404,35 @@ function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
22784
23404
  const constInfo = localConstants.find((c) => c.name === obj.text && c.isModule);
22785
23405
  if (constInfo?.value === undefined)
22786
23406
  return null;
22787
- const sf = ts19.createSourceFile("__rec.ts", `(${constInfo.value})`, ts19.ScriptTarget.Latest, true);
23407
+ const sf = ts20.createSourceFile("__rec.ts", `(${constInfo.value})`, ts20.ScriptTarget.Latest, true);
22788
23408
  if (sf.statements.length !== 1)
22789
23409
  return null;
22790
23410
  const stmt = sf.statements[0];
22791
- if (!ts19.isExpressionStatement(stmt))
23411
+ if (!ts20.isExpressionStatement(stmt))
22792
23412
  return null;
22793
23413
  let parsed = stmt.expression;
22794
- while (ts19.isParenthesizedExpression(parsed))
23414
+ while (ts20.isParenthesizedExpression(parsed))
22795
23415
  parsed = parsed.expression;
22796
- if (!ts19.isObjectLiteralExpression(parsed))
23416
+ if (!ts20.isObjectLiteralExpression(parsed))
22797
23417
  return null;
22798
23418
  const entries = [];
22799
23419
  for (const prop of parsed.properties) {
22800
- if (!ts19.isPropertyAssignment(prop))
23420
+ if (!ts20.isPropertyAssignment(prop))
22801
23421
  return null;
22802
23422
  let key;
22803
- if (ts19.isIdentifier(prop.name)) {
23423
+ if (ts20.isIdentifier(prop.name)) {
22804
23424
  key = prop.name.text;
22805
- } else if (ts19.isStringLiteral(prop.name) || ts19.isNoSubstitutionTemplateLiteral(prop.name)) {
23425
+ } else if (ts20.isStringLiteral(prop.name) || ts20.isNoSubstitutionTemplateLiteral(prop.name)) {
22806
23426
  key = prop.name.text;
22807
23427
  } else {
22808
23428
  return null;
22809
23429
  }
22810
23430
  let v = prop.initializer;
22811
- while (ts19.isParenthesizedExpression(v))
23431
+ while (ts20.isParenthesizedExpression(v))
22812
23432
  v = v.expression;
22813
- if (ts19.isNumericLiteral(v)) {
23433
+ if (ts20.isNumericLiteral(v)) {
22814
23434
  entries.push({ key, value: { kind: "number", text: v.text } });
22815
- } else if (ts19.isStringLiteral(v) || ts19.isNoSubstitutionTemplateLiteral(v)) {
23435
+ } else if (ts20.isStringLiteral(v) || ts20.isNoSubstitutionTemplateLiteral(v)) {
22816
23436
  entries.push({ key, value: { kind: "string", text: v.text } });
22817
23437
  } else {
22818
23438
  return null;
@@ -23595,7 +24215,7 @@ function compileJSX(source, filePath, options) {
23595
24215
  return { files, errors };
23596
24216
  }
23597
24217
  // src/shared-program.ts
23598
- import ts20 from "typescript";
24218
+ import ts21 from "typescript";
23599
24219
  function commonParent(paths) {
23600
24220
  if (paths.length === 0)
23601
24221
  return process.cwd();
@@ -23616,10 +24236,10 @@ function commonParent(paths) {
23616
24236
  function createProgramForCorpus(files, options = {}) {
23617
24237
  const baseUrl = options.baseUrl ?? commonParent(files);
23618
24238
  const compilerOptions = {
23619
- target: ts20.ScriptTarget.Latest,
23620
- module: ts20.ModuleKind.ESNext,
23621
- moduleResolution: ts20.ModuleResolutionKind.Bundler,
23622
- jsx: ts20.JsxEmit.ReactJSX,
24239
+ target: ts21.ScriptTarget.Latest,
24240
+ module: ts21.ModuleKind.ESNext,
24241
+ moduleResolution: ts21.ModuleResolutionKind.Bundler,
24242
+ jsx: ts21.JsxEmit.ReactJSX,
23623
24243
  strict: true,
23624
24244
  skipLibCheck: true,
23625
24245
  noEmit: true,
@@ -23629,7 +24249,7 @@ function createProgramForCorpus(files, options = {}) {
23629
24249
  ...options.compilerOptions
23630
24250
  };
23631
24251
  const absolute = files.map((f) => path_default.resolve(f));
23632
- return ts20.createProgram(absolute, compilerOptions, undefined, options.oldProgram);
24252
+ return ts21.createProgram(absolute, compilerOptions, undefined, options.oldProgram);
23633
24253
  }
23634
24254
  // src/adapters/interface.ts
23635
24255
  class BaseAdapter {
@@ -24184,6 +24804,8 @@ function collectLoopBoundNames(ir) {
24184
24804
  names.add(binding.name);
24185
24805
  if (node.filterPredicate)
24186
24806
  names.add(node.filterPredicate.param);
24807
+ for (const name of node.preamble?.declaredNames ?? [])
24808
+ names.add(name);
24187
24809
  for (const child of node.children)
24188
24810
  visit3(child);
24189
24811
  if (node.childComponent) {
@@ -24611,7 +25233,7 @@ function dangerousInnerHtmlDiagnostic(expr, loc, reason) {
24611
25233
  };
24612
25234
  }
24613
25235
  // src/combine-client-js.ts
24614
- import ts21 from "typescript";
25236
+ import ts22 from "typescript";
24615
25237
  var CHILD_PLACEHOLDER_RE = /import '\/\* @bf-child:(\w+) \*\/'/g;
24616
25238
  function combineParentChildClientJs(files) {
24617
25239
  const result = new Map;
@@ -24668,10 +25290,10 @@ function combineParentChildClientJs(files) {
24668
25290
  return result;
24669
25291
  }
24670
25292
  function parseAndMerge(content, importsBySource, otherImports, codeSections) {
24671
- const sourceFile = ts21.createSourceFile("combine.js", content, ts21.ScriptTarget.Latest, false, ts21.ScriptKind.JS);
25293
+ const sourceFile = ts22.createSourceFile("combine.js", content, ts22.ScriptTarget.Latest, false, ts22.ScriptKind.JS);
24672
25294
  const importSpans = [];
24673
25295
  for (const stmt of sourceFile.statements) {
24674
- if (!ts21.isImportDeclaration(stmt))
25296
+ if (!ts22.isImportDeclaration(stmt))
24675
25297
  continue;
24676
25298
  const start = stmt.getStart(sourceFile);
24677
25299
  const end = stmt.getEnd();
@@ -24681,8 +25303,8 @@ function parseAndMerge(content, importsBySource, otherImports, codeSections) {
24681
25303
  continue;
24682
25304
  const clause = stmt.importClause;
24683
25305
  const bindings = clause?.namedBindings;
24684
- const specifier = ts21.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : "";
24685
- if (clause && !clause.name && bindings && ts21.isNamedImports(bindings)) {
25306
+ const specifier = ts22.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : "";
25307
+ if (clause && !clause.name && bindings && ts22.isNamedImports(bindings)) {
24686
25308
  if (!importsBySource.has(specifier)) {
24687
25309
  importsBySource.set(specifier, new Set);
24688
25310
  }
@@ -24849,7 +25471,7 @@ function escapeRe(s) {
24849
25471
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24850
25472
  }
24851
25473
  // src/debug.ts
24852
- import ts22 from "typescript";
25474
+ import ts23 from "typescript";
24853
25475
  function buildComponentGraph(source, filePath, componentName) {
24854
25476
  const ctx = analyzeComponent(source, filePath, componentName);
24855
25477
  if (!ctx.jsxReturn) {
@@ -26134,7 +26756,7 @@ function truncateExpr(expr, max = 40) {
26134
26756
  function exprReadsPropMember(expr, propsObjectName) {
26135
26757
  let sf;
26136
26758
  try {
26137
- sf = ts22.createSourceFile("__attr.tsx", `(${expr})`, ts22.ScriptTarget.Latest, true, ts22.ScriptKind.TSX);
26759
+ sf = ts23.createSourceFile("__attr.tsx", `(${expr})`, ts23.ScriptTarget.Latest, true, ts23.ScriptKind.TSX);
26138
26760
  } catch {
26139
26761
  return false;
26140
26762
  }
@@ -26142,11 +26764,11 @@ function exprReadsPropMember(expr, propsObjectName) {
26142
26764
  const visit3 = (n) => {
26143
26765
  if (found)
26144
26766
  return;
26145
- if (ts22.isPropertyAccessExpression(n) && ts22.isIdentifier(n.expression) && n.expression.text === propsObjectName && n.name.text !== "children") {
26767
+ if (ts23.isPropertyAccessExpression(n) && ts23.isIdentifier(n.expression) && n.expression.text === propsObjectName && n.name.text !== "children") {
26146
26768
  found = true;
26147
26769
  return;
26148
26770
  }
26149
- ts22.forEachChild(n, visit3);
26771
+ ts23.forEachChild(n, visit3);
26150
26772
  };
26151
26773
  visit3(sf);
26152
26774
  return found;
@@ -26216,7 +26838,7 @@ function findSourceFile2(meta) {
26216
26838
  return null;
26217
26839
  }
26218
26840
  // src/profiler.ts
26219
- import ts23 from "typescript";
26841
+ import ts24 from "typescript";
26220
26842
  var PROFILE_SCHEMA_VERSION = 1;
26221
26843
  var DEFAULT_FANOUT_THRESHOLD = 8;
26222
26844
  function buildStaticBudget(source, filePath, componentName, options = {}) {
@@ -26486,15 +27108,15 @@ function joinProfilerEvents(events, index) {
26486
27108
  return { joined, unattributed, diagnostics };
26487
27109
  }
26488
27110
  function findUninstrumentedEffects(source, filePath, instrumentedLines) {
26489
- const sf = ts23.createSourceFile(filePath, source, ts23.ScriptTarget.Latest, true, ts23.ScriptKind.TSX);
27111
+ const sf = ts24.createSourceFile(filePath, source, ts24.ScriptTarget.Latest, true, ts24.ScriptKind.TSX);
26490
27112
  const out = [];
26491
27113
  const visit3 = (node) => {
26492
- if (ts23.isCallExpression(node) && ts23.isIdentifier(node.expression) && node.expression.text === "createEffect") {
27114
+ if (ts24.isCallExpression(node) && ts24.isIdentifier(node.expression) && node.expression.text === "createEffect") {
26493
27115
  const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
26494
27116
  if (!instrumentedLines.has(line))
26495
27117
  out.push({ file: filePath, line });
26496
27118
  }
26497
- ts23.forEachChild(node, visit3);
27119
+ ts24.forEachChild(node, visit3);
26498
27120
  };
26499
27121
  visit3(sf);
26500
27122
  out.sort((a, b) => a.line - b.line);
@@ -26802,13 +27424,13 @@ function assessBatchSafety(args) {
26802
27424
  const signalGetters = new Set(args.graph.signals.map((s) => s.name));
26803
27425
  let sf;
26804
27426
  try {
26805
- sf = ts23.createSourceFile("__h.ts", `const __h = ${args.handler}`, ts23.ScriptTarget.Latest, true);
27427
+ sf = ts24.createSourceFile("__h.ts", `const __h = ${args.handler}`, ts24.ScriptTarget.Latest, true);
26806
27428
  } catch {
26807
27429
  return "unverified";
26808
27430
  }
26809
27431
  const calls = [];
26810
27432
  const visit3 = (node) => {
26811
- if (ts23.isCallExpression(node) && ts23.isIdentifier(node.expression)) {
27433
+ if (ts24.isCallExpression(node) && ts24.isIdentifier(node.expression)) {
26812
27434
  const name = node.expression.text;
26813
27435
  if (setters.has(name))
26814
27436
  calls.push({ pos: node.getStart(sf), kind: "write" });
@@ -26817,7 +27439,7 @@ function assessBatchSafety(args) {
26817
27439
  else if (!signalGetters.has(name) && !memoNames.has(name))
26818
27440
  calls.push({ pos: node.getStart(sf), kind: "risky" });
26819
27441
  }
26820
- ts23.forEachChild(node, visit3);
27442
+ ts24.forEachChild(node, visit3);
26821
27443
  };
26822
27444
  visit3(sf);
26823
27445
  calls.sort((a, b) => a.pos - b.pos);
@@ -27559,6 +28181,7 @@ export {
27559
28181
  diffStaticBudget,
27560
28182
  diffProfiles,
27561
28183
  describeFallback,
28184
+ derivesScopeFromSlot,
27562
28185
  decideClientOnlyElision,
27563
28186
  dangerousInnerHtmlMetacharViolation,
27564
28187
  dangerousInnerHtmlDiagnostic,