@barefootjs/go-template 0.31.3 → 0.31.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vite.js CHANGED
@@ -5,7 +5,7 @@ import { barefoot as coreBarefoot } from "@barefootjs/vite";
5
5
  import { devModuleUrl, loadManifest, resolveDevOrigin, resolveScriptAssets, toPosixRelative } from "@barefootjs/vite";
6
6
 
7
7
  // ../jsx/src/compiler.ts
8
- import ts23 from "typescript";
8
+ import ts24 from "typescript";
9
9
 
10
10
  // ../jsx/src/analyzer.ts
11
11
  import ts9 from "typescript";
@@ -1946,6 +1946,20 @@ function templatePartsToJsExpr(parts, opts) {
1946
1946
  return result;
1947
1947
  }
1948
1948
 
1949
+ // ../jsx/src/identifier-pattern.ts
1950
+ function withUnicodeFlag(flags) {
1951
+ return flags.includes("u") ? flags : `${flags}u`;
1952
+ }
1953
+ function escapeIdentifierForRegex(name) {
1954
+ return name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1955
+ }
1956
+ var ID_BOUNDARY_BEFORE = "(?<![\\p{ID_Continue}$])";
1957
+ var ID_BOUNDARY_AFTER = "(?![\\p{ID_Continue}$])";
1958
+ function identifierPattern(name, flags = "") {
1959
+ const esc = escapeIdentifierForRegex(name);
1960
+ return new RegExp(`${ID_BOUNDARY_BEFORE}${esc}${ID_BOUNDARY_AFTER}`, withUnicodeFlag(flags));
1961
+ }
1962
+
1949
1963
  // ../jsx/src/scanner/js-scanner.ts
1950
1964
  import ts2 from "typescript";
