@barefootjs/test 0.18.4 → 0.18.7

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 +307 -98
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -187301,7 +187301,6 @@ var UNSUPPORTED_METHODS = new Set([
187301
187301
  "some",
187302
187302
  "forEach",
187303
187303
  "flatMap",
187304
- "replaceAll",
187305
187304
  "charAt",
187306
187305
  "charCodeAt",
187307
187306
  "codePointAt",
@@ -187477,6 +187476,9 @@ function convertNode(node, raw) {
187477
187476
  if (callee.property === "trim") {
187478
187477
  return { kind: "array-method", method: "trim", object: callee.object, args };
187479
187478
  }
187479
+ if (callee.property === "trimStart" || callee.property === "trimEnd") {
187480
+ return { kind: "array-method", method: callee.property, object: callee.object, args };
187481
+ }
187480
187482
  if (callee.property === "toFixed") {
187481
187483
  return { kind: "array-method", method: "toFixed", object: callee.object, args };
187482
187484
  }
@@ -187502,24 +187504,25 @@ function convertNode(node, raw) {
187502
187504
  }
187503
187505
  return { kind: "array-method", method: callee.property, object: callee.object, args };
187504
187506
  }
187505
- if (callee.property === "replace") {
187507
+ if (callee.property === "replace" || callee.property === "replaceAll") {
187508
+ const method = callee.property;
187506
187509
  if (args.length < 2) {
187507
187510
  return {
187508
187511
  kind: "unsupported",
187509
187512
  raw,
187510
- reason: `\`.replace(${args.length === 0 ? "" : "pattern"})\` needs both a pattern and a replacement — JS coerces the missing argument to the string "undefined", a degenerate result. Pass both arguments, or pre-compute the value before the template.`
187513
+ reason: `\`.${method}(${args.length === 0 ? "" : "pattern"})\` needs both a pattern and a replacement — JS coerces the missing argument to the string "undefined", a degenerate result. Pass both arguments, or pre-compute the value before the template.`
187511
187514
  };
187512
187515
  }
187513
187516
  const patternNode = node.arguments[0];
187514
187517
  if (patternNode && import_typescript.default.isRegularExpressionLiteral(patternNode)) {
187515
- return { kind: "array-method", method: "replace", object: callee.object, args };
187518
+ return { kind: "array-method", method, object: callee.object, args };
187516
187519
  }
187517
187520
  const badArg = args[0].kind === "unsupported" || args[0].kind === "object-literal" ? args[0] : args[1].kind === "unsupported" || args[1].kind === "object-literal" ? args[1] : undefined;
187518
187521
  if (badArg) {
187519
187522
  const reason = badArg.kind === "unsupported" ? badArg.reason : "Unsupported syntax: ObjectLiteralExpression";
187520
187523
  return { kind: "unsupported", raw, reason };
187521
187524
  }
187522
- return { kind: "array-method", method: "replace", object: callee.object, args };
187525
+ return { kind: "array-method", method, object: callee.object, args };
187523
187526
  }
187524
187527
  if (callee.property === "repeat") {
187525
187528
  return { kind: "array-method", method: "repeat", object: callee.object, args };
@@ -187554,7 +187557,7 @@ function convertNode(node, raw) {
187554
187557
  if (import_typescript.default.isPropertyAccessExpression(node)) {
187555
187558
  const object = convertNode(node.expression, raw);
187556
187559
  const property = node.name.text;
187557
- return { kind: "member", object, property, computed: false };
187560
+ return { kind: "member", object, property, computed: false, optional: !!node.questionDotToken };
187558
187561
  }
187559
187562
  if (import_typescript.default.isElementAccessExpression(node)) {
187560
187563
  const object = convertNode(node.expression, raw);
@@ -187563,10 +187566,10 @@ function convertNode(node, raw) {
187563
187566
  return { kind: "unsupported", raw, reason: "Element access with no index expression" };
187564
187567
  }
187565
187568
  if (import_typescript.default.isNumericLiteral(argNode)) {
187566
- return { kind: "member", object, property: argNode.text, computed: true };
187569
+ return { kind: "member", object, property: argNode.text, computed: true, optional: !!node.questionDotToken };
187567
187570
  }
187568
187571
  if (import_typescript.default.isStringLiteral(argNode)) {
187569
- return { kind: "member", object, property: argNode.text, computed: true };
187572
+ return { kind: "member", object, property: argNode.text, computed: true, optional: !!node.questionDotToken };
187570
187573
  }
187571
187574
  const index = convertNode(argNode, raw);
187572
187575
  if (index.kind === "unsupported" || index.kind === "object-literal")
@@ -188117,7 +188120,7 @@ function substituteDestructuredFields(expr, fieldMap, syntheticParam, restName)
188117
188120
  return e;
188118
188121
  let node = { kind: "identifier", name: syntheticParam };
188119
188122
  for (const segment of entry.path) {
188120
- node = { kind: "member", object: node, property: segment, computed: false };
188123
+ node = { kind: "member", object: node, property: segment, computed: false, optional: false };
188121
188124
  }
188122
188125
  if (entry.defaultExpr) {
188123
188126
  return { kind: "logical", op: "??", left: node, right: entry.defaultExpr };
@@ -188132,10 +188135,11 @@ function substituteDestructuredFields(expr, fieldMap, syntheticParam, restName)
188132
188135
  kind: "member",
188133
188136
  object: { kind: "identifier", name: syntheticParam },
188134
188137
  property: e.property,
188135
- computed: false
188138
+ computed: false,
188139
+ optional: e.optional
188136
188140
  };
188137
188141
  }
188138
- return { kind: "member", object: walk(e.object), property: e.property, computed: e.computed };
188142
+ return { kind: "member", object: walk(e.object), property: e.property, computed: e.computed, optional: e.optional };
188139
188143
  case "index-access":
188140
188144
  return { kind: "index-access", object: walk(e.object), index: walk(e.index) };
188141
188145
  case "binary":
@@ -188247,10 +188251,10 @@ function checkSupport(expr) {
188247
188251
  return { supported: true, level: "L2" };
188248
188252
  }
188249
188253
  case "array-method": {
188250
- if (expr.method === "replace" && expr.args[0]?.kind === "regex") {
188254
+ if ((expr.method === "replace" || expr.method === "replaceAll") && expr.args[0]?.kind === "regex") {
188251
188255
  return {
188252
188256
  supported: false,
188253
- reason: "String.prototype.replace supports only a string pattern + string replacement (the regex form is deferred); use a string pattern or wrap the expression in /* @client */"
188257
+ 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 */`
188254
188258
  };
188255
188259
  }
188256
188260
  const objSupport = checkSupport(expr.object);
@@ -188596,7 +188600,7 @@ function inlineBinding(expr, name, value) {
188596
188600
  case "call":
188597
188601
  return { kind: "call", callee: walk(e.callee, enclosing), args: e.args.map((a) => walk(a, enclosing)) };
188598
188602
  case "member":
188599
- return { kind: "member", object: walk(e.object, enclosing), property: e.property, computed: e.computed };
188603
+ return { kind: "member", object: walk(e.object, enclosing), property: e.property, computed: e.computed, optional: e.optional };
188600
188604
  case "index-access":
188601
188605
  return { kind: "index-access", object: walk(e.object, enclosing), index: walk(e.index, enclosing) };
188602
188606
  case "binary":
@@ -189095,6 +189099,73 @@ function toHTMLAttrName(key) {
189095
189099
  return svgKebab;
189096
189100
  return key;
189097
189101
  }
189102
+ // ../shared/src/html-entities.ts
189103
+ var NAMED_ENTITIES = {
189104
+ amp: "&",
189105
+ lt: "<",
189106
+ gt: ">",
189107
+ quot: '"',
189108
+ apos: "'",
189109
+ nbsp: " ",
189110
+ copy: "©",
189111
+ reg: "®",
189112
+ trade: "™",
189113
+ deg: "°",
189114
+ plusmn: "±",
189115
+ times: "×",
189116
+ divide: "÷",
189117
+ middot: "·",
189118
+ bull: "•",
189119
+ hellip: "…",
189120
+ ndash: "–",
189121
+ mdash: "—",
189122
+ lsquo: "‘",
189123
+ rsquo: "’",
189124
+ ldquo: "“",
189125
+ rdquo: "”",
189126
+ laquo: "«",
189127
+ raquo: "»",
189128
+ sect: "§",
189129
+ para: "¶",
189130
+ dagger: "†",
189131
+ Dagger: "‡",
189132
+ euro: "€",
189133
+ pound: "£",
189134
+ yen: "¥",
189135
+ cent: "¢",
189136
+ sup1: "¹",
189137
+ sup2: "²",
189138
+ sup3: "³",
189139
+ frac12: "½",
189140
+ frac14: "¼",
189141
+ frac34: "¾",
189142
+ larr: "←",
189143
+ uarr: "↑",
189144
+ rarr: "→",
189145
+ darr: "↓",
189146
+ harr: "↔",
189147
+ minus: "−",
189148
+ infin: "∞",
189149
+ ne: "≠",
189150
+ le: "≤",
189151
+ ge: "≥"
189152
+ };
189153
+ function decodeEntities(text) {
189154
+ return text.replace(/&(#[xX]?[0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);/g, (match, body) => {
189155
+ if (body[0] === "#") {
189156
+ const isHex = body[1] === "x" || body[1] === "X";
189157
+ const digits = body.slice(isHex ? 2 : 1);
189158
+ if (!isHex && !/^[0-9]+$/.test(digits))
189159
+ return match;
189160
+ const code2 = parseInt(digits, isHex ? 16 : 10);
189161
+ if (!Number.isFinite(code2) || code2 > 1114111 || code2 >= 55296 && code2 <= 57343) {
189162
+ return match;
189163
+ }
189164
+ return String.fromCodePoint(code2);
189165
+ }
189166
+ return NAMED_ENTITIES[body] ?? match;
189167
+ });
189168
+ }
189098
189169
  // ../jsx/src/ir-to-client-js/utils.ts
189099
189170
  var PROPS_PARAM = "_p";
189100
189171
  // ../jsx/src/ir-to-client-js/component-scope.ts
@@ -189179,6 +189250,32 @@ var VOID_ELEMENTS = new Set([
189179
189250
  "track",
189180
189251
  "wbr"
189181
189252
  ]);
189253
+ var SKELETON_PATH_HAZARD_TAGS = new Set([
189254
+ "table",
189255
+ "thead",
189256
+ "tbody",
189257
+ "tfoot",
189258
+ "caption",
189259
+ "colgroup",
189260
+ "col",
189261
+ "select",
189262
+ "optgroup",
189263
+ "p",
189264
+ "pre",
189265
+ "textarea",
189266
+ "listing",
189267
+ "template",
189268
+ "math"
189269
+ ]);
189270
+ var SKELETON_PATH_FORCE_CLOSE_GROUPS = [
189271
+ new Set(["a"]),
189272
+ new Set(["button"]),
189273
+ new Set(["form"]),
189274
+ new Set(["option"]),
189275
+ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]),
189276
+ new Set(["dd", "dt"]),
189277
+ new Set(["li"])
189278
+ ];
189182
189279
 
189183
189280
  // ../jsx/src/prop-rewrite.ts
189184
189281
  function collectAstPropRefs(node, propNames, out) {
@@ -189706,6 +189803,8 @@ function needsTypeBasedDetection(source) {
189706
189803
  return true;
189707
189804
  if (/\.map\s*\(/.test(source))
189708
189805
  return true;
189806
+ if (source.includes("createSelector"))
189807
+ return true;
189709
189808
  return false;
189710
189809
  }
189711
189810
  function findBrandPackageImportLoc(sourceFile, filePath) {
@@ -190682,6 +190781,7 @@ var CLIENT_EXPORTS = new Set([
190682
190781
  "createEffect",
190683
190782
  "createDisposableEffect",
190684
190783
  "createMemo",
190784
+ "createSelector",
190685
190785
  "createRoot",
190686
190786
  "onCleanup",
190687
190787
  "onMount",
@@ -192634,9 +192734,15 @@ function exprHasFunctionCalls(expr) {
192634
192734
  return found;
192635
192735
  }
192636
192736
  function rewriteBarePropRefs2(text, expr, ctx) {
192637
- const propNames = getDestructuredPropNames(ctx);
192737
+ let propNames = getDestructuredPropNames(ctx);
192638
192738
  if (!propNames)
192639
192739
  return;
192740
+ if (ctx.loopParams.size > 0) {
192741
+ const filtered = new Set([...propNames].filter((n) => !ctx.loopParams.has(n)));
192742
+ if (filtered.size === 0)
192743
+ return;
192744
+ propNames = filtered;
192745
+ }
192640
192746
  const extraPropRefs = collectBranchLocalPropRefsViaSubstitution(expr, ctx);
192641
192747
  return rewriteBarePropRefs(text, expr, propNames, extraPropRefs);
192642
192748
  }
@@ -192701,6 +192807,7 @@ function createTransformContext(analyzer) {
192701
192807
  isRoot: true,
192702
192808
  insideComponentChildren: false,
192703
192809
  loopParams: new Set,
192810
+ loopDepth: 0,
192704
192811
  patterns: {
192705
192812
  signals: analyzer.signals.map((s) => ({
192706
192813
  getter: s.getter,
@@ -192801,26 +192908,29 @@ function makeBindingEnv(ctx) {
192801
192908
  function parseValueExpr(trimmed) {
192802
192909
  return parseExpression(trimmed.startsWith("{") ? `(${trimmed})` : trimmed);
192803
192910
  }
192804
- function attachParsedExpressions(node) {
192911
+ var EMPTY_BOUND = new Set;
192912
+ function attachParsedExpressions(node, analyzer, bound = EMPTY_BOUND) {
192913
+ const parse2 = (trimmed) => resolveCallbackMethodFunctionReferences(parseExpression(trimmed), analyzer, bound);
192914
+ const parseValue = (trimmed) => resolveCallbackMethodFunctionReferences(parseValueExpr(trimmed), analyzer, bound);
192805
192915
  if (node.type === "expression") {
192806
192916
  const trimmed = node.expr.trim();
192807
192917
  if (trimmed)
192808
- node.parsed = parseExpression(trimmed);
192918
+ node.parsed = parse2(trimmed);
192809
192919
  } else if (node.type === "conditional" || node.type === "if-statement") {
192810
192920
  const trimmed = node.condition.trim();
192811
192921
  if (trimmed)
192812
- node.parsedCondition = parseExpression(trimmed);
192922
+ node.parsedCondition = parse2(trimmed);
192813
192923
  }
192814
192924
  if (node.type === "element") {
192815
192925
  for (const attr of node.attrs) {
192816
192926
  if (attr.value.kind === "expression") {
192817
192927
  const trimmed = attr.value.expr.trim();
192818
192928
  if (trimmed)
192819
- attr.value.parsed = parseValueExpr(trimmed);
192929
+ attr.value.parsed = parseValue(trimmed);
192820
192930
  } else if (attr.value.kind === "spread") {
192821
192931
  const trimmed = attr.value.expr.trim();
192822
192932
  if (trimmed)
192823
- attr.value.parsed = parseExpression(trimmed);
192933
+ attr.value.parsed = parse2(trimmed);
192824
192934
  }
192825
192935
  }
192826
192936
  } else if (node.type === "component") {
@@ -192828,14 +192938,14 @@ function attachParsedExpressions(node) {
192828
192938
  if (prop.value.kind === "expression") {
192829
192939
  const trimmed = prop.value.expr.trim();
192830
192940
  if (trimmed)
192831
- prop.value.parsed = parseValueExpr(trimmed);
192941
+ prop.value.parsed = parseValue(trimmed);
192832
192942
  }
192833
192943
  }
192834
192944
  } else if (node.type === "provider") {
192835
192945
  if (node.valueProp.value.kind === "expression") {
192836
192946
  const trimmed = node.valueProp.value.expr.trim();
192837
192947
  if (trimmed)
192838
- node.valueProp.value.parsed = parseValueExpr(trimmed);
192948
+ node.valueProp.value.parsed = parseValue(trimmed);
192839
192949
  }
192840
192950
  }
192841
192951
  switch (node.type) {
@@ -192844,47 +192954,51 @@ function attachParsedExpressions(node) {
192844
192954
  case "fragment":
192845
192955
  case "provider":
192846
192956
  for (const child of node.children)
192847
- attachParsedExpressions(child);
192957
+ attachParsedExpressions(child, analyzer, bound);
192848
192958
  break;
192849
192959
  case "async":
192850
- attachParsedExpressions(node.fallback);
192960
+ attachParsedExpressions(node.fallback, analyzer, bound);
192851
192961
  for (const child of node.children)
192852
- attachParsedExpressions(child);
192962
+ attachParsedExpressions(child, analyzer, bound);
192853
192963
  break;
192854
192964
  case "loop": {
192855
192965
  const trimmedArray = node.array.trim();
192856
192966
  if (trimmedArray)
192857
- node.arrayParsed = parseExpression(trimmedArray);
192967
+ node.arrayParsed = parse2(trimmedArray);
192968
+ const loopBound = new Set(bound);
192969
+ loopBound.add(node.param);
192970
+ if (node.index)
192971
+ loopBound.add(node.index);
192858
192972
  for (const child of node.children)
192859
- attachParsedExpressions(child);
192973
+ attachParsedExpressions(child, analyzer, loopBound);
192860
192974
  if (node.childComponent) {
192861
192975
  for (const child of node.childComponent.children)
192862
- attachParsedExpressions(child);
192976
+ attachParsedExpressions(child, analyzer, loopBound);
192863
192977
  }
192864
192978
  for (const nested of node.nestedComponents ?? []) {
192865
192979
  for (const child of nested.children)
192866
- attachParsedExpressions(child);
192980
+ attachParsedExpressions(child, analyzer, loopBound);
192867
192981
  }
192868
192982
  for (const frag of node.flatMapCallback?.fragments ?? []) {
192869
- attachParsedExpressions(frag.ir);
192983
+ attachParsedExpressions(frag.ir, analyzer, loopBound);
192870
192984
  }
192871
192985
  break;
192872
192986
  }
192873
192987
  case "conditional":
192874
- attachParsedExpressions(node.whenTrue);
192875
- attachParsedExpressions(node.whenFalse);
192988
+ attachParsedExpressions(node.whenTrue, analyzer, bound);
192989
+ attachParsedExpressions(node.whenFalse, analyzer, bound);
192876
192990
  break;
192877
192991
  case "if-statement":
192878
- attachParsedExpressions(node.consequent);
192992
+ attachParsedExpressions(node.consequent, analyzer, bound);
192879
192993
  if (node.alternate)
192880
- attachParsedExpressions(node.alternate);
192994
+ attachParsedExpressions(node.alternate, analyzer, bound);
192881
192995
  break;
192882
192996
  }
192883
192997
  }
192884
192998
  function jsxToIR(analyzer) {
192885
192999
  const root = buildIRRoot(analyzer);
192886
193000
  if (root)
192887
- attachParsedExpressions(root);
193001
+ attachParsedExpressions(root, analyzer);
192888
193002
  return root;
192889
193003
  }
192890
193004
  function buildIRRoot(analyzer) {
@@ -193354,7 +193468,7 @@ function transformText(node, ctx) {
193354
193468
  }
193355
193469
  return {
193356
193470
  type: "text",
193357
- value: text,
193471
+ value: decodeEntities(text),
193358
193472
  loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
193359
193473
  };
193360
193474
  }
@@ -193910,6 +194024,22 @@ function isIteratorShapeCall(node) {
193910
194024
  return null;
193911
194025
  return { array: node.expression.expression, shape: name };
193912
194026
  }
194027
+ function isObjectIteratorCall(node) {
194028
+ if (!import_typescript11.default.isCallExpression(node))
194029
+ return null;
194030
+ if (!import_typescript11.default.isPropertyAccessExpression(node.expression))
194031
+ return null;
194032
+ if (!import_typescript11.default.isIdentifier(node.expression.expression))
194033
+ return null;
194034
+ if (node.expression.expression.text !== "Object")
194035
+ return null;
194036
+ if (node.arguments.length !== 1)
194037
+ return null;
194038
+ const name = node.expression.name.text;
194039
+ if (name !== "entries" && name !== "keys" && name !== "values")
194040
+ return null;
194041
+ return { object: node.arguments[0], shape: name };
194042
+ }
193913
194043
  function extractSortComparator(callback, _method, ctx) {
193914
194044
  const outerRaw = ctx.getJS(callback);
193915
194045
  const unsupported = () => ({
@@ -193955,8 +194085,8 @@ function extractSortComparator(callback, _method, ctx) {
193955
194085
  };
193956
194086
  }
193957
194087
  function resolveSortComparatorIdentifier(name, ctx) {
193958
- const constInfo = findLocalConst(name, ctx);
193959
- const fnInfo = findLocalFunction(name, ctx);
194088
+ const constInfo = findLocalConst(name, ctx.analyzer);
194089
+ const fnInfo = findLocalFunction(name, ctx.analyzer);
193960
194090
  if (constInfo && fnInfo)
193961
194091
  return null;
193962
194092
  if (constInfo) {
@@ -193969,6 +194099,72 @@ function resolveSortComparatorIdentifier(name, ctx) {
193969
194099
  }
193970
194100
  return null;
193971
194101
  }
194102
+ function resolveCallbackMethodFunctionReferenceIdentifier(name, analyzer) {
194103
+ const constInfo = findLocalConst(name, analyzer);
194104
+ const fnInfo = findLocalFunction(name, analyzer);
194105
+ if (constInfo && fnInfo)
194106
+ return null;
194107
+ if (constInfo) {
194108
+ const ast = parseConstInitializer(constInfo);
194109
+ return ast && (import_typescript11.default.isArrowFunction(ast) || import_typescript11.default.isFunctionExpression(ast)) ? ast : null;
194110
+ }
194111
+ if (fnInfo) {
194112
+ const ast = parseFunctionInfoAsExpr(fnInfo);
194113
+ return ast && (import_typescript11.default.isArrowFunction(ast) || import_typescript11.default.isFunctionExpression(ast)) ? ast : null;
194114
+ }
194115
+ return null;
194116
+ }
194117
+ function resolveCallbackMethodFunctionReferences(expr, analyzer, bound = EMPTY_BOUND) {
194118
+ function visit2(e, bound2) {
194119
+ switch (e.kind) {
194120
+ case "literal":
194121
+ case "identifier":
194122
+ case "regex":
194123
+ case "unsupported":
194124
+ return e;
194125
+ case "call": {
194126
+ const callee = visit2(e.callee, bound2);
194127
+ const args = e.args.map((a) => visit2(a, bound2));
194128
+ if (callee.kind === "member" && !callee.computed && CALLBACK_METHODS.has(callee.property) && args[0]?.kind === "identifier" && !bound2.has(args[0].name)) {
194129
+ const resolved = resolveCallbackMethodFunctionReferenceIdentifier(args[0].name, analyzer);
194130
+ const arrow = resolved ? tsNodeToParsedExpr(resolved) : null;
194131
+ if (arrow && arrow.kind === "arrow")
194132
+ args[0] = arrow;
194133
+ }
194134
+ return { ...e, callee, args };
194135
+ }
194136
+ case "member":
194137
+ return { ...e, object: visit2(e.object, bound2) };
194138
+ case "index-access":
194139
+ return { ...e, object: visit2(e.object, bound2), index: visit2(e.index, bound2) };
194140
+ case "binary":
194141
+ case "logical":
194142
+ return { ...e, left: visit2(e.left, bound2), right: visit2(e.right, bound2) };
194143
+ case "unary":
194144
+ return { ...e, argument: visit2(e.argument, bound2) };
194145
+ case "conditional":
194146
+ return { ...e, test: visit2(e.test, bound2), consequent: visit2(e.consequent, bound2), alternate: visit2(e.alternate, bound2) };
194147
+ case "template-literal":
194148
+ return { ...e, parts: e.parts.map((p) => p.type === "expression" ? { ...p, expr: visit2(p.expr, bound2) } : p) };
194149
+ case "array-literal":
194150
+ return { ...e, elements: e.elements.map((el) => visit2(el, bound2)) };
194151
+ case "array-method":
194152
+ return {
194153
+ ...e,
194154
+ object: visit2(e.object, bound2),
194155
+ args: e.args.map((a) => visit2(a, bound2)),
194156
+ ...e.method === "flat" && e.depthExpr ? { depthExpr: visit2(e.depthExpr, bound2) } : {}
194157
+ };
194158
+ case "object-literal":
194159
+ return { ...e, properties: e.properties.map((p) => ({ ...p, value: visit2(p.value, bound2) })) };
194160
+ case "arrow": {
194161
+ const inner = e.params.length === 0 ? bound2 : new Set([...bound2, ...e.params]);
194162
+ return { ...e, body: visit2(e.body, inner) };
194163
+ }
194164
+ }
194165
+ }
194166
+ return visit2(expr, bound);
194167
+ }
193972
194168
  function extractFilterPredicate(callback, ctx) {
193973
194169
  if (!import_typescript11.default.isArrowFunction(callback))
193974
194170
  return { result: null };
@@ -194328,6 +194524,7 @@ function extractItemConditionalKey(cond) {
194328
194524
  }
194329
194525
  function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194330
194526
  const isNested = ctx.loopParams.size > 0;
194527
+ const depth = ctx.loopDepth;
194331
194528
  const propAccess = node.expression;
194332
194529
  const mapSource = propAccess.expression;
194333
194530
  let array = "";
@@ -194340,6 +194537,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194340
194537
  let templateMapPreamble;
194341
194538
  let typedMapPreamble;
194342
194539
  let iterationShape;
194540
+ let objectIteration;
194343
194541
  const setArray = (node2) => {
194344
194542
  array = ctx.getJS(node2);
194345
194543
  templateArray = rewriteBarePropRefs2(array, node2, ctx);
@@ -194354,6 +194552,12 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194354
194552
  } else if (iteratorInfo.shape === "keys") {
194355
194553
  iterationShape = "keys";
194356
194554
  }
194555
+ } else {
194556
+ const objectIteratorInfo = isObjectIteratorCall(mapSource);
194557
+ if (objectIteratorInfo) {
194558
+ chainSource = objectIteratorInfo.object;
194559
+ objectIteration = objectIteratorInfo.shape;
194560
+ }
194357
194561
  }
194358
194562
  const filterInfo = isFilterCall(chainSource);
194359
194563
  const sortInfo = isSortCall(chainSource);
@@ -194428,13 +194632,11 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194428
194632
  setArray(innerSort.array);
194429
194633
  }
194430
194634
  } else {
194431
- array = ctx.getJS(filterInfo.array);
194432
- arrayExpr = filterInfo.array;
194635
+ setArray(filterInfo.array);
194433
194636
  }
194434
194637
  }
194435
194638
  } else {
194436
- array = ctx.getJS(chainSource);
194437
- arrayExpr = chainSource;
194639
+ setArray(chainSource);
194438
194640
  }
194439
194641
  const callback = node.arguments[0];
194440
194642
  let param = "item";
@@ -194451,7 +194653,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194451
194653
  if (firstParam.type) {
194452
194654
  paramType = firstParam.type.getText(ctx.sourceFile);
194453
194655
  }
194454
- if (iterationShape === "entries" && import_typescript11.default.isArrayBindingPattern(firstParam.name)) {
194656
+ const isEntriesShape = iterationShape === "entries" || objectIteration === "entries";
194657
+ if (isEntriesShape && import_typescript11.default.isArrayBindingPattern(firstParam.name)) {
194455
194658
  const elements = firstParam.name.elements.filter((el) => !import_typescript11.default.isOmittedExpression(el));
194456
194659
  if (elements.length === 2 && import_typescript11.default.isBindingElement(elements[0]) && import_typescript11.default.isIdentifier(elements[0].name) && import_typescript11.default.isBindingElement(elements[1]) && import_typescript11.default.isIdentifier(elements[1].name)) {
194457
194660
  index = elements[0].name.text;
@@ -194473,7 +194676,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194473
194676
  }
194474
194677
  }
194475
194678
  }
194476
- if (callback.parameters.length > 1 && iterationShape !== "entries") {
194679
+ if (callback.parameters.length > 1 && iterationShape !== "entries" && objectIteration !== "entries") {
194477
194680
  const secondParam = callback.parameters[1];
194478
194681
  index = secondParam.name.getText(ctx.sourceFile);
194479
194682
  if (secondParam.type) {
@@ -194488,6 +194691,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194488
194691
  }
194489
194692
  if (index)
194490
194693
  ctx.loopParams.add(index);
194694
+ ctx.loopDepth++;
194491
194695
  const tryTransformRenderableBody = (expr) => {
194492
194696
  if (!import_typescript11.default.isBinaryExpression(expr))
194493
194697
  return;
@@ -194584,6 +194788,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194584
194788
  }
194585
194789
  if (index)
194586
194790
  ctx.loopParams.delete(index);
194791
+ ctx.loopDepth--;
194587
194792
  }
194588
194793
  if (children.length === 0 && !flatMapCallback) {
194589
194794
  return null;
@@ -194612,7 +194817,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194612
194817
  const callsReactive = exprCallsReactiveGetters(arrayExpr, ctx);
194613
194818
  const hasCalls = exprHasFunctionCalls(arrayExpr);
194614
194819
  const isDirectPropArray = method !== "flatMap" && isArrayExprDirectPropRef(arrayExpr, ctx);
194615
- const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls;
194820
+ const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls && !objectIteration;
194616
194821
  const nestedComponents = collectNestedComponents(children).filter((c) => c.name !== childComponent?.name);
194617
194822
  return {
194618
194823
  type: "loop",
@@ -194639,6 +194844,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194639
194844
  sortComparator,
194640
194845
  chainOrder,
194641
194846
  iterationShape,
194847
+ objectIteration,
194848
+ depth,
194642
194849
  clientOnly: isClientOnly || undefined,
194643
194850
  mapPreamble,
194644
194851
  templateMapPreamble,
@@ -194881,7 +195088,7 @@ function getAttributeValue(attr, ctx) {
194881
195088
  return AttrValueOf.booleanAttr();
194882
195089
  }
194883
195090
  if (import_typescript11.default.isStringLiteral(attr.initializer)) {
194884
- return AttrValueOf.literal(attr.initializer.text);
195091
+ return AttrValueOf.literal(decodeEntities(attr.initializer.text));
194885
195092
  }
194886
195093
  if (import_typescript11.default.isJsxExpression(attr.initializer) && attr.initializer.expression) {
194887
195094
  let expr = attr.initializer.expression;
@@ -194979,7 +195186,7 @@ function parseTemplateLiteral(expr, ctx) {
194979
195186
  }
194980
195187
  function tryResolveTemplateSpanFromConst(expr, ctx) {
194981
195188
  if (import_typescript11.default.isIdentifier(expr)) {
194982
- const constInfo = findLocalConst(expr.text, ctx);
195189
+ const constInfo = findLocalConst(expr.text, ctx.analyzer);
194983
195190
  if (!constInfo)
194984
195191
  return null;
194985
195192
  const ast = parseConstInitializer(constInfo);
@@ -194993,7 +195200,7 @@ function tryResolveTemplateSpanFromConst(expr, ctx) {
194993
195200
  if (import_typescript11.default.isElementAccessExpression(expr)) {
194994
195201
  if (!import_typescript11.default.isIdentifier(expr.expression))
194995
195202
  return null;
194996
- const constInfo = findLocalConst(expr.expression.text, ctx);
195203
+ const constInfo = findLocalConst(expr.expression.text, ctx.analyzer);
194997
195204
  if (!constInfo)
194998
195205
  return null;
194999
195206
  const ast = parseConstInitializer(constInfo);
@@ -195019,16 +195226,16 @@ function tryResolveTemplateSpanFromConst(expr, ctx) {
195019
195226
  }
195020
195227
  return null;
195021
195228
  }
195022
- function findLocalConst(name, ctx) {
195023
- const matches = ctx.analyzer.localConstants.filter((c) => c.name === name);
195229
+ function findLocalConst(name, analyzer) {
195230
+ const matches = analyzer.localConstants.filter((c) => c.name === name);
195024
195231
  if (matches.length === 0)
195025
195232
  return;
195026
195233
  const fnScoped = matches.filter((c) => !c.isModule);
195027
195234
  const pool = fnScoped.length > 0 ? fnScoped : matches;
195028
195235
  return pool[pool.length - 1];
195029
195236
  }
195030
- function findLocalFunction(name, ctx) {
195031
- const matches = ctx.analyzer.localFunctions.filter((f) => f.name === name);
195237
+ function findLocalFunction(name, analyzer) {
195238
+ const matches = analyzer.localFunctions.filter((f) => f.name === name);
195032
195239
  if (matches.length === 0)
195033
195240
  return;
195034
195241
  const fnScoped = matches.filter((f) => !f.isModule);
@@ -195070,7 +195277,9 @@ function hasDynamicTagBinding(name, sourceFile) {
195070
195277
  return found;
195071
195278
  }
195072
195279
  function tryResolveIdentifierAsTemplateLiteral(ident, ctx) {
195073
- const constInfo = findLocalConst(ident.text, ctx);
195280
+ if (ctx.loopParams.has(ident.text))
195281
+ return null;
195282
+ const constInfo = findLocalConst(ident.text, ctx.analyzer);
195074
195283
  if (!constInfo)
195075
195284
  return null;
195076
195285
  const ast = parseConstInitializer(constInfo);
@@ -195167,8 +195376,8 @@ function tryDesugarInterleaveTaggedTemplate(expr, ctx) {
195167
195376
  return rewritten ?? expr;
195168
195377
  }
195169
195378
  function resolveInterleaveTagIdentifier(name, ctx) {
195170
- const constInfo = findLocalConst(name, ctx);
195171
- const fnInfo = findLocalFunction(name, ctx);
195379
+ const constInfo = findLocalConst(name, ctx.analyzer);
195380
+ const fnInfo = findLocalFunction(name, ctx.analyzer);
195172
195381
  if (constInfo && fnInfo)
195173
195382
  return null;
195174
195383
  if (constInfo) {
@@ -195693,6 +195902,49 @@ function buildIfStatementChain(analyzer, ctx) {
195693
195902
  return alternate;
195694
195903
  }
195695
195904
 
195905
+ // ../jsx/src/ir-to-client-js/control-flow/stringify/template-parse.ts
195906
+ var SVG_ROOT_TAGS = new Set([
195907
+ "svg",
195908
+ "path",
195909
+ "circle",
195910
+ "rect",
195911
+ "line",
195912
+ "polyline",
195913
+ "polygon",
195914
+ "ellipse",
195915
+ "text",
195916
+ "tspan",
195917
+ "textPath",
195918
+ "g",
195919
+ "defs",
195920
+ "use",
195921
+ "symbol",
195922
+ "switch",
195923
+ "clipPath",
195924
+ "mask",
195925
+ "marker",
195926
+ "pattern",
195927
+ "linearGradient",
195928
+ "radialGradient",
195929
+ "stop",
195930
+ "image",
195931
+ "foreignObject",
195932
+ "filter",
195933
+ "feBlend",
195934
+ "feColorMatrix",
195935
+ "feComposite",
195936
+ "feFlood",
195937
+ "feGaussianBlur",
195938
+ "feMerge",
195939
+ "feMergeNode",
195940
+ "feMorphology",
195941
+ "feOffset",
195942
+ "feTurbulence",
195943
+ "animate",
195944
+ "animateTransform",
195945
+ "animateMotion"
195946
+ ]);
195947
+
195696
195948
  // ../jsx/src/ir-to-client-js/collect-elements.ts
195697
195949
  var EMPTY_RENDER_EXPRS = new Set(["null", "undefined", "false", "''", '""', "``"]);
195698
195950
 
@@ -195908,49 +196160,6 @@ var QUERY_HREF_SOURCES = new Set([
195908
196160
  "@barefootjs/client/runtime"
195909
196161
  ]);
195910
196162
 
195911
- // ../jsx/src/ir-to-client-js/control-flow/stringify/template-parse.ts
195912
- var SVG_ROOT_TAGS = new Set([
195913
- "svg",
195914
- "path",
195915
- "circle",
195916
- "rect",
195917
- "line",
195918
- "polyline",
195919
- "polygon",
195920
- "ellipse",
195921
- "text",
195922
- "tspan",
195923
- "textPath",
195924
- "g",
195925
- "defs",
195926
- "use",
195927
- "symbol",
195928
- "switch",
195929
- "clipPath",
195930
- "mask",
195931
- "marker",
195932
- "pattern",
195933
- "linearGradient",
195934
- "radialGradient",
195935
- "stop",
195936
- "image",
195937
- "foreignObject",
195938
- "filter",
195939
- "feBlend",
195940
- "feColorMatrix",
195941
- "feComposite",
195942
- "feFlood",
195943
- "feGaussianBlur",
195944
- "feMerge",
195945
- "feMergeNode",
195946
- "feMorphology",
195947
- "feOffset",
195948
- "feTurbulence",
195949
- "animate",
195950
- "animateTransform",
195951
- "animateMotion"
195952
- ]);
195953
-
195954
196163
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
195955
196164
  var NON_BUBBLING_EVENTS = new Set([
195956
196165
  "blur",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/test",
3
- "version": "0.18.4",
3
+ "version": "0.18.7",
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.18.4"
42
+ "@barefootjs/jsx": "0.18.7"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.0.0"