@barefootjs/go-template 0.31.4 → 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";
@@ -2597,7 +2597,7 @@ var REACTIVE_PRIMITIVES = new Set([
2597
2597
  ]);
2598
2598
 
2599
2599
  // ../jsx/src/jsx-to-ir.ts
2600
- import ts12 from "typescript";
2600
+ import ts13 from "typescript";
2601
2601
 
2602
2602
  // ../jsx/src/types.ts
2603
2603
  var SCOPE_FORBIDDEN = {
@@ -2647,6 +2647,7 @@ function preambleAnalysisTemplateText(p) {
2647
2647
  }
2648
2648
 
2649
2649
  // ../jsx/src/module-exports.ts
2650
+ import ts10 from "typescript";
2650
2651
  function formatParamWithType(p) {
2651
2652
  const rest = p.isRest ? "..." : "";
2652
2653
  const optional = p.optional ? "?" : "";
@@ -2677,12 +2678,55 @@ function findReachableNames(primaryRefs, declarations) {
2677
2678
  }
2678
2679
  return reachable;
2679
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
+ }
2680
2724
 
2681
2725
  // ../jsx/src/reactivity-checker.ts
2682
- import ts10 from "typescript";
2726
+ import ts11 from "typescript";
2683
2727
 
2684
2728
  // ../jsx/src/free-refs.ts
2685
- import ts11 from "typescript";
2729
+ import ts12 from "typescript";
2686
2730
  var _bindingMapCache = new WeakMap;
2687
2731
 
2688
2732
  // ../jsx/src/to-locale-date-lowering.ts
@@ -3096,13 +3140,13 @@ var KEYWORDS_AND_GLOBALS = new Set([
3096
3140
  ]);
3097
3141
 
3098
3142
  // ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
3099
- import ts13 from "typescript";
3143
+ import ts14 from "typescript";
3100
3144
 
3101
3145
  // ../jsx/src/value-references.ts
3102
- import ts14 from "typescript";
3146
+ import ts15 from "typescript";
3103
3147
 
3104
3148
  // ../jsx/src/relocate.ts
3105
- import ts15 from "typescript";
3149
+ import ts16 from "typescript";
3106
3150
 
3107
3151
  // ../jsx/src/lowering-registry.ts
3108
3152
  var plugins = [];
@@ -3298,10 +3342,10 @@ function formatDateLocalNames(metadata) {
3298
3342
  }
3299
3343
 
3300
3344
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3301
- import ts16 from "typescript";
3345
+ import ts17 from "typescript";
3302
3346
 
3303
3347
  // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3304
- import ts17 from "typescript";
3348
+ import ts18 from "typescript";
3305
3349
  var NO_PREAMBLE = {
3306
3350
  lazySafe: true,
3307
3351
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3351,7 +3395,7 @@ var INERT_BINDING_GLOBALS = new Set([
3351
3395
  ]);
3352
3396
 
3353
3397
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
3354
- import ts18 from "typescript";
3398
+ import ts19 from "typescript";
3355
3399
 
3356
3400
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3357
3401
  var NON_BUBBLING_EVENTS = new Set([
@@ -3366,7 +3410,7 @@ var NON_BUBBLING_EVENTS = new Set([
3366
3410
  ]);
3367
3411
 
3368
3412
  // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
3369
- import ts19 from "typescript";
3413
+ import ts20 from "typescript";
3370
3414
 
3371
3415
  // ../jsx/src/ir-to-client-js/source-map.ts
3372
3416
  var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -3457,15 +3501,15 @@ class SourceMapGenerator {
3457
3501
  }
3458
3502
 
3459
3503
  // ../jsx/src/preprocess-inline-jsx-callbacks.ts
3460
- import ts20 from "typescript";
3504
+ import ts21 from "typescript";
3461
3505
 
3462
3506
  // ../jsx/src/ssr-defaults.ts
3463
- import ts21 from "typescript";
3507
+ import ts22 from "typescript";
3464
3508
  var UNRESOLVED = Symbol("unresolved");
3465
3509
  var NO_RETURN = Symbol("no-return");
3466
3510
 
3467
3511
  // ../jsx/src/augment-inherited-props.ts
3468
- import ts22 from "typescript";
3512
+ import ts23 from "typescript";
3469
3513
  function collectContextConsumers(metadata) {
3470
3514
  const constants = metadata.localConstants ?? [];
3471
3515
  const contextDefaults = new Map;
@@ -3497,47 +3541,47 @@ function collectContextConsumers(metadata) {
3497
3541
  }
3498
3542
  function parseUseContextArg(source) {
3499
3543
  const expr = parseSingleExpression(source);
3500
- if (!expr || !ts22.isCallExpression(expr))
3544
+ if (!expr || !ts23.isCallExpression(expr))
3501
3545
  return null;
3502
- if (!ts22.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3546
+ if (!ts23.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3503
3547
  return null;
3504
3548
  if (expr.arguments.length !== 1)
3505
3549
  return null;
3506
3550
  const arg = expr.arguments[0];
3507
- return ts22.isIdentifier(arg) ? arg.text : null;
3551
+ return ts23.isIdentifier(arg) ? arg.text : null;
3508
3552
  }
3509
3553
  function parseCreateContextDefault(source) {
3510
3554
  const expr = parseSingleExpression(source);
3511
- if (!expr || !ts22.isCallExpression(expr))
3555
+ if (!expr || !ts23.isCallExpression(expr))
3512
3556
  return null;
3513
3557
  if (expr.arguments.length === 0)
3514
3558
  return null;
3515
3559
  const arg = expr.arguments[0];
3516
- if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3560
+ if (ts23.isStringLiteral(arg) || ts23.isNoSubstitutionTemplateLiteral(arg))
3517
3561
  return arg.text;
3518
- if (ts22.isNumericLiteral(arg))
3562
+ if (ts23.isNumericLiteral(arg))
3519
3563
  return Number(arg.text);
3520
- if (arg.kind === ts22.SyntaxKind.TrueKeyword)
3564
+ if (arg.kind === ts23.SyntaxKind.TrueKeyword)
3521
3565
  return true;
3522
- if (arg.kind === ts22.SyntaxKind.FalseKeyword)
3566
+ if (arg.kind === ts23.SyntaxKind.FalseKeyword)
3523
3567
  return false;
3524
3568
  return null;
3525
3569
  }
3526
3570
  function isObjectLiteralCreateContextDefault(source) {
3527
3571
  const expr = parseSingleExpression(source);
3528
- if (!expr || !ts22.isCallExpression(expr))
3572
+ if (!expr || !ts23.isCallExpression(expr))
3529
3573
  return false;
3530
3574
  if (expr.arguments.length === 0)
3531
3575
  return false;
3532
- return ts22.isObjectLiteralExpression(expr.arguments[0]);
3576
+ return ts23.isObjectLiteralExpression(expr.arguments[0]);
3533
3577
  }
3534
3578
  function parseSingleExpression(source) {
3535
- const sf = ts22.createSourceFile("__ctx.ts", `(${source})`, ts22.ScriptTarget.Latest, false);
3579
+ const sf = ts23.createSourceFile("__ctx.ts", `(${source})`, ts23.ScriptTarget.Latest, false);
3536
3580
  const stmt = sf.statements[0];
3537
- if (!stmt || !ts22.isExpressionStatement(stmt))
3581
+ if (!stmt || !ts23.isExpressionStatement(stmt))
3538
3582
  return null;
3539
3583
  let e = stmt.expression;
3540
- while (ts22.isParenthesizedExpression(e))
3584
+ while (ts23.isParenthesizedExpression(e))
3541
3585
  e = e.expression;
3542
3586
  return e;
3543
3587
  }
@@ -3562,25 +3606,25 @@ function augmentInheritedPropAccesses(ir) {
3562
3606
  const pinCoalesceLiterals = (s) => {
3563
3607
  if (!s || !s.includes(propsObj))
3564
3608
  return;
3565
- const sf = ts22.createSourceFile("__aug.ts", `(${s})`, ts22.ScriptTarget.Latest, false);
3609
+ const sf = ts23.createSourceFile("__aug.ts", `(${s})`, ts23.ScriptTarget.Latest, false);
3566
3610
  const visit = (n) => {
3567
- 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)) {
3568
3612
  let left = n.left;
3569
- while (ts22.isParenthesizedExpression(left))
3613
+ while (ts23.isParenthesizedExpression(left))
3570
3614
  left = left.expression;
3571
- 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) {
3572
3616
  const name = left.name.text;
3573
3617
  let right = n.right;
3574
- while (ts22.isParenthesizedExpression(right))
3618
+ while (ts23.isParenthesizedExpression(right))
3575
3619
  right = right.expression;
3576
- if (ts22.isPrefixUnaryExpression(right))
3620
+ if (ts23.isPrefixUnaryExpression(right))
3577
3621
  right = right.operand;
3578
- 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;
3579
3623
  if (kind && !coalesceLiteralTypes.has(name))
3580
3624
  coalesceLiteralTypes.set(name, kind);
3581
3625
  }
3582
3626
  }
3583
- ts22.forEachChild(n, visit);
3627
+ ts23.forEachChild(n, visit);
3584
3628
  };
3585
3629
  visit(sf);
3586
3630
  };
@@ -3691,33 +3735,33 @@ function augmentInheritedPropAccesses(ir) {
3691
3735
  }
3692
3736
  }
3693
3737
  function parseStaticStringConst(source) {
3694
- 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);
3695
3739
  const stmt = sf.statements[0];
3696
- if (!stmt || !ts22.isVariableStatement(stmt))
3740
+ if (!stmt || !ts23.isVariableStatement(stmt))
3697
3741
  return null;
3698
3742
  let init = stmt.declarationList.declarations[0]?.initializer;
3699
- while (init && ts22.isParenthesizedExpression(init))
3743
+ while (init && ts23.isParenthesizedExpression(init))
3700
3744
  init = init.expression;
3701
3745
  if (!init)
3702
3746
  return null;
3703
- if (ts22.isStringLiteral(init) || ts22.isNoSubstitutionTemplateLiteral(init)) {
3747
+ if (ts23.isStringLiteral(init) || ts23.isNoSubstitutionTemplateLiteral(init)) {
3704
3748
  return init.text;
3705
3749
  }
3706
3750
  return evalStringArrayJoin(source);
3707
3751
  }
3708
3752
  function evalTemplateOfStringConsts(source, resolved) {
3709
- 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);
3710
3754
  const stmt = sf.statements[0];
3711
- if (!stmt || !ts22.isVariableStatement(stmt))
3755
+ if (!stmt || !ts23.isVariableStatement(stmt))
3712
3756
  return null;
3713
3757
  let init = stmt.declarationList.declarations[0]?.initializer;
3714
- while (init && ts22.isParenthesizedExpression(init))
3758
+ while (init && ts23.isParenthesizedExpression(init))
3715
3759
  init = init.expression;
3716
- if (!init || !ts22.isTemplateExpression(init))
3760
+ if (!init || !ts23.isTemplateExpression(init))
3717
3761
  return null;
3718
3762
  let out = init.head.text;
3719
3763
  for (const span of init.templateSpans) {
3720
- if (!ts22.isIdentifier(span.expression))
3764
+ if (!ts23.isIdentifier(span.expression))
3721
3765
  return null;
3722
3766
  const value = resolved.get(span.expression.text);
3723
3767
  if (value === undefined)
@@ -3745,28 +3789,28 @@ function collectModuleStringConsts(constants) {
3745
3789
  return map;
3746
3790
  }
3747
3791
  function evalStringArrayJoin(source) {
3748
- 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);
3749
3793
  const stmt = sf.statements[0];
3750
- if (!stmt || !ts22.isVariableStatement(stmt))
3794
+ if (!stmt || !ts23.isVariableStatement(stmt))
3751
3795
  return null;
3752
3796
  let node = stmt.declarationList.declarations[0]?.initializer;
3753
- while (node && ts22.isParenthesizedExpression(node))
3797
+ while (node && ts23.isParenthesizedExpression(node))
3754
3798
  node = node.expression;
3755
- if (!node || !ts22.isCallExpression(node))
3799
+ if (!node || !ts23.isCallExpression(node))
3756
3800
  return null;
3757
3801
  const callee = node.expression;
3758
- if (!ts22.isPropertyAccessExpression(callee))
3802
+ if (!ts23.isPropertyAccessExpression(callee))
3759
3803
  return null;
3760
3804
  if (callee.name.text !== "join")
3761
3805
  return null;
3762
3806
  let recv = callee.expression;
3763
- while (ts22.isParenthesizedExpression(recv))
3807
+ while (ts23.isParenthesizedExpression(recv))
3764
3808
  recv = recv.expression;
3765
- if (!ts22.isArrayLiteralExpression(recv))
3809
+ if (!ts23.isArrayLiteralExpression(recv))
3766
3810
  return null;
3767
3811
  const parts = [];
3768
3812
  for (const el of recv.elements) {
3769
- if (ts22.isStringLiteral(el) || ts22.isNoSubstitutionTemplateLiteral(el)) {
3813
+ if (ts23.isStringLiteral(el) || ts23.isNoSubstitutionTemplateLiteral(el)) {
3770
3814
  parts.push(el.text);
3771
3815
  } else {
3772
3816
  return null;
@@ -3775,7 +3819,7 @@ function evalStringArrayJoin(source) {
3775
3819
  let sep = ",";
3776
3820
  if (node.arguments.length >= 1) {
3777
3821
  const arg = node.arguments[0];
3778
- if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3822
+ if (ts23.isStringLiteral(arg) || ts23.isNoSubstitutionTemplateLiteral(arg))
3779
3823
  sep = arg.text;
3780
3824
  else
3781
3825
  return null;
@@ -3783,11 +3827,11 @@ function evalStringArrayJoin(source) {
3783
3827
  return parts.join(sep);
3784
3828
  }
3785
3829
  function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3786
- if (!ts22.isElementAccessExpression(val))
3830
+ if (!ts23.isElementAccessExpression(val))
3787
3831
  return null;
3788
3832
  const obj = val.expression;
3789
3833
  const arg = val.argumentExpression;
3790
- if (!ts22.isIdentifier(obj) || !ts22.isIdentifier(arg))
3834
+ if (!ts23.isIdentifier(obj) || !ts23.isIdentifier(arg))
3791
3835
  return null;
3792
3836
  let indexPropName;
3793
3837
  let defaultKey;
@@ -3803,35 +3847,35 @@ function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3803
3847
  const constInfo = localConstants.find((c) => c.name === obj.text && c.isModule);
3804
3848
  if (constInfo?.value === undefined)
3805
3849
  return null;
3806
- 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);
3807
3851
  if (sf.statements.length !== 1)
3808
3852
  return null;
3809
3853
  const stmt = sf.statements[0];
3810
- if (!ts22.isExpressionStatement(stmt))
3854
+ if (!ts23.isExpressionStatement(stmt))
3811
3855
  return null;
3812
3856
  let parsed = stmt.expression;
3813
- while (ts22.isParenthesizedExpression(parsed))
3857
+ while (ts23.isParenthesizedExpression(parsed))
3814
3858
  parsed = parsed.expression;
3815
- if (!ts22.isObjectLiteralExpression(parsed))
3859
+ if (!ts23.isObjectLiteralExpression(parsed))
3816
3860
  return null;
3817
3861
  const entries = [];
3818
3862
  for (const prop of parsed.properties) {
3819
- if (!ts22.isPropertyAssignment(prop))
3863
+ if (!ts23.isPropertyAssignment(prop))
3820
3864
  return null;
3821
3865
  let key;
3822
- if (ts22.isIdentifier(prop.name)) {
3866
+ if (ts23.isIdentifier(prop.name)) {
3823
3867
  key = prop.name.text;
3824
- } else if (ts22.isStringLiteral(prop.name) || ts22.isNoSubstitutionTemplateLiteral(prop.name)) {
3868
+ } else if (ts23.isStringLiteral(prop.name) || ts23.isNoSubstitutionTemplateLiteral(prop.name)) {
3825
3869
  key = prop.name.text;
3826
3870
  } else {
3827
3871
  return null;
3828
3872
  }
3829
3873
  let v = prop.initializer;
3830
- while (ts22.isParenthesizedExpression(v))
3874
+ while (ts23.isParenthesizedExpression(v))
3831
3875
  v = v.expression;
3832
- if (ts22.isNumericLiteral(v)) {
3876
+ if (ts23.isNumericLiteral(v)) {
3833
3877
  entries.push({ key, value: { kind: "number", text: v.text } });
3834
- } else if (ts22.isStringLiteral(v) || ts22.isNoSubstitutionTemplateLiteral(v)) {
3878
+ } else if (ts23.isStringLiteral(v) || ts23.isNoSubstitutionTemplateLiteral(v)) {
3835
3879
  entries.push({ key, value: { kind: "string", text: v.text } });
3836
3880
  } else {
3837
3881
  return null;
@@ -3887,7 +3931,7 @@ function computeSsrSeedPlan(metadata) {
3887
3931
  // ../jsx/src/rich-type-refusal.ts
3888
3932
  var EMPTY_BINDINGS2 = new Map;
3889
3933
  // ../jsx/src/shared-program.ts
3890
- import ts24 from "typescript";
3934
+ import ts25 from "typescript";
3891
3935
  // ../jsx/src/adapters/interface.ts
3892
3936
  class BaseAdapter {
3893
3937
  renderChildren(children) {
@@ -3940,7 +3984,7 @@ class JsxAdapter extends BaseAdapter {
3940
3984
  ...localFunctions.map((f) => ({ name: f.name, body: f.body })),
3941
3985
  ...localConstants.map((c) => ({ name: c.name, body: c.value }))
3942
3986
  ];
3943
- 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)));
3944
3988
  const reachableBodies = [...reachable].map((name) => {
3945
3989
  const func = localFunctions.find((f) => f.name === name);
3946
3990
  if (func)
@@ -3972,7 +4016,8 @@ class JsxAdapter extends BaseAdapter {
3972
4016
  if (signal.setter) {
3973
4017
  const setterUsed = identifierPattern(signal.setter).test(setterRefText);
3974
4018
  if (setterUsed) {
3975
- 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[]) => {}`);
3976
4021
  }
3977
4022
  }
3978
4023
  }
@@ -4168,7 +4213,7 @@ class JsxAdapter extends BaseAdapter {
4168
4213
  }
4169
4214
 
4170
4215
  // ../jsx/src/adapters/template-imports.ts
4171
- import ts25 from "typescript";
4216
+ import ts26 from "typescript";
4172
4217
  var CLIENT_PACKAGE_SOURCES = new Set([
4173
4218
  "@barefootjs/client",
4174
4219
  "@barefootjs/client/runtime"
@@ -4307,7 +4352,8 @@ export default ${this.componentName}` : "";
4307
4352
  const noArgDefault = hasRequiredProps ? "" : ` = {} as ${propsTypeExpr}`;
4308
4353
  const lines = [];
4309
4354
  const exportPrefix = ir.metadata.isExported === false ? "" : "export ";
4310
- lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
4355
+ const typeParameters = ir.metadata.typeParameters ?? "";
4356
+ lines.push(`${exportPrefix}function ${name}${typeParameters}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
4311
4357
  if (hasClientInteractivity) {
4312
4358
  lines.push(` const __scopeId = (/_s\\d/.test(__bfScope || '') ? __bfScope : null) || __instanceId || \`${name}_\${Math.random().toString(36).slice(2, 8)}\``);
4313
4359
  } else {
@@ -4905,7 +4951,7 @@ function dangerousInnerHtmlDiagnostic(expr, loc, reason) {
4905
4951
  };
4906
4952
  }
4907
4953
  // ../jsx/src/combine-client-js.ts
4908
- import ts26 from "typescript";
4954
+ import ts27 from "typescript";
4909
4955
  // ../jsx/src/loop-destructure.ts
4910
4956
  function isLowerableLoopDestructure(loop) {
4911
4957
  const bindings = loop.paramBindings;
@@ -5045,9 +5091,9 @@ function escapeRe(s) {
5045
5091
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5046
5092
  }
5047
5093
  // ../jsx/src/debug.ts
5048
- import ts27 from "typescript";
5049
- // ../jsx/src/profiler.ts
5050
5094
  import ts28 from "typescript";
5095
+ // ../jsx/src/profiler.ts
5096
+ import ts29 from "typescript";
5051
5097
 
5052
5098
  // ../jsx/src/index.ts
5053
5099
  registerBuiltinLoweringPlugins();
@@ -6678,7 +6724,7 @@ function computeObjectMemoInitialValue(ctx, memo) {
6678
6724
  }
6679
6725
 
6680
6726
  // src/adapter/memo/template-interp.ts
6681
- import ts29 from "typescript";
6727
+ import ts30 from "typescript";
6682
6728
  function computeTemplateLiteralMemoInitialValue(ctx, memo, propsParams) {
6683
6729
  const localKeyBindings = new Map;
6684
6730
  let templateValue;
@@ -7309,7 +7355,7 @@ function collectPropsReadByCtorInit(body, propsObjectName, propNames) {
7309
7355
  }
7310
7356
 
7311
7357
  // src/adapter/spread/spread-codegen.ts
7312
- import ts30 from "typescript";
7358
+ import ts31 from "typescript";
7313
7359
  function collectSpreadSlots(ctx, node) {
7314
7360
  const result = [];
7315
7361
  collectSpreadSlotsRecursive(ctx, node, result);
@@ -7544,7 +7590,7 @@ function recordIndexAccessToGoMap(ctx, val, ir) {
7544
7590
  if (val.kind !== "index-access" || val.object.kind !== "identifier" || val.index.kind !== "identifier") {
7545
7591
  return null;
7546
7592
  }
7547
- const tsVal = ts30.factory.createElementAccessExpression(ts30.factory.createIdentifier(val.object.name), ts30.factory.createIdentifier(val.index.name));
7593
+ const tsVal = ts31.factory.createElementAccessExpression(ts31.factory.createIdentifier(val.object.name), ts31.factory.createIdentifier(val.index.name));
7548
7594
  const parsed = parseRecordIndexAccess(tsVal, ir.metadata.localConstants ?? [], ir.metadata.propsParams);
7549
7595
  if (!parsed)
7550
7596
  return null;
@@ -7845,7 +7891,7 @@ class GoTemplateAdapter extends BaseAdapter {
7845
7891
  }
7846
7892
  inLoop = false;
7847
7893
  bakedStaticChildLoopCache = new Map;
7848
- loopParamStack = [];
7894
+ scope = BindingScope.EMPTY;
7849
7895
  loopKeyDepthStack = [];
7850
7896
  loopScalarItemStack = [];
7851
7897
  loopWrapperStack = [];
@@ -7903,6 +7949,7 @@ class GoTemplateAdapter extends BaseAdapter {
7903
7949
  this.state.referencedDerivedConsts = new Set;
7904
7950
  this.state.templateVarCounter = 0;
7905
7951
  this.state.pendingChildrenDefines = [];
7952
+ this.scope = BindingScope.EMPTY;
7906
7953
  this.primeCompileState(ir);
7907
7954
  this.state.stringValueNames = collectStringValueNames(ir);
7908
7955
  this.recordDerivedFieldDeps(ir, new Set((ir.metadata.propsParams ?? []).map((p) => p.name)));
@@ -9783,8 +9830,7 @@ ${goFields.join(`
9783
9830
  const inlinedNum = this.resolveModuleNumericConst(name);
9784
9831
  if (inlinedNum !== null)
9785
9832
  return inlinedNum;
9786
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
9787
- if (currentLoopParam && name === currentLoopParam)
9833
+ if (this.isCurrentLoopItem(name))
9788
9834
  return ".";
9789
9835
  if (this.isOuterLoopParam(name))
9790
9836
  return `$${name}`;
@@ -9851,16 +9897,16 @@ ${goFields.join(`
9851
9897
  }
9852
9898
  return false;
9853
9899
  }
9900
+ isCurrentLoopItem(name) {
9901
+ const hit = this.scope.lookup(name);
9902
+ return hit !== null && hit.depth === 0 && hit.binding.source === "item";
9903
+ }
9854
9904
  isOuterLoopParam(name) {
9855
- const top = this.loopParamStack.length - 1;
9856
- for (let i = 0;i < top; i++) {
9857
- if (this.loopParamStack[i] === name)
9858
- return true;
9859
- }
9860
- return false;
9905
+ const hit = this.scope.lookup(name);
9906
+ return hit !== null && hit.depth > 0 && hit.binding.source === "item";
9861
9907
  }
9862
9908
  rootFieldRef(name) {
9863
- const prefix = this.loopParamStack.length > 0 ? "$." : ".";
9909
+ const prefix = this.inLoop ? "$." : ".";
9864
9910
  return `${prefix}${capitalizeFieldName(name)}`;
9865
9911
  }
9866
9912
  searchParamsFieldRef(name) {
@@ -9870,9 +9916,8 @@ ${goFields.join(`
9870
9916
  return collectModuleStringConsts(constants);
9871
9917
  }
9872
9918
  resolveModuleStringConst(name) {
9873
- if (this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name) {
9919
+ if (this.isCurrentLoopItem(name))
9874
9920
  return null;
9875
- }
9876
9921
  if (this.loopVarRefCount.has(name))
9877
9922
  return null;
9878
9923
  if (this.isOuterLoopParam(name))
@@ -9883,9 +9928,8 @@ ${goFields.join(`
9883
9928
  return `"${escapeGoString(value)}"`;
9884
9929
  }
9885
9930
  resolveModuleNumericConst(name) {
9886
- if (this.loopParamStack.length > 0 && this.loopParamStack[this.loopParamStack.length - 1] === name) {
9931
+ if (this.isCurrentLoopItem(name))
9887
9932
  return null;
9888
- }
9889
9933
  if (this.loopVarRefCount.has(name))
9890
9934
  return null;
9891
9935
  if (this.isOuterLoopParam(name))
@@ -9940,7 +9984,7 @@ ${goFields.join(`
9940
9984
  if (property === "length" && object.kind === "call" && object.callee.kind === "identifier" && object.args.length === 0) {
9941
9985
  const slice = this.state.memoBackedLoopSlice.get(object.callee.name);
9942
9986
  if (slice) {
9943
- const prefix = this.loopParamStack.length > 0 ? "$." : ".";
9987
+ const prefix = this.inLoop ? "$." : ".";
9944
9988
  return `len ${prefix}${slice}`;
9945
9989
  }
9946
9990
  }
@@ -9965,8 +10009,7 @@ ${goFields.join(`
9965
10009
  if (staticValue !== null)
9966
10010
  return staticValue;
9967
10011
  }
9968
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
9969
- if (object.kind === "identifier" && currentLoopParam && object.name === currentLoopParam) {
10012
+ if (object.kind === "identifier" && this.isCurrentLoopItem(object.name)) {
9970
10013
  return `.${goFieldNameForKey(property)}`;
9971
10014
  }
9972
10015
  const obj = emit(object);
@@ -10728,7 +10771,7 @@ ${goFields.join(`
10728
10771
  return this.renderParsedExpr(parsed);
10729
10772
  }
10730
10773
  isLoopShadowedName(name) {
10731
- 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);
10732
10775
  }
10733
10776
  loopRowChildPropOverrides(comp) {
10734
10777
  const childShape = this.childComponentShapes.get(comp.name);
@@ -10943,8 +10986,7 @@ ${goFields.join(`
10943
10986
  const inlined = this.resolveModuleStringConst(expr.name);
10944
10987
  if (inlined !== null)
10945
10988
  return plain(inlined);
10946
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
10947
- if (currentLoopParam && expr.name === currentLoopParam) {
10989
+ if (this.isCurrentLoopItem(expr.name)) {
10948
10990
  return plain(".");
10949
10991
  }
10950
10992
  if (this.isOuterLoopParam(expr.name)) {
@@ -11001,11 +11043,8 @@ ${goFields.join(`
11001
11043
  if (expr.object.kind === "identifier" && this.state.propsObjectName && expr.object.name === this.state.propsObjectName) {
11002
11044
  return plain(this.rootFieldRef(expr.property));
11003
11045
  }
11004
- {
11005
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
11006
- if (expr.object.kind === "identifier" && currentLoopParam && expr.object.name === currentLoopParam) {
11007
- return plain(`.${capitalizeFieldName(expr.property)}`);
11008
- }
11046
+ if (expr.object.kind === "identifier" && this.isCurrentLoopItem(expr.object.name)) {
11047
+ return plain(`.${capitalizeFieldName(expr.property)}`);
11009
11048
  }
11010
11049
  const obj = this.renderConditionExpr(expr.object);
11011
11050
  if (expr.property === "length") {
@@ -11183,12 +11222,12 @@ ${goFields.join(`
11183
11222
  });
11184
11223
  }
11185
11224
  const bakedChildLoop = loop.childComponent ? this.getBakedStaticChildLoop(loop.markerId, loop.childComponent, loop.arrayParsed, loop.param, loop.key ?? undefined) : null;
11186
- 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() });
11187
11226
  if (bakedElementLoop) {
11188
11227
  return this.renderUnrolledStaticElementLoop(loop, bakedElementLoop.items);
11189
11228
  }
11190
11229
  const arrayName = loop.array.trim();
11191
- if (bakedChildLoop === null && /^[A-Za-z_$][\w$]*$/.test(arrayName)) {
11230
+ if (bakedChildLoop === null && /^[A-Za-z_$][\w$]*$/.test(arrayName) && !this.scope.isBound(arrayName)) {
11192
11231
  const arrayConst = this.state.localConstants.find((c) => c.name === arrayName);
11193
11232
  if (arrayConst && !arrayConst.isModule && arrayConst.parsed && !this.isStringExpr(arrayConst.parsed, new Set)) {
11194
11233
  this.state.errors.push({
@@ -11216,6 +11255,9 @@ ${goFields.join(`
11216
11255
  }
11217
11256
  const wasInLoopOuter = this.inLoop;
11218
11257
  this.inLoop = true;
11258
+ const scopeLoop = loop.iterationShape === "keys" ? { ...loop, param: "" } : loop;
11259
+ const prevScope = this.scope;
11260
+ this.scope = prevScope.enterLoopRow(scopeLoop);
11219
11261
  const addedLoopVars = [];
11220
11262
  for (const d of loop.preamble?.declarations ?? []) {
11221
11263
  this.loopVarRefCount.set(d.name, (this.loopVarRefCount.get(d.name) ?? 0) + 1);
@@ -11227,17 +11269,14 @@ ${goFields.join(`
11227
11269
  this.loopBindingStack.push(built.bindings);
11228
11270
  this.loopRestExcludeStack.push(built.restExcludes);
11229
11271
  pushedBindingMap = true;
11230
- this.loopParamStack.push("");
11231
11272
  if (rangeIndex !== "_") {
11232
11273
  this.loopVarRefCount.set(rangeIndex, (this.loopVarRefCount.get(rangeIndex) ?? 0) + 1);
11233
11274
  addedLoopVars.push(rangeIndex);
11234
11275
  }
11235
11276
  } else if (loop.iterationShape === "keys") {
11236
- this.loopParamStack.push("");
11237
11277
  this.loopVarRefCount.set(param, (this.loopVarRefCount.get(param) ?? 0) + 1);
11238
11278
  addedLoopVars.push(param);
11239
11279
  } else {
11240
- this.loopParamStack.push(param);
11241
11280
  if (rangeIndex !== "_") {
11242
11281
  this.loopVarRefCount.set(rangeIndex, (this.loopVarRefCount.get(rangeIndex) ?? 0) + 1);
11243
11282
  addedLoopVars.push(rangeIndex);
@@ -11259,7 +11298,7 @@ ${goFields.join(`
11259
11298
  else
11260
11299
  this.loopVarRefCount.set(v, rc);
11261
11300
  }
11262
- this.loopParamStack.pop();
11301
+ this.scope = prevScope;
11263
11302
  if (pushedBindingMap) {
11264
11303
  this.loopBindingStack.pop();
11265
11304
  this.loopRestExcludeStack.pop();
@@ -11291,7 +11330,8 @@ ${goFields.join(`
11291
11330
  this.loopWrapperStack.push(false);
11292
11331
  this.loopKeyDepthStack.push(loop.depth);
11293
11332
  this.loopScalarItemStack.push(this.scalarLiteralLoopGoType(loop.arrayParsed, loop.itemType) !== null);
11294
- this.loopParamStack.push(loop.param);
11333
+ const prevScope = this.scope;
11334
+ this.scope = prevScope.enterLoopRow(loop);
11295
11335
  let body = "";
11296
11336
  for (const item of items) {
11297
11337
  this.staticLoopItemStack.push({ param: loop.param, item });
@@ -11311,7 +11351,7 @@ ${goFields.join(`
11311
11351
  break;
11312
11352
  }
11313
11353
  }
11314
- this.loopParamStack.pop();
11354
+ this.scope = prevScope;
11315
11355
  this.loopScalarItemStack.pop();
11316
11356
  this.loopKeyDepthStack.pop();
11317
11357
  this.loopWrapperStack.pop();
@@ -11480,8 +11520,7 @@ ${children}`;
11480
11520
  }
11481
11521
  if (this.inLoop) {
11482
11522
  const trimmed = value.expr.trim();
11483
- const currentLoopParam = this.loopParamStack[this.loopParamStack.length - 1];
11484
- if (currentLoopParam && trimmed === currentLoopParam) {
11523
+ if (this.isCurrentLoopItem(trimmed)) {
11485
11524
  return `{{bf_spread_attrs (bf_js_keys .)}}`;
11486
11525
  }
11487
11526
  const restInfo = this.lookupRestExclude(trimmed);