1951
1965
  function* iterateJsTokens(text, start = 0, end = text.length) {
@@ -2135,6 +2149,83 @@ function extractFreeIdentifiersFromText(text) {
2135
2149
  return extractFreeIdentifiersFromNode(expr);
2136
2150
  }
2137
2151
 
2152
+ // ../jsx/src/scope/binding-scope.ts
2153
+ class BindingScope {
2154
+ frames;
2155
+ static EMPTY = new BindingScope([]);
2156
+ constructor(frames) {
2157
+ this.frames = frames;
2158
+ }
2159
+ enterLoopRow(loop) {
2160
+ const bindings = new Map;
2161
+ if (loop.paramBindings && loop.paramBindings.length > 0) {
2162
+ for (const b of loop.paramBindings)
2163
+ bindings.set(b.name, { source: "destructure" });
2164
+ } else {
2165
+ bindings.set(loop.param, { source: "item" });
2166
+ }
2167
+ if (loop.index != null)
2168
+ bindings.set(loop.index, { source: "index" });
2169
+ for (const name of loop.preamble?.declaredNames ?? [])
2170
+ bindings.set(name, { source: "preamble" });
2171
+ const frame = { kind: "loop-row", bindings };
2172
+ return new BindingScope([frame, ...this.frames]);
2173
+ }
2174
+ enterCallback(params) {
2175
+ const bindings = new Map;
2176
+ for (const name of params)
2177
+ bindings.set(name, { source: "param" });
2178
+ const frame = { kind: "callback", bindings };
2179
+ return new BindingScope([frame, ...this.frames]);
2180
+ }
2181
+ isBound(name) {
2182
+ for (const frame of this.frames) {
2183
+ if (frame.bindings.has(name))
2184
+ return true;
2185
+ }
2186
+ return false;
2187
+ }
2188
+ lookup(name) {
2189
+ for (let depth = 0;depth < this.frames.length; depth++) {
2190
+ const frame = this.frames[depth];
2191
+ const binding = frame.bindings.get(name);
2192
+ if (binding)
2193
+ return { depth, frame, binding };
2194
+ }
2195
+ return null;
2196
+ }
2197
+ boundNames() {
2198
+ if (this.boundNamesCache)
2199
+ return this.boundNamesCache;
2200
+ const names = new Set;
2201
+ for (const frame of this.frames) {
2202
+ for (const name of frame.bindings.keys())
2203
+ names.add(name);
2204
+ }
2205
+ this.boundNamesCache = names;
2206
+ return names;
2207
+ }
2208
+ boundNamesCache;
2209
+ valueBoundNamesCache;
2210
+ valueBoundNames() {
2211
+ if (this.valueBoundNamesCache)
2212
+ return this.valueBoundNamesCache;
2213
+ const names = new Set;
2214
+ for (const frame of this.frames) {
2215
+ for (const [name, binding] of frame.bindings) {
2216
+ if (binding.source === "item" || binding.source === "index" || binding.source === "destructure") {
2217
+ names.add(name);
2218
+ }
2219
+ }
2220
+ }
2221
+ this.valueBoundNamesCache = names;
2222
+ return names;
2223
+ }
2224
+ asShadowPredicate() {
2225
+ return (name) => this.isBound(name);
2226
+ }
2227
+ }
2228
+
2138
2229
  // ../jsx/src/ir-to-client-js/html-template.ts
2139
2230
  var VOID_ELEMENTS = new Set([
2140
2231
  "area",
@@ -2506,7 +2597,7 @@ var REACTIVE_PRIMITIVES = new Set([
2506
2597
  ]);
2507
2598
 
2508
2599
  // ../jsx/src/jsx-to-ir.ts
2509
- import ts12 from "typescript";
2600
+ import ts13 from "typescript";
2510
2601
 
2511
2602
  // ../jsx/src/types.ts
2512
2603
  var SCOPE_FORBIDDEN = {
@@ -2556,6 +2647,7 @@ function preambleAnalysisTemplateText(p) {
2556
2647
  }
2557
2648
 
2558
2649
  // ../jsx/src/module-exports.ts
2650
+ import ts10 from "typescript";
2559
2651
  function formatParamWithType(p) {
2560
2652
  const rest = p.isRest ? "..." : "";
2561
2653
  const optional = p.optional ? "?" : "";
@@ -2569,7 +2661,7 @@ function findReachableNames(primaryRefs, declarations) {
2569
2661
  const reachable = new Set;
2570
2662
  const queue = [];
2571
2663
  for (const name of allNames) {
2572
- if (new RegExp(`\\b${name}\\b`).test(primaryRefs)) {
2664
+ if (identifierPattern(name).test(primaryRefs)) {
2573
2665
  reachable.add(name);
2574
2666
  queue.push(name);
2575
2667
  }
@@ -2578,7 +2670,7 @@ function findReachableNames(primaryRefs, declarations) {
2578
2670
  const current = queue.shift();
2579
2671
  const body = bodyMap.get(current) || "";
2580
2672
  for (const name of allNames) {
2581
- if (!reachable.has(name) && new RegExp(`\\b${name}\\b`).test(body)) {
2673
+ if (!reachable.has(name) && identifierPattern(name).test(body)) {
2582
2674
  reachable.add(name);
2583
2675
  queue.push(name);
2584
2676
  }
@@ -2586,12 +2678,55 @@ function findReachableNames(primaryRefs, declarations) {
2586
2678
  }
2587
2679
  return reachable;
2588
2680
  }
2681
+ function findAssignedNames(bodyText, candidates) {
2682
+ const assigned = new Set;
2683
+ if (candidates.size === 0)
2684
+ return assigned;
2685
+ const sf = ts10.createSourceFile("bf-assignment-scan.tsx", bodyText, ts10.ScriptTarget.Latest, false, ts10.ScriptKind.TSX);
2686
+ const record = (target) => {
2687
+ if (ts10.isIdentifier(target) && candidates.has(target.text)) {
2688
+ assigned.add(target.text);
2689
+ }
2690
+ };
2691
+ const visit = (node) => {
2692
+ if (ts10.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
2693
+ record(node.left);
2694
+ } else if ((ts10.isPrefixUnaryExpression(node) || ts10.isPostfixUnaryExpression(node)) && (node.operator === ts10.SyntaxKind.PlusPlusToken || node.operator === ts10.SyntaxKind.MinusMinusToken)) {
2695
+ record(node.operand);
2696
+ }
2697
+ ts10.forEachChild(node, visit);
2698
+ };
2699
+ ts10.forEachChild(sf, visit);
2700
+ return assigned;
2701
+ }
2702
+ function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNames) {
2703
+ let reachable = findReachableNames(primaryRefs, declarations);
2704
+ if (mutableNames.size === 0)
2705
+ return reachable;
2706
+ let seedText = primaryRefs;
2707
+ for (let round = 0;round <= declarations.length; round++) {
2708
+ const survivingMutables = new Set([...reachable].filter((name) => mutableNames.has(name)));
2709
+ if (survivingMutables.size === 0)
2710
+ return reachable;
2711
+ const added = declarations.filter((d) => !reachable.has(d.name)).filter((d) => findAssignedNames(d.body, survivingMutables).size > 0).map((d) => d.name);
2712
+ if (added.length === 0)
2713
+ return reachable;
2714
+ seedText += `
2715
+ ` + added.join(`
2716
+ `);
2717
+ reachable = findReachableNames(seedText, declarations);
2718
+ }
2719
+ return reachable;
2720
+ }
2721
+ function isAssignmentOperator(kind) {
2722
+ return kind >= ts10.SyntaxKind.FirstAssignment && kind <= ts10.SyntaxKind.LastAssignment;
2723
+ }
2589
2724
 
2590
2725
  // ../jsx/src/reactivity-checker.ts
2591
- import ts10 from "typescript";
2726
+ import ts11 from "typescript";
2592
2727
 
2593
2728
  // ../jsx/src/free-refs.ts
2594
- import ts11 from "typescript";
2729
+ import ts12 from "typescript";
2595
2730
  var _bindingMapCache = new WeakMap;
2596
2731
 
2597
2732
  // ../jsx/src/to-locale-date-lowering.ts
@@ -2909,83 +3044,6 @@ var toLocaleDatePlugin = {
2909
3044
  }
2910
3045
  };
2911
3046
 
2912
- // ../jsx/src/scope/binding-scope.ts
2913
- class BindingScope {
2914
- frames;
2915
- static EMPTY = new BindingScope([]);
2916
- constructor(frames) {
2917
- this.frames = frames;
2918
- }
2919
- enterLoopRow(loop) {
2920
- const bindings = new Map;
2921
- if (loop.paramBindings && loop.paramBindings.length > 0) {
2922
- for (const b of loop.paramBindings)
2923
- bindings.set(b.name, { source: "destructure" });
2924
- } else {
2925
- bindings.set(loop.param, { source: "item" });
2926
- }
2927
- if (loop.index != null)
2928
- bindings.set(loop.index, { source: "index" });
2929
- for (const name of loop.preamble?.declaredNames ?? [])
2930
- bindings.set(name, { source: "preamble" });
2931
- const frame = { kind: "loop-row", bindings };
2932
- return new BindingScope([frame, ...this.frames]);
2933
- }
2934
- enterCallback(params) {
2935
- const bindings = new Map;
2936
- for (const name of params)
2937
- bindings.set(name, { source: "param" });
2938
- const frame = { kind: "callback", bindings };
2939
- return new BindingScope([frame, ...this.frames]);
2940
- }
2941
- isBound(name) {
2942
- for (const frame of this.frames) {
2943
- if (frame.bindings.has(name))
2944
- return true;
2945
- }
2946
- return false;
2947
- }
2948
- lookup(name) {
2949
- for (let depth = 0;depth < this.frames.length; depth++) {
2950
- const frame = this.frames[depth];
2951
- const binding = frame.bindings.get(name);
2952
- if (binding)
2953
- return { depth, frame, binding };
2954
- }
2955
- return null;
2956
- }
2957
- boundNames() {
2958
- if (this.boundNamesCache)
2959
- return this.boundNamesCache;
2960
- const names = new Set;
2961
- for (const frame of this.frames) {
2962
- for (const name of frame.bindings.keys())
2963
- names.add(name);
2964
- }
2965
- this.boundNamesCache = names;
2966
- return names;
2967
- }
2968
- boundNamesCache;
2969
- valueBoundNamesCache;
2970
- valueBoundNames() {
2971
- if (this.valueBoundNamesCache)
2972
- return this.valueBoundNamesCache;
2973
- const names = new Set;
2974
- for (const frame of this.frames) {
2975
- for (const [name, binding] of frame.bindings) {
2976
- if (binding.source === "item" || binding.source === "index" || binding.source === "destructure") {
2977
- names.add(name);
2978
- }
2979
- }
2980
- }
2981
- this.valueBoundNamesCache = names;
2982
- return names;
2983
- }
2984
- asShadowPredicate() {
2985
- return (name) => this.isBound(name);
2986
- }
2987
- }
2988
-
2989
3047
  // ../jsx/src/jsx-to-ir.ts
2990
3048
  var EMPTY_BOUND = new Set;
2991
3049
  var constInitializerCache = new WeakMap;
@@ -3082,13 +3140,13 @@ var KEYWORDS_AND_GLOBALS = new Set([
3082
3140
  ]);
3083
3141
 
3084
3142
  // ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
3085
- import ts13 from "typescript";
3143
+ import ts14 from "typescript";
3086
3144
 
3087
3145
  // ../jsx/src/value-references.ts
3088
- import ts14 from "typescript";
3146
+ import ts15 from "typescript";
3089
3147
 
3090
3148
  // ../jsx/src/relocate.ts
3091
- import ts15 from "typescript";
3149
+ import ts16 from "typescript";
3092
3150
 
3093
3151
  // ../jsx/src/lowering-registry.ts
3094
3152
  var plugins = [];
@@ -3284,10 +3342,10 @@ function formatDateLocalNames(metadata) {
3284
3342
  }
3285
3343
 
3286
3344
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3287
- import ts16 from "typescript";
3345
+ import ts17 from "typescript";
3288
3346
 
3289
3347
  // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3290
- import ts17 from "typescript";
3348
+ import ts18 from "typescript";
3291
3349
  var NO_PREAMBLE = {
3292
3350
  lazySafe: true,
3293
3351
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3337,7 +3395,7 @@ var INERT_BINDING_GLOBALS = new Set([
3337
3395
  ]);
3338
3396
 
3339
3397
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
3340
- import ts18 from "typescript";
3398
+ import ts19 from "typescript";
3341
3399
 
3342
3400
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3343
3401
  var NON_BUBBLING_EVENTS = new Set([
@@ -3352,7 +3410,7 @@ var NON_BUBBLING_EVENTS = new Set([
3352
3410
  ]);
3353
3411
 
3354
3412
  // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
3355
- import ts19 from "typescript";
3413
+ import ts20 from "typescript";
3356
3414
 
3357
3415
  // ../jsx/src/ir-to-client-js/source-map.ts
3358
3416
  var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -3443,15 +3501,15 @@ class SourceMapGenerator {
3443
3501
  }
3444
3502
 
3445
3503
  // ../jsx/src/preprocess-inline-jsx-callbacks.ts
3446
- import ts20 from "typescript";
3504
+ import ts21 from "typescript";
3447
3505
 
3448
3506
  // ../jsx/src/ssr-defaults.ts
3449
- import ts21 from "typescript";
3507
+ import ts22 from "typescript";
3450
3508
  var UNRESOLVED = Symbol("unresolved");
3451
3509
  var NO_RETURN = Symbol("no-return");
3452
3510
 
3453
3511
  // ../jsx/src/augment-inherited-props.ts
3454
- import ts22 from "typescript";
3512
+ import ts23 from "typescript";
3455
3513
  function collectContextConsumers(metadata) {
3456
3514
  const constants = metadata.localConstants ?? [];
3457
3515
  const contextDefaults = new Map;
@@ -3483,47 +3541,47 @@ function collectContextConsumers(metadata) {
3483
3541
  }
3484
3542
  function parseUseContextArg(source) {
3485
3543
  const expr = parseSingleExpression(source);
3486
- if (!expr || !ts22.isCallExpression(expr))
3544
+ if (!expr || !ts23.isCallExpression(expr))
3487
3545
  return null;
3488
- if (!ts22.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3546
+ if (!ts23.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3489
3547
  return null;
3490
3548
  if (expr.arguments.length !== 1)
3491
3549
  return null;
3492
3550
  const arg = expr.arguments[0];
3493
- return ts22.isIdentifier(arg) ? arg.text : null;
3551
+ return ts23.isIdentifier(arg) ? arg.text : null;
3494
3552
  }
3495
3553
  function parseCreateContextDefault(source) {
3496
3554
  const expr = parseSingleExpression(source);
3497
- if (!expr || !ts22.isCallExpression(expr))
3555
+ if (!expr || !ts23.isCallExpression(expr))
3498
3556
  return null;
3499
3557
  if (expr.arguments.length === 0)
3500
3558
  return null;
3501
3559
  const arg = expr.arguments[0];
3502
- if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3560
+ if (ts23.isStringLiteral(arg) || ts23.isNoSubstitutionTemplateLiteral(arg))
3503
3561
  return arg.text;
3504
- if (ts22.isNumericLiteral(arg))
3562
+ if (ts23.isNumericLiteral(arg))
3505
3563
  return Number(arg.text);
3506
- if (arg.kind === ts22.SyntaxKind.TrueKeyword)
3564
+ if (arg.kind === ts23.SyntaxKind.TrueKeyword)
3507
3565
  return true;
3508
- if (arg.kind === ts22.SyntaxKind.FalseKeyword)
3566
+ if (arg.kind === ts23.SyntaxKind.FalseKeyword)
3509
3567
  return false;
3510
3568
  return null;
3511
3569
  }
3512
3570
  function isObjectLiteralCreateContextDefault(source) {
3513
3571
  const expr = parseSingleExpression(source);
3514
- if (!expr || !ts22.isCallExpression(expr))
3572
+ if (!expr || !ts23.isCallExpression(expr))
3515
3573
  return false;
3516
3574
  if (expr.arguments.length === 0)
3517
3575
  return false;
3518
- return ts22.isObjectLiteralExpression(expr.arguments[0]);
3576
+ return ts23.isObjectLiteralExpression(expr.arguments[0]);
3519
3577
  }
3520
3578
  function parseSingleExpression(source) {
3521
- const sf = ts22.createSourceFile("__ctx.ts", `(${source})`, ts22.ScriptTarget.Latest, false);
3579
+ const sf = ts23.createSourceFile("__ctx.ts", `(${source})`, ts23.ScriptTarget.Latest, false);
3522
3580
  const stmt = sf.statements[0];
3523
- if (!stmt || !ts22.isExpressionStatement(stmt))
3581
+ if (!stmt || !ts23.isExpressionStatement(stmt))
3524
3582
  return null;
3525
3583
  let e = stmt.expression;
3526
- while (ts22.isParenthesizedExpression(e))
3584
+ while (ts23.isParenthesizedExpression(e))
3527
3585
  e = e.expression;
3528
3586
  return e;
3529
3587
  }
@@ -3548,25 +3606,25 @@ function augmentInheritedPropAccesses(ir) {
3548
3606
  const pinCoalesceLiterals = (s) => {
3549
3607
  if (!s || !s.includes(propsObj))
3550
3608
  return;
3551
- const sf = ts22.createSourceFile("__aug.ts", `(${s})`, ts22.ScriptTarget.Latest, false);
3609
+ const sf = ts23.createSourceFile("__aug.ts", `(${s})`, ts23.ScriptTarget.Latest, false);
3552
3610
  const visit = (n) => {
3553
- if (ts22.isBinaryExpression(n) && (n.operatorToken.kind === ts22.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts22.SyntaxKind.BarBarToken)) {
3611
+ if (ts23.isBinaryExpression(n) && (n.operatorToken.kind === ts23.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts23.SyntaxKind.BarBarToken)) {
3554
3612
  let left = n.left;
3555
- while (ts22.isParenthesizedExpression(left))
3613
+ while (ts23.isParenthesizedExpression(left))
3556
3614
  left = left.expression;
3557
- if (ts22.isPropertyAccessExpression(left) && ts22.isIdentifier(left.expression) && left.expression.text === propsObj) {
3615
+ if (ts23.isPropertyAccessExpression(left) && ts23.isIdentifier(left.expression) && left.expression.text === propsObj) {
3558
3616
  const name = left.name.text;
3559
3617
  let right = n.right;
3560
- while (ts22.isParenthesizedExpression(right))
3618
+ while (ts23.isParenthesizedExpression(right))
3561
3619
  right = right.expression;
3562
- if (ts22.isPrefixUnaryExpression(right))
3620
+ if (ts23.isPrefixUnaryExpression(right))
3563
3621
  right = right.operand;
3564
- const kind = ts22.isNumericLiteral(right) ? "number" : right.kind === ts22.SyntaxKind.TrueKeyword || right.kind === ts22.SyntaxKind.FalseKeyword ? "boolean" : ts22.isStringLiteralLike(right) ? "string" : null;
3622
+ const kind = ts23.isNumericLiteral(right) ? "number" : right.kind === ts23.SyntaxKind.TrueKeyword || right.kind === ts23.SyntaxKind.FalseKeyword ? "boolean" : ts23.isStringLiteralLike(right) ? "string" : null;
3565
3623
  if (kind && !coalesceLiteralTypes.has(name))
3566
3624
  coalesceLiteralTypes.set(name, kind);
3567
3625
  }
3568
3626
  }
3569
- ts22.forEachChild(n, visit);
3627
+ ts23.forEachChild(n, visit);
3570
3628
  };
3571
3629
  visit(sf);
3572
3630
  };
@@ -3677,33 +3735,33 @@ function augmentInheritedPropAccesses(ir) {
3677
3735
  }
3678
3736
  }
3679
3737
  function parseStaticStringConst(source) {
3680
- const sf = ts22.createSourceFile("__const.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3738
+ const sf = ts23.createSourceFile("__const.ts", `const __x = (${source});`, ts23.ScriptTarget.Latest, false);
3681
3739
  const stmt = sf.statements[0];
3682
- if (!stmt || !ts22.isVariableStatement(stmt))
3740
+ if (!stmt || !ts23.isVariableStatement(stmt))
3683
3741
  return null;
3684
3742
  let init = stmt.declarationList.declarations[0]?.initializer;
3685
- while (init && ts22.isParenthesizedExpression(init))
3743
+ while (init && ts23.isParenthesizedExpression(init))
3686
3744
  init = init.expression;
3687
3745
  if (!init)
3688
3746
  return null;
3689
- if (ts22.isStringLiteral(init) || ts22.isNoSubstitutionTemplateLiteral(init)) {
3747
+ if (ts23.isStringLiteral(init) || ts23.isNoSubstitutionTemplateLiteral(init)) {
3690
3748
  return init.text;
3691
3749
  }
3692
3750
  return evalStringArrayJoin(source);
3693
3751
  }
3694
3752
  function evalTemplateOfStringConsts(source, resolved) {
3695
- const sf = ts22.createSourceFile("__const.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3753
+ const sf = ts23.createSourceFile("__const.ts", `const __x = (${source});`, ts23.ScriptTarget.Latest, false);
3696
3754
  const stmt = sf.statements[0];
3697
- if (!stmt || !ts22.isVariableStatement(stmt))
3755
+ if (!stmt || !ts23.isVariableStatement(stmt))
3698
3756
  return null;
3699
3757
  let init = stmt.declarationList.declarations[0]?.initializer;
3700
- while (init && ts22.isParenthesizedExpression(init))
3758
+ while (init && ts23.isParenthesizedExpression(init))
3701
3759
  init = init.expression;
3702
- if (!init || !ts22.isTemplateExpression(init))
3760
+ if (!init || !ts23.isTemplateExpression(init))
3703
3761
  return null;
3704
3762
  let out = init.head.text;
3705
3763
  for (const span of init.templateSpans) {
3706
- if (!ts22.isIdentifier(span.expression))
3764
+ if (!ts23.isIdentifier(span.expression))
3707
3765
  return null;
3708
3766
  const value = resolved.get(span.expression.text);
3709
3767
  if (value === undefined)
@@ -3731,28 +3789,28 @@ function collectModuleStringConsts(constants) {
3731
3789
  return map;
3732
3790
  }
3733
3791
  function evalStringArrayJoin(source) {
3734
- const sf = ts22.createSourceFile("__join.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3792
+ const sf = ts23.createSourceFile("__join.ts", `const __x = (${source});`, ts23.ScriptTarget.Latest, false);
3735
3793
  const stmt = sf.statements[0];
3736
- if (!stmt || !ts22.isVariableStatement(stmt))
3794
+ if (!stmt || !ts23.isVariableStatement(stmt))
3737
3795
  return null;
3738
3796
  let node = stmt.declarationList.declarations[0]?.initializer;
3739
- while (node && ts22.isParenthesizedExpression(node))
3797
+ while (node && ts23.isParenthesizedExpression(node))
3740
3798
  node = node.expression;
3741
- if (!node || !ts22.isCallExpression(node))
3799
+ if (!node || !ts23.isCallExpression(node))
3742
3800
  return null;
3743
3801
  const callee = node.expression;
3744
- if (!ts22.isPropertyAccessExpression(callee))
3802
+ if (!ts23.isPropertyAccessExpression(callee))
3745
3803
  return null;
3746
3804
  if (callee.name.text !== "join")
3747
3805
  return null;
3748
3806
  let recv = callee.expression;
3749
- while (ts22.isParenthesizedExpression(recv))
3807
+ while (ts23.isParenthesizedExpression(recv))
3750
3808
  recv = recv.expression;
3751
- if (!ts22.isArrayLiteralExpression(recv))
3809
+ if (!ts23.isArrayLiteralExpression(recv))
3752
3810
  return null;
3753
3811
  const parts = [];
3754
3812
  for (const el of recv.elements) {
3755
- if (ts22.isStringLiteral(el) || ts22.isNoSubstitutionTemplateLiteral(el)) {
3813
+ if (ts23.isStringLiteral(el) || ts23.isNoSubstitutionTemplateLiteral(el)) {
3756
3814
  parts.push(el.text);
3757
3815
  } else {
3758
3816
  return null;
@@ -3761,7 +3819,7 @@ function evalStringArrayJoin(source) {
3761
3819
  let sep = ",";
3762
3820
  if (node.arguments.length >= 1) {
3763
3821
  const arg = node.arguments[0];
3764
- if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3822
+ if (ts23.isStringLiteral(arg) || ts23.isNoSubstitutionTemplateLiteral(arg))
3765
3823
  sep = arg.text;
3766
3824
  else
3767
3825
  return null;
@@ -3769,11 +3827,11 @@ function evalStringArrayJoin(source) {
3769
3827
  return parts.join(sep);
3770
3828
  }
3771
3829
  function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3772
- if (!ts22.isElementAccessExpression(val))
3830
+ if (!ts23.isElementAccessExpression(val))
3773
3831
  return null;
3774
3832
  const obj = val.expression;
3775
3833
  const arg = val.argumentExpression;
3776
- if (!ts22.isIdentifier(obj) || !ts22.isIdentifier(arg))
3834
+ if (!ts23.isIdentifier(obj) || !ts23.isIdentifier(arg))
3777
3835
  return null;
3778
3836
  let indexPropName;
3779
3837
  let defaultKey;
@@ -3789,35 +3847,35 @@ function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3789
3847
  const constInfo = localConstants.find((c) => c.name === obj.text && c.isModule);
3790
3848
  if (constInfo?.value === undefined)
3791
3849
  return null;
3792
- const sf = ts22.createSourceFile("__rec.ts", `(${constInfo.value})`, ts22.ScriptTarget.Latest, true);
3850
+ const sf = ts23.createSourceFile("__rec.ts", `(${constInfo.value})`, ts23.ScriptTarget.Latest, true);
3793
3851
  if (sf.statements.length !== 1)
3794
3852
  return null;
3795
3853
  const stmt = sf.statements[0];
3796
- if (!ts22.isExpressionStatement(stmt))
3854
+ if (!ts23.isExpressionStatement(stmt))
3797
3855
  return null;
3798
3856
  let parsed = stmt.expression;
3799
- while (ts22.isParenthesizedExpression(parsed))
3857
+ while (ts23.isParenthesizedExpression(parsed))
3800
3858
  parsed = parsed.expression;
3801
- if (!ts22.isObjectLiteralExpression(parsed))
3859
+ if (!ts23.isObjectLiteralExpression(parsed))
3802
3860
  return null;
3803
3861
  const entries = [];
3804
3862
  for (const prop of parsed.properties) {
3805
- if (!ts22.isPropertyAssignment(prop))
3863
+ if (!ts23.isPropertyAssignment(prop))
3806
3864
  return null;
3807
3865
  let key;
3808
- if (ts22.isIdentifier(prop.name)) {
3866
+ if (ts23.isIdentifier(prop.name)) {
3809
3867
  key = prop.name.text;
3810
- } else if (ts22.isStringLiteral(prop.name) || ts22.isNoSubstitutionTemplateLiteral(prop.name)) {
3868
+ } else if (ts23.isStringLiteral(prop.name) || ts23.isNoSubstitutionTemplateLiteral(prop.name)) {
3811
3869
  key = prop.name.text;
3812
3870
  } else {
3813
3871
  return null;
3814
3872
  }
3815
3873
  let v = prop.initializer;
3816
- while (ts22.isParenthesizedExpression(v))
3874
+ while (ts23.isParenthesizedExpression(v))
3817
3875
  v = v.expression;
3818
- if (ts22.isNumericLiteral(v)) {
3876
+ if (ts23.isNumericLiteral(v)) {
3819
3877
  entries.push({ key, value: { kind: "number", text: v.text } });
3820
- } else if (ts22.isStringLiteral(v) || ts22.isNoSubstitutionTemplateLiteral(v)) {
3878
+ } else if (ts23.isStringLiteral(v) || ts23.isNoSubstitutionTemplateLiteral(v)) {
3821
3879
  entries.push({ key, value: { kind: "string", text: v.text } });
3822
3880
  } else {
3823
3881
  return null;
@@ -3873,7 +3931,7 @@ function computeSsrSeedPlan(metadata) {
3873
3931
  // ../jsx/src/rich-type-refusal.ts
3874
3932
  var EMPTY_BINDINGS2 = new Map;
3875
3933
  // ../jsx/src/shared-program.ts
3876
- import ts24 from "typescript";
3934
+ import ts25 from "typescript";
3877
3935
  // ../jsx/src/adapters/interface.ts
3878
3936
  class BaseAdapter {
3879
3937
  renderChildren(children) {
@@ -3926,7 +3984,7 @@ class JsxAdapter extends BaseAdapter {
3926
3984
  ...localFunctions.map((f) => ({ name: f.name, body: f.body })),
3927
3985
  ...localConstants.map((c) => ({ name: c.name, body: c.value }))
3928
3986
  ];
3929
- const reachable = findReachableNames(primaryRefText, declarations);
3987
+ const reachable = closeOverWritersOfMutableBindings(primaryRefText, declarations, new Set(ir.metadata.localConstants.filter((c) => (c.declarationKind ?? "const") !== "const").map((c) => c.name)));
3930
3988
  const reachableBodies = [...reachable].map((name) => {
3931
3989
  const func = localFunctions.find((f) => f.name === name);
3932
3990
  if (func)
@@ -3956,9 +4014,10 @@ class JsxAdapter extends BaseAdapter {
3956
4014
  lines.push(` const ${signal.getter} = () => ${initialValue}`);
3957
4015
  }
3958
4016
  if (signal.setter) {
3959
- const setterUsed = new RegExp(`\\b${signal.setter}\\b`).test(setterRefText);
4017
+ const setterUsed = identifierPattern(signal.setter).test(setterRefText);
3960
4018
  if (setterUsed) {
3961
- lines.push(` const ${signal.setter} = (..._args: any[]) => {}`);
4019
+ const setterType = preserveTypes && signal.type.kind !== "unknown" ? `(valueOrFn: ${signal.type.raw} | ((prev: ${signal.type.raw}) => ${signal.type.raw})) => void` : null;
4020
+ lines.push(setterType ? ` const ${signal.setter}: ${setterType} = () => {}` : ` const ${signal.setter} = (..._args: any[]) => {}`);
3962
4021
  }
3963
4022
  }
3964
4023
  }
@@ -4154,6 +4213,7 @@ class JsxAdapter extends BaseAdapter {
4154
4213
  }
4155
4214
 
4156
4215
  // ../jsx/src/adapters/template-imports.ts
4216
+ import ts26 from "typescript";
4157
4217
  var CLIENT_PACKAGE_SOURCES = new Set([
4158
4218
  "@barefootjs/client",
4159
4219
  "@barefootjs/client/runtime"
@@ -4292,7 +4352,8 @@ export default ${this.componentName}` : "";
4292
4352
  const noArgDefault = hasRequiredProps ? "" : ` = {} as ${propsTypeExpr}`;
4293
4353
  const lines = [];
4294
4354
  const exportPrefix = ir.metadata.isExported === false ? "" : "export ";
4295
- lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
4355
+ const typeParameters = ir.metadata.typeParameters ?? "";
4356
+ lines.push(`${exportPrefix}function ${name}${typeParameters}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
4296
4357
  if (hasClientInteractivity) {
4297
4358
  lines.push(` const __scopeId = (/_s\\d/.test(__bfScope || '') ? __bfScope : null) || __instanceId || \`${name}_\${Math.random().toString(36).slice(2, 8)}\``);
4298
4359
  } else {
@@ -4890,7 +4951,7 @@ function dangerousInnerHtmlDiagnostic(expr, loc, reason) {
4890
4951
  };
4891
4952
  }
4892
4953
  // ../jsx/src/combine-client-js.ts
4893
- import ts25 from "typescript";
4954
+ import ts27 from "typescript";
4894
4955
  // ../jsx/src/loop-destructure.ts
4895
4956
  function isLowerableLoopDestructure(loop) {
4896
4957
  const bindings = loop.paramBindings;
@@ -5030,9 +5091,9 @@ function escapeRe(s) {
5030
5091
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5031
5092
  }
5032
5093
  // ../jsx/src/debug.ts
5033
- import ts26 from "typescript";
5094
+ import ts28 from "typescript";
5034
5095
  // ../jsx/src/profiler.ts
5035
- import ts27 from "typescript";
5096
+ import ts29 from "typescript";
5036
5097
 
5037
5098
  // ../jsx/src/index.ts
5038
5099
  registerBuiltinLoweringPlugins();
@@ -6663,7 +6724,7 @@ function computeObjectMemoInitialValue(ctx, memo) {
6663
6724
  }
6664
6725
 
6665
6726
  // src/adapter/memo/template-interp.ts
6666
- import ts28 from "typescript";
6727
+ import ts30 from "typescript";
6667
6728
  function computeTemplateLiteralMemoInitialValue(ctx, memo, propsParams) {
6668
6729
  const localKeyBindings = new Map;
6669
6730
  let templateValue;
@@ -7294,7 +7355,7 @@ function collectPropsReadByCtorInit(body, propsObjectName, propNames) {
7294
7355
  }
7295
7356
 
7296
7357
  // src/adapter/spread/spread-codegen.ts
7297
- import ts29 from "typescript";
7358
+ import ts31 from "typescript";
7298
7359
  function collectSpreadSlots(ctx, node) {
7299
7360
  const result = [];
7300
7361
  collectSpreadSlotsRecursive(ctx, node, result);
@@ -7529,7 +7590,7 @@ function recordIndexAccessToGoMap(ctx, val, ir) {
7529
7590
  if (val.kind !== "index-access" || val.object.kind !== "identifier" || val.index.kind !== "identifier") {
7530
7591
  return null;
7531
7592
  }
7532
- const tsVal = ts29.factory.createElementAccessExpression(ts29.factory.createIdentifier(val.object.name), ts29.factory.createIdentifier(val.index.name));
7593
+ const tsVal = ts31.factory.createElementAccessExpression(ts31.factory.createIdentifier(val.object.name), ts31.factory.createIdentifier(val.index.name));
7533
7594
  const parsed = parseRecordIndexAccess(tsVal, ir.metadata.localConstants ?? [], ir.metadata.propsParams);
7534
7595
  if (!parsed)
7535
7596
  return null;
@@ -7830,7 +7891,7 @@ class GoTemplateAdapter extends BaseAdapter {
7830
7891
  }
7831
7892
  inLoop = false;
7832
7893
  bakedStaticChildLoopCache = new Map;
7833
- loopParamStack = [];
7894
+ scope = BindingScope.EMPTY;
7834
7895
  loopKeyDepthStack = [];
7835
7896
  loopScalarItemStack = [];
7836
7897
  loopWrapperStack = [];
@@ -7888,6 +7949,7 @@ class GoTemplateAdapter extends BaseAdapter {
7888
7949
  this.state.referencedDerivedConsts = new Set;
7889
7950
  this.state.templateVarCounter = 0;
7890
7951
  this.state.pendingChildrenDefines = [];
7952
+ this.scope = BindingScope.EMPTY;
7891
7953
  this.primeCompileState(ir);
7892
7954
  this.state.stringValueNames = collectStringValueNames(ir);
7893
7955
  this.recordDerivedFieldDeps(ir, new Set((ir.metadata.propsParams ?? []).map((p) => p.name)));
@@ -9437,9 +9499,9 @@ ${goFields.join(`
9437
9499
  }
9438
9500
  }
9439
9501
  const propsObjectName = this.state.propsObjectName;
9440
- const identifierPattern = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
9441
- const bareIdentifier = identifierPattern.test(expr) ? expr : null;
9442
- const barePropAccess = propsObjectName && expr.startsWith(`${propsObjectName}.`) && identifierPattern.test(expr.slice(propsObjectName.length + 1)) ? expr.slice(propsObjectName.length + 1) : null;
9502
+ const identifierPattern2 = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
9503
+ const bareIdentifier = identifierPattern2.test(expr) ? expr : null;
9504
+ const barePropAccess = propsObjectName && expr.startsWith(`${propsObjectName}.`) && identifierPattern2.test(expr.slice(propsObjectName.length + 1)) ? expr.slice(propsObjectName.length + 1) : null;
9443
9505
  const passthroughName = bareIdentifier ?? barePropAccess;
9444
9506
  const localConst = this.state.localConstants.find((c) => c.name === passthroughName);
9445
9507
  const isPropsDestructureAlias = localConst !== undefined && propsObjectName !== null && localConst.value === `${propsObjectName}.${passthroughName}`;
@@ -9768,8 +9830,7 @@ ${goFields.join(`
9768
9830
  const inlinedNum = this.resolveModuleNumericConst(name);
9769
9831
  if (inlinedNum !== null)
9770
9832
  return inlinedNum;
9771
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
9772
- if (currentLoopParam && name === currentLoopParam)
9833
+ if (this.isCurrentLoopItem(name))
9773
9834
  return ".";
9774
9835
  if (this.isOuterLoopParam(name))
9775
9836
  return `$${name}`;
@@ -9836,16 +9897,16 @@ ${goFields.join(`
9836
9897
  }
9837
9898
  return false;
9838
9899
  }
9900
+ isCurrentLoopItem(name) {
9901
+ const hit = this.scope.lookup(name);
9902
+ return hit !== null && hit.depth === 0 && hit.binding.source === "item";
9903
+ }
9839
9904
  isOuterLoopParam(name) {
9840
- const top = this.loopParamStack.length - 1;
9841
- for (let i = 0;i < top; i++) {
9842
- if (this.loopParamStack[i] === name)
9843
- return true;
9844
- }
9845
- return false;
9905
+ const hit = this.scope.lookup(name);
9906
+ return hit !== null && hit.depth > 0 && hit.binding.source === "item";
9846
9907
  }
9847
9908
  rootFieldRef(name) {
9848
- const prefix = this.loopParamStack.length > 0 ? "$." : ".";
9909
+ const prefix = this.inLoop ? "$." : ".";
9849
9910
  return `${prefix}${capitalizeFieldName(name)}`;
9850
9911
  }
9851
9912
  searchParamsFieldRef(name) {
@@ -9855,9 +9916,8 @@ ${goFields.join(`
9855
9916
  return collectModuleStringConsts(constants);
9856
9917
  }
9857
9918
  resolveModuleStringConst(name) {
9858
- if (this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name) {
9919
+ if (this.isCurrentLoopItem(name))
9859
9920
  return null;
9860
- }
9861
9921
  if (this.loopVarRefCount.has(name))
9862
9922
  return null;
9863
9923
  if (this.isOuterLoopParam(name))
@@ -9868,9 +9928,8 @@ ${goFields.join(`
9868
9928
  return `"${escapeGoString(value)}"`;
9869
9929
  }
9870
9930
  resolveModuleNumericConst(name) {
9871
- if (this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name) {
9931
+ if (this.isCurrentLoopItem(name))
9872
9932
  return null;
9873
- }
9874
9933
  if (this.loopVarRefCount.has(name))
9875
9934
  return null;
9876
9935
  if (this.isOuterLoopParam(name))
@@ -9925,7 +9984,7 @@ ${goFields.join(`
9925
9984
  if (property === "length" && object.kind === "call" && object.callee.kind === "identifier" && object.args.length === 0) {
9926
9985
  const slice = this.state.memoBackedLoopSlice.get(object.callee.name);
9927
9986
  if (slice) {
9928
- const prefix = this.loopParamStack.length > 0 ? "$." : ".";
9987
+ const prefix = this.inLoop ? "$." : ".";
9929
9988
  return `len ${prefix}${slice}`;
9930
9989
  }
9931
9990
  }
@@ -9950,8 +10009,7 @@ ${goFields.join(`
9950
10009
  if (staticValue !== null)
9951
10010
  return staticValue;
9952
10011
  }
9953
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
9954
- if (object.kind === "identifier" && currentLoopParam && object.name === currentLoopParam) {
10012
+ if (object.kind === "identifier" && this.isCurrentLoopItem(object.name)) {
9955
10013
  return `.${goFieldNameForKey(property)}`;
9956
10014
  }
9957
10015
  const obj = emit(object);
@@ -10713,7 +10771,7 @@ ${goFields.join(`
10713
10771
  return this.renderParsedExpr(parsed);
10714
10772
  }
10715
10773
  isLoopShadowedName(name) {
10716
- return this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name || this.loopVarRefCount.has(name) || this.isOuterLoopParam(name) || this.loopBindingStack.some((bindings) => bindings.has(name));
10774
+ return this.scope.isBound(name) || this.loopVarRefCount.has(name);
10717
10775
  }
10718
10776
  loopRowChildPropOverrides(comp) {
10719
10777
  const childShape = this.childComponentShapes.get(comp.name);
@@ -10928,8 +10986,7 @@ ${goFields.join(`
10928
10986
  const inlined = this.resolveModuleStringConst(expr.name);
10929
10987
  if (inlined !== null)
10930
10988
  return plain(inlined);
10931
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
10932
- if (currentLoopParam && expr.name === currentLoopParam) {
10989
+ if (this.isCurrentLoopItem(expr.name)) {
10933
10990
  return plain(".");
10934
10991
  }
10935
10992
  if (this.isOuterLoopParam(expr.name)) {
@@ -10986,11 +11043,8 @@ ${goFields.join(`
10986
11043
  if (expr.object.kind === "identifier" && this.state.propsObjectName && expr.object.name === this.state.propsObjectName) {
10987
11044
  return plain(this.rootFieldRef(expr.property));
10988
11045
  }
10989
- {
10990
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
10991
- if (expr.object.kind === "identifier" && currentLoopParam && expr.object.name === currentLoopParam) {
10992
- return plain(`.${capitalizeFieldName(expr.property)}`);
10993
- }
11046
+ if (expr.object.kind === "identifier" && this.isCurrentLoopItem(expr.object.name)) {
11047
+ return plain(`.${capitalizeFieldName(expr.property)}`);
10994
11048
  }
10995
11049
  const obj = this.renderConditionExpr(expr.object);
10996
11050
  if (expr.property === "length") {
@@ -11168,12 +11222,12 @@ ${goFields.join(`
11168
11222
  });
11169
11223
  }
11170
11224
  const bakedChildLoop = loop.childComponent ? this.getBakedStaticChildLoop(loop.markerId, loop.childComponent, loop.arrayParsed, loop.param, loop.key ?? undefined) : null;
11171
- const bakedElementLoop = loop.childComponent ? null : analyzeBakeableStaticElementLoop(loop, this.state.localConstants, { isNameShadowed: (name) => this.state.staticLoopSourceBoundNames.has(name) });
11225
+ const bakedElementLoop = loop.childComponent ? null : analyzeBakeableStaticElementLoop(loop, this.state.localConstants, { isNameShadowed: this.scope.asShadowPredicate() });
11172
11226
  if (bakedElementLoop) {
11173
11227
  return this.renderUnrolledStaticElementLoop(loop, bakedElementLoop.items);
11174
11228
  }
11175
11229
  const arrayName = loop.array.trim();
11176
- if (bakedChildLoop === null && /^[A-Za-z_$][\w$]*$/.test(arrayName)) {
11230
+ if (bakedChildLoop === null && /^[A-Za-z_$][\w$]*$/.test(arrayName) && !this.scope.isBound(arrayName)) {
11177
11231
  const arrayConst = this.state.localConstants.find((c) => c.name === arrayName);
11178
11232
  if (arrayConst && !arrayConst.isModule && arrayConst.parsed && !this.isStringExpr(arrayConst.parsed, new Set)) {
11179
11233
  this.state.errors.push({
@@ -11201,6 +11255,9 @@ ${goFields.join(`
11201
11255
  }
11202
11256
  const wasInLoopOuter = this.inLoop;
11203
11257
  this.inLoop = true;
11258
+ const scopeLoop = loop.iterationShape === "keys" ? { ...loop, param: "" } : loop;
11259
+ const prevScope = this.scope;
11260
+ this.scope = prevScope.enterLoopRow(scopeLoop);
11204
11261
  const addedLoopVars = [];
11205
11262
  for (const d of loop.preamble?.declarations ?? []) {
11206
11263
  this.loopVarRefCount.set(d.name, (this.loopVarRefCount.get(d.name) ?? 0) + 1);
@@ -11212,17 +11269,14 @@ ${goFields.join(`
11212
11269
  this.loopBindingStack.push(built.bindings);
11213
11270
  this.loopRestExcludeStack.push(built.restExcludes);
11214
11271
  pushedBindingMap = true;
11215
- this.loopParamStack.push("");
11216
11272
  if (rangeIndex !== "_") {
11217
11273
  this.loopVarRefCount.set(rangeIndex, (this.loopVarRefCount.get(rangeIndex) ?? 0) + 1);
11218
11274
  addedLoopVars.push(rangeIndex);
11219
11275
  }
11220
11276
  } else if (loop.iterationShape === "keys") {
11221
- this.loopParamStack.push("");
11222
11277
  this.loopVarRefCount.set(param, (this.loopVarRefCount.get(param) ?? 0) + 1);
11223
11278
  addedLoopVars.push(param);
11224
11279
  } else {
11225
- this.loopParamStack.push(param);
11226
11280
  if (rangeIndex !== "_") {
11227
11281
  this.loopVarRefCount.set(rangeIndex, (this.loopVarRefCount.get(rangeIndex) ?? 0) + 1);
11228
11282
  addedLoopVars.push(rangeIndex);
@@ -11244,7 +11298,7 @@ ${goFields.join(`
11244
11298
  else
11245
11299
  this.loopVarRefCount.set(v, rc);
11246
11300
  }
11247
- this.loopParamStack.pop();
11301
+ this.scope = prevScope;
11248
11302
  if (pushedBindingMap) {
11249
11303
  this.loopBindingStack.pop();
11250
11304
  this.loopRestExcludeStack.pop();
@@ -11276,7 +11330,8 @@ ${goFields.join(`
11276
11330
  this.loopWrapperStack.push(false);
11277
11331
  this.loopKeyDepthStack.push(loop.depth);
11278
11332
  this.loopScalarItemStack.push(this.scalarLiteralLoopGoType(loop.arrayParsed, loop.itemType) !== null);
11279
- this.loopParamStack.push(loop.param);
11333
+ const prevScope = this.scope;
11334
+ this.scope = prevScope.enterLoopRow(loop);
11280
11335
  let body = "";
11281
11336
  for (const item of items) {
11282
11337
  this.staticLoopItemStack.push({ param: loop.param, item });
@@ -11296,7 +11351,7 @@ ${goFields.join(`
11296
11351
  break;
11297
11352
  }
11298
11353
  }
11299
- this.loopParamStack.pop();
11354
+ this.scope = prevScope;
11300
11355
  this.loopScalarItemStack.pop();
11301
11356
  this.loopKeyDepthStack.pop();
11302
11357
  this.loopWrapperStack.pop();
@@ -11465,8 +11520,7 @@ ${children}`;
11465
11520
  }
11466
11521
  if (this.inLoop) {
11467
11522
  const trimmed = value.expr.trim();
11468
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
11469
- if (currentLoopParam && trimmed === currentLoopParam) {
11523
+ if (this.isCurrentLoopItem(trimmed)) {
11470
11524
  return `{{bf_spread_attrs (bf_js_keys .)}}`;
11471
11525
  }
11472
11526
  const restInfo = this.lookupRestExclude(trimmed);