@barefootjs/cli 0.31.2 → 0.31.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +230 -34
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -6164,7 +6164,8 @@ function visit(node, ctx2, targetComponentName, namedExports) {
6164
6164
  if (!ctx2.componentNode) {
6165
6165
  collectAmbientGlobals(node, ctx2);
6166
6166
  }
6167
- if (ts9.isVariableStatement(node) && !ctx2.componentNode) {
6167
+ const isDeclareStatement = ts9.isVariableStatement(node) && (node.modifiers?.some((m) => m.kind === ts9.SyntaxKind.DeclareKeyword) ?? false);
6168
+ if (ts9.isVariableStatement(node) && !ctx2.componentNode && !isDeclareStatement) {
6168
6169
  const isExported = node.modifiers?.some((m) => m.kind === ts9.SyntaxKind.ExportKeyword) ?? false;
6169
6170
  const isLet = (node.declarationList.flags & ts9.NodeFlags.Let) !== 0;
6170
6171
  const isModuleClientDirective = hasLeadingClientDirectiveOnStatement(node, ctx2.sourceFile);
@@ -6180,7 +6181,7 @@ function visit(node, ctx2, targetComponentName, namedExports) {
6180
6181
  }
6181
6182
  continue;
6182
6183
  }
6183
- if (ts9.isIdentifier(decl.name) && decl.initializer && !isArrowComponentFunction(decl)) {
6184
+ if (ts9.isIdentifier(decl.name) && (decl.initializer || isLet) && !isArrowComponentFunction(decl)) {
6184
6185
  collectConstant(decl, ctx2, true, isLet ? "let" : "const", isExported);
6185
6186
  }
6186
6187
  }
@@ -7590,6 +7591,7 @@ function collectConstant(node, ctx2, _isModule, declarationKind = "const", isExp
7590
7591
  value: value2,
7591
7592
  parsed,
7592
7593
  typedValue: typedValue !== value2 ? typedValue : void 0,
7594
+ typeAnnotation: node.type ? node.type.getText(ctx2.sourceFile) : void 0,
7593
7595
  valueBranches,
7594
7596
  declarationKind,
7595
7597
  isExported,
@@ -9982,6 +9984,176 @@ var init_to_locale_date_lowering = __esm({
9982
9984
  }
9983
9985
  });
9984
9986
 
9987
+ // ../jsx/src/scope/binding-scope.ts
9988
+ var BindingScope;
9989
+ var init_binding_scope = __esm({
9990
+ "../jsx/src/scope/binding-scope.ts"() {
9991
+ "use strict";
9992
+ BindingScope = class _BindingScope {
9993
+ constructor(frames2) {
9994
+ this.frames = frames2;
9995
+ }
9996
+ static EMPTY = new _BindingScope([]);
9997
+ /**
9998
+ * Child scope with a new `'loop-row'` frame for one loop's per-item
9999
+ * bindings. Parent (`this`) is not mutated; the returned scope is a
10000
+ * NEW object with `frames = [newFrame, ...this.frames]`.
10001
+ *
10002
+ * Binding semantics mirror `jsx-to-ir.ts`'s `ctx.loopParams` add site
10003
+ * EXACTLY (verified against lines ~4320-4345 and the matching delete
10004
+ * site ~4695-4710 of `packages/jsx/src/jsx-to-ir.ts`):
10005
+ *
10006
+ * - When `loop.paramBindings` is non-empty (a destructured callback
10007
+ * param, e.g. `.map(({ id, name }) => ...)`), each `paramBindings[i].name`
10008
+ * is bound with source `'destructure'` and the raw `param` text
10009
+ * (which for a destructured callback holds the ORIGINAL pattern
10010
+ * source, e.g. `"{ id, name }"`, not a usable identifier) is NOT
10011
+ * bound. This matches `jsx-to-ir.ts`:
10012
+ * `if (paramBindings) { for (const b of paramBindings) ctx.loopParams.add(b.name) }`
10013
+ * — the `else` branch (`ctx.loopParams.add(param)`) is skipped
10014
+ * entirely when `paramBindings` is present.
10015
+ * - Otherwise (a plain identifier param, e.g. `.map(item => ...)`),
10016
+ * `param` itself is bound with source `'item'`.
10017
+ * - `index` (the second callback param, e.g. `.map((item, i) => ...)`)
10018
+ * is bound with source `'index'` when non-null/non-undefined.
10019
+ * - Every name in `preamble.declaredNames` (a `.map()` callback's
10020
+ * pre-return `const`/`let`/`function` locals, #2447) is bound with
10021
+ * source `'preamble'`.
10022
+ *
10023
+ * NOTE on a sibling mechanism this method does NOT mirror:
10024
+ * `adapters/loop-bound-names.ts`'s `collectLoopBoundNames` adds BOTH
10025
+ * `node.param` AND every `paramBindings[i].name` unconditionally
10026
+ * (never skipping `param` in the destructured case) — a deliberately
10027
+ * coarser, over-inclusive collection used only to subtract names from
10028
+ * a flat string-typing Set (safe to over-exclude there). This method
10029
+ * follows the precise `jsx-to-ir.ts` `ctx.loopParams` semantics, since
10030
+ * that is the mechanism actually doing scope-shadowed name RESOLUTION
10031
+ * (the behavior `BindingScope` replaces), not coarse exclusion.
10032
+ */
10033
+ enterLoopRow(loop) {
10034
+ const bindings = /* @__PURE__ */ new Map();
10035
+ if (loop.paramBindings && loop.paramBindings.length > 0) {
10036
+ for (const b of loop.paramBindings) bindings.set(b.name, { source: "destructure" });
10037
+ } else {
10038
+ bindings.set(loop.param, { source: "item" });
10039
+ }
10040
+ if (loop.index != null) bindings.set(loop.index, { source: "index" });
10041
+ for (const name2 of loop.preamble?.declaredNames ?? []) bindings.set(name2, { source: "preamble" });
10042
+ const frame = { kind: "loop-row", bindings };
10043
+ return new _BindingScope([frame, ...this.frames]);
10044
+ }
10045
+ /**
10046
+ * Child scope with a new `'callback'` frame binding `params` (a filter
10047
+ * predicate's `x`, a sort comparator's `(a, b)`, or a nested arrow's
10048
+ * parameter list) with source `'param'`. Parent is not mutated.
10049
+ */
10050
+ enterCallback(params) {
10051
+ const bindings = /* @__PURE__ */ new Map();
10052
+ for (const name2 of params) bindings.set(name2, { source: "param" });
10053
+ const frame = { kind: "callback", bindings };
10054
+ return new _BindingScope([frame, ...this.frames]);
10055
+ }
10056
+ /** Innermost-first membership check across every frame in the stack. */
10057
+ isBound(name2) {
10058
+ for (const frame of this.frames) {
10059
+ if (frame.bindings.has(name2)) return true;
10060
+ }
10061
+ return false;
10062
+ }
10063
+ /**
10064
+ * Resolves `name` against the frame stack innermost-first. `depth 0`
10065
+ * means the innermost (most recently entered) frame; `null` when `name`
10066
+ * is not bound in any frame.
10067
+ */
10068
+ lookup(name2) {
10069
+ for (let depth = 0; depth < this.frames.length; depth++) {
10070
+ const frame = this.frames[depth];
10071
+ const binding = frame.bindings.get(name2);
10072
+ if (binding) return { depth, frame, binding };
10073
+ }
10074
+ return null;
10075
+ }
10076
+ /**
10077
+ * Union of every frame's bound names (every `ScopeBindingSource`), for
10078
+ * migration interop with legacy `Set<string>`-shaped consumers (e.g.
10079
+ * `collectLoopBoundNames`'s return type) as later stages migrate them
10080
+ * onto `BindingScope`.
10081
+ *
10082
+ * This is the SHADOW-GUARD query — see {@link valueBoundNames} for the
10083
+ * other consumer class and why the two must not be conflated.
10084
+ */
10085
+ boundNames() {
10086
+ if (this.boundNamesCache) return this.boundNamesCache;
10087
+ const names = /* @__PURE__ */ new Set();
10088
+ for (const frame of this.frames) {
10089
+ for (const name2 of frame.bindings.keys()) names.add(name2);
10090
+ }
10091
+ this.boundNamesCache = names;
10092
+ return names;
10093
+ }
10094
+ // Both name queries are hot (shadow guards, slot/reactivity classifiers,
10095
+ // binding-env memo keying) and the scope is immutable, so each computes
10096
+ // once per instance. Callers receive the cached set as ReadonlySet —
10097
+ // never mutate it.
10098
+ boundNamesCache;
10099
+ valueBoundNamesCache;
10100
+ /**
10101
+ * Union of names bound via `'item'`/`'index'`/`'destructure'` sources
10102
+ * only — the loop row's own per-item identity — excluding `'preamble'`
10103
+ * (a `.map()` callback's pre-return `const`/`let`/`function` locals,
10104
+ * #2447) and `'param'` (an `enterCallback` frame's filter/sort/nested-
10105
+ * arrow parameters).
10106
+ *
10107
+ * `BindingScope` has exactly two consumer classes, and conflating them
10108
+ * is the #2482 Stage 1a Commit 2 regression this split exists to
10109
+ * prevent (a `ctx.scope`-wide preamble merge flipped `tag-cloud` and
10110
+ * `preamble-cells` conformance fixtures before this method existed):
10111
+ *
10112
+ * - SHADOW GUARDS (`tryResolveTemplateSpanFromConst`,
10113
+ * `tryResolveIdentifierAsTemplateLiteral`, `rewriteBarePropRefs`
10114
+ * in `jsx-to-ir.ts`) ask "is this name resolved to SOMETHING in
10115
+ * this scope, so an outer const/prop of the same name must not be
10116
+ * substituted here at this transform position" — every source
10117
+ * qualifies, including a preamble local shadowing a module const.
10118
+ * These call `isBound` / `boundNames()`.
10119
+ * - REACTIVITY / SLOT-ID CLASSIFIERS (`referencesLoopParam`,
10120
+ * `hasReactiveAttributes`, and the `BindingEnvironment.loopParams`
10121
+ * feed built from `makeBindingEnv`, all in `jsx-to-ir.ts`) ask
10122
+ * "does this expression read a value that changes per row and so
10123
+ * needs its own patchable slot" — a preamble local already gets
10124
+ * ITS OWN dedicated slot/region-patch machinery
10125
+ * (`preambleRegions` / `markPreambleAttrSlots`, #2447), so folding
10126
+ * it into this classification double-counts it. Worse: widening a
10127
+ * text child's `reactive` flag this way is read by
10128
+ * `hasDynamicContent` to decide whether the loop ROW's own root
10129
+ * element needs a slot — an unrelated, narrower decision that must
10130
+ * not move just because a preamble local is now scope-visible.
10131
+ * These call `valueBoundNames()`.
10132
+ */
10133
+ valueBoundNames() {
10134
+ if (this.valueBoundNamesCache) return this.valueBoundNamesCache;
10135
+ const names = /* @__PURE__ */ new Set();
10136
+ for (const frame of this.frames) {
10137
+ for (const [name2, binding] of frame.bindings) {
10138
+ if (binding.source === "item" || binding.source === "index" || binding.source === "destructure") {
10139
+ names.add(name2);
10140
+ }
10141
+ }
10142
+ }
10143
+ this.valueBoundNamesCache = names;
10144
+ return names;
10145
+ }
10146
+ /**
10147
+ * Drop-in for `resolveStaticLoopSource`'s `opts.isNameShadowed`
10148
+ * (`packages/jsx/src/static-literal.ts:112-128`).
10149
+ */
10150
+ asShadowPredicate() {
10151
+ return (name2) => this.isBound(name2);
10152
+ }
10153
+ };
10154
+ }
10155
+ });
10156
+
9985
10157
  // ../jsx/src/jsx-to-ir.ts
9986
10158
  import ts12 from "typescript";
9987
10159
  function hasLeadingClientDirective(expr, sourceFile) {
@@ -10151,8 +10323,9 @@ function rewriteBarePropRefs2(text, expr, ctx2) {
10151
10323
  const dateLowered = lowerToLocaleDateCalls(lowerDateCalls(text, expr, ctx2), expr, ctx2);
10152
10324
  let propNames = getDestructuredPropNames(ctx2);
10153
10325
  if (!propNames) return dateLowered === text ? void 0 : dateLowered;
10154
- if (ctx2.loopParams.size > 0) {
10155
- const filtered = new Set([...propNames].filter((n) => !ctx2.loopParams.has(n)));
10326
+ const shadowingNames = ctx2.scope.boundNames();
10327
+ if (shadowingNames.size > 0) {
10328
+ const filtered = new Set([...propNames].filter((n) => !shadowingNames.has(n)));
10156
10329
  if (filtered.size === 0) return dateLowered === text ? void 0 : dateLowered;
10157
10330
  propNames = filtered;
10158
10331
  }
@@ -10220,7 +10393,7 @@ function createTransformContext(analyzer) {
10220
10393
  spreadIdCounter: 0,
10221
10394
  isRoot: true,
10222
10395
  insideComponentChildren: false,
10223
- loopParams: /* @__PURE__ */ new Set(),
10396
+ scope: BindingScope.EMPTY,
10224
10397
  loopDepth: 0,
10225
10398
  patterns: {
10226
10399
  signals: analyzer.signals.map((s) => ({
@@ -10289,7 +10462,8 @@ function generateSpreadSlotId(ctx2) {
10289
10462
  return `Spread_${ctx2.spreadIdCounter++}`;
10290
10463
  }
10291
10464
  function makeBindingEnv(ctx2) {
10292
- const loopKey = ctx2.loopParams.size === 0 ? "" : Array.from(ctx2.loopParams).sort().join("\0");
10465
+ const boundNames = ctx2.scope.valueBoundNames();
10466
+ const loopKey = boundNames.size === 0 ? "" : Array.from(boundNames).sort().join("\0");
10293
10467
  if (ctx2._bindingEnv && ctx2._bindingEnvLoopKey === loopKey) {
10294
10468
  return ctx2._bindingEnv;
10295
10469
  }
@@ -10304,9 +10478,11 @@ function makeBindingEnv(ctx2) {
10304
10478
  localFunctions: a.localFunctions,
10305
10479
  imports: a.imports,
10306
10480
  ambientGlobals: a.ambientGlobals,
10307
- // Snapshot the env must observe a stable view even if `ctx.loopParams`
10308
- // is later mutated by an enclosing visitor frame.
10309
- loopParams: new Set(ctx2.loopParams),
10481
+ // `valueBoundNames()` returns a per-instance set that is never
10482
+ // mutated (cached on the immutable `BindingScope`) a stable
10483
+ // snapshot even if `ctx.scope` is later reassigned by an enclosing
10484
+ // visitor frame, which swaps the instance rather than mutating it.
10485
+ loopParams: boundNames,
10310
10486
  checker: a.checker
10311
10487
  };
10312
10488
  ctx2._bindingEnv = env;
@@ -11003,7 +11179,8 @@ function transformExpressionInner(expr, ctx2, node, isClientOnly) {
11003
11179
  freeRefs
11004
11180
  };
11005
11181
  const reactive = isReactiveExpression(exprText, ctx2, expr) || isReactiveOrigin(origin);
11006
- const refsLoopParam = ctx2.loopParams.size > 0 && Array.from(ctx2.loopParams).some((p) => new RegExp(`\\b${p}\\b`).test(exprText));
11182
+ const scopeValueNames = ctx2.scope.valueBoundNames();
11183
+ const refsLoopParam = scopeValueNames.size > 0 && Array.from(scopeValueNames).some((p) => new RegExp(`\\b${p}\\b`).test(exprText));
11007
11184
  const callsReactive = exprCallsReactiveGetters(expr, ctx2);
11008
11185
  const hasCalls = exprHasFunctionCalls(expr);
11009
11186
  const needsSlot = reactive || isClientOnly || refsLoopParam || callsReactive || hasCalls;
@@ -12055,7 +12232,7 @@ function extractItemConditionalKey(cond) {
12055
12232
  return a ?? b;
12056
12233
  }
12057
12234
  function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
12058
- const isNested = ctx2.loopParams.size > 0;
12235
+ const isNested = ctx2.scope.valueBoundNames().size > 0;
12059
12236
  const diagCountAtEntry = ctx2.analyzer.errors.length;
12060
12237
  const depth = ctx2.loopDepth;
12061
12238
  const propAccess = node.expression;
@@ -12250,12 +12427,8 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
12250
12427
  indexType = secondParam.type.getText(ctx2.sourceFile);
12251
12428
  }
12252
12429
  }
12253
- if (paramBindings) {
12254
- for (const b of paramBindings) ctx2.loopParams.add(b.name);
12255
- } else {
12256
- ctx2.loopParams.add(param);
12257
- }
12258
- if (index) ctx2.loopParams.add(index);
12430
+ const savedScope = ctx2.scope;
12431
+ ctx2.scope = ctx2.scope.enterLoopRow({ param, index, paramBindings });
12259
12432
  ctx2.loopDepth++;
12260
12433
  const tryTransformRenderableBody = (expr) => {
12261
12434
  if (!ts12.isBinaryExpression(expr)) return;
@@ -12317,6 +12490,23 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
12317
12490
  const returnStmt = children2.length === 0 ? body2.statements.find(
12318
12491
  (s) => ts12.isReturnStatement(s) && s.expression != null
12319
12492
  ) : void 0;
12493
+ let rowScopeBeforePreamble = null;
12494
+ if (returnStmt) {
12495
+ const preambleNames = /* @__PURE__ */ new Set();
12496
+ for (const stmt of body2.statements) {
12497
+ if (stmt === returnStmt) break;
12498
+ collectPreambleDeclaredNames(stmt, preambleNames);
12499
+ }
12500
+ if (preambleNames.size > 0) {
12501
+ rowScopeBeforePreamble = ctx2.scope;
12502
+ ctx2.scope = savedScope.enterLoopRow({
12503
+ param,
12504
+ index,
12505
+ paramBindings,
12506
+ preamble: { declaredNames: [...preambleNames] }
12507
+ });
12508
+ }
12509
+ }
12320
12510
  if (returnStmt && returnStmt.expression) {
12321
12511
  let returnExpr = returnStmt.expression;
12322
12512
  while (ts12.isParenthesizedExpression(returnExpr)) {
@@ -12408,6 +12598,9 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
12408
12598
  }
12409
12599
  }
12410
12600
  }
12601
+ if (rowScopeBeforePreamble) {
12602
+ ctx2.scope = rowScopeBeforePreamble;
12603
+ }
12411
12604
  if (method2 === "flatMap" && children2.length === 0 && !flatMapProjectionCall(body2)) {
12412
12605
  flatMapCallback = buildFlatMapCallback(callback, body2, ctx2);
12413
12606
  }
@@ -12441,12 +12634,7 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
12441
12634
  )
12442
12635
  );
12443
12636
  }
12444
- if (paramBindings) {
12445
- for (const b of paramBindings) ctx2.loopParams.delete(b.name);
12446
- } else {
12447
- ctx2.loopParams.delete(param);
12448
- }
12449
- if (index) ctx2.loopParams.delete(index);
12637
+ ctx2.scope = savedScope;
12450
12638
  ctx2.loopDepth--;
12451
12639
  }
12452
12640
  if (children2.length === 0 && !flatMapCallback) {
@@ -13207,7 +13395,7 @@ function parseTemplateLiteral(expr, ctx2) {
13207
13395
  }
13208
13396
  function tryResolveTemplateSpanFromConst(expr, ctx2) {
13209
13397
  if (ts12.isIdentifier(expr)) {
13210
- if (ctx2.loopParams.has(expr.text)) return null;
13398
+ if (ctx2.scope.isBound(expr.text)) return null;
13211
13399
  const constInfo = findLocalConst(expr.text, ctx2.analyzer);
13212
13400
  if (!constInfo) return null;
13213
13401
  const ast = parseConstInitializer(constInfo);
@@ -13219,7 +13407,7 @@ function tryResolveTemplateSpanFromConst(expr, ctx2) {
13219
13407
  }
13220
13408
  if (ts12.isElementAccessExpression(expr)) {
13221
13409
  if (!ts12.isIdentifier(expr.expression)) return null;
13222
- if (ctx2.loopParams.has(expr.expression.text)) return null;
13410
+ if (ctx2.scope.isBound(expr.expression.text)) return null;
13223
13411
  const constInfo = findLocalConst(expr.expression.text, ctx2.analyzer);
13224
13412
  if (!constInfo) return null;
13225
13413
  const ast = parseConstInitializer(constInfo);
@@ -13285,7 +13473,7 @@ function hasDynamicTagBinding(name2, sourceFile) {
13285
13473
  return found;
13286
13474
  }
13287
13475
  function tryResolveIdentifierAsTemplateLiteral(ident, ctx2) {
13288
- if (ctx2.loopParams.has(ident.text)) return null;
13476
+ if (ctx2.scope.isBound(ident.text)) return null;
13289
13477
  const constInfo = findLocalConst(ident.text, ctx2.analyzer);
13290
13478
  if (!constInfo) return null;
13291
13479
  const ast = parseConstInitializer(constInfo);
@@ -13621,8 +13809,9 @@ function isSignalOrMemoArray(array, ctx2) {
13621
13809
  return false;
13622
13810
  }
13623
13811
  function referencesLoopParam(expr, ctx2) {
13624
- if (ctx2.loopParams.size === 0) return false;
13625
- for (const p of ctx2.loopParams) {
13812
+ const boundNames = ctx2.scope.valueBoundNames();
13813
+ if (boundNames.size === 0) return false;
13814
+ for (const p of boundNames) {
13626
13815
  if (new RegExp(`\\b${p}\\b`).test(expr)) return true;
13627
13816
  }
13628
13817
  return false;
@@ -13688,8 +13877,9 @@ function hasReactiveAttributes(attrs, ctx2) {
13688
13877
  if (isSignalOrMemoReference(valueToCheck, ctx2) || isPropsReference(valueToCheck, ctx2)) {
13689
13878
  return true;
13690
13879
  }
13691
- if (ctx2.loopParams.size > 0) {
13692
- for (const p of ctx2.loopParams) {
13880
+ const scopeValueNames = ctx2.scope.valueBoundNames();
13881
+ if (scopeValueNames.size > 0) {
13882
+ for (const p of scopeValueNames) {
13693
13883
  if (new RegExp(`\\b${p}\\b`).test(valueToCheck)) return true;
13694
13884
  }
13695
13885
  }
@@ -13913,6 +14103,7 @@ var init_jsx_to_ir = __esm({
13913
14103
  init_strip_types();
13914
14104
  init_template_parts();
13915
14105
  init_src();
14106
+ init_binding_scope();
13916
14107
  CLIENT_DIRECTIVE_INTERIOR_RE2 = /^\s*@client\s*$/;
13917
14108
  BLOCK_COMMENT_RE2 = /\/\*([\s\S]*?)\*\//g;
13918
14109
  EMPTY_BOUND = /* @__PURE__ */ new Set();
@@ -24937,7 +25128,7 @@ var init_jsx_adapter = __esm({
24937
25128
  if (moduleScopeNames.has(constant.name)) continue;
24938
25129
  const keyword = constant.declarationKind ?? "const";
24939
25130
  if (!constant.value) {
24940
- const typeAnnotation = preserveTypes && constant.type ? `: ${constant.type.raw}` : "";
25131
+ const typeAnnotation = preserveTypes && (constant.typeAnnotation ?? constant.type) ? `: ${constant.typeAnnotation ?? constant.type?.raw}` : "";
24941
25132
  lines.push(` ${keyword} ${constant.name}${typeAnnotation}`);
24942
25133
  continue;
24943
25134
  }
@@ -24945,7 +25136,8 @@ var init_jsx_adapter = __esm({
24945
25136
  if (/^createContext\b/.test(value2) || /^new WeakMap\b/.test(value2)) continue;
24946
25137
  if (!reachable.has(constant.name)) continue;
24947
25138
  const constValue = preserveTypes ? constant.typedValue ?? constant.value : constant.value;
24948
- lines.push(` ${keyword} ${constant.name} = ${constValue}`);
25139
+ const letTypeAnnotation = preserveTypes && keyword === "let" && constant.typeAnnotation ? `: ${constant.typeAnnotation}` : "";
25140
+ lines.push(` ${keyword} ${constant.name}${letTypeAnnotation} = ${constValue}`);
24949
25141
  }
24950
25142
  for (const func of localFunctions) {
24951
25143
  if (moduleScopeNames.has(func.name)) continue;
@@ -25102,14 +25294,16 @@ var init_jsx_adapter = __esm({
25102
25294
  const keyword = c.declarationKind ?? "const";
25103
25295
  const exportKw = c.isExported ? "export " : "";
25104
25296
  if (!c.value) {
25105
- entries2.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}` });
25297
+ const typeAnnotation = preserveTypes && (c.typeAnnotation ?? c.type) ? `: ${c.typeAnnotation ?? c.type?.raw}` : "";
25298
+ entries2.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${typeAnnotation}` });
25106
25299
  continue;
25107
25300
  }
25108
25301
  const trimmed = c.value.trim();
25109
25302
  if (/^new WeakMap\b/.test(trimmed)) continue;
25110
25303
  if (c.isExported && /^createContext\b/.test(trimmed)) continue;
25111
25304
  const value2 = preserveTypes ? c.typedValue ?? c.value : c.value;
25112
- entries2.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name} = ${value2}` });
25305
+ const letTypeAnnotation = preserveTypes && keyword === "let" && c.typeAnnotation ? `: ${c.typeAnnotation}` : "";
25306
+ entries2.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${letTypeAnnotation} = ${value2}` });
25113
25307
  }
25114
25308
  for (const f of ir.metadata.localFunctions) {
25115
25309
  if (!f.isModule || !moduleNames.has(f.name)) continue;
@@ -28832,6 +29026,7 @@ __export(src_exports, {
28832
29026
  BROWSER_ONLY_CLIENT_APIS: () => BROWSER_ONLY_CLIENT_APIS,
28833
29027
  BUILTIN_LOWERING_PLUGINS: () => BUILTIN_LOWERING_PLUGINS,
28834
29028
  BaseAdapter: () => BaseAdapter,
29029
+ BindingScope: () => BindingScope,
28835
29030
  CALLBACK_METHODS: () => CALLBACK_METHODS,
28836
29031
  ENV_SIGNAL_READERS: () => ENV_SIGNAL_READERS,
28837
29032
  ErrorCodes: () => ErrorCodes,
@@ -29031,6 +29226,7 @@ var init_src2 = __esm({
29031
29226
  init_expression_parser();
29032
29227
  init_loop_chain();
29033
29228
  init_loop_destructure();
29229
+ init_binding_scope();
29034
29230
  init_debug();
29035
29231
  init_profiler();
29036
29232
  init_debug_profile();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/cli",
3
- "version": "0.31.2",
3
+ "version": "0.31.3",
4
4
  "description": "CLI for agent-driven UI component discovery and scaffolding",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,12 +30,12 @@
30
30
  "esbuild": "^0.25.0",
31
31
  "typescript": "^5.0.0",
32
32
  "vite": "^6.0.0",
33
- "@barefootjs/client": "0.31.2",
34
- "@barefootjs/shared": "0.31.2"
33
+ "@barefootjs/client": "0.31.3",
34
+ "@barefootjs/shared": "0.31.3"
35
35
  },
36
36
  "devDependencies": {
37
- "@barefootjs/jsx": "0.31.2",
38
- "@barefootjs/vite": "0.31.2",
37
+ "@barefootjs/jsx": "0.31.3",
38
+ "@barefootjs/vite": "0.31.3",
39
39
  "@happy-dom/global-registrator": "^20.0.11",
40
40
  "@types/node": "^22.0.0",
41
41
  "happy-dom": "^20.0.11"