@barefootjs/xslate 0.31.4 → 0.31.6

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";
@@ -2527,7 +2527,7 @@ var REACTIVE_PRIMITIVES = new Set([
2527
2527
  ]);
2528
2528
 
2529
2529
  // ../jsx/src/jsx-to-ir.ts
2530
- import ts12 from "typescript";
2530
+ import ts13 from "typescript";
2531
2531
 
2532
2532
  // ../jsx/src/types.ts
2533
2533
  var SCOPE_FORBIDDEN = {
@@ -2577,6 +2577,7 @@ function preambleAnalysisTemplateText(p) {
2577
2577
  }
2578
2578
 
2579
2579
  // ../jsx/src/module-exports.ts
2580
+ import ts10 from "typescript";
2580
2581
  function formatParamWithType(p) {
2581
2582
  const rest = p.isRest ? "..." : "";
2582
2583
  const optional = p.optional ? "?" : "";
@@ -2607,12 +2608,55 @@ function findReachableNames(primaryRefs, declarations) {
2607
2608
  }
2608
2609
  return reachable;
2609
2610
  }
2611
+ function findAssignedNames(bodyText, candidates) {
2612
+ const assigned = new Set;
2613
+ if (candidates.size === 0)
2614
+ return assigned;
2615
+ const sf = ts10.createSourceFile("bf-assignment-scan.tsx", bodyText, ts10.ScriptTarget.Latest, false, ts10.ScriptKind.TSX);
2616
+ const record = (target) => {
2617
+ if (ts10.isIdentifier(target) && candidates.has(target.text)) {
2618
+ assigned.add(target.text);
2619
+ }
2620
+ };
2621
+ const visit = (node) => {
2622
+ if (ts10.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
2623
+ record(node.left);
2624
+ } else if ((ts10.isPrefixUnaryExpression(node) || ts10.isPostfixUnaryExpression(node)) && (node.operator === ts10.SyntaxKind.PlusPlusToken || node.operator === ts10.SyntaxKind.MinusMinusToken)) {
2625
+ record(node.operand);
2626
+ }
2627
+ ts10.forEachChild(node, visit);
2628
+ };
2629
+ ts10.forEachChild(sf, visit);
2630
+ return assigned;
2631
+ }
2632
+ function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNames) {
2633
+ let reachable = findReachableNames(primaryRefs, declarations);
2634
+ if (mutableNames.size === 0)
2635
+ return reachable;
2636
+ let seedText = primaryRefs;
2637
+ for (let round = 0;round <= declarations.length; round++) {
2638
+ const survivingMutables = new Set([...reachable].filter((name) => mutableNames.has(name)));
2639
+ if (survivingMutables.size === 0)
2640
+ return reachable;
2641
+ const added = declarations.filter((d) => !reachable.has(d.name)).filter((d) => findAssignedNames(d.body, survivingMutables).size > 0).map((d) => d.name);
2642
+ if (added.length === 0)
2643
+ return reachable;
2644
+ seedText += `
2645
+ ` + added.join(`
2646
+ `);
2647
+ reachable = findReachableNames(seedText, declarations);
2648
+ }
2649
+ return reachable;
2650
+ }
2651
+ function isAssignmentOperator(kind) {
2652
+ return kind >= ts10.SyntaxKind.FirstAssignment && kind <= ts10.SyntaxKind.LastAssignment;
2653
+ }
2610
2654
 
2611
2655
  // ../jsx/src/reactivity-checker.ts
2612
- import ts10 from "typescript";
2656
+ import ts11 from "typescript";
2613
2657
 
2614
2658
  // ../jsx/src/free-refs.ts
2615
- import ts11 from "typescript";
2659
+ import ts12 from "typescript";
2616
2660
  var _bindingMapCache = new WeakMap;
2617
2661
 
2618
2662
  // ../jsx/src/to-locale-date-lowering.ts
@@ -3026,13 +3070,13 @@ var KEYWORDS_AND_GLOBALS = new Set([
3026
3070
  ]);
3027
3071
 
3028
3072
  // ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
3029
- import ts13 from "typescript";
3073
+ import ts14 from "typescript";
3030
3074
 
3031
3075
  // ../jsx/src/value-references.ts
3032
- import ts14 from "typescript";
3076
+ import ts15 from "typescript";
3033
3077
 
3034
3078
  // ../jsx/src/relocate.ts
3035
- import ts15 from "typescript";
3079
+ import ts16 from "typescript";
3036
3080
 
3037
3081
  // ../jsx/src/lowering-registry.ts
3038
3082
  var plugins = [];
@@ -3249,10 +3293,10 @@ function matchSearchParamsMethodCall(callee, args, localNames) {
3249
3293
  }
