@barefootjs/test 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +300 -24
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -187670,6 +187670,7 @@ function createAnalyzerContext(sourceFile, filePath) {
|
|
|
187670
187670
|
jsxConstants: new Map,
|
|
187671
187671
|
inlineableJsxConsts: new Map,
|
|
187672
187672
|
jsxFunctions: new Map,
|
|
187673
|
+
jsxMultiReturnFunctions: new Map,
|
|
187673
187674
|
reactiveFactories: new Map,
|
|
187674
187675
|
signalTupleRefs: new Map,
|
|
187675
187676
|
propsType: null,
|
|
@@ -187801,20 +187802,11 @@ init_path();
|
|
|
187801
187802
|
var ErrorCodes = {
|
|
187802
187803
|
MISSING_USE_CLIENT: "BF001",
|
|
187803
187804
|
CLIENT_IMPORTING_SERVER: "BF003",
|
|
187804
|
-
UNKNOWN_SIGNAL: "BF010",
|
|
187805
187805
|
SIGNAL_OUTSIDE_COMPONENT: "BF011",
|
|
187806
|
-
INVALID_SIGNAL_USAGE: "BF012",
|
|
187807
|
-
INVALID_JSX_EXPRESSION: "BF020",
|
|
187808
187806
|
UNSUPPORTED_JSX_PATTERN: "BF021",
|
|
187809
|
-
INVALID_JSX_ATTRIBUTE: "BF022",
|
|
187810
187807
|
MISSING_KEY_IN_LIST: "BF023",
|
|
187811
187808
|
MISSING_KEY_IN_NESTED_LIST: "BF024",
|
|
187812
187809
|
UNSUPPORTED_DESTRUCTURE_REST: "BF025",
|
|
187813
|
-
TYPE_INFERENCE_FAILED: "BF030",
|
|
187814
|
-
PROPS_TYPE_MISMATCH: "BF031",
|
|
187815
|
-
COMPONENT_NOT_FOUND: "BF040",
|
|
187816
|
-
CIRCULAR_DEPENDENCY: "BF041",
|
|
187817
|
-
INVALID_COMPONENT_NAME: "BF042",
|
|
187818
187810
|
PROPS_DESTRUCTURING: "BF043",
|
|
187819
187811
|
SIGNAL_GETTER_NOT_CALLED: "BF044",
|
|
187820
187812
|
JSX_IN_LOCAL_FUNCTION: "BF045",
|
|
@@ -187833,20 +187825,11 @@ var ErrorCodes = {
|
|
|
187833
187825
|
var errorMessages = {
|
|
187834
187826
|
[ErrorCodes.MISSING_USE_CLIENT]: "'use client' directive required for components with createSignal or event handlers",
|
|
187835
187827
|
[ErrorCodes.CLIENT_IMPORTING_SERVER]: "Client component cannot import server component",
|
|
187836
|
-
[ErrorCodes.UNKNOWN_SIGNAL]: "Unknown signal reference",
|
|
187837
187828
|
[ErrorCodes.SIGNAL_OUTSIDE_COMPONENT]: "Module-level reactive declaration (createSignal / createMemo) is not allowed. " + "The downstream codegen drops the declaration silently and every reference becomes a ReferenceError at SSR and at hydrate. " + "Move the declaration inside a component function so each mount gets its own state.",
|
|
187838
|
-
[ErrorCodes.INVALID_SIGNAL_USAGE]: "Invalid signal usage",
|
|
187839
|
-
[ErrorCodes.INVALID_JSX_EXPRESSION]: "Invalid JSX expression",
|
|
187840
187829
|
[ErrorCodes.UNSUPPORTED_JSX_PATTERN]: "Unsupported JSX pattern",
|
|
187841
|
-
[ErrorCodes.INVALID_JSX_ATTRIBUTE]: "Invalid JSX attribute",
|
|
187842
187830
|
[ErrorCodes.MISSING_KEY_IN_LIST]: "Missing key attribute in list rendering. Add a key prop for efficient updates",
|
|
187843
187831
|
[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",
|
|
187844
187832
|
[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.",
|
|
187845
|
-
[ErrorCodes.TYPE_INFERENCE_FAILED]: "Failed to infer type",
|
|
187846
|
-
[ErrorCodes.PROPS_TYPE_MISMATCH]: "Props type mismatch",
|
|
187847
|
-
[ErrorCodes.COMPONENT_NOT_FOUND]: "Component not found",
|
|
187848
|
-
[ErrorCodes.CIRCULAR_DEPENDENCY]: "Circular dependency detected",
|
|
187849
|
-
[ErrorCodes.INVALID_COMPONENT_NAME]: "Component name must start with uppercase letter",
|
|
187850
187833
|
[ErrorCodes.PROPS_DESTRUCTURING]: "Props destructuring in function parameters breaks reactivity. Use props object directly.",
|
|
187851
187834
|
[ErrorCodes.SIGNAL_GETTER_NOT_CALLED]: "Signal/memo getter passed without calling it. Use getter() to read the value.",
|
|
187852
187835
|
[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.",
|
|
@@ -187858,7 +187841,7 @@ var errorMessages = {
|
|
|
187858
187841
|
[ErrorCodes.STRIPPED_CLIENT_IMPORT_REFERENCED]: "Import was stripped from the client bundle but its binding is still referenced. Client components ('use client' .tsx) are not callable as plain functions from imperative .ts modules — render them as JSX from a 'use client' parent instead. If the flagged name is a local shadow rather than the stripped import, please file an issue.",
|
|
187859
187842
|
[ErrorCodes.STAGE_REACTIVE_IN_TEMPLATE]: "Reactive binding (signal getter or memo) referenced from template scope. The template lambda runs at module scope without the reactive context, so the value cannot be evaluated at SSR. Wrap the JSX expression in /* @client */ to defer it to hydrate, or restructure so the template uses a prop or static value.",
|
|
187860
187843
|
[ErrorCodes.STAGE_INIT_LOCAL_IN_TEMPLATE]: "Init-scope local referenced from template scope. The template lambda runs at module scope (via render() / renderChild()) and cannot reach init-body locals. Wrap the JSX expression in /* @client */, or lift the value to a prop or module-scope const.",
|
|
187861
|
-
[ErrorCodes.STAGE_AWAIT_IN_TEMPLATE]: "AwaitExpression in template scope. The
|
|
187844
|
+
[ErrorCodes.STAGE_AWAIT_IN_TEMPLATE]: "AwaitExpression in template scope. The generated template and init functions are synchronous — a bare `await` produces a SyntaxError at parse time. Move the await into the component body (before the return) or into an onMount/effect callback, and pass the resolved value to JSX.",
|
|
187862
187845
|
[ErrorCodes.INLINE_JSX_CALLBACK_CAPTURE]: "Inline JSX-returning arrow function captures a non-module identifier. Extract the callback into a top-level 'use client' component (e.g. `function MyNode(n) { return <div/> }` then `renderNode={MyNode}`) or pass captured values via component props.",
|
|
187863
187846
|
[ErrorCodes.UNRECOGNIZED_REACTIVE_FACTORY]: "Tuple destructuring of a non-reactive factory call. The compiler only recognizes createSignal / createMemo calls and same-file helpers that wrap them with a single `return [a, b]` exit."
|
|
187864
187847
|
};
|
|
@@ -188947,6 +188930,139 @@ function extractSingleJsxReturn(body) {
|
|
|
188947
188930
|
return null;
|
|
188948
188931
|
return jsxReturn;
|
|
188949
188932
|
}
|
|
188933
|
+
function extractMultiReturnJsxBranches(body) {
|
|
188934
|
+
const branches = [];
|
|
188935
|
+
let fallback = null;
|
|
188936
|
+
const stmts = body.statements;
|
|
188937
|
+
for (let i2 = 0;i2 < stmts.length; i2++) {
|
|
188938
|
+
const stmt = stmts[i2];
|
|
188939
|
+
if (import_typescript6.default.isIfStatement(stmt)) {
|
|
188940
|
+
let current = stmt;
|
|
188941
|
+
while (import_typescript6.default.isIfStatement(current)) {
|
|
188942
|
+
const ifStmt = current;
|
|
188943
|
+
if (!isDirectReturnBlock(ifStmt.thenStatement))
|
|
188944
|
+
return null;
|
|
188945
|
+
const jsxReturn = findJsxReturnInBlock(ifStmt.thenStatement);
|
|
188946
|
+
const nullReturn = findNullReturnInBlock(ifStmt.thenStatement);
|
|
188947
|
+
if (!jsxReturn && !nullReturn)
|
|
188948
|
+
return null;
|
|
188949
|
+
branches.push({ condition: ifStmt.expression, jsxReturn: jsxReturn ?? null });
|
|
188950
|
+
if (ifStmt.elseStatement) {
|
|
188951
|
+
if (import_typescript6.default.isIfStatement(ifStmt.elseStatement)) {
|
|
188952
|
+
current = ifStmt.elseStatement;
|
|
188953
|
+
continue;
|
|
188954
|
+
}
|
|
188955
|
+
if (!isDirectReturnBlock(ifStmt.elseStatement))
|
|
188956
|
+
return null;
|
|
188957
|
+
const elseJsx = findJsxReturnInBlock(ifStmt.elseStatement);
|
|
188958
|
+
if (elseJsx) {
|
|
188959
|
+
fallback = elseJsx;
|
|
188960
|
+
} else if (!findNullReturnInBlock(ifStmt.elseStatement)) {
|
|
188961
|
+
return null;
|
|
188962
|
+
}
|
|
188963
|
+
if (branches.length === 0)
|
|
188964
|
+
return null;
|
|
188965
|
+
return { branches, fallback };
|
|
188966
|
+
}
|
|
188967
|
+
break;
|
|
188968
|
+
}
|
|
188969
|
+
continue;
|
|
188970
|
+
}
|
|
188971
|
+
if (import_typescript6.default.isSwitchStatement(stmt)) {
|
|
188972
|
+
if (branches.length > 0)
|
|
188973
|
+
return null;
|
|
188974
|
+
if (!import_typescript6.default.isIdentifier(stmt.expression) && !import_typescript6.default.isPropertyAccessExpression(stmt.expression)) {
|
|
188975
|
+
return null;
|
|
188976
|
+
}
|
|
188977
|
+
const hasDefault = stmt.caseBlock.clauses.some((c) => import_typescript6.default.isDefaultClause(c));
|
|
188978
|
+
if (!hasDefault)
|
|
188979
|
+
return null;
|
|
188980
|
+
for (const clause of stmt.caseBlock.clauses) {
|
|
188981
|
+
const jsxReturn = findJsxReturnInCaseClause(clause);
|
|
188982
|
+
const nullReturn = findNullReturnInCaseClause(clause);
|
|
188983
|
+
if (!jsxReturn && !nullReturn)
|
|
188984
|
+
return null;
|
|
188985
|
+
if (import_typescript6.default.isCaseClause(clause)) {
|
|
188986
|
+
branches.push({
|
|
188987
|
+
condition: clause.expression,
|
|
188988
|
+
jsxReturn: jsxReturn ?? null
|
|
188989
|
+
});
|
|
188990
|
+
} else {
|
|
188991
|
+
fallback = jsxReturn ?? null;
|
|
188992
|
+
}
|
|
188993
|
+
}
|
|
188994
|
+
if (branches.length === 0)
|
|
188995
|
+
return null;
|
|
188996
|
+
return { branches, fallback, switchDiscriminant: stmt.expression };
|
|
188997
|
+
}
|
|
188998
|
+
if (import_typescript6.default.isReturnStatement(stmt) && stmt.expression) {
|
|
188999
|
+
const expr = unwrapJsxTransparent(stmt.expression);
|
|
189000
|
+
if (import_typescript6.default.isJsxElement(expr) || import_typescript6.default.isJsxSelfClosingElement(expr) || import_typescript6.default.isJsxFragment(expr)) {
|
|
189001
|
+
fallback = expr;
|
|
189002
|
+
} else if (expr.kind === import_typescript6.default.SyntaxKind.NullKeyword) {} else {
|
|
189003
|
+
return null;
|
|
189004
|
+
}
|
|
189005
|
+
continue;
|
|
189006
|
+
}
|
|
189007
|
+
if (import_typescript6.default.isVariableStatement(stmt))
|
|
189008
|
+
return null;
|
|
189009
|
+
return null;
|
|
189010
|
+
}
|
|
189011
|
+
if (branches.length === 0)
|
|
189012
|
+
return null;
|
|
189013
|
+
return { branches, fallback };
|
|
189014
|
+
}
|
|
189015
|
+
function isDirectReturnBlock(node) {
|
|
189016
|
+
if (import_typescript6.default.isReturnStatement(node))
|
|
189017
|
+
return true;
|
|
189018
|
+
if (import_typescript6.default.isBlock(node)) {
|
|
189019
|
+
let returnCount = 0;
|
|
189020
|
+
for (const stmt of node.statements) {
|
|
189021
|
+
if (import_typescript6.default.isReturnStatement(stmt)) {
|
|
189022
|
+
returnCount++;
|
|
189023
|
+
} else if (import_typescript6.default.isIfStatement(stmt) || import_typescript6.default.isSwitchStatement(stmt) || import_typescript6.default.isForStatement(stmt) || import_typescript6.default.isForOfStatement(stmt) || import_typescript6.default.isForInStatement(stmt) || import_typescript6.default.isWhileStatement(stmt) || import_typescript6.default.isDoStatement(stmt) || import_typescript6.default.isTryStatement(stmt)) {
|
|
189024
|
+
return false;
|
|
189025
|
+
}
|
|
189026
|
+
}
|
|
189027
|
+
return returnCount === 1;
|
|
189028
|
+
}
|
|
189029
|
+
return false;
|
|
189030
|
+
}
|
|
189031
|
+
function findNullReturnInBlock(node) {
|
|
189032
|
+
if (import_typescript6.default.isBlock(node)) {
|
|
189033
|
+
for (const stmt of node.statements) {
|
|
189034
|
+
if (import_typescript6.default.isReturnStatement(stmt) && stmt.expression) {
|
|
189035
|
+
const expr = unwrapJsxTransparent(stmt.expression);
|
|
189036
|
+
if (expr.kind === import_typescript6.default.SyntaxKind.NullKeyword)
|
|
189037
|
+
return true;
|
|
189038
|
+
}
|
|
189039
|
+
}
|
|
189040
|
+
}
|
|
189041
|
+
if (import_typescript6.default.isReturnStatement(node) && node.expression) {
|
|
189042
|
+
const expr = unwrapJsxTransparent(node.expression);
|
|
189043
|
+
if (expr.kind === import_typescript6.default.SyntaxKind.NullKeyword)
|
|
189044
|
+
return true;
|
|
189045
|
+
}
|
|
189046
|
+
return false;
|
|
189047
|
+
}
|
|
189048
|
+
function findJsxReturnInCaseClause(clause) {
|
|
189049
|
+
for (const stmt of clause.statements) {
|
|
189050
|
+
if (import_typescript6.default.isReturnStatement(stmt) && stmt.expression) {
|
|
189051
|
+
return extractJsxFromExpression(stmt.expression);
|
|
189052
|
+
}
|
|
189053
|
+
}
|
|
189054
|
+
return null;
|
|
189055
|
+
}
|
|
189056
|
+
function findNullReturnInCaseClause(clause) {
|
|
189057
|
+
for (const stmt of clause.statements) {
|
|
189058
|
+
if (import_typescript6.default.isReturnStatement(stmt) && stmt.expression) {
|
|
189059
|
+
const expr = unwrapJsxTransparent(stmt.expression);
|
|
189060
|
+
if (expr.kind === import_typescript6.default.SyntaxKind.NullKeyword)
|
|
189061
|
+
return true;
|
|
189062
|
+
}
|
|
189063
|
+
}
|
|
189064
|
+
return false;
|
|
189065
|
+
}
|
|
188950
189066
|
function isMultiReturnJsxFunctionBody(body) {
|
|
188951
189067
|
let returnCount = 0;
|
|
188952
189068
|
let hasJsxReturn = false;
|
|
@@ -189030,6 +189146,15 @@ function collectFunction(node, ctx, _isModule, isExported = false) {
|
|
|
189030
189146
|
jsxReturn,
|
|
189031
189147
|
params: node.parameters.map((p) => p.name.getText(ctx.sourceFile))
|
|
189032
189148
|
});
|
|
189149
|
+
} else {
|
|
189150
|
+
const multi = extractMultiReturnJsxBranches(node.body);
|
|
189151
|
+
if (multi) {
|
|
189152
|
+
isJsxFunction = true;
|
|
189153
|
+
ctx.jsxMultiReturnFunctions.set(name, {
|
|
189154
|
+
...multi,
|
|
189155
|
+
params: node.parameters.map((p) => p.name.getText(ctx.sourceFile))
|
|
189156
|
+
});
|
|
189157
|
+
}
|
|
189033
189158
|
}
|
|
189034
189159
|
}
|
|
189035
189160
|
const isAsync = node.modifiers?.some((m) => m.kind === import_typescript6.default.SyntaxKind.AsyncKeyword) ?? false;
|
|
@@ -189282,6 +189407,15 @@ function collectConstant(node, ctx, _isModule, declarationKind = "const", isExpo
|
|
|
189282
189407
|
jsxReturn,
|
|
189283
189408
|
params: init.parameters.map((p) => p.name.getText(ctx.sourceFile))
|
|
189284
189409
|
});
|
|
189410
|
+
} else {
|
|
189411
|
+
const multi = extractMultiReturnJsxBranches(arrowBody);
|
|
189412
|
+
if (multi) {
|
|
189413
|
+
isJsxFunction = true;
|
|
189414
|
+
ctx.jsxMultiReturnFunctions.set(name, {
|
|
189415
|
+
...multi,
|
|
189416
|
+
params: init.parameters.map((p) => p.name.getText(ctx.sourceFile))
|
|
189417
|
+
});
|
|
189418
|
+
}
|
|
189285
189419
|
}
|
|
189286
189420
|
} else {
|
|
189287
189421
|
let body = arrowBody;
|
|
@@ -189541,7 +189675,7 @@ function inferTypeFromValue(value) {
|
|
|
189541
189675
|
if (/\.(some|every|includes)\s*\([\s\S]*\)\s*$/.test(trimmed)) {
|
|
189542
189676
|
return { kind: "primitive", raw: "boolean", primitive: "boolean" };
|
|
189543
189677
|
}
|
|
189544
|
-
if (/\.(indexOf|findIndex|lastIndexOf)\s*\([\s\S]*\)\s*$/.test(trimmed)) {
|
|
189678
|
+
if (/\.(indexOf|findIndex|findLastIndex|lastIndexOf)\s*\([\s\S]*\)\s*$/.test(trimmed)) {
|
|
189545
189679
|
return { kind: "primitive", raw: "number", primitive: "number" };
|
|
189546
189680
|
}
|
|
189547
189681
|
if (/^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
@@ -190144,8 +190278,6 @@ var UNSUPPORTED_METHODS = new Set([
|
|
|
190144
190278
|
"reduceRight",
|
|
190145
190279
|
"every",
|
|
190146
190280
|
"some",
|
|
190147
|
-
"findLast",
|
|
190148
|
-
"findLastIndex",
|
|
190149
190281
|
"forEach",
|
|
190150
190282
|
"flatMap",
|
|
190151
190283
|
"flat"
|
|
@@ -190188,7 +190320,7 @@ function convertNode(node, raw) {
|
|
|
190188
190320
|
if (import_typescript7.default.isCallExpression(node)) {
|
|
190189
190321
|
const callee = convertNode(node.expression, raw);
|
|
190190
190322
|
const args = node.arguments.map((arg) => convertNode(arg, raw));
|
|
190191
|
-
if (callee.kind === "member" && ["filter", "every", "some", "find", "findIndex"].includes(callee.property)) {
|
|
190323
|
+
if (callee.kind === "member" && ["filter", "every", "some", "find", "findIndex", "findLast", "findLastIndex"].includes(callee.property)) {
|
|
190192
190324
|
if (args.length === 1 && args[0].kind === "arrow-fn") {
|
|
190193
190325
|
const arrowFn = args[0];
|
|
190194
190326
|
return {
|
|
@@ -192035,6 +192167,18 @@ function transformExpressionInner(expr, ctx, node, isClientOnly) {
|
|
|
192035
192167
|
}
|
|
192036
192168
|
return ir;
|
|
192037
192169
|
}
|
|
192170
|
+
if (containsAwaitExpression(expr)) {
|
|
192171
|
+
ctx.analyzer.errors.push(createError(ErrorCodes.STAGE_AWAIT_IN_TEMPLATE, getSourceLocation(expr, ctx.sourceFile, ctx.filePath)));
|
|
192172
|
+
return {
|
|
192173
|
+
type: "expression",
|
|
192174
|
+
expr: "undefined",
|
|
192175
|
+
typeInfo: null,
|
|
192176
|
+
reactive: false,
|
|
192177
|
+
slotId: null,
|
|
192178
|
+
loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath),
|
|
192179
|
+
origin: { phase: "tick", scope: "template", effect: "pure", freeRefs: [] }
|
|
192180
|
+
};
|
|
192181
|
+
}
|
|
192038
192182
|
const exprText = ctx.getJS(expr);
|
|
192039
192183
|
const freeRefs = resolveFreeRefs(expr, makeBindingEnv(ctx));
|
|
192040
192184
|
const origin = {
|
|
@@ -192106,6 +192250,97 @@ function transformJsxFunctionCall(callExpr, jsxFunc, ctx, _isClientOnly) {
|
|
|
192106
192250
|
ctx.analyzer.getJS = originalAnalyzerGetJS;
|
|
192107
192251
|
}
|
|
192108
192252
|
}
|
|
192253
|
+
function transformMultiReturnJsxFunctionCall(callExpr, info, ctx) {
|
|
192254
|
+
const substitutions = new Map;
|
|
192255
|
+
for (let i2 = 0;i2 < info.params.length; i2++) {
|
|
192256
|
+
const paramName = info.params[i2];
|
|
192257
|
+
const arg = callExpr.arguments[i2];
|
|
192258
|
+
if (arg) {
|
|
192259
|
+
substitutions.set(paramName, ctx.getJS(arg));
|
|
192260
|
+
}
|
|
192261
|
+
}
|
|
192262
|
+
const baseGetJS = ctx.analyzer.getJS.bind(ctx.analyzer);
|
|
192263
|
+
const originalCtxGetJS = ctx.getJS;
|
|
192264
|
+
const originalAnalyzerGetJS = ctx.analyzer.getJS;
|
|
192265
|
+
const substitutedGetJS = (node) => {
|
|
192266
|
+
let text = baseGetJS(node);
|
|
192267
|
+
for (const [paramName, argExpr] of substitutions) {
|
|
192268
|
+
text = text.replace(new RegExp(`\\b${paramName}\\b`, "g"), argExpr);
|
|
192269
|
+
}
|
|
192270
|
+
return text;
|
|
192271
|
+
};
|
|
192272
|
+
ctx.getJS = substitutedGetJS;
|
|
192273
|
+
ctx.analyzer.getJS = substitutedGetJS;
|
|
192274
|
+
try {
|
|
192275
|
+
const loc = getSourceLocation(callExpr, ctx.sourceFile, ctx.filePath);
|
|
192276
|
+
const nullExpr = {
|
|
192277
|
+
type: "expression",
|
|
192278
|
+
expr: "null",
|
|
192279
|
+
typeInfo: { kind: "primitive", raw: "null", primitive: "null" },
|
|
192280
|
+
reactive: false,
|
|
192281
|
+
slotId: null,
|
|
192282
|
+
loc,
|
|
192283
|
+
origin: { phase: "tick", scope: "template", effect: "pure", freeRefs: [] }
|
|
192284
|
+
};
|
|
192285
|
+
let result = info.fallback ? transformNode(info.fallback, ctx) ?? nullExpr : nullExpr;
|
|
192286
|
+
for (let i2 = info.branches.length - 1;i2 >= 0; i2--) {
|
|
192287
|
+
const branch = info.branches[i2];
|
|
192288
|
+
let conditionText;
|
|
192289
|
+
if (info.switchDiscriminant) {
|
|
192290
|
+
const discText = substitutedGetJS(info.switchDiscriminant);
|
|
192291
|
+
const caseText = substitutedGetJS(branch.condition);
|
|
192292
|
+
conditionText = `${discText} === ${caseText}`;
|
|
192293
|
+
} else {
|
|
192294
|
+
conditionText = substitutedGetJS(branch.condition);
|
|
192295
|
+
}
|
|
192296
|
+
const env = makeBindingEnv(ctx);
|
|
192297
|
+
const caseFreeRefs = resolveFreeRefs(branch.condition, env);
|
|
192298
|
+
const discFreeRefs = info.switchDiscriminant ? resolveFreeRefs(info.switchDiscriminant, env) : [];
|
|
192299
|
+
const conditionOrigin = {
|
|
192300
|
+
phase: "tick",
|
|
192301
|
+
scope: "template",
|
|
192302
|
+
effect: "pure",
|
|
192303
|
+
freeRefs: [...discFreeRefs, ...caseFreeRefs]
|
|
192304
|
+
};
|
|
192305
|
+
const reactive = isReactiveExpression(conditionText, ctx, branch.condition) || isReactiveOrigin(conditionOrigin);
|
|
192306
|
+
const loopParamReactive = !reactive && referencesLoopParam(conditionText, ctx);
|
|
192307
|
+
const callsReactive = exprCallsReactiveGetters(branch.condition, ctx) || (info.switchDiscriminant ? exprCallsReactiveGetters(info.switchDiscriminant, ctx) : false);
|
|
192308
|
+
const hasCalls = exprHasFunctionCalls(branch.condition) || (info.switchDiscriminant ? exprHasFunctionCalls(info.switchDiscriminant) : false);
|
|
192309
|
+
const needsSlot = reactive || loopParamReactive || callsReactive || hasCalls;
|
|
192310
|
+
const slotId = needsSlot ? generateSlotId(ctx) : null;
|
|
192311
|
+
const whenTrue = branch.jsxReturn ? transformNode(branch.jsxReturn, ctx) ?? nullExpr : nullExpr;
|
|
192312
|
+
let templateCondition;
|
|
192313
|
+
if (info.switchDiscriminant) {
|
|
192314
|
+
const discRewritten = rewriteBarePropRefs2(substitutedGetJS(info.switchDiscriminant), info.switchDiscriminant, ctx);
|
|
192315
|
+
const caseRewritten = rewriteBarePropRefs2(substitutedGetJS(branch.condition), branch.condition, ctx);
|
|
192316
|
+
const discPart = discRewritten ?? substitutedGetJS(info.switchDiscriminant);
|
|
192317
|
+
const casePart = caseRewritten ?? substitutedGetJS(branch.condition);
|
|
192318
|
+
templateCondition = `${discPart} === ${casePart}`;
|
|
192319
|
+
} else {
|
|
192320
|
+
templateCondition = rewriteBarePropRefs2(conditionText, branch.condition, ctx);
|
|
192321
|
+
}
|
|
192322
|
+
const conditional = {
|
|
192323
|
+
type: "conditional",
|
|
192324
|
+
condition: conditionText,
|
|
192325
|
+
templateCondition,
|
|
192326
|
+
conditionType: null,
|
|
192327
|
+
reactive,
|
|
192328
|
+
whenTrue,
|
|
192329
|
+
whenFalse: result,
|
|
192330
|
+
slotId,
|
|
192331
|
+
callsReactiveGetters: callsReactive || undefined,
|
|
192332
|
+
hasFunctionCalls: hasCalls || undefined,
|
|
192333
|
+
loc,
|
|
192334
|
+
origin: conditionOrigin
|
|
192335
|
+
};
|
|
192336
|
+
result = conditional;
|
|
192337
|
+
}
|
|
192338
|
+
return result;
|
|
192339
|
+
} finally {
|
|
192340
|
+
ctx.getJS = originalCtxGetJS;
|
|
192341
|
+
ctx.analyzer.getJS = originalAnalyzerGetJS;
|
|
192342
|
+
}
|
|
192343
|
+
}
|
|
192109
192344
|
function transformConditional(node, ctx) {
|
|
192110
192345
|
const condition = ctx.getJS(node.condition);
|
|
192111
192346
|
const conditionOrigin = {
|
|
@@ -192187,6 +192422,13 @@ function containsJsxInExpression(node) {
|
|
|
192187
192422
|
}
|
|
192188
192423
|
return import_typescript10.default.forEachChild(node, containsJsxInExpression) ?? false;
|
|
192189
192424
|
}
|
|
192425
|
+
function containsAwaitExpression(node) {
|
|
192426
|
+
if (import_typescript10.default.isAwaitExpression(node))
|
|
192427
|
+
return true;
|
|
192428
|
+
if (import_typescript10.default.isFunctionDeclaration(node) || import_typescript10.default.isFunctionExpression(node) || import_typescript10.default.isArrowFunction(node))
|
|
192429
|
+
return false;
|
|
192430
|
+
return import_typescript10.default.forEachChild(node, containsAwaitExpression) ?? false;
|
|
192431
|
+
}
|
|
192190
192432
|
function transformNullishCoalescing(node, ctx) {
|
|
192191
192433
|
const leftText = ctx.getJS(node.left);
|
|
192192
192434
|
const isNullish = node.operatorToken.kind === import_typescript10.default.SyntaxKind.QuestionQuestionToken;
|
|
@@ -192277,6 +192519,10 @@ function transformJsxExpression(expr, ctx, isClientOnly = false) {
|
|
|
192277
192519
|
if (jsxFunc) {
|
|
192278
192520
|
return transformJsxFunctionCall(node, jsxFunc, ctx, isClientOnly);
|
|
192279
192521
|
}
|
|
192522
|
+
const multiJsxFunc = ctx.analyzer.jsxMultiReturnFunctions.get(callee.text);
|
|
192523
|
+
if (multiJsxFunc) {
|
|
192524
|
+
return transformMultiReturnJsxFunctionCall(node, multiJsxFunc, ctx);
|
|
192525
|
+
}
|
|
192280
192526
|
}
|
|
192281
192527
|
return null;
|
|
192282
192528
|
}
|
|
@@ -192313,6 +192559,16 @@ function transformJsxExpression(expr, ctx, isClientOnly = false) {
|
|
|
192313
192559
|
case import_typescript10.default.SyntaxKind.ArrayLiteralExpression:
|
|
192314
192560
|
return null;
|
|
192315
192561
|
case import_typescript10.default.SyntaxKind.AwaitExpression:
|
|
192562
|
+
ctx.analyzer.errors.push(createError(ErrorCodes.STAGE_AWAIT_IN_TEMPLATE, getSourceLocation(node, ctx.sourceFile, ctx.filePath)));
|
|
192563
|
+
return {
|
|
192564
|
+
type: "expression",
|
|
192565
|
+
expr: "undefined",
|
|
192566
|
+
typeInfo: null,
|
|
192567
|
+
reactive: false,
|
|
192568
|
+
slotId: null,
|
|
192569
|
+
loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath),
|
|
192570
|
+
origin: { phase: "tick", scope: "template", effect: "pure", freeRefs: [] }
|
|
192571
|
+
};
|
|
192316
192572
|
case import_typescript10.default.SyntaxKind.YieldExpression:
|
|
192317
192573
|
return null;
|
|
192318
192574
|
case import_typescript10.default.SyntaxKind.SpreadElement:
|
|
@@ -192964,7 +193220,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
192964
193220
|
const bodyIsMultiRoot = loopBodyIsMultiRoot(children);
|
|
192965
193221
|
const callsReactive = exprCallsReactiveGetters(arrayExpr, ctx);
|
|
192966
193222
|
const hasCalls = exprHasFunctionCalls(arrayExpr);
|
|
192967
|
-
const
|
|
193223
|
+
const isDirectPropArray = method !== "flatMap" && isArrayExprDirectPropRef(arrayExpr, ctx);
|
|
193224
|
+
const isStaticArray = !isSignalOrMemoArray(array, ctx) && !isDirectPropArray && !hasCalls;
|
|
192968
193225
|
const nestedComponents = collectNestedComponents(children).filter((c) => c.name !== childComponent?.name);
|
|
192969
193226
|
return {
|
|
192970
193227
|
type: "loop",
|
|
@@ -192980,6 +193237,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
192980
193237
|
slotId: null,
|
|
192981
193238
|
markerId: `l${ctx.loopMarkerCounter++}`,
|
|
192982
193239
|
isStaticArray,
|
|
193240
|
+
isPropDerivedArray: isDirectPropArray || undefined,
|
|
192983
193241
|
callsReactiveGetters: callsReactive || undefined,
|
|
192984
193242
|
hasFunctionCalls: hasCalls || undefined,
|
|
192985
193243
|
bodyIsMultiRoot: bodyIsMultiRoot || undefined,
|
|
@@ -193239,6 +193497,10 @@ function getAttributeValue(attr, ctx) {
|
|
|
193239
193497
|
expr = branchInit;
|
|
193240
193498
|
}
|
|
193241
193499
|
}
|
|
193500
|
+
if (import_typescript10.default.isAwaitExpression(expr)) {
|
|
193501
|
+
ctx.analyzer.errors.push(createError(ErrorCodes.STAGE_AWAIT_IN_TEMPLATE, getSourceLocation(expr, ctx.sourceFile, ctx.filePath)));
|
|
193502
|
+
return AttrValueOf.expression("undefined");
|
|
193503
|
+
}
|
|
193242
193504
|
checkBareSignalOrMemoIdentifier(expr, ctx);
|
|
193243
193505
|
if (attr.name.getText(ctx.sourceFile) === "style" && import_typescript10.default.isObjectLiteralExpression(expr)) {
|
|
193244
193506
|
const cssString = tryStaticStyleObjectToCss(expr);
|
|
@@ -193560,6 +193822,20 @@ function checkBareSignalOrMemoIdentifier(expr, ctx) {
|
|
|
193560
193822
|
}
|
|
193561
193823
|
}
|
|
193562
193824
|
}
|
|
193825
|
+
function isArrayExprDirectPropRef(arrayExpr, ctx) {
|
|
193826
|
+
const propNames = new Set(ctx.patterns.props.map((p) => p.name));
|
|
193827
|
+
const propsObjName = ctx.analyzer.propsObjectName;
|
|
193828
|
+
if (import_typescript10.default.isIdentifier(arrayExpr)) {
|
|
193829
|
+
return propNames.has(arrayExpr.text);
|
|
193830
|
+
}
|
|
193831
|
+
if (import_typescript10.default.isPropertyAccessExpression(arrayExpr) && propsObjName) {
|
|
193832
|
+
const obj = arrayExpr.expression;
|
|
193833
|
+
if (import_typescript10.default.isIdentifier(obj) && obj.text === propsObjName) {
|
|
193834
|
+
return true;
|
|
193835
|
+
}
|
|
193836
|
+
}
|
|
193837
|
+
return false;
|
|
193838
|
+
}
|
|
193563
193839
|
function isSignalOrMemoArray(array, ctx) {
|
|
193564
193840
|
for (const { pattern } of ctx.patterns.signals) {
|
|
193565
193841
|
if (pattern.test(array))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/test",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Test utilities for BarefootJS - IR-based component testing without a browser",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"directory": "packages/test"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@barefootjs/jsx": "0.1.
|
|
42
|
+
"@barefootjs/jsx": "0.1.3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.0.0"
|