@barefootjs/test 0.18.4 → 0.18.5

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 +120 -19
  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
@@ -192701,6 +192772,7 @@ function createTransformContext(analyzer) {
192701
192772
  isRoot: true,
192702
192773
  insideComponentChildren: false,
192703
192774
  loopParams: new Set,
192775
+ loopDepth: 0,
192704
192776
  patterns: {
192705
192777
  signals: analyzer.signals.map((s) => ({
192706
192778
  getter: s.getter,
@@ -193354,7 +193426,7 @@ function transformText(node, ctx) {
193354
193426
  }
193355
193427
  return {
193356
193428
  type: "text",
193357
- value: text,
193429
+ value: decodeEntities(text),
193358
193430
  loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
193359
193431
  };
193360
193432
  }
@@ -193910,6 +193982,22 @@ function isIteratorShapeCall(node) {
193910
193982
  return null;
193911
193983
  return { array: node.expression.expression, shape: name };
193912
193984
  }
193985
+ function isObjectIteratorCall(node) {
193986
+ if (!import_typescript11.default.isCallExpression(node))
193987
+ return null;
193988
+ if (!import_typescript11.default.isPropertyAccessExpression(node.expression))
193989
+ return null;
193990
+ if (!import_typescript11.default.isIdentifier(node.expression.expression))
193991
+ return null;
193992
+ if (node.expression.expression.text !== "Object")
193993
+ return null;
193994
+ if (node.arguments.length !== 1)
193995
+ return null;
193996
+ const name = node.expression.name.text;
193997
+ if (name !== "entries" && name !== "keys" && name !== "values")
193998
+ return null;
193999
+ return { object: node.arguments[0], shape: name };
194000
+ }
193913
194001
  function extractSortComparator(callback, _method, ctx) {
193914
194002
  const outerRaw = ctx.getJS(callback);
193915
194003
  const unsupported = () => ({
@@ -194328,6 +194416,7 @@ function extractItemConditionalKey(cond) {
194328
194416
  }
194329
194417
  function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194330
194418
  const isNested = ctx.loopParams.size > 0;
194419
+ const depth = ctx.loopDepth;
194331
194420
  const propAccess = node.expression;
194332
194421
  const mapSource = propAccess.expression;
194333
194422
  let array = "";
@@ -194340,6 +194429,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194340
194429
  let templateMapPreamble;
194341
194430
  let typedMapPreamble;
194342
194431
  let iterationShape;
194432
+ let objectIteration;
194343
194433
  const setArray = (node2) => {
194344
194434
  array = ctx.getJS(node2);
194345
194435
  templateArray = rewriteBarePropRefs2(array, node2, ctx);
@@ -194354,6 +194444,12 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194354
194444
  } else if (iteratorInfo.shape === "keys") {
194355
194445
  iterationShape = "keys";
194356
194446
  }
194447
+ } else {
194448
+ const objectIteratorInfo = isObjectIteratorCall(mapSource);
194449
+ if (objectIteratorInfo) {
194450
+ chainSource = objectIteratorInfo.object;
194451
+ objectIteration = objectIteratorInfo.shape;
194452
+ }
194357
194453
  }
194358
194454
  const filterInfo = isFilterCall(chainSource);
194359
194455
  const sortInfo = isSortCall(chainSource);
@@ -194451,7 +194547,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194451
194547
  if (firstParam.type) {
194452
194548
  paramType = firstParam.type.getText(ctx.sourceFile);
194453
194549
  }
194454
- if (iterationShape === "entries" && import_typescript11.default.isArrayBindingPattern(firstParam.name)) {
194550
+ const isEntriesShape = iterationShape === "entries" || objectIteration === "entries";
194551
+ if (isEntriesShape && import_typescript11.default.isArrayBindingPattern(firstParam.name)) {
194455
194552
  const elements = firstParam.name.elements.filter((el) => !import_typescript11.default.isOmittedExpression(el));
194456
194553
  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
194554
  index = elements[0].name.text;
@@ -194473,7 +194570,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194473
194570
  }
194474
194571
  }
194475
194572
  }
194476
- if (callback.parameters.length > 1 && iterationShape !== "entries") {
194573
+ if (callback.parameters.length > 1 && iterationShape !== "entries" && objectIteration !== "entries") {
194477
194574
  const secondParam = callback.parameters[1];
194478
194575
  index = secondParam.name.getText(ctx.sourceFile);
194479
194576
  if (secondParam.type) {
@@ -194488,6 +194585,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194488
194585
  }
194489
194586
  if (index)
194490
194587
  ctx.loopParams.add(index);
194588
+ ctx.loopDepth++;
194491
194589
  const tryTransformRenderableBody = (expr) => {
194492
194590
  if (!import_typescript11.default.isBinaryExpression(expr))
194493
194591
  return;
@@ -194584,6 +194682,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194584
194682
  }
194585
194683
  if (index)
194586
194684
  ctx.loopParams.delete(index);
194685
+ ctx.loopDepth--;
194587
194686
  }
194588
194687
  if (children.length === 0 && !flatMapCallback) {
194589
194688
  return null;
@@ -194612,7 +194711,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194612
194711
  const callsReactive = exprCallsReactiveGetters(arrayExpr, ctx);
194613
194712
  const hasCalls = exprHasFunctionCalls(arrayExpr);
194614
194713
  const isDirectPropArray = method !== "flatMap" && isArrayExprDirectPropRef(arrayExpr, ctx);
194615
- const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls;
194714
+ const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls && !objectIteration;
194616
194715
  const nestedComponents = collectNestedComponents(children).filter((c) => c.name !== childComponent?.name);
194617
194716
  return {
194618
194717
  type: "loop",
@@ -194639,6 +194738,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
194639
194738
  sortComparator,
194640
194739
  chainOrder,
194641
194740
  iterationShape,
194741
+ objectIteration,
194742
+ depth,
194642
194743
  clientOnly: isClientOnly || undefined,
194643
194744
  mapPreamble,
194644
194745
  templateMapPreamble,
@@ -194881,7 +194982,7 @@ function getAttributeValue(attr, ctx) {
194881
194982
  return AttrValueOf.booleanAttr();
194882
194983
  }
194883
194984
  if (import_typescript11.default.isStringLiteral(attr.initializer)) {
194884
- return AttrValueOf.literal(attr.initializer.text);
194985
+ return AttrValueOf.literal(decodeEntities(attr.initializer.text));
194885
194986
  }
194886
194987
  if (import_typescript11.default.isJsxExpression(attr.initializer) && attr.initializer.expression) {
194887
194988
  let expr = attr.initializer.expression;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/test",
3
- "version": "0.18.4",
3
+ "version": "0.18.5",
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.5"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.0.0"