3250
3294
 
3251
3295
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3252
- import ts16 from "typescript";
3296
+ import ts17 from "typescript";
3253
3297
 
3254
3298
  // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3255
- import ts17 from "typescript";
3299
+ import ts18 from "typescript";
3256
3300
  var NO_PREAMBLE = {
3257
3301
  lazySafe: true,
3258
3302
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3302,7 +3346,7 @@ var INERT_BINDING_GLOBALS = new Set([
3302
3346
  ]);
3303
3347
 
3304
3348
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
3305
- import ts18 from "typescript";
3349
+ import ts19 from "typescript";
3306
3350
 
3307
3351
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3308
3352
  var NON_BUBBLING_EVENTS = new Set([
@@ -3317,7 +3361,7 @@ var NON_BUBBLING_EVENTS = new Set([
3317
3361
  ]);
3318
3362
 
3319
3363
  // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
3320
- import ts19 from "typescript";
3364
+ import ts20 from "typescript";
3321
3365
 
3322
3366
  // ../jsx/src/ir-to-client-js/source-map.ts
3323
3367
  var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -3408,15 +3452,15 @@ class SourceMapGenerator {
3408
3452
  }
3409
3453
 
3410
3454
  // ../jsx/src/preprocess-inline-jsx-callbacks.ts
3411
- import ts20 from "typescript";
3455
+ import ts21 from "typescript";
3412
3456
 
3413
3457
  // ../jsx/src/ssr-defaults.ts
3414
- import ts21 from "typescript";
3458
+ import ts22 from "typescript";
3415
3459
  var UNRESOLVED = Symbol("unresolved");
3416
3460
  var NO_RETURN = Symbol("no-return");
3417
3461
 
3418
3462
  // ../jsx/src/augment-inherited-props.ts
3419
- import ts22 from "typescript";
3463
+ import ts23 from "typescript";
3420
3464
  function collectContextConsumers(metadata) {
3421
3465
  const constants = metadata.localConstants ?? [];
3422
3466
  const contextDefaults = new Map;
@@ -3448,47 +3492,47 @@ function collectContextConsumers(metadata) {
3448
3492
  }
3449
3493
  function parseUseContextArg(source) {
3450
3494
  const expr = parseSingleExpression(source);
3451
- if (!expr || !ts22.isCallExpression(expr))
3495
+ if (!expr || !ts23.isCallExpression(expr))
3452
3496
  return null;
3453
- if (!ts22.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3497
+ if (!ts23.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3454
3498
  return null;
3455
3499
  if (expr.arguments.length !== 1)
3456
3500
  return null;
3457
3501
  const arg = expr.arguments[0];
3458
- return ts22.isIdentifier(arg) ? arg.text : null;
3502
+ return ts23.isIdentifier(arg) ? arg.text : null;
3459
3503
  }
3460
3504
  function parseCreateContextDefault(source) {
3461
3505
  const expr = parseSingleExpression(source);
3462
- if (!expr || !ts22.isCallExpression(expr))
3506
+ if (!expr || !ts23.isCallExpression(expr))
3463
3507
  return null;
3464
3508
  if (expr.arguments.length === 0)
3465
3509
  return null;
3466
3510
  const arg = expr.arguments[0];
3467
- if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3511
+ if (ts23.isStringLiteral(arg) || ts23.isNoSubstitutionTemplateLiteral(arg))
3468
3512
  return arg.text;
3469
- if (ts22.isNumericLiteral(arg))
3513
+ if (ts23.isNumericLiteral(arg))
3470
3514
  return Number(arg.text);
3471
- if (arg.kind === ts22.SyntaxKind.TrueKeyword)
3515
+ if (arg.kind === ts23.SyntaxKind.TrueKeyword)
3472
3516
  return true;
3473
- if (arg.kind === ts22.SyntaxKind.FalseKeyword)
3517
+ if (arg.kind === ts23.SyntaxKind.FalseKeyword)
3474
3518
  return false;
3475
3519
  return null;
3476
3520
  }
3477
3521
  function isObjectLiteralCreateContextDefault(source) {
3478
3522
  const expr = parseSingleExpression(source);
3479
- if (!expr || !ts22.isCallExpression(expr))
3523
+ if (!expr || !ts23.isCallExpression(expr))
3480
3524
  return false;
3481
3525
  if (expr.arguments.length === 0)
3482
3526
  return false;
3483
- return ts22.isObjectLiteralExpression(expr.arguments[0]);
3527
+ return ts23.isObjectLiteralExpression(expr.arguments[0]);
3484
3528
  }
3485
3529
  function parseSingleExpression(source) {
3486
- const sf = ts22.createSourceFile("__ctx.ts", `(${source})`, ts22.ScriptTarget.Latest, false);
3530
+ const sf = ts23.createSourceFile("__ctx.ts", `(${source})`, ts23.ScriptTarget.Latest, false);
3487
3531
  const stmt = sf.statements[0];
3488
- if (!stmt || !ts22.isExpressionStatement(stmt))
3532
+ if (!stmt || !ts23.isExpressionStatement(stmt))
3489
3533
  return null;
3490
3534
  let e = stmt.expression;
3491
- while (ts22.isParenthesizedExpression(e))
3535
+ while (ts23.isParenthesizedExpression(e))
3492
3536
  e = e.expression;
3493
3537
  return e;
3494
3538
  }
@@ -3513,25 +3557,25 @@ function augmentInheritedPropAccesses(ir) {
3513
3557
  const pinCoalesceLiterals = (s) => {
3514
3558
  if (!s || !s.includes(propsObj))
3515
3559
  return;
3516
- const sf = ts22.createSourceFile("__aug.ts", `(${s})`, ts22.ScriptTarget.Latest, false);
3560
+ const sf = ts23.createSourceFile("__aug.ts", `(${s})`, ts23.ScriptTarget.Latest, false);
3517
3561
  const visit = (n) => {
3518
- if (ts22.isBinaryExpression(n) && (n.operatorToken.kind === ts22.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts22.SyntaxKind.BarBarToken)) {
3562
+ if (ts23.isBinaryExpression(n) && (n.operatorToken.kind === ts23.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts23.SyntaxKind.BarBarToken)) {
3519
3563
  let left = n.left;
3520
- while (ts22.isParenthesizedExpression(left))
3564
+ while (ts23.isParenthesizedExpression(left))
3521
3565
  left = left.expression;
3522
- if (ts22.isPropertyAccessExpression(left) && ts22.isIdentifier(left.expression) && left.expression.text === propsObj) {
3566
+ if (ts23.isPropertyAccessExpression(left) && ts23.isIdentifier(left.expression) && left.expression.text === propsObj) {
3523
3567
  const name = left.name.text;
3524
3568
  let right = n.right;
3525
- while (ts22.isParenthesizedExpression(right))
3569
+ while (ts23.isParenthesizedExpression(right))
3526
3570
  right = right.expression;
3527
- if (ts22.isPrefixUnaryExpression(right))
3571
+ if (ts23.isPrefixUnaryExpression(right))
3528
3572
  right = right.operand;
3529
- const kind = ts22.isNumericLiteral(right) ? "number" : right.kind === ts22.SyntaxKind.TrueKeyword || right.kind === ts22.SyntaxKind.FalseKeyword ? "boolean" : ts22.isStringLiteralLike(right) ? "string" : null;
3573
+ const kind = ts23.isNumericLiteral(right) ? "number" : right.kind === ts23.SyntaxKind.TrueKeyword || right.kind === ts23.SyntaxKind.FalseKeyword ? "boolean" : ts23.isStringLiteralLike(right) ? "string" : null;
3530
3574
  if (kind && !coalesceLiteralTypes.has(name))
3531
3575
  coalesceLiteralTypes.set(name, kind);
3532
3576
  }
3533
3577
  }
3534
- ts22.forEachChild(n, visit);
3578
+ ts23.forEachChild(n, visit);
3535
3579
  };
3536
3580
  visit(sf);
3537
3581
  };
@@ -3642,33 +3686,33 @@ function augmentInheritedPropAccesses(ir) {
3642
3686
  }
3643
3687
  }
3644
3688
  function parseStaticStringConst(source) {
3645
- const sf = ts22.createSourceFile("__const.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3689
+ const sf = ts23.createSourceFile("__const.ts", `const __x = (${source});`, ts23.ScriptTarget.Latest, false);
3646
3690
  const stmt = sf.statements[0];
3647
- if (!stmt || !ts22.isVariableStatement(stmt))
3691
+ if (!stmt || !ts23.isVariableStatement(stmt))
3648
3692
  return null;
3649
3693
  let init = stmt.declarationList.declarations[0]?.initializer;
3650
- while (init && ts22.isParenthesizedExpression(init))
3694
+ while (init && ts23.isParenthesizedExpression(init))
3651
3695
  init = init.expression;
3652
3696
  if (!init)
3653
3697
  return null;
3654
- if (ts22.isStringLiteral(init) || ts22.isNoSubstitutionTemplateLiteral(init)) {
3698
+ if (ts23.isStringLiteral(init) || ts23.isNoSubstitutionTemplateLiteral(init)) {
3655
3699
  return init.text;
3656
3700
  }
3657
3701
  return evalStringArrayJoin(source);
3658
3702
  }
3659
3703
  function evalTemplateOfStringConsts(source, resolved) {
3660
- const sf = ts22.createSourceFile("__const.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3704
+ const sf = ts23.createSourceFile("__const.ts", `const __x = (${source});`, ts23.ScriptTarget.Latest, false);
3661
3705
  const stmt = sf.statements[0];
3662
- if (!stmt || !ts22.isVariableStatement(stmt))
3706
+ if (!stmt || !ts23.isVariableStatement(stmt))
3663
3707
  return null;
3664
3708
  let init = stmt.declarationList.declarations[0]?.initializer;
3665
- while (init && ts22.isParenthesizedExpression(init))
3709
+ while (init && ts23.isParenthesizedExpression(init))
3666
3710
  init = init.expression;
3667
- if (!init || !ts22.isTemplateExpression(init))
3711
+ if (!init || !ts23.isTemplateExpression(init))
3668
3712
  return null;
3669
3713
  let out = init.head.text;
3670
3714
  for (const span of init.templateSpans) {
3671
- if (!ts22.isIdentifier(span.expression))
3715
+ if (!ts23.isIdentifier(span.expression))
3672
3716
  return null;
3673
3717
  const value = resolved.get(span.expression.text);
3674
3718
  if (value === undefined)
@@ -3695,34 +3739,36 @@ function collectModuleStringConsts(constants) {
3695
3739
  }
3696
3740
  return map;
3697
3741
  }
3698
- function lookupStaticRecordLiteral(objectName, key, constants) {
3742
+ function lookupStaticRecordLiteral(objectName, key, constants, isShadowed) {
3743
+ if (isShadowed(objectName))
3744
+ return null;
3699
3745
  const constInfo = (constants ?? []).find((c) => c.name === objectName && c.isModule);
3700
3746
  if (constInfo?.value === undefined)
3701
3747
  return null;
3702
- const sf = ts22.createSourceFile("__rec.ts", `(${constInfo.value})`, ts22.ScriptTarget.Latest, true);
3748
+ const sf = ts23.createSourceFile("__rec.ts", `(${constInfo.value})`, ts23.ScriptTarget.Latest, true);
3703
3749
  if (sf.statements.length !== 1)
3704
3750
  return null;
3705
3751
  const stmt = sf.statements[0];
3706
- if (!ts22.isExpressionStatement(stmt))
3752
+ if (!ts23.isExpressionStatement(stmt))
3707
3753
  return null;
3708
3754
  let parsed = stmt.expression;
3709
- while (ts22.isParenthesizedExpression(parsed))
3755
+ while (ts23.isParenthesizedExpression(parsed))
3710
3756
  parsed = parsed.expression;
3711
- if (!ts22.isObjectLiteralExpression(parsed))
3757
+ if (!ts23.isObjectLiteralExpression(parsed))
3712
3758
  return null;
3713
3759
  for (const prop of parsed.properties) {
3714
- if (!ts22.isPropertyAssignment(prop))
3760
+ if (!ts23.isPropertyAssignment(prop))
3715
3761
  continue;
3716
3762
  const name = prop.name;
3717
- const propKey = ts22.isIdentifier(name) || ts22.isStringLiteral(name) || ts22.isNoSubstitutionTemplateLiteral(name) ? name.text : null;
3763
+ const propKey = ts23.isIdentifier(name) || ts23.isStringLiteral(name) || ts23.isNoSubstitutionTemplateLiteral(name) ? name.text : null;
3718
3764
  if (propKey !== key)
3719
3765
  continue;
3720
3766
  let v = prop.initializer;
3721
- while (ts22.isParenthesizedExpression(v))
3767
+ while (ts23.isParenthesizedExpression(v))
3722
3768
  v = v.expression;
3723
- if (ts22.isNumericLiteral(v))
3769
+ if (ts23.isNumericLiteral(v))
3724
3770
  return { kind: "number", text: v.text };
3725
- if (ts22.isStringLiteral(v) || ts22.isNoSubstitutionTemplateLiteral(v)) {
3771
+ if (ts23.isStringLiteral(v) || ts23.isNoSubstitutionTemplateLiteral(v)) {
3726
3772
  return { kind: "string", text: v.text };
3727
3773
  }
3728
3774
  return null;
@@ -3730,28 +3776,28 @@ function lookupStaticRecordLiteral(objectName, key, constants) {
3730
3776
  return null;
3731
3777
  }
3732
3778
  function evalStringArrayJoin(source) {
3733
- const sf = ts22.createSourceFile("__join.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3779
+ const sf = ts23.createSourceFile("__join.ts", `const __x = (${source});`, ts23.ScriptTarget.Latest, false);
3734
3780
  const stmt = sf.statements[0];
3735
- if (!stmt || !ts22.isVariableStatement(stmt))
3781
+ if (!stmt || !ts23.isVariableStatement(stmt))
3736
3782
  return null;
3737
3783
  let node = stmt.declarationList.declarations[0]?.initializer;
3738
- while (node && ts22.isParenthesizedExpression(node))
3784
+ while (node && ts23.isParenthesizedExpression(node))
3739
3785
  node = node.expression;
3740
- if (!node || !ts22.isCallExpression(node))
3786
+ if (!node || !ts23.isCallExpression(node))
3741
3787
  return null;
3742
3788
  const callee = node.expression;
3743
- if (!ts22.isPropertyAccessExpression(callee))
3789
+ if (!ts23.isPropertyAccessExpression(callee))
3744
3790
  return null;
3745
3791
  if (callee.name.text !== "join")
3746
3792
  return null;
3747
3793
  let recv = callee.expression;
3748
- while (ts22.isParenthesizedExpression(recv))
3794
+ while (ts23.isParenthesizedExpression(recv))
3749
3795
  recv = recv.expression;
3750
- if (!ts22.isArrayLiteralExpression(recv))
3796
+ if (!ts23.isArrayLiteralExpression(recv))
3751
3797
  return null;
3752
3798
  const parts = [];
3753
3799
  for (const el of recv.elements) {
3754
- if (ts22.isStringLiteral(el) || ts22.isNoSubstitutionTemplateLiteral(el)) {
3800
+ if (ts23.isStringLiteral(el) || ts23.isNoSubstitutionTemplateLiteral(el)) {
3755
3801
  parts.push(el.text);
3756
3802
  } else {
3757
3803
  return null;
@@ -3760,7 +3806,7 @@ function evalStringArrayJoin(source) {
3760
3806
  let sep = ",";
3761
3807
  if (node.arguments.length >= 1) {
3762
3808
  const arg = node.arguments[0];
3763
- if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3809
+ if (ts23.isStringLiteral(arg) || ts23.isNoSubstitutionTemplateLiteral(arg))
3764
3810
  sep = arg.text;
3765
3811
  else
3766
3812
  return null;
@@ -3768,11 +3814,11 @@ function evalStringArrayJoin(source) {
3768
3814
  return parts.join(sep);
3769
3815
  }
3770
3816
  function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3771
- if (!ts22.isElementAccessExpression(val))
3817
+ if (!ts23.isElementAccessExpression(val))
3772
3818
  return null;
3773
3819
  const obj = val.expression;
3774
3820
  const arg = val.argumentExpression;
3775
- if (!ts22.isIdentifier(obj) || !ts22.isIdentifier(arg))
3821
+ if (!ts23.isIdentifier(obj) || !ts23.isIdentifier(arg))
3776
3822
  return null;
3777
3823
  let indexPropName;
3778
3824
  let defaultKey;
@@ -3788,35 +3834,35 @@ function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3788
3834
  const constInfo = localConstants.find((c) => c.name === obj.text && c.isModule);
3789
3835
  if (constInfo?.value === undefined)
3790
3836
  return null;
3791
- const sf = ts22.createSourceFile("__rec.ts", `(${constInfo.value})`, ts22.ScriptTarget.Latest, true);
3837
+ const sf = ts23.createSourceFile("__rec.ts", `(${constInfo.value})`, ts23.ScriptTarget.Latest, true);
3792
3838
  if (sf.statements.length !== 1)
3793
3839
  return null;
3794
3840
  const stmt = sf.statements[0];
3795
- if (!ts22.isExpressionStatement(stmt))
3841
+ if (!ts23.isExpressionStatement(stmt))
3796
3842
  return null;
3797
3843
  let parsed = stmt.expression;
3798
- while (ts22.isParenthesizedExpression(parsed))
3844
+ while (ts23.isParenthesizedExpression(parsed))
3799
3845
  parsed = parsed.expression;
3800
- if (!ts22.isObjectLiteralExpression(parsed))
3846
+ if (!ts23.isObjectLiteralExpression(parsed))
3801
3847
  return null;
3802
3848
  const entries = [];
3803
3849
  for (const prop of parsed.properties) {
3804
- if (!ts22.isPropertyAssignment(prop))
3850
+ if (!ts23.isPropertyAssignment(prop))
3805
3851
  return null;
3806
3852
  let key;
3807
- if (ts22.isIdentifier(prop.name)) {
3853
+ if (ts23.isIdentifier(prop.name)) {
3808
3854
  key = prop.name.text;
3809
- } else if (ts22.isStringLiteral(prop.name) || ts22.isNoSubstitutionTemplateLiteral(prop.name)) {
3855
+ } else if (ts23.isStringLiteral(prop.name) || ts23.isNoSubstitutionTemplateLiteral(prop.name)) {
3810
3856
  key = prop.name.text;
3811
3857
  } else {
3812
3858
  return null;
3813
3859
  }
3814
3860
  let v = prop.initializer;
3815
- while (ts22.isParenthesizedExpression(v))
3861
+ while (ts23.isParenthesizedExpression(v))
3816
3862
  v = v.expression;
3817
- if (ts22.isNumericLiteral(v)) {
3863
+ if (ts23.isNumericLiteral(v)) {
3818
3864
  entries.push({ key, value: { kind: "number", text: v.text } });
3819
- } else if (ts22.isStringLiteral(v) || ts22.isNoSubstitutionTemplateLiteral(v)) {
3865
+ } else if (ts23.isStringLiteral(v) || ts23.isNoSubstitutionTemplateLiteral(v)) {
3820
3866
  entries.push({ key, value: { kind: "string", text: v.text } });
3821
3867
  } else {
3822
3868
  return null;
@@ -3872,7 +3918,7 @@ function computeSsrSeedPlan(metadata) {
3872
3918
  // ../jsx/src/rich-type-refusal.ts
3873
3919
  var EMPTY_BINDINGS2 = new Map;
3874
3920
  // ../jsx/src/shared-program.ts
3875
- import ts24 from "typescript";
3921
+ import ts25 from "typescript";
3876
3922
  // ../jsx/src/adapters/interface.ts
3877
3923
  class BaseAdapter {
3878
3924
  renderChildren(children) {
@@ -3925,7 +3971,7 @@ class JsxAdapter extends BaseAdapter {
3925
3971
  ...localFunctions.map((f) => ({ name: f.name, body: f.body })),
3926
3972
  ...localConstants.map((c) => ({ name: c.name, body: c.value }))
3927
3973
  ];
3928
- const reachable = findReachableNames(primaryRefText, declarations);
3974
+ const reachable = closeOverWritersOfMutableBindings(primaryRefText, declarations, new Set(ir.metadata.localConstants.filter((c) => (c.declarationKind ?? "const") !== "const").map((c) => c.name)));
3929
3975
  const reachableBodies = [...reachable].map((name) => {
3930
3976
  const func = localFunctions.find((f) => f.name === name);
3931
3977
  if (func)
@@ -3957,7 +4003,8 @@ class JsxAdapter extends BaseAdapter {
3957
4003
  if (signal.setter) {
3958
4004
  const setterUsed = identifierPattern(signal.setter).test(setterRefText);
3959
4005
  if (setterUsed) {
3960
- lines.push(` const ${signal.setter} = (..._args: any[]) => {}`);
4006
+ const setterType = preserveTypes && signal.type.kind !== "unknown" ? `(valueOrFn: ${signal.type.raw} | ((prev: ${signal.type.raw}) => ${signal.type.raw})) => void` : null;
4007
+ lines.push(setterType ? ` const ${signal.setter}: ${setterType} = () => {}` : ` const ${signal.setter} = (..._args: any[]) => {}`);
3961
4008
  }
3962
4009
  }
3963
4010
  }
@@ -4153,7 +4200,7 @@ class JsxAdapter extends BaseAdapter {
4153
4200
  }
4154
4201
 
4155
4202
  // ../jsx/src/adapters/template-imports.ts
4156
- import ts25 from "typescript";
4203
+ import ts26 from "typescript";
4157
4204
  var CLIENT_PACKAGE_SOURCES = new Set([
4158
4205
  "@barefootjs/client",
4159
4206
  "@barefootjs/client/runtime"
@@ -4292,7 +4339,8 @@ export default ${this.componentName}` : "";
4292
4339
  const noArgDefault = hasRequiredProps ? "" : ` = {} as ${propsTypeExpr}`;
4293
4340
  const lines = [];
4294
4341
  const exportPrefix = ir.metadata.isExported === false ? "" : "export ";
4295
- lines.push(`${exportPrefix}function ${name}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
4342
+ const typeParameters = ir.metadata.typeParameters ?? "";
4343
+ lines.push(`${exportPrefix}function ${name}${typeParameters}(${fullPropsDestructure}${typeAnnotation}${noArgDefault}) {`);
4296
4344
  if (hasClientInteractivity) {
4297
4345
  lines.push(` const __scopeId = (/_s\\d/.test(__bfScope || '') ? __bfScope : null) || __instanceId || \`${name}_\${Math.random().toString(36).slice(2, 8)}\``);
4298
4346
  } else {
@@ -4917,7 +4965,7 @@ function dangerousInnerHtmlDiagnostic(expr, loc, reason) {
4917
4965
  };
4918
4966
  }
4919
4967
  // ../jsx/src/combine-client-js.ts
4920
- import ts26 from "typescript";
4968
+ import ts27 from "typescript";
4921
4969
  // ../jsx/src/loop-destructure.ts
4922
4970
  function isLowerableLoopDestructure(loop) {
4923
4971
  const bindings = loop.paramBindings;
@@ -5057,9 +5105,9 @@ function escapeRe(s) {
5057
5105
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5058
5106
  }
5059
5107
  // ../jsx/src/debug.ts
5060
- import ts27 from "typescript";
5061
- // ../jsx/src/profiler.ts
5062
5108
  import ts28 from "typescript";
5109
+ // ../jsx/src/profiler.ts
5110
+ import ts29 from "typescript";
5063
5111
 
5064
5112
  // ../jsx/src/index.ts
5065
5113
  registerBuiltinLoweringPlugins();
@@ -5830,7 +5878,7 @@ function collectImportedLoopChildComponentErrors(ir, componentName) {
5830
5878
  }
5831
5879
 
5832
5880
  // src/adapter/spread/spread-codegen.ts
5833
- import ts29 from "typescript";
5881
+ import ts30 from "typescript";
5834
5882
  function conditionalSpreadToKolon(ctx, expr) {
5835
5883
  if (!expr || expr.kind !== "conditional")
5836
5884
  return null;
@@ -5885,7 +5933,7 @@ function recordIndexAccessToKolon(ctx, val) {
5885
5933
  if (val.kind !== "index-access" || val.object.kind !== "identifier" || val.index.kind !== "identifier") {
5886
5934
  return null;
5887
5935
  }
5888
- const tsVal = ts29.factory.createElementAccessExpression(ts29.factory.createIdentifier(val.object.name), ts29.factory.createIdentifier(val.index.name));
5936
+ const tsVal = ts30.factory.createElementAccessExpression(ts30.factory.createIdentifier(val.object.name), ts30.factory.createIdentifier(val.index.name));
5889
5937
  const parsed = parseRecordIndexAccess(tsVal, ctx.localConstants ?? [], ctx.propsParams);
5890
5938
  if (!parsed)
5891
5939
  return null;
@@ -6002,8 +6050,7 @@ class XslateAdapter extends BaseAdapter {
6002
6050
  _searchParamsLocals = new Set;
6003
6051
  _loweringMatchers = [];
6004
6052
  localConstants = [];
6005
- staticLoopSourceBoundNames = new Set;
6006
- loopBoundNames = new Map;
6053
+ scope = BindingScope.EMPTY;
6007
6054
  nullableOptionalProps = new Set;
6008
6055
  constructor(options = {}) {
6009
6056
  super();
@@ -6019,8 +6066,7 @@ class XslateAdapter extends BaseAdapter {
6019
6066
  this.propsParams = ir.metadata.propsParams.map((p) => ({ name: p.name }));
6020
6067
  this.booleanTypedProps = collectBooleanTypedProps(ir);
6021
6068
  this.localConstants = ir.metadata.localConstants ?? [];
6022
- this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
6023
- this.loopBoundNames.clear();
6069
+ this.scope = BindingScope.EMPTY;
6024
6070
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
6025
6071
  this.stringValueNames = collectStringValueNames(ir);
6026
6072
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -6303,7 +6349,7 @@ ${whenTrue}
6303
6349
  });
6304
6350
  }
6305
6351
  const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
6306
- isNameShadowed: (name) => this.staticLoopSourceBoundNames.has(name)
6352
+ isNameShadowed: this.scope.asShadowPredicate()
6307
6353
  });
6308
6354
  const staticArray = staticItems !== null ? staticValueToKolon(staticItems) : null;
6309
6355
  const arrayName = loop.array.trim();
@@ -6316,7 +6362,8 @@ ${whenTrue}
6316
6362
  message: `Loop array \`${arrayName}\` is a local computed value (\`${arrayConst.value}\`) that the Xslate adapter cannot bind as a template variable — only numeric/string-literal locals inline at their use site.`,
6317
6363
  loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
6318
6364
  suggestion: {
6319
- message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client."
6365
+ message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client.",
6366
+ escape: [{ kind: "prop-precompute" }, { kind: "client-directive" }]
6320
6367
  }
6321
6368
  });
6322
6369
  }
@@ -6360,40 +6407,15 @@ ${whenTrue}
6360
6407
  this.inLoop = true;
6361
6408
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
6362
6409
  this.currentLoopKeyDepth = loop.depth;
6410
+ const prevScope = this.scope;
6411
+ this.scope = prevScope.enterLoopRow(loop);
6363
6412
  const preambleLines = (loop.preamble?.declarations ?? []).map((d) => `: my $${d.name} = ${this.convertExpressionToKolon(d.raw, d.valueParsed)};`);
6364
- const loopBound = [];
6365
- if (loop.objectIteration === "entries") {
6366
- loopBound.push("__bf_pair", loop.index ?? param, param);
6367
- } else if (loop.objectIteration === "keys" || loop.objectIteration === "values") {
6368
- loopBound.push(param);
6369
- } else if (loop.iterationShape === "keys") {
6370
- loopBound.push("__bf_item", param);
6371
- } else if (supportableDestructure) {
6372
- loopBound.push("__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name));
6373
- if (loop.index)
6374
- loopBound.push(loop.index);
6375
- } else {
6376
- loopBound.push(param);
6377
- if (loop.index)
6378
- loopBound.push(loop.index);
6379
- }
6380
- for (const d of loop.preamble?.declarations ?? [])
6381
- loopBound.push(d.name);
6382
- for (const n of loopBound) {
6383
- this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
6384
- }
6385
6413
  const childrenUnderLoop = this.renderChildren(loop.children);
6386
- for (const n of loopBound) {
6387
- const c = (this.loopBoundNames.get(n) ?? 1) - 1;
6388
- if (c <= 0)
6389
- this.loopBoundNames.delete(n);
6390
- else
6391
- this.loopBoundNames.set(n, c);
6392
- }
6393
6414
  this.currentLoopKeyDepth = prevLoopKeyDepth;
6394
6415
  this.inLoop = prevInLoop;
6395
6416
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `<: $bf.comment("loop-i:" ~ ${this.convertExpressionToKolon(loop.key)}) | mark_raw :>
6396
6417
  ${childrenUnderLoop}` : childrenUnderLoop;
6418
+ this.scope = prevScope;
6397
6419
  const lines = [];
6398
6420
  lines.push(`<: $bf.comment("loop:${loop.markerId}") | mark_raw :>`);
6399
6421
  const forHeader = loop.objectIteration === "entries" ? `: for ${array}.kv() -> $${loopVar} {` : loop.objectIteration === "keys" ? `: for ${array}.keys() -> $${loopVar} {` : loop.objectIteration === "values" ? `: for ${array}.values() -> $${loopVar} {` : `: for ${array} -> $${loopVar} {`;
@@ -6623,7 +6645,7 @@ ${name}="<: ${val} :>"
6623
6645
  if (ternaryHashref !== null) {
6624
6646
  return `<: $bf.spread_attrs(${ternaryHashref}) | mark_raw :>`;
6625
6647
  }
6626
- if (/^[A-Za-z_$][\w$]*$/.test(trimmed) && !this.loopBoundNames.has(trimmed)) {
6648
+ if (/^[A-Za-z_$][\w$]*$/.test(trimmed) && !this.scope.isBound(trimmed)) {
6627
6649
  const localConst = (this.localConstants ?? []).find((c) => c.name === trimmed && !c.isModule);
6628
6650
  if (localConst?.value !== undefined) {
6629
6651
  const initTrimmed = localConst.value.trim();
@@ -6847,10 +6869,10 @@ Options:
6847
6869
  return this.booleanTypedProps.has(bare);
6848
6870
  }
6849
6871
  isLoopBoundName(name) {
6850
- return this.loopBoundNames.has(name);
6872
+ return this.scope.isBound(name);
6851
6873
  }
6852
6874
  _resolveLiteralConst(name) {
6853
- if (this.staticLoopSourceBoundNames.has(name))
6875
+ if (this.scope.isBound(name))
6854
6876
  return null;
6855
6877
  const c = (this.localConstants ?? []).find((lc) => lc.name === name);
6856
6878
  if (c?.value === undefined)
@@ -6864,9 +6886,7 @@ Options:
6864
6886
  return null;
6865
6887
  }
6866
6888
  _resolveStaticRecordLiteral(objectName, key) {
6867
- if (this.staticLoopSourceBoundNames.has(objectName))
6868
- return null;
6869
- const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants);
6889
+ const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants, (name) => this.scope.isBound(name));
6870
6890
  if (!hit)
6871
6891
  return null;
6872
6892
  return hit.kind === "number" ? hit.text : `'${hit.text.replace(/[\\']/g, (m) => `\\${m}`)}'`;
@@ -1,5 +1,5 @@
1
1
  package BarefootJS::Backend::Xslate;
2
- our $VERSION = "0.31.3";
2
+ our $VERSION = "0.31.5";
3
3
  use strict;
4
4
  use warnings;
5
5
  use utf8;