@barefootjs/test 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 +131 -36
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -190429,7 +190429,8 @@ function visit(node, ctx, targetComponentName, namedExports) {
190429
190429
  if (!ctx.componentNode) {
190430
190430
  collectAmbientGlobals(node, ctx);
190431
190431
  }
190432
- if (import_typescript9.default.isVariableStatement(node) && !ctx.componentNode) {
190432
+ const isDeclareStatement = import_typescript9.default.isVariableStatement(node) && (node.modifiers?.some((m) => m.kind === import_typescript9.default.SyntaxKind.DeclareKeyword) ?? false);
190433
+ if (import_typescript9.default.isVariableStatement(node) && !ctx.componentNode && !isDeclareStatement) {
190433
190434
  const isExported = node.modifiers?.some((m) => m.kind === import_typescript9.default.SyntaxKind.ExportKeyword) ?? false;
190434
190435
  const isLet = (node.declarationList.flags & import_typescript9.default.NodeFlags.Let) !== 0;
190435
190436
  const isModuleClientDirective = hasLeadingClientDirectiveOnStatement(node, ctx.sourceFile);
@@ -190442,7 +190443,7 @@ function visit(node, ctx, targetComponentName, namedExports) {
190442
190443
  }
190443
190444
  continue;
190444
190445
  }
190445
- if (import_typescript9.default.isIdentifier(decl.name) && decl.initializer && !isArrowComponentFunction(decl)) {
190446
+ if (import_typescript9.default.isIdentifier(decl.name) && (decl.initializer || isLet) && !isArrowComponentFunction(decl)) {
190446
190447
  collectConstant(decl, ctx, true, isLet ? "let" : "const", isExported);
190447
190448
  }
190448
190449
  }
@@ -192013,6 +192014,7 @@ function collectConstant(node, ctx, _isModule, declarationKind = "const", isExpo
192013
192014
  value,
192014
192015
  parsed,
192015
192016
  typedValue: typedValue !== value ? typedValue : undefined,
192017
+ typeAnnotation: node.type ? node.type.getText(ctx.sourceFile) : undefined,
192016
192018
  valueBranches,
192017
192019
  declarationKind,
192018
192020
  isExported,
@@ -194292,6 +194294,83 @@ var toLocaleDatePlugin = {
194292
194294
  }
194293
194295
  };
194294
194296
 
194297
+ // ../jsx/src/scope/binding-scope.ts
194298
+ class BindingScope {
194299
+ frames;
194300
+ static EMPTY = new BindingScope([]);
194301
+ constructor(frames) {
194302
+ this.frames = frames;
194303
+ }
194304
+ enterLoopRow(loop) {
194305
+ const bindings = new Map;
194306
+ if (loop.paramBindings && loop.paramBindings.length > 0) {
194307
+ for (const b of loop.paramBindings)
194308
+ bindings.set(b.name, { source: "destructure" });
194309
+ } else {
194310
+ bindings.set(loop.param, { source: "item" });
194311
+ }
194312
+ if (loop.index != null)
194313
+ bindings.set(loop.index, { source: "index" });
194314
+ for (const name of loop.preamble?.declaredNames ?? [])
194315
+ bindings.set(name, { source: "preamble" });
194316
+ const frame = { kind: "loop-row", bindings };
194317
+ return new BindingScope([frame, ...this.frames]);
194318
+ }
194319
+ enterCallback(params) {
194320
+ const bindings = new Map;
194321
+ for (const name of params)
194322
+ bindings.set(name, { source: "param" });
194323
+ const frame = { kind: "callback", bindings };
194324
+ return new BindingScope([frame, ...this.frames]);
194325
+ }
194326
+ isBound(name) {
194327
+ for (const frame of this.frames) {
194328
+ if (frame.bindings.has(name))
194329
+ return true;
194330
+ }
194331
+ return false;
194332
+ }
194333
+ lookup(name) {
194334
+ for (let depth = 0;depth < this.frames.length; depth++) {
194335
+ const frame = this.frames[depth];
194336
+ const binding = frame.bindings.get(name);
194337
+ if (binding)
194338
+ return { depth, frame, binding };
194339
+ }
194340
+ return null;
194341
+ }
194342
+ boundNames() {
194343
+ if (this.boundNamesCache)
194344
+ return this.boundNamesCache;
194345
+ const names = new Set;
194346
+ for (const frame of this.frames) {
194347
+ for (const name of frame.bindings.keys())
194348
+ names.add(name);
194349
+ }
194350
+ this.boundNamesCache = names;
194351
+ return names;
194352
+ }
194353
+ boundNamesCache;
194354
+ valueBoundNamesCache;
194355
+ valueBoundNames() {
194356
+ if (this.valueBoundNamesCache)
194357
+ return this.valueBoundNamesCache;
194358
+ const names = new Set;
194359
+ for (const frame of this.frames) {
194360
+ for (const [name, binding] of frame.bindings) {
194361
+ if (binding.source === "item" || binding.source === "index" || binding.source === "destructure") {
194362
+ names.add(name);
194363
+ }
194364
+ }
194365
+ }
194366
+ this.valueBoundNamesCache = names;
194367
+ return names;
194368
+ }
194369
+ asShadowPredicate() {
194370
+ return (name) => this.isBound(name);
194371
+ }
194372
+ }
194373
+
194295
194374
  // ../jsx/src/jsx-to-ir.ts
194296
194375
  var CLIENT_DIRECTIVE_INTERIOR_RE2 = /^\s*@client\s*$/;
194297
194376
  var BLOCK_COMMENT_RE2 = /\/\*([\s\S]*?)\*\//g;
@@ -194472,8 +194551,9 @@ function rewriteBarePropRefs2(text, expr, ctx) {
194472
194551
  let propNames = getDestructuredPropNames(ctx);
194473
194552
  if (!propNames)
194474
194553
  return dateLowered === text ? undefined : dateLowered;
194475
- if (ctx.loopParams.size > 0) {
194476
- const filtered = new Set([...propNames].filter((n) => !ctx.loopParams.has(n)));
194554
+ const shadowingNames = ctx.scope.boundNames();
194555
+ if (shadowingNames.size > 0) {
194556
+ const filtered = new Set([...propNames].filter((n) => !shadowingNames.has(n)));
194477
194557
  if (filtered.size === 0)
194478
194558
  return dateLowered === text ? undefined : dateLowered;
194479
194559
  propNames = filtered;
@@ -194549,7 +194629,7 @@ function createTransformContext(analyzer) {
194549
194629
  spreadIdCounter: 0,
194550
194630
  isRoot: true,
194551
194631
  insideComponentChildren: false,
194552
- loopParams: new Set,
194632
+ scope: BindingScope.EMPTY,
194553
194633
  loopDepth: 0,
194554
194634
  patterns: {
194555
194635
  signals: analyzer.signals.map((s) => ({
@@ -194626,7 +194706,8 @@ function generateSpreadSlotId(ctx) {
194626
194706
  return `Spread_${ctx.spreadIdCounter++}`;
194627
194707
  }
194628
194708
  function makeBindingEnv(ctx) {
194629
- const loopKey = ctx.loopParams.size === 0 ? "" : Array.from(ctx.loopParams).sort().join("\x00");
194709
+ const boundNames = ctx.scope.valueBoundNames();
194710
+ const loopKey = boundNames.size === 0 ? "" : Array.from(boundNames).sort().join("\x00");
194630
194711
  if (ctx._bindingEnv && ctx._bindingEnvLoopKey === loopKey) {
194631
194712
  return ctx._bindingEnv;
194632
194713
  }
@@ -194641,7 +194722,7 @@ function makeBindingEnv(ctx) {
194641
194722
  localFunctions: a.localFunctions,
194642
194723
  imports: a.imports,
194643
194724
  ambientGlobals: a.ambientGlobals,
194644
- loopParams: new Set(ctx.loopParams),
194725
+ loopParams: boundNames,
194645
194726
  checker: a.checker
194646
194727
  };
194647
194728
  ctx._bindingEnv = env;
@@ -195334,7 +195415,8 @@ function transformExpressionInner(expr, ctx, node, isClientOnly) {
195334
195415
  freeRefs
195335
195416
  };
195336
195417
  const reactive = isReactiveExpression(exprText, ctx, expr) || isReactiveOrigin(origin);
195337
- const refsLoopParam = ctx.loopParams.size > 0 && Array.from(ctx.loopParams).some((p) => new RegExp(`\\b${p}\\b`).test(exprText));
195418
+ const scopeValueNames = ctx.scope.valueBoundNames();
195419
+ const refsLoopParam = scopeValueNames.size > 0 && Array.from(scopeValueNames).some((p) => new RegExp(`\\b${p}\\b`).test(exprText));
195338
195420
  const callsReactive = exprCallsReactiveGetters(expr, ctx);
195339
195421
  const hasCalls = exprHasFunctionCalls(expr);
195340
195422
  const needsSlot = reactive || isClientOnly || refsLoopParam || callsReactive || hasCalls;
@@ -196422,7 +196504,7 @@ function extractItemConditionalKey(cond) {
196422
196504
  return a ?? b;
196423
196505
  }
196424
196506
  function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
196425
- const isNested = ctx.loopParams.size > 0;
196507
+ const isNested = ctx.scope.valueBoundNames().size > 0;
196426
196508
  const diagCountAtEntry = ctx.analyzer.errors.length;
196427
196509
  const depth = ctx.loopDepth;
196428
196510
  const propAccess = node.expression;
@@ -196581,14 +196663,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
196581
196663
  indexType = secondParam.type.getText(ctx.sourceFile);
196582
196664
  }
196583
196665
  }
196584
- if (paramBindings) {
196585
- for (const b of paramBindings)
196586
- ctx.loopParams.add(b.name);
196587
- } else {
196588
- ctx.loopParams.add(param);
196589
- }
196590
- if (index)
196591
- ctx.loopParams.add(index);
196666
+ const savedScope = ctx.scope;
196667
+ ctx.scope = ctx.scope.enterLoopRow({ param, index, paramBindings });
196592
196668
  ctx.loopDepth++;
196593
196669
  const tryTransformRenderableBody = (expr) => {
196594
196670
  if (!import_typescript12.default.isBinaryExpression(expr))
@@ -196649,6 +196725,24 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
196649
196725
  }
196650
196726
  }
196651
196727
  const returnStmt = children.length === 0 ? body.statements.find((s) => import_typescript12.default.isReturnStatement(s) && s.expression != null) : undefined;
196728
+ let rowScopeBeforePreamble = null;
196729
+ if (returnStmt) {
196730
+ const preambleNames = new Set;
196731
+ for (const stmt of body.statements) {
196732
+ if (stmt === returnStmt)
196733
+ break;
196734
+ collectPreambleDeclaredNames(stmt, preambleNames);
196735
+ }
196736
+ if (preambleNames.size > 0) {
196737
+ rowScopeBeforePreamble = ctx.scope;
196738
+ ctx.scope = savedScope.enterLoopRow({
196739
+ param,
196740
+ index,
196741
+ paramBindings,
196742
+ preamble: { declaredNames: [...preambleNames] }
196743
+ });
196744
+ }
196745
+ }
196652
196746
  if (returnStmt && returnStmt.expression) {
196653
196747
  let returnExpr = returnStmt.expression;
196654
196748
  while (import_typescript12.default.isParenthesizedExpression(returnExpr)) {
@@ -196718,6 +196812,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
196718
196812
  }
196719
196813
  }
196720
196814
  }
196815
+ if (rowScopeBeforePreamble) {
196816
+ ctx.scope = rowScopeBeforePreamble;
196817
+ }
196721
196818
  if (method === "flatMap" && children.length === 0 && !flatMapProjectionCall(body)) {
196722
196819
  flatMapCallback = buildFlatMapCallback(callback, body, ctx);
196723
196820
  }
@@ -196746,14 +196843,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
196746
196843
  }
196747
196844
  }));
196748
196845
  }
196749
- if (paramBindings) {
196750
- for (const b of paramBindings)
196751
- ctx.loopParams.delete(b.name);
196752
- } else {
196753
- ctx.loopParams.delete(param);
196754
- }
196755
- if (index)
196756
- ctx.loopParams.delete(index);
196846
+ ctx.scope = savedScope;
196757
196847
  ctx.loopDepth--;
196758
196848
  }
196759
196849
  if (children.length === 0 && !flatMapCallback) {
@@ -197500,7 +197590,7 @@ function parseTemplateLiteral(expr, ctx) {
197500
197590
  }
197501
197591
  function tryResolveTemplateSpanFromConst(expr, ctx) {
197502
197592
  if (import_typescript12.default.isIdentifier(expr)) {
197503
- if (ctx.loopParams.has(expr.text))
197593
+ if (ctx.scope.isBound(expr.text))
197504
197594
  return null;
197505
197595
  const constInfo = findLocalConst(expr.text, ctx.analyzer);
197506
197596
  if (!constInfo)
@@ -197516,7 +197606,7 @@ function tryResolveTemplateSpanFromConst(expr, ctx) {
197516
197606
  if (import_typescript12.default.isElementAccessExpression(expr)) {
197517
197607
  if (!import_typescript12.default.isIdentifier(expr.expression))
197518
197608
  return null;
197519
- if (ctx.loopParams.has(expr.expression.text))
197609
+ if (ctx.scope.isBound(expr.expression.text))
197520
197610
  return null;
197521
197611
  const constInfo = findLocalConst(expr.expression.text, ctx.analyzer);
197522
197612
  if (!constInfo)
@@ -197595,7 +197685,7 @@ function hasDynamicTagBinding(name, sourceFile) {
197595
197685
  return found;
197596
197686
  }
197597
197687
  function tryResolveIdentifierAsTemplateLiteral(ident, ctx) {
197598
- if (ctx.loopParams.has(ident.text))
197688
+ if (ctx.scope.isBound(ident.text))
197599
197689
  return null;
197600
197690
  const constInfo = findLocalConst(ident.text, ctx.analyzer);
197601
197691
  if (!constInfo)
@@ -197944,9 +198034,10 @@ function isSignalOrMemoArray(array, ctx) {
197944
198034
  return false;
197945
198035
  }
197946
198036
  function referencesLoopParam(expr, ctx) {
197947
- if (ctx.loopParams.size === 0)
198037
+ const boundNames = ctx.scope.valueBoundNames();
198038
+ if (boundNames.size === 0)
197948
198039
  return false;
197949
- for (const p of ctx.loopParams) {
198040
+ for (const p of boundNames) {
197950
198041
  if (new RegExp(`\\b${p}\\b`).test(expr))
197951
198042
  return true;
197952
198043
  }
@@ -198026,8 +198117,9 @@ function hasReactiveAttributes(attrs, ctx) {
198026
198117
  if (isSignalOrMemoReference(valueToCheck, ctx) || isPropsReference(valueToCheck, ctx)) {
198027
198118
  return true;
198028
198119
  }
198029
- if (ctx.loopParams.size > 0) {
198030
- for (const p of ctx.loopParams) {
198120
+ const scopeValueNames = ctx.scope.valueBoundNames();
198121
+ if (scopeValueNames.size > 0) {
198122
+ for (const p of scopeValueNames) {
198031
198123
  if (new RegExp(`\\b${p}\\b`).test(valueToCheck))
198032
198124
  return true;
198033
198125
  }
@@ -198785,7 +198877,7 @@ class JsxAdapter extends BaseAdapter {
198785
198877
  continue;
198786
198878
  const keyword = constant.declarationKind ?? "const";
198787
198879
  if (!constant.value) {
198788
- const typeAnnotation = preserveTypes && constant.type ? `: ${constant.type.raw}` : "";
198880
+ const typeAnnotation = preserveTypes && (constant.typeAnnotation ?? constant.type) ? `: ${constant.typeAnnotation ?? constant.type?.raw}` : "";
198789
198881
  lines.push(` ${keyword} ${constant.name}${typeAnnotation}`);
198790
198882
  continue;
198791
198883
  }
@@ -198795,7 +198887,8 @@ class JsxAdapter extends BaseAdapter {
198795
198887
  if (!reachable.has(constant.name))
198796
198888
  continue;
198797
198889
  const constValue = preserveTypes ? constant.typedValue ?? constant.value : constant.value;
198798
- lines.push(` ${keyword} ${constant.name} = ${constValue}`);
198890
+ const letTypeAnnotation = preserveTypes && keyword === "let" && constant.typeAnnotation ? `: ${constant.typeAnnotation}` : "";
198891
+ lines.push(` ${keyword} ${constant.name}${letTypeAnnotation} = ${constValue}`);
198799
198892
  }
198800
198893
  for (const func of localFunctions) {
198801
198894
  if (moduleScopeNames.has(func.name))
@@ -198902,7 +198995,8 @@ class JsxAdapter extends BaseAdapter {
198902
198995
  const keyword = c.declarationKind ?? "const";
198903
198996
  const exportKw = c.isExported ? "export " : "";
198904
198997
  if (!c.value) {
198905
- entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}` });
198998
+ const typeAnnotation = preserveTypes && (c.typeAnnotation ?? c.type) ? `: ${c.typeAnnotation ?? c.type?.raw}` : "";
198999
+ entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${typeAnnotation}` });
198906
199000
  continue;
198907
199001
  }
198908
199002
  const trimmed = c.value.trim();
@@ -198911,7 +199005,8 @@ class JsxAdapter extends BaseAdapter {
198911
199005
  if (c.isExported && /^createContext\b/.test(trimmed))
198912
199006
  continue;
198913
199007
  const value = preserveTypes ? c.typedValue ?? c.value : c.value;
198914
- entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name} = ${value}` });
199008
+ const letTypeAnnotation = preserveTypes && keyword === "let" && c.typeAnnotation ? `: ${c.typeAnnotation}` : "";
199009
+ entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${letTypeAnnotation} = ${value}` });
198915
199010
  }
198916
199011
  for (const f of ir.metadata.localFunctions) {
198917
199012
  if (!f.isModule || !moduleNames.has(f.name))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/test",
3
- "version": "0.31.2",
3
+ "version": "0.31.3",
4
4
  "description": "Test utilities for BarefootJS - IR-based component testing without a browser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,7 +39,7 @@
39
39
  "directory": "packages/test"
40
40
  },
41
41
  "dependencies": {
42
- "@barefootjs/jsx": "0.31.2"
42
+ "@barefootjs/jsx": "0.31.3"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.0.0"