@barefootjs/test 0.32.0 → 0.33.1

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/index.js CHANGED
@@ -187454,7 +187454,7 @@ function convertNode(node, raw) {
187454
187454
  }
187455
187455
  if (n === undefined || Number.isNaN(n)) {
187456
187456
  const parsedDepth = convertNode(depthNode, raw);
187457
- if (checkSupport(parsedDepth).supported) {
187457
+ if (checkSupport(parsedDepth, "rendered").supported) {
187458
187458
  depthExpr = parsedDepth;
187459
187459
  flatDepth = 1;
187460
187460
  } else {
@@ -187548,10 +187548,12 @@ function convertNode(node, raw) {
187548
187548
  const k = objectLiteralKeyName(prop.name);
187549
187549
  if (k === null)
187550
187550
  return { kind: "unsupported", raw, reason: `Unsupported syntax: ${import_typescript.default.SyntaxKind[node.kind]}` };
187551
- properties.push({ key: k.key, keyKind: k.keyKind, shorthand: false, value: convertNode(prop.initializer, raw) });
187551
+ properties.push({ kind: "prop", key: k.key, keyKind: k.keyKind, shorthand: false, value: convertNode(prop.initializer, raw) });
187552
187552
  } else if (import_typescript.default.isShorthandPropertyAssignment(prop)) {
187553
187553
  const key = prop.name.text;
187554
- properties.push({ key, keyKind: "identifier", shorthand: true, value: { kind: "identifier", name: key } });
187554
+ properties.push({ kind: "prop", key, keyKind: "identifier", shorthand: true, value: { kind: "identifier", name: key } });
187555
+ } else if (import_typescript.default.isSpreadAssignment(prop)) {
187556
+ properties.push({ kind: "spread", expr: convertNode(prop.expression, raw) });
187555
187557
  } else {
187556
187558
  return { kind: "unsupported", raw, reason: `Unsupported syntax: ${import_typescript.default.SyntaxKind[node.kind]}` };
187557
187559
  }
@@ -188231,14 +188233,23 @@ function getUnaryOperatorString(op) {
188231
188233
  }
188232
188234
  }
188233
188235
  function isSupported(expr) {
188234
- return checkSupport(expr);
188236
+ return checkSupport(expr, "rendered");
188235
188237
  }
188236
- function checkSupport(expr) {
188238
+ function checkSupport(expr, pos) {
188237
188239
  switch (expr.kind) {
188238
188240
  case "unsupported":
188239
188241
  return { supported: false, reason: expr.reason };
188240
- case "object-literal":
188241
- return { supported: false, reason: "Unsupported syntax: ObjectLiteralExpression" };
188242
+ case "object-literal": {
188243
+ if (pos !== "value") {
188244
+ return { supported: false, reason: "Unsupported syntax: ObjectLiteralExpression" };
188245
+ }
188246
+ for (const prop of expr.properties) {
188247
+ const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos);
188248
+ if (!propSupport.supported)
188249
+ return propSupport;
188250
+ }
188251
+ return { supported: true, level: "L2" };
188252
+ }
188242
188253
  case "identifier":
188243
188254
  return { supported: true, level: "L1" };
188244
188255
  case "literal":
@@ -188248,7 +188259,7 @@ function checkSupport(expr) {
188248
188259
  return { supported: false, reason: "Standalone arrow functions / regex literals are not supported" };
188249
188260
  case "array-literal": {
188250
188261
  for (const el of expr.elements) {
188251
- const elSupport = checkSupport(el);
188262
+ const elSupport = checkSupport(el, pos);
188252
188263
  if (!elSupport.supported)
188253
188264
  return elSupport;
188254
188265
  }
@@ -188261,16 +188272,16 @@ function checkSupport(expr) {
188261
188272
  reason: `String.prototype.${expr.method} supports only a string pattern + string replacement (the regex form is deferred); use a string pattern or wrap the expression in /* @client */`
188262
188273
  };
188263
188274
  }
188264
- const objSupport = checkSupport(expr.object);
188275
+ const objSupport = checkSupport(expr.object, pos);
188265
188276
  if (!objSupport.supported)
188266
188277
  return objSupport;
188267
188278
  for (const arg of expr.args) {
188268
- const argSupport = checkSupport(arg);
188279
+ const argSupport = checkSupport(arg, pos);
188269
188280
  if (!argSupport.supported)
188270
188281
  return argSupport;
188271
188282
  }
188272
188283
  if (expr.method === "flat" && expr.depthExpr) {
188273
- const depthSupport = checkSupport(expr.depthExpr);
188284
+ const depthSupport = checkSupport(expr.depthExpr, pos);
188274
188285
  if (!depthSupport.supported)
188275
188286
  return depthSupport;
188276
188287
  }
@@ -188279,10 +188290,10 @@ function checkSupport(expr) {
188279
188290
  case "call": {
188280
188291
  const cb = asCallbackMethodCall(expr);
188281
188292
  if (cb) {
188282
- const objSupport = checkSupport(cb.object);
188293
+ const objSupport = checkSupport(cb.object, pos);
188283
188294
  if (!objSupport.supported)
188284
188295
  return objSupport;
188285
- const bodySupport = checkSupport(cb.arrow.body);
188296
+ const bodySupport = checkSupport(cb.arrow.body, pos);
188286
188297
  if (!bodySupport.supported) {
188287
188298
  return {
188288
188299
  supported: false,
@@ -188291,13 +188302,13 @@ function checkSupport(expr) {
188291
188302
  };
188292
188303
  }
188293
188304
  for (const rest of cb.args) {
188294
- const restSupport = checkSupport(rest);
188305
+ const restSupport = checkSupport(rest, pos);
188295
188306
  if (!restSupport.supported)
188296
188307
  return restSupport;
188297
188308
  }
188298
188309
  return { supported: true, level: "L5" };
188299
188310
  }
188300
- const calleeSupport = checkSupport(expr.callee);
188311
+ const calleeSupport = checkSupport(expr.callee, pos);
188301
188312
  if (!calleeSupport.supported) {
188302
188313
  return calleeSupport;
188303
188314
  }
@@ -188316,7 +188327,7 @@ function checkSupport(expr) {
188316
188327
  return { supported: true, level: "L1" };
188317
188328
  }
188318
188329
  for (const arg of expr.args) {
188319
- const argSupport = checkSupport(arg);
188330
+ const argSupport = checkSupport(arg, pos);
188320
188331
  if (!argSupport.supported) {
188321
188332
  return argSupport;
188322
188333
  }
@@ -188324,7 +188335,7 @@ function checkSupport(expr) {
188324
188335
  return { supported: true, level: "L2" };
188325
188336
  }
188326
188337
  case "member": {
188327
- const objSupport = checkSupport(expr.object);
188338
+ const objSupport = checkSupport(expr.object, pos);
188328
188339
  if (!objSupport.supported) {
188329
188340
  return objSupport;
188330
188341
  }
@@ -188334,19 +188345,19 @@ function checkSupport(expr) {
188334
188345
  return { supported: true, level: "L2" };
188335
188346
  }
188336
188347
  case "index-access": {
188337
- const objSupport = checkSupport(expr.object);
188348
+ const objSupport = checkSupport(expr.object, pos);
188338
188349
  if (!objSupport.supported)
188339
188350
  return objSupport;
188340
- const indexSupport = checkSupport(expr.index);
188351
+ const indexSupport = checkSupport(expr.index, pos);
188341
188352
  if (!indexSupport.supported)
188342
188353
  return indexSupport;
188343
188354
  return { supported: true, level: "L2" };
188344
188355
  }
188345
188356
  case "binary": {
188346
- const leftSupport = checkSupport(expr.left);
188357
+ const leftSupport = checkSupport(expr.left, pos);
188347
188358
  if (!leftSupport.supported)
188348
188359
  return leftSupport;
188349
- const rightSupport = checkSupport(expr.right);
188360
+ const rightSupport = checkSupport(expr.right, pos);
188350
188361
  if (!rightSupport.supported)
188351
188362
  return rightSupport;
188352
188363
  if (["===", "==", "!==", "!=", ">", "<", ">=", "<="].includes(expr.op)) {
@@ -188358,7 +188369,7 @@ function checkSupport(expr) {
188358
188369
  return { supported: false, reason: `Unknown operator: ${expr.op}` };
188359
188370
  }
188360
188371
  case "unary": {
188361
- const argSupport = checkSupport(expr.argument);
188372
+ const argSupport = checkSupport(expr.argument, pos);
188362
188373
  if (!argSupport.supported)
188363
188374
  return argSupport;
188364
188375
  if (expr.op === "!") {
@@ -188370,25 +188381,25 @@ function checkSupport(expr) {
188370
188381
  return { supported: false, reason: `Unsupported unary operator: ${expr.op}` };
188371
188382
  }
188372
188383
  case "logical": {
188373
- const leftSupport = checkSupport(expr.left);
188384
+ const leftSupport = checkSupport(expr.left, pos);
188374
188385
  if (!leftSupport.supported)
188375
188386
  return leftSupport;
188376
188387
  if (expr.op === "??" && expr.right.kind === "object-literal" && expr.right.properties.length === 0) {
188377
188388
  return { supported: true, level: "L4" };
188378
188389
  }
188379
- const rightSupport = checkSupport(expr.right);
188390
+ const rightSupport = checkSupport(expr.right, pos);
188380
188391
  if (!rightSupport.supported)
188381
188392
  return rightSupport;
188382
188393
  return { supported: true, level: "L4" };
188383
188394
  }
188384
188395
  case "conditional": {
188385
- const testSupport = checkSupport(expr.test);
188396
+ const testSupport = checkSupport(expr.test, pos);
188386
188397
  if (!testSupport.supported)
188387
188398
  return testSupport;
188388
- const consSupport = checkSupport(expr.consequent);
188399
+ const consSupport = checkSupport(expr.consequent, pos);
188389
188400
  if (!consSupport.supported)
188390
188401
  return consSupport;
188391
- const altSupport = checkSupport(expr.alternate);
188402
+ const altSupport = checkSupport(expr.alternate, pos);
188392
188403
  if (!altSupport.supported)
188393
188404
  return altSupport;
188394
188405
  return { supported: true, level: "L4" };
@@ -188396,7 +188407,7 @@ function checkSupport(expr) {
188396
188407
  case "template-literal": {
188397
188408
  for (const part of expr.parts) {
188398
188409
  if (part.type === "expression") {
188399
- const partSupport = checkSupport(part.expr);
188410
+ const partSupport = checkSupport(part.expr, pos);
188400
188411
  if (!partSupport.supported)
188401
188412
  return partSupport;
188402
188413
  }
@@ -188521,7 +188532,7 @@ function isPureInit(e, pureCallNames) {
188521
188532
  case "array-literal":
188522
188533
  return e.elements.every(pure);
188523
188534
  case "object-literal":
188524
- return e.properties.every((p) => pure(p.value));
188535
+ return e.properties.every((p) => pure(p.kind === "spread" ? p.expr : p.value));
188525
188536
  case "call":
188526
188537
  return e.callee.kind === "identifier" && e.args.length === 0 && pureCallNames !== undefined && pureCallNames.has(e.callee.name);
188527
188538
  case "array-method":
@@ -188575,7 +188586,7 @@ function usesPerPath(name, expr) {
188575
188586
  }
188576
188587
  return add(walk(e.object), sum(e.args));
188577
188588
  case "object-literal":
188578
- return sum(e.properties.map((p) => p.value));
188589
+ return sum(e.properties.map((p) => p.kind === "spread" ? p.expr : p.value));
188579
188590
  case "arrow":
188580
188591
  return walk(e.body).max > 0 ? { min: 0, max: Number.POSITIVE_INFINITY } : { min: 0, max: 0 };
188581
188592
  }
@@ -188641,7 +188652,7 @@ function inlineBinding(expr, name, value) {
188641
188652
  case "object-literal":
188642
188653
  return {
188643
188654
  kind: "object-literal",
188644
- properties: e.properties.map((p) => ({ ...p, value: walk(p.value, enclosing) })),
188655
+ properties: e.properties.map((p) => p.kind === "spread" ? { ...p, expr: walk(p.expr, enclosing) } : { ...p, value: walk(p.value, enclosing) }),
188645
188656
  raw: e.raw
188646
188657
  };
188647
188658
  case "literal":
@@ -190085,6 +190096,7 @@ var ErrorCodes = {
190085
190096
  MISSING_KEY_IN_LIST: "BF023",
190086
190097
  MISSING_KEY_IN_NESTED_LIST: "BF024",
190087
190098
  UNSUPPORTED_DESTRUCTURE_REST: "BF025",
190099
+ RETURN_VALUE_NOT_JSX: "BF027",
190088
190100
  PROPS_DESTRUCTURING: "BF043",
190089
190101
  SIGNAL_GETTER_NOT_CALLED: "BF044",
190090
190102
  JSX_IN_LOCAL_FUNCTION: "BF045",
@@ -190116,6 +190128,7 @@ var errorMessages = {
190116
190128
  [ErrorCodes.MISSING_KEY_IN_LIST]: "Missing key attribute in list rendering. Add a key prop for efficient updates",
190117
190129
  [ErrorCodes.MISSING_KEY_IN_NESTED_LIST]: "Nested .map() loop requires key attribute for event delegation. Add a key prop to elements in the inner loop",
190118
190130
  [ErrorCodes.UNSUPPORTED_DESTRUCTURE_REST]: "Computed property key in .map() callback destructure is not supported. Rewrite the callback to destructure explicit bindings (e.g., `({ a, b }) => ...`) so the compiler can rewrite references to per-item signal accessors.",
190131
+ [ErrorCodes.RETURN_VALUE_NOT_JSX]: "Component's return value is not recognized as JSX — return the JSX expression directly instead of binding it to a local variable first.",
190119
190132
  [ErrorCodes.PROPS_DESTRUCTURING]: "Props destructuring in function parameters breaks reactivity. Use props object directly.",
190120
190133
  [ErrorCodes.SIGNAL_GETTER_NOT_CALLED]: "Signal/memo getter passed without calling it. Use getter() to read the value.",
190121
190134
  [ErrorCodes.JSX_IN_LOCAL_FUNCTION]: "Local function returns JSX but cannot be inlined. Extract it as a top-level PascalCase component or use a single return statement.",
@@ -190685,6 +190698,14 @@ function visitComponentBody(node, ctx) {
190685
190698
  }
190686
190699
  }
190687
190700
  if (isTopLevel && (import_typescript9.default.isTryStatement(node) || import_typescript9.default.isSwitchStatement(node) || import_typescript9.default.isForStatement(node) || import_typescript9.default.isForInStatement(node) || import_typescript9.default.isForOfStatement(node) || import_typescript9.default.isWhileStatement(node) || import_typescript9.default.isDoStatement(node) || import_typescript9.default.isThrowStatement(node) || import_typescript9.default.isBlock(node) && node.parent === ctx.componentBodyBlock)) {
190701
+ if (import_typescript9.default.isBlock(node)) {
190702
+ const returnedLocal = findBlockBodyReturnedJsxLocalName(node);
190703
+ if (returnedLocal) {
190704
+ ctx.errors.push(createError(ErrorCodes.RETURN_VALUE_NOT_JSX, getSourceLocation(node, ctx.sourceFile, ctx.filePath), {
190705
+ message: `Component '${ctx.componentName ?? "(unknown)"}' return value is not recognized ` + `as JSX — return the JSX expression directly instead of binding it to a local ` + `variable first (\`return ${returnedLocal}\` after \`const ${returnedLocal} = ` + `<jsx/>\` is not resolved at return position).`
190706
+ }));
190707
+ }
190708
+ }
190688
190709
  collectInitStatement(node, ctx);
190689
190710
  return;
190690
190711
  }
@@ -190720,6 +190741,31 @@ function unwrapJsxTransparent(expr) {
190720
190741
  }
190721
190742
  return current;
190722
190743
  }
190744
+ function findBlockBodyReturnedJsxLocalName(block) {
190745
+ const stmts = block.statements;
190746
+ const last = stmts[stmts.length - 1];
190747
+ if (!last || !import_typescript9.default.isReturnStatement(last) || !last.expression)
190748
+ return null;
190749
+ const returned = unwrapJsxTransparent(last.expression);
190750
+ if (!import_typescript9.default.isIdentifier(returned))
190751
+ return null;
190752
+ const name = returned.text;
190753
+ for (const stmt of stmts) {
190754
+ if (!import_typescript9.default.isVariableStatement(stmt))
190755
+ continue;
190756
+ for (const decl of stmt.declarationList.declarations) {
190757
+ if (!import_typescript9.default.isIdentifier(decl.name) || decl.name.text !== name || !decl.initializer)
190758
+ continue;
190759
+ let init = decl.initializer;
190760
+ while (import_typescript9.default.isParenthesizedExpression(init))
190761
+ init = init.expression;
190762
+ if (import_typescript9.default.isJsxElement(init) || import_typescript9.default.isJsxSelfClosingElement(init) || import_typescript9.default.isJsxFragment(init) || initializerShapeContainsJsx(init) || isMapLikeCallWithJsx(init)) {
190763
+ return name;
190764
+ }
190765
+ }
190766
+ }
190767
+ return null;
190768
+ }
190723
190769
  function extractJsxFromExpression(expr) {
190724
190770
  const inner = unwrapJsxTransparent(expr);
190725
190771
  if (import_typescript9.default.isJsxElement(inner) || import_typescript9.default.isJsxFragment(inner) || import_typescript9.default.isJsxSelfClosingElement(inner)) {
@@ -194362,6 +194408,8 @@ function matchToLocaleDateStringCall(callee, args, metadata) {
194362
194408
  let tz = null;
194363
194409
  const probeOptions = {};
194364
194410
  for (const prop of options.properties) {
194411
+ if (prop.kind === "spread")
194412
+ return null;
194365
194413
  if (prop.value.kind !== "literal" || prop.value.literalType !== "string")
194366
194414
  return null;
194367
194415
  const value = String(prop.value.value);
@@ -194934,8 +194982,14 @@ function buildIRRoot(analyzer) {
194934
194982
  }
194935
194983
  ctx.isRoot = false;
194936
194984
  const ir = transformJsxExpression(jsxReturn, ctx);
194937
- if (ir === null)
194985
+ if (ir === null) {
194986
+ if (import_typescript13.default.isIdentifier(jsxReturn) && (analyzer.jsxConstants.has(jsxReturn.text) || analyzer.inlineableJsxConsts.has(jsxReturn.text))) {
194987
+ analyzer.errors.push(createError(ErrorCodes.RETURN_VALUE_NOT_JSX, getSourceLocation(jsxReturn, analyzer.sourceFile, analyzer.filePath), {
194988
+ message: `Component '${analyzer.componentName ?? "(unknown)"}' return value is not recognized ` + `as JSX — return the JSX expression directly instead of binding it to a local variable ` + `first (\`return ${jsxReturn.text}\` after \`const ${jsxReturn.text} = <jsx/>\` is not ` + `resolved at return position).`
194989
+ }));
194990
+ }
194938
194991
  return null;
194992
+ }
194939
194993
  return wrapInScopeElement(ir);
194940
194994
  }
194941
194995
  function needsScopeWrapper(ir) {
@@ -196126,7 +196180,10 @@ function resolveCallbackMethodFunctionReferences(expr, analyzer, bound = EMPTY_B
196126
196180
  ...e.method === "flat" && e.depthExpr ? { depthExpr: visit2(e.depthExpr, bound2) } : {}
196127
196181
  };
196128
196182
  case "object-literal":
196129
- return { ...e, properties: e.properties.map((p) => ({ ...p, value: visit2(p.value, bound2) })) };
196183
+ return {
196184
+ ...e,
196185
+ properties: e.properties.map((p) => p.kind === "spread" ? { ...p, expr: visit2(p.expr, bound2) } : { ...p, value: visit2(p.value, bound2) })
196186
+ };
196130
196187
  case "arrow": {
196131
196188
  const inner = e.params.length === 0 ? bound2 : new Set([...bound2, ...e.params]);
196132
196189
  return { ...e, body: visit2(e.body, inner) };
@@ -198047,6 +198104,35 @@ function getStringValue(node) {
198047
198104
  }
198048
198105
  return null;
198049
198106
  }
198107
+ function unwrapTransparentTsWrappers(node) {
198108
+ let n = node;
198109
+ while (import_typescript13.default.isParenthesizedExpression(n) || import_typescript13.default.isAsExpression(n) || import_typescript13.default.isSatisfiesExpression(n) || import_typescript13.default.isNonNullExpression(n)) {
198110
+ n = n.expression;
198111
+ }
198112
+ return n;
198113
+ }
198114
+ function expressionWrapsJsx(node) {
198115
+ const n = unwrapTransparentTsWrappers(node);
198116
+ if (import_typescript13.default.isJsxElement(n) || import_typescript13.default.isJsxSelfClosingElement(n) || import_typescript13.default.isJsxFragment(n))
198117
+ return true;
198118
+ if (import_typescript13.default.isConditionalExpression(n)) {
198119
+ return expressionWrapsJsx(n.whenTrue) || expressionWrapsJsx(n.whenFalse);
198120
+ }
198121
+ if (import_typescript13.default.isArrayLiteralExpression(n)) {
198122
+ return n.elements.some((el) => expressionWrapsJsx(import_typescript13.default.isSpreadElement(el) ? el.expression : el));
198123
+ }
198124
+ return false;
198125
+ }
198126
+ function reportNakedJsxWrapperProp(ctx, attr, propName, jsxExpr) {
198127
+ const shape = import_typescript13.default.isConditionalExpression(jsxExpr) ? "a ternary" : "an array literal";
198128
+ ctx.analyzer.errors.push(createError(ErrorCodes.UNSUPPORTED_JSX_PATTERN, getSourceLocation(attr, ctx.sourceFile, ctx.filePath), {
198129
+ message: `Prop '${propName}' is ${shape} wrapping JSX (${jsxExpr.getText(ctx.sourceFile)}). ` + `This shape is not compiled — only a JSX element/fragment given DIRECTLY as the prop value is.`,
198130
+ suggestion: {
198131
+ message: `Move the conditional/array out of the prop position: compute it in a local ` + `const and pass it as the component's children instead of a named prop ` + `(e.g. const ${propName} = ${jsxExpr.getText(ctx.sourceFile)}; <Comp>{${propName}}</Comp>). ` + `Wrapping the ternary/array in a fragment at the prop position ` + `(${propName}={<>{${jsxExpr.getText(ctx.sourceFile)}}</>}) is NOT a safe escape here: it compiles, ` + `but the child's own reactive prop getter receives the branch's HTML unbranded and re-escapes it as ` + `text on the child's very next reactive run, corrupting the DOM (a narrower gap #2651's door ` + `inventory left open — tracked separately).`,
198132
+ escape: [{ kind: "rewrite" }]
198133
+ }
198134
+ }));
198135
+ }
198050
198136
  function processComponentProps(attributes, ctx) {
198051
198137
  const props = [];
198052
198138
  for (const attr of attributes.properties) {
@@ -198058,10 +198144,7 @@ function processComponentProps(attributes, ctx) {
198058
198144
  continue;
198059
198145
  const name = attr.name.getText(ctx.sourceFile);
198060
198146
  if (attr.initializer && import_typescript13.default.isJsxExpression(attr.initializer) && attr.initializer.expression) {
198061
- let jsxExpr = attr.initializer.expression;
198062
- while (import_typescript13.default.isParenthesizedExpression(jsxExpr)) {
198063
- jsxExpr = jsxExpr.expression;
198064
- }
198147
+ const jsxExpr = unwrapTransparentTsWrappers(attr.initializer.expression);
198065
198148
  if (import_typescript13.default.isJsxElement(jsxExpr) || import_typescript13.default.isJsxSelfClosingElement(jsxExpr) || import_typescript13.default.isJsxFragment(jsxExpr)) {
198066
198149
  const prevInsideComponentChildren = ctx.insideComponentChildren;
198067
198150
  ctx.insideComponentChildren = true;
@@ -198076,6 +198159,10 @@ function processComponentProps(attributes, ctx) {
198076
198159
  continue;
198077
198160
  }
198078
198161
  }
198162
+ if ((import_typescript13.default.isConditionalExpression(jsxExpr) || import_typescript13.default.isArrayLiteralExpression(jsxExpr)) && expressionWrapsJsx(jsxExpr)) {
198163
+ reportNakedJsxWrapperProp(ctx, attr, name, jsxExpr);
198164
+ continue;
198165
+ }
198079
198166
  }
198080
198167
  let value = getAttributeValue(attr, ctx);
198081
198168
  if (value.kind === "template") {
@@ -199533,6 +199620,8 @@ function matchQueryHrefCall(callee, args, localNames) {
199533
199620
  return null;
199534
199621
  const triples = [];
199535
199622
  for (const p of obj.properties) {
199623
+ if (p.kind === "spread")
199624
+ return null;
199536
199625
  const v = p.value;
199537
199626
  if (v.kind === "conditional" && isOmitBranch(v.alternate)) {
199538
199627
  triples.push({ guard: v.test, key: p.key, value: v.consequent });
@@ -200241,6 +200330,8 @@ function resolveConstants(constants3) {
200241
200330
  for (const c of constants3) {
200242
200331
  if (c.parsed?.kind === "object-literal") {
200243
200332
  for (const prop of c.parsed.properties) {
200333
+ if (prop.kind === "spread")
200334
+ continue;
200244
200335
  const value2 = resolveObjectPropValue(prop.value, resolved);
200245
200336
  if (value2 !== null)
200246
200337
  resolved.set(`${c.name}.${prop.key}`, value2);
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-constants.d.ts","sourceRoot":"","sources":["../src/resolve-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,GAChG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA0CrB"}
1
+ {"version":3,"file":"resolve-constants.d.ts","sourceRoot":"","sources":["../src/resolve-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,GAChG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6CrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/test",
3
- "version": "0.32.0",
3
+ "version": "0.33.1",
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.32.0"
42
+ "@barefootjs/jsx": "0.33.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.0.0"
@@ -39,6 +39,9 @@ export function resolveConstants(
39
39
  // below (Copilot review, PR #2361).
40
40
  if (c.parsed?.kind === 'object-literal') {
41
41
  for (const prop of c.parsed.properties) {
42
+ // A spread (`{ ...t }`, #2696 Step 2) has no static `name.key`
43
+ // member path to expose — skip it, same as an unresolvable value.
44
+ if (prop.kind === 'spread') continue
42
45
  const value = resolveObjectPropValue(prop.value, resolved)
43
46
  if (value !== null) resolved.set(`${c.name}.${prop.key}`, value)
44
47
  }