@barefootjs/test 0.6.0 → 0.7.0
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 +233 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -190459,7 +190459,6 @@ var UNSUPPORTED_METHODS = new Set([
|
|
|
190459
190459
|
"some",
|
|
190460
190460
|
"forEach",
|
|
190461
190461
|
"flatMap",
|
|
190462
|
-
"flat",
|
|
190463
190462
|
"replaceAll",
|
|
190464
190463
|
"charAt",
|
|
190465
190464
|
"charCodeAt",
|
|
@@ -190471,6 +190470,9 @@ var UNSUPPORTED_METHODS = new Set([
|
|
|
190471
190470
|
"matchAll",
|
|
190472
190471
|
"search"
|
|
190473
190472
|
]);
|
|
190473
|
+
var UNSUPPORTED_METHOD_REASONS = {
|
|
190474
|
+
forEach: `'.forEach()' returns undefined and has no template-position meaning. ` + `Use it for side effects inside an event handler or createEffect callback ` + `(client JS), or use '.map(...)' if you meant to render each item.`
|
|
190475
|
+
};
|
|
190474
190476
|
var LOWERED_ARRAY_METHODS = new Set([
|
|
190475
190477
|
"includes",
|
|
190476
190478
|
"indexOf",
|
|
@@ -190558,6 +190560,32 @@ function convertNode(node, raw) {
|
|
|
190558
190560
|
if (callee.property === "reverse" || callee.property === "toReversed") {
|
|
190559
190561
|
return { kind: "array-method", method: callee.property, object: callee.object, args };
|
|
190560
190562
|
}
|
|
190563
|
+
if (callee.property === "flat") {
|
|
190564
|
+
const depthNode = node.arguments[0];
|
|
190565
|
+
let flatDepth;
|
|
190566
|
+
if (depthNode === undefined) {
|
|
190567
|
+
flatDepth = 1;
|
|
190568
|
+
} else if (import_typescript8.default.isIdentifier(depthNode) && depthNode.text === "Infinity") {
|
|
190569
|
+
flatDepth = "infinity";
|
|
190570
|
+
} else {
|
|
190571
|
+
let n;
|
|
190572
|
+
if (import_typescript8.default.isNumericLiteral(depthNode)) {
|
|
190573
|
+
n = Number(depthNode.text);
|
|
190574
|
+
} else if (import_typescript8.default.isPrefixUnaryExpression(depthNode) && depthNode.operator === import_typescript8.default.SyntaxKind.MinusToken && import_typescript8.default.isNumericLiteral(depthNode.operand)) {
|
|
190575
|
+
n = -Number(depthNode.operand.text);
|
|
190576
|
+
}
|
|
190577
|
+
if (n === undefined || Number.isNaN(n)) {
|
|
190578
|
+
return {
|
|
190579
|
+
kind: "unsupported",
|
|
190580
|
+
raw,
|
|
190581
|
+
reason: `\`.flat(depth)\` needs a literal integer or \`Infinity\` depth — a computed depth can't be resolved at template time. Use a literal depth, or pre-compute the value before the template.`
|
|
190582
|
+
};
|
|
190583
|
+
}
|
|
190584
|
+
const truncated = Math.trunc(n);
|
|
190585
|
+
flatDepth = truncated < 0 ? 0 : truncated;
|
|
190586
|
+
}
|
|
190587
|
+
return { kind: "array-method", method: "flat", object: callee.object, args: [], flatDepth };
|
|
190588
|
+
}
|
|
190561
190589
|
if (callee.property === "toLowerCase") {
|
|
190562
190590
|
return { kind: "array-method", method: "toLowerCase", object: callee.object, args };
|
|
190563
190591
|
}
|
|
@@ -190641,6 +190669,50 @@ function convertNode(node, raw) {
|
|
|
190641
190669
|
` + `(reverse the operands for descending order). ` + `Wrap the call in /* @client */ to evaluate at hydration.`
|
|
190642
190670
|
};
|
|
190643
190671
|
}
|
|
190672
|
+
if ((callee.property === "reduce" || callee.property === "reduceRight") && node.arguments.length === 2) {
|
|
190673
|
+
const reduceOp = extractReduceOpFromTS(node.arguments[0], node.arguments[1]);
|
|
190674
|
+
if (reduceOp) {
|
|
190675
|
+
return {
|
|
190676
|
+
kind: "array-method",
|
|
190677
|
+
method: callee.property,
|
|
190678
|
+
object: callee.object,
|
|
190679
|
+
args: [],
|
|
190680
|
+
reduceOp
|
|
190681
|
+
};
|
|
190682
|
+
}
|
|
190683
|
+
const m = callee.property;
|
|
190684
|
+
return {
|
|
190685
|
+
kind: "unsupported",
|
|
190686
|
+
raw,
|
|
190687
|
+
reason: `Reduce shape not supported. Accepted (arithmetic fold, explicit init):
|
|
190688
|
+
` + ` arr.${m}((acc, x) => acc + x, 0)
|
|
190689
|
+
` + ` arr.${m}((acc, x) => acc + x.field, 0)
|
|
190690
|
+
` + ` arr.${m}((acc, x) => acc * x.field, 1)
|
|
190691
|
+
` + ` arr.${m}((acc, x) => acc + x.field, '') (string concat)
|
|
190692
|
+
` + `The accumulator must be the left operand and the initial ` + `value a number / string literal. ` + `Wrap the call in /* @client */ to evaluate at hydration.`
|
|
190693
|
+
};
|
|
190694
|
+
}
|
|
190695
|
+
if (callee.property === "flatMap") {
|
|
190696
|
+
const flatMapOp = node.arguments.length === 1 ? extractFlatMapOpFromTS(node.arguments[0]) : null;
|
|
190697
|
+
if (flatMapOp) {
|
|
190698
|
+
return {
|
|
190699
|
+
kind: "array-method",
|
|
190700
|
+
method: "flatMap",
|
|
190701
|
+
object: callee.object,
|
|
190702
|
+
args: [],
|
|
190703
|
+
flatMapOp
|
|
190704
|
+
};
|
|
190705
|
+
}
|
|
190706
|
+
return {
|
|
190707
|
+
kind: "unsupported",
|
|
190708
|
+
raw,
|
|
190709
|
+
reason: `flatMap shape not supported. Accepted (self / field leaves, no thisArg):
|
|
190710
|
+
` + ` arr.flatMap(i => i) (flatten one level)
|
|
190711
|
+
` + ` arr.flatMap(i => i.field) (flatten a per-item array field)
|
|
190712
|
+
` + ` arr.flatMap(i => [i.a, i.b]) (gather per-item fields)
|
|
190713
|
+
` + `Richer callbacks (computed / nested access, arithmetic, calls, ` + `literal elements) and the 2-arg \`flatMap(fn, thisArg)\` form ` + `aren't lowered. Wrap the call in /* @client */ to evaluate at hydration.`
|
|
190714
|
+
};
|
|
190715
|
+
}
|
|
190644
190716
|
}
|
|
190645
190717
|
return { kind: "call", callee, args };
|
|
190646
190718
|
}
|
|
@@ -190959,6 +191031,119 @@ function classifySortOperand(expr, paramA, paramB) {
|
|
|
190959
191031
|
}
|
|
190960
191032
|
return null;
|
|
190961
191033
|
}
|
|
191034
|
+
function extractReduceOpFromTS(reducerNode, initNode) {
|
|
191035
|
+
const init = classifyReduceInit(initNode);
|
|
191036
|
+
if (!init)
|
|
191037
|
+
return null;
|
|
191038
|
+
if (!import_typescript8.default.isArrowFunction(reducerNode) && !import_typescript8.default.isFunctionExpression(reducerNode))
|
|
191039
|
+
return null;
|
|
191040
|
+
if (reducerNode.parameters.length !== 2)
|
|
191041
|
+
return null;
|
|
191042
|
+
const pAcc = reducerNode.parameters[0];
|
|
191043
|
+
const pItem = reducerNode.parameters[1];
|
|
191044
|
+
if (!import_typescript8.default.isIdentifier(pAcc.name) || !import_typescript8.default.isIdentifier(pItem.name))
|
|
191045
|
+
return null;
|
|
191046
|
+
const paramAcc = pAcc.name.text;
|
|
191047
|
+
const paramItem = pItem.name.text;
|
|
191048
|
+
let body;
|
|
191049
|
+
if (import_typescript8.default.isArrowFunction(reducerNode) && !import_typescript8.default.isBlock(reducerNode.body)) {
|
|
191050
|
+
body = reducerNode.body;
|
|
191051
|
+
} else {
|
|
191052
|
+
const block = reducerNode.body;
|
|
191053
|
+
const stmts = block.statements;
|
|
191054
|
+
if (stmts.length !== 1 || !import_typescript8.default.isReturnStatement(stmts[0]) || !stmts[0].expression)
|
|
191055
|
+
return null;
|
|
191056
|
+
body = stmts[0].expression;
|
|
191057
|
+
}
|
|
191058
|
+
const raw = body.getText();
|
|
191059
|
+
const expr = unwrapParens(body);
|
|
191060
|
+
if (!import_typescript8.default.isBinaryExpression(expr))
|
|
191061
|
+
return null;
|
|
191062
|
+
let op;
|
|
191063
|
+
if (expr.operatorToken.kind === import_typescript8.default.SyntaxKind.PlusToken)
|
|
191064
|
+
op = "+";
|
|
191065
|
+
else if (expr.operatorToken.kind === import_typescript8.default.SyntaxKind.AsteriskToken)
|
|
191066
|
+
op = "*";
|
|
191067
|
+
else
|
|
191068
|
+
return null;
|
|
191069
|
+
const left = unwrapParens(expr.left);
|
|
191070
|
+
if (!import_typescript8.default.isIdentifier(left) || left.text !== paramAcc)
|
|
191071
|
+
return null;
|
|
191072
|
+
const key = classifyReduceKey(unwrapParens(expr.right), paramItem);
|
|
191073
|
+
if (!key)
|
|
191074
|
+
return null;
|
|
191075
|
+
const type2 = init.type;
|
|
191076
|
+
if (type2 === "string" && op !== "+")
|
|
191077
|
+
return null;
|
|
191078
|
+
return { op, key, type: type2, init: init.value, raw, paramAcc, paramItem };
|
|
191079
|
+
}
|
|
191080
|
+
function extractFlatMapOpFromTS(cbNode) {
|
|
191081
|
+
if (!import_typescript8.default.isArrowFunction(cbNode) && !import_typescript8.default.isFunctionExpression(cbNode))
|
|
191082
|
+
return null;
|
|
191083
|
+
if (cbNode.parameters.length !== 1)
|
|
191084
|
+
return null;
|
|
191085
|
+
const p = cbNode.parameters[0];
|
|
191086
|
+
if (!import_typescript8.default.isIdentifier(p.name))
|
|
191087
|
+
return null;
|
|
191088
|
+
const param = p.name.text;
|
|
191089
|
+
let body;
|
|
191090
|
+
if (import_typescript8.default.isArrowFunction(cbNode) && !import_typescript8.default.isBlock(cbNode.body)) {
|
|
191091
|
+
body = cbNode.body;
|
|
191092
|
+
} else {
|
|
191093
|
+
const block = cbNode.body;
|
|
191094
|
+
const stmts = block.statements;
|
|
191095
|
+
if (stmts.length !== 1 || !import_typescript8.default.isReturnStatement(stmts[0]) || !stmts[0].expression)
|
|
191096
|
+
return null;
|
|
191097
|
+
body = stmts[0].expression;
|
|
191098
|
+
}
|
|
191099
|
+
const raw = body.getText();
|
|
191100
|
+
const inner = unwrapParens(body);
|
|
191101
|
+
if (import_typescript8.default.isArrayLiteralExpression(inner)) {
|
|
191102
|
+
if (inner.elements.length === 0)
|
|
191103
|
+
return null;
|
|
191104
|
+
const elements = [];
|
|
191105
|
+
for (const el of inner.elements) {
|
|
191106
|
+
if (import_typescript8.default.isSpreadElement(el) || import_typescript8.default.isOmittedExpression(el))
|
|
191107
|
+
return null;
|
|
191108
|
+
const leaf2 = classifyReduceKey(unwrapParens(el), param);
|
|
191109
|
+
if (!leaf2)
|
|
191110
|
+
return null;
|
|
191111
|
+
elements.push(leaf2);
|
|
191112
|
+
}
|
|
191113
|
+
return { projection: { kind: "tuple", elements }, param, raw };
|
|
191114
|
+
}
|
|
191115
|
+
const leaf = classifyReduceKey(inner, param);
|
|
191116
|
+
if (!leaf)
|
|
191117
|
+
return null;
|
|
191118
|
+
return { projection: leaf, param, raw };
|
|
191119
|
+
}
|
|
191120
|
+
function classifyReduceKey(expr, paramItem) {
|
|
191121
|
+
if (import_typescript8.default.isIdentifier(expr)) {
|
|
191122
|
+
return expr.text === paramItem ? { kind: "self" } : null;
|
|
191123
|
+
}
|
|
191124
|
+
if (import_typescript8.default.isPropertyAccessExpression(expr) && import_typescript8.default.isIdentifier(expr.expression)) {
|
|
191125
|
+
if (expr.expression.text === paramItem)
|
|
191126
|
+
return { kind: "field", field: expr.name.text };
|
|
191127
|
+
}
|
|
191128
|
+
return null;
|
|
191129
|
+
}
|
|
191130
|
+
function classifyReduceInit(node) {
|
|
191131
|
+
let n = unwrapParens(node);
|
|
191132
|
+
if (import_typescript8.default.isPrefixUnaryExpression(n) && n.operator === import_typescript8.default.SyntaxKind.MinusToken) {
|
|
191133
|
+
if (import_typescript8.default.isNumericLiteral(n.operand))
|
|
191134
|
+
return { type: "numeric", value: "-" + n.operand.text };
|
|
191135
|
+
return null;
|
|
191136
|
+
}
|
|
191137
|
+
if (import_typescript8.default.isNumericLiteral(n))
|
|
191138
|
+
return { type: "numeric", value: n.text };
|
|
191139
|
+
if (import_typescript8.default.isStringLiteral(n)) {
|
|
191140
|
+
const raw = n.getText();
|
|
191141
|
+
if (raw.length < 2 || raw.slice(1, -1) !== n.text)
|
|
191142
|
+
return null;
|
|
191143
|
+
return { type: "string", value: n.text };
|
|
191144
|
+
}
|
|
191145
|
+
return null;
|
|
191146
|
+
}
|
|
190962
191147
|
function collectDestructureBindings(pattern, pathPrefix, fieldMap, raw, excludedTopKeys) {
|
|
190963
191148
|
let restName;
|
|
190964
191149
|
for (const el of pattern.elements) {
|
|
@@ -191267,6 +191452,15 @@ function substituteDestructuredFields(expr, fieldMap, syntheticParam, restName)
|
|
|
191267
191452
|
if (e.method === "sort" || e.method === "toSorted") {
|
|
191268
191453
|
return { kind: "array-method", method: e.method, object: walk(e.object), args: [], comparator: e.comparator };
|
|
191269
191454
|
}
|
|
191455
|
+
if (e.method === "reduce" || e.method === "reduceRight") {
|
|
191456
|
+
return { kind: "array-method", method: e.method, object: walk(e.object), args: [], reduceOp: e.reduceOp };
|
|
191457
|
+
}
|
|
191458
|
+
if (e.method === "flat") {
|
|
191459
|
+
return { kind: "array-method", method: "flat", object: walk(e.object), args: [], flatDepth: e.flatDepth };
|
|
191460
|
+
}
|
|
191461
|
+
if (e.method === "flatMap") {
|
|
191462
|
+
return { kind: "array-method", method: "flatMap", object: walk(e.object), args: [], flatMapOp: e.flatMapOp };
|
|
191463
|
+
}
|
|
191270
191464
|
return { kind: "array-method", method: e.method, object: walk(e.object), args: e.args.map(walk) };
|
|
191271
191465
|
case "literal":
|
|
191272
191466
|
case "unsupported":
|
|
@@ -191387,7 +191581,8 @@ function checkSupport(expr) {
|
|
|
191387
191581
|
return {
|
|
191388
191582
|
supported: false,
|
|
191389
191583
|
level: "L5_UNSUPPORTED",
|
|
191390
|
-
|
|
191584
|
+
selfContained: true,
|
|
191585
|
+
reason: UNSUPPORTED_METHOD_REASONS[methodName] ?? `'${methodName}()' can't render on the server. Pre-compute the value, or add /* @client */ for client-only (no SSR).`
|
|
191391
191586
|
};
|
|
191392
191587
|
}
|
|
191393
191588
|
}
|
|
@@ -192387,6 +192582,7 @@ function transformComponentElement(node, ctx, name) {
|
|
|
192387
192582
|
children,
|
|
192388
192583
|
template: name.toLowerCase(),
|
|
192389
192584
|
slotId,
|
|
192585
|
+
...isDynamicTagLocal(name, ctx) ? { dynamicTag: true } : {},
|
|
192390
192586
|
loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
|
|
192391
192587
|
};
|
|
192392
192588
|
}
|
|
@@ -192402,6 +192598,7 @@ function transformSelfClosingComponent(node, ctx, name) {
|
|
|
192402
192598
|
children: [],
|
|
192403
192599
|
template: name.toLowerCase(),
|
|
192404
192600
|
slotId,
|
|
192601
|
+
...isDynamicTagLocal(name, ctx) ? { dynamicTag: true } : {},
|
|
192405
192602
|
loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
|
|
192406
192603
|
};
|
|
192407
192604
|
}
|
|
@@ -194094,6 +194291,40 @@ function findLocalConst(name, ctx) {
|
|
|
194094
194291
|
const pool = fnScoped.length > 0 ? fnScoped : matches;
|
|
194095
194292
|
return pool[pool.length - 1];
|
|
194096
194293
|
}
|
|
194294
|
+
function isDynamicTagLocal(name, ctx) {
|
|
194295
|
+
if (!hasDynamicTagBinding(name, ctx.sourceFile))
|
|
194296
|
+
return false;
|
|
194297
|
+
const a = ctx.analyzer;
|
|
194298
|
+
if (a.jsxConstants?.has(name))
|
|
194299
|
+
return false;
|
|
194300
|
+
if (a.jsxFunctions?.has(name))
|
|
194301
|
+
return false;
|
|
194302
|
+
if (a.jsxMultiReturnFunctions?.has(name))
|
|
194303
|
+
return false;
|
|
194304
|
+
if (a.inlineableJsxConsts?.has(name))
|
|
194305
|
+
return false;
|
|
194306
|
+
return true;
|
|
194307
|
+
}
|
|
194308
|
+
function hasDynamicTagBinding(name, sourceFile) {
|
|
194309
|
+
let found = false;
|
|
194310
|
+
const visit2 = (node) => {
|
|
194311
|
+
if (found)
|
|
194312
|
+
return;
|
|
194313
|
+
if (import_typescript11.default.isVariableDeclaration(node) && import_typescript11.default.isIdentifier(node.name) && node.name.text === name && node.initializer) {
|
|
194314
|
+
let init = node.initializer;
|
|
194315
|
+
while (import_typescript11.default.isAsExpression(init) || import_typescript11.default.isSatisfiesExpression(init) || import_typescript11.default.isParenthesizedExpression(init) || import_typescript11.default.isNonNullExpression(init)) {
|
|
194316
|
+
init = init.expression;
|
|
194317
|
+
}
|
|
194318
|
+
if (import_typescript11.default.isPropertyAccessExpression(init) && init.name.text === "tag") {
|
|
194319
|
+
found = true;
|
|
194320
|
+
return;
|
|
194321
|
+
}
|
|
194322
|
+
}
|
|
194323
|
+
import_typescript11.default.forEachChild(node, visit2);
|
|
194324
|
+
};
|
|
194325
|
+
visit2(sourceFile);
|
|
194326
|
+
return found;
|
|
194327
|
+
}
|
|
194097
194328
|
function tryResolveIdentifierAsTemplateLiteral(ident, ctx) {
|
|
194098
194329
|
const constInfo = findLocalConst(ident.text, ctx);
|
|
194099
194330
|
if (!constInfo)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/test",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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.
|
|
42
|
+
"@barefootjs/jsx": "0.7.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.0.0"
|