@barefootjs/test 0.24.1 → 0.26.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 +356 -78
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -189766,7 +189766,8 @@ var ErrorCodes = {
|
|
|
189766
189766
|
UNRECOGNIZED_REACTIVE_FACTORY: "BF110",
|
|
189767
189767
|
REACTIVE_FACTORY_RENAME_UNSUPPORTED: "BF111",
|
|
189768
189768
|
REACTIVE_FACTORY_MODULE_CAPTURE: "BF112",
|
|
189769
|
-
REACTIVE_FACTORY_IMPORT_COLLISION: "BF113"
|
|
189769
|
+
REACTIVE_FACTORY_IMPORT_COLLISION: "BF113",
|
|
189770
|
+
REACTIVE_FACTORY_PARAM_SHADOWED: "BF114"
|
|
189770
189771
|
};
|
|
189771
189772
|
var errorMessages = {
|
|
189772
189773
|
[ErrorCodes.MISSING_USE_CLIENT]: "'use client' directive required for components with createSignal or event handlers",
|
|
@@ -189793,7 +189794,8 @@ var errorMessages = {
|
|
|
189793
189794
|
[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.",
|
|
189794
189795
|
[ErrorCodes.REACTIVE_FACTORY_RENAME_UNSUPPORTED]: "Reactive factory object return/destructure must use shorthand properties only. " + "Property renames (`{ lists: myLists }`), defaults, and rest elements are not " + "supported — destructure with the factory's own property names.",
|
|
189795
189796
|
[ErrorCodes.REACTIVE_FACTORY_MODULE_CAPTURE]: "Imported reactive factory references bindings from its own module scope, so its " + "body cannot be inlined into the component file. Move those helpers into the " + "component file, pass them to the factory as parameters, or define the factory " + "in the component file.",
|
|
189796
|
-
[ErrorCodes.REACTIVE_FACTORY_IMPORT_COLLISION]: "Inlining an imported reactive factory requires re-importing one of its helper " + "imports into this file, but that name is already bound here to something else. " + "Rename the conflicting binding in this file, or alias the import in the factory's own file."
|
|
189797
|
+
[ErrorCodes.REACTIVE_FACTORY_IMPORT_COLLISION]: "Inlining an imported reactive factory requires re-importing one of its helper " + "imports into this file, but that name is already bound here to something else. " + "Rename the conflicting binding in this file, or alias the import in the factory's own file.",
|
|
189798
|
+
[ErrorCodes.REACTIVE_FACTORY_PARAM_SHADOWED]: "Reactive factory parameter is shadowed by a nested declaration inside the factory body, so argument substitution at the inline site would be ambiguous. Rename the inner binding so it does not collide with the parameter."
|
|
189797
189799
|
};
|
|
189798
189800
|
function createError(code2, loc, options) {
|
|
189799
189801
|
if (code2 === undefined || !(code2 in errorMessages)) {
|
|
@@ -191419,6 +191421,37 @@ function extractFreeIdentifiersFromNode(node) {
|
|
|
191419
191421
|
visit2(node);
|
|
191420
191422
|
return ids;
|
|
191421
191423
|
}
|
|
191424
|
+
function extractFreeTypeIdentifiersFromNode(node) {
|
|
191425
|
+
const ids = new Set;
|
|
191426
|
+
const boundTypeParams = new Set;
|
|
191427
|
+
function rootName(name) {
|
|
191428
|
+
return import_typescript8.default.isQualifiedName(name) ? rootName(name.left) : name;
|
|
191429
|
+
}
|
|
191430
|
+
function visit2(n) {
|
|
191431
|
+
if (import_typescript8.default.isTypeReferenceNode(n)) {
|
|
191432
|
+
const name = rootName(n.typeName).text;
|
|
191433
|
+
if (!boundTypeParams.has(name))
|
|
191434
|
+
ids.add(name);
|
|
191435
|
+
}
|
|
191436
|
+
if (import_typescript8.default.isTypeQueryNode(n)) {
|
|
191437
|
+
const name = rootName(n.exprName).text;
|
|
191438
|
+
if (!boundTypeParams.has(name))
|
|
191439
|
+
ids.add(name);
|
|
191440
|
+
}
|
|
191441
|
+
if (import_typescript8.default.isFunctionLike(n) && n.typeParameters && n.typeParameters.length > 0) {
|
|
191442
|
+
const names = n.typeParameters.map((p) => p.name.text);
|
|
191443
|
+
for (const p of names)
|
|
191444
|
+
boundTypeParams.add(p);
|
|
191445
|
+
import_typescript8.default.forEachChild(n, visit2);
|
|
191446
|
+
for (const p of names)
|
|
191447
|
+
boundTypeParams.delete(p);
|
|
191448
|
+
return;
|
|
191449
|
+
}
|
|
191450
|
+
import_typescript8.default.forEachChild(n, visit2);
|
|
191451
|
+
}
|
|
191452
|
+
visit2(node);
|
|
191453
|
+
return ids;
|
|
191454
|
+
}
|
|
191422
191455
|
function initializerShapeContainsJsx(node) {
|
|
191423
191456
|
let found = false;
|
|
191424
191457
|
function visit2(n) {
|
|
@@ -192241,16 +192274,17 @@ function buildEntryImportIndex(sf, filePath) {
|
|
|
192241
192274
|
continue;
|
|
192242
192275
|
if (!import_typescript8.default.isStringLiteral(stmt.moduleSpecifier))
|
|
192243
192276
|
continue;
|
|
192244
|
-
if (stmt.importClause?.isTypeOnly)
|
|
192245
|
-
continue;
|
|
192246
192277
|
const src = stmt.moduleSpecifier.text;
|
|
192247
192278
|
const targetKey = src.startsWith("./") || src.startsWith("../") ? resolveRelativeImportToFile(src, filePath) ?? "unresolved:" + src : src;
|
|
192279
|
+
const wholeTypeOnly = stmt.importClause?.isTypeOnly === true;
|
|
192248
192280
|
const namedBindings = stmt.importClause?.namedBindings;
|
|
192249
192281
|
if (namedBindings && import_typescript8.default.isNamedImports(namedBindings)) {
|
|
192250
192282
|
for (const el of namedBindings.elements) {
|
|
192251
|
-
|
|
192252
|
-
|
|
192253
|
-
|
|
192283
|
+
index.set(el.name.text, {
|
|
192284
|
+
targetKey,
|
|
192285
|
+
exportedName: (el.propertyName ?? el.name).text,
|
|
192286
|
+
isTypeOnly: wholeTypeOnly || el.isTypeOnly
|
|
192287
|
+
});
|
|
192254
192288
|
}
|
|
192255
192289
|
}
|
|
192256
192290
|
}
|
|
@@ -192280,6 +192314,9 @@ function collectEntryBindingNames(sf) {
|
|
|
192280
192314
|
if ((import_typescript8.default.isFunctionDeclaration(node) || import_typescript8.default.isClassDeclaration(node) || import_typescript8.default.isEnumDeclaration(node)) && node.name) {
|
|
192281
192315
|
names.add(node.name.text);
|
|
192282
192316
|
}
|
|
192317
|
+
if ((import_typescript8.default.isTypeAliasDeclaration(node) || import_typescript8.default.isInterfaceDeclaration(node)) && node.name) {
|
|
192318
|
+
names.add(node.name.text);
|
|
192319
|
+
}
|
|
192283
192320
|
if (import_typescript8.default.isFunctionLike(node)) {
|
|
192284
192321
|
for (const p of node.parameters) {
|
|
192285
192322
|
const out = [];
|
|
@@ -192293,6 +192330,7 @@ function collectEntryBindingNames(sf) {
|
|
|
192293
192330
|
visit2(sf);
|
|
192294
192331
|
return names;
|
|
192295
192332
|
}
|
|
192333
|
+
var MAX_REEXPORT_HOPS = 1;
|
|
192296
192334
|
function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
192297
192335
|
const candidateCallees = new Set;
|
|
192298
192336
|
function collectCandidates(node) {
|
|
@@ -192336,29 +192374,28 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192336
192374
|
const entryBindingNames = collectEntryBindingNames(entrySourceFile);
|
|
192337
192375
|
const entryImportIndex = buildEntryImportIndex(entrySourceFile, filePath);
|
|
192338
192376
|
const plannedInjections = new Map;
|
|
192339
|
-
|
|
192340
|
-
|
|
192341
|
-
|
|
192342
|
-
|
|
192377
|
+
const helperCache = new Map;
|
|
192378
|
+
function loadHelperFile(abs) {
|
|
192379
|
+
const cached = helperCache.get(abs);
|
|
192380
|
+
if (cached !== undefined)
|
|
192381
|
+
return cached;
|
|
192343
192382
|
let content;
|
|
192344
192383
|
try {
|
|
192345
|
-
content = fs.readFileSync(
|
|
192384
|
+
content = fs.readFileSync(abs, "utf8");
|
|
192346
192385
|
} catch {
|
|
192347
|
-
|
|
192386
|
+
helperCache.set(abs, null);
|
|
192387
|
+
return null;
|
|
192348
192388
|
}
|
|
192349
|
-
const alreadyKnown = (name) => result.factories.has(name) || result.declined.has(name) || result.reactiveShaped.has(name);
|
|
192350
192389
|
const hasAnyPrimitiveText = [...REACTIVE_PRIMITIVES].some((p) => content.includes(p));
|
|
192351
|
-
|
|
192352
|
-
|
|
192353
|
-
|
|
192354
|
-
|
|
192355
|
-
}
|
|
192356
|
-
continue;
|
|
192390
|
+
const hasReexportText = content.includes("export") && content.includes("from");
|
|
192391
|
+
if (!hasAnyPrimitiveText && !hasReexportText) {
|
|
192392
|
+
helperCache.set(abs, "clean");
|
|
192393
|
+
return "clean";
|
|
192357
192394
|
}
|
|
192358
|
-
const
|
|
192395
|
+
const sf = import_typescript8.default.createSourceFile(abs + ".prescan", content, import_typescript8.default.ScriptTarget.Latest, true, import_typescript8.default.ScriptKind.TSX);
|
|
192359
192396
|
const localFns = new Map;
|
|
192360
192397
|
const exportedFns = new Map;
|
|
192361
|
-
for (const stmt of
|
|
192398
|
+
for (const stmt of sf.statements) {
|
|
192362
192399
|
if (import_typescript8.default.isFunctionDeclaration(stmt) && stmt.name && stmt.body) {
|
|
192363
192400
|
localFns.set(stmt.name.text, stmt);
|
|
192364
192401
|
const hasExportModifier = stmt.modifiers?.some((m) => m.kind === import_typescript8.default.SyntaxKind.ExportKeyword) ?? false;
|
|
@@ -192368,27 +192405,89 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192368
192405
|
}
|
|
192369
192406
|
}
|
|
192370
192407
|
}
|
|
192371
|
-
|
|
192372
|
-
|
|
192408
|
+
const reexports = new Map;
|
|
192409
|
+
let hasStarReexport = false;
|
|
192410
|
+
for (const stmt of sf.statements) {
|
|
192411
|
+
if (!import_typescript8.default.isExportDeclaration(stmt) || stmt.isTypeOnly)
|
|
192412
|
+
continue;
|
|
192413
|
+
if (!stmt.moduleSpecifier) {
|
|
192414
|
+
if (stmt.exportClause && import_typescript8.default.isNamedExports(stmt.exportClause)) {
|
|
192415
|
+
for (const el of stmt.exportClause.elements) {
|
|
192416
|
+
if (el.isTypeOnly)
|
|
192417
|
+
continue;
|
|
192418
|
+
const fn = localFns.get((el.propertyName ?? el.name).text);
|
|
192419
|
+
if (fn)
|
|
192420
|
+
exportedFns.set(el.name.text, fn);
|
|
192421
|
+
}
|
|
192422
|
+
}
|
|
192423
|
+
continue;
|
|
192424
|
+
}
|
|
192425
|
+
if (!import_typescript8.default.isStringLiteral(stmt.moduleSpecifier))
|
|
192426
|
+
continue;
|
|
192427
|
+
if (stmt.exportClause && import_typescript8.default.isNamedExports(stmt.exportClause)) {
|
|
192373
192428
|
for (const el of stmt.exportClause.elements) {
|
|
192374
192429
|
if (el.isTypeOnly)
|
|
192375
192430
|
continue;
|
|
192376
|
-
|
|
192377
|
-
|
|
192378
|
-
|
|
192431
|
+
reexports.set(el.name.text, {
|
|
192432
|
+
source: stmt.moduleSpecifier.text,
|
|
192433
|
+
innerName: (el.propertyName ?? el.name).text
|
|
192434
|
+
});
|
|
192379
192435
|
}
|
|
192380
|
-
}
|
|
192436
|
+
} else if (!stmt.exportClause) {
|
|
192437
|
+
hasStarReexport = true;
|
|
192438
|
+
}
|
|
192439
|
+
}
|
|
192440
|
+
const moduleBindings = collectHelperModuleValueBindings(sf);
|
|
192441
|
+
const info = { sf, exportedFns, reexports, hasStarReexport, moduleBindings };
|
|
192442
|
+
helperCache.set(abs, info);
|
|
192443
|
+
return info;
|
|
192444
|
+
}
|
|
192445
|
+
function lookupExportedFactory(abs, exportedName, visited, hopsLeft) {
|
|
192446
|
+
if (visited.has(abs))
|
|
192447
|
+
return { kind: "unknown" };
|
|
192448
|
+
visited.add(abs);
|
|
192449
|
+
const file = loadHelperFile(abs);
|
|
192450
|
+
if (file === null)
|
|
192451
|
+
return { kind: "unknown" };
|
|
192452
|
+
if (file === "clean")
|
|
192453
|
+
return { kind: "clean" };
|
|
192454
|
+
const fn = file.exportedFns.get(exportedName);
|
|
192455
|
+
if (fn)
|
|
192456
|
+
return { kind: "fn", fn, file, definingPath: abs };
|
|
192457
|
+
const re = file.reexports.get(exportedName);
|
|
192458
|
+
if (re) {
|
|
192459
|
+
if (hopsLeft <= 0)
|
|
192460
|
+
return { kind: "unknown" };
|
|
192461
|
+
if (!re.source.startsWith("./") && !re.source.startsWith("../"))
|
|
192462
|
+
return { kind: "unknown" };
|
|
192463
|
+
const target = resolveRelativeImportToFile(re.source, abs);
|
|
192464
|
+
if (!target)
|
|
192465
|
+
return { kind: "unknown" };
|
|
192466
|
+
return lookupExportedFactory(target, re.innerName, visited, hopsLeft - 1);
|
|
192381
192467
|
}
|
|
192382
|
-
|
|
192468
|
+
if (file.hasStarReexport)
|
|
192469
|
+
return { kind: "unknown" };
|
|
192470
|
+
return { kind: "clean" };
|
|
192471
|
+
}
|
|
192472
|
+
for (const { src, specs } of importsToCheck) {
|
|
192473
|
+
const resolved = resolveRelativeImportToFile(src, filePath);
|
|
192474
|
+
if (!resolved)
|
|
192475
|
+
continue;
|
|
192476
|
+
const alreadyKnown = (name) => result.factories.has(name) || result.declined.has(name) || result.reactiveShaped.has(name);
|
|
192383
192477
|
for (const spec of specs) {
|
|
192384
192478
|
if (alreadyKnown(spec.local))
|
|
192385
192479
|
continue;
|
|
192386
|
-
const
|
|
192387
|
-
if (
|
|
192480
|
+
const found = lookupExportedFactory(resolved, spec.exported, new Set, MAX_REEXPORT_HOPS);
|
|
192481
|
+
if (found.kind === "clean") {
|
|
192388
192482
|
result.cleanFactoryImports.add(spec.local);
|
|
192389
192483
|
continue;
|
|
192390
192484
|
}
|
|
192391
|
-
|
|
192485
|
+
if (found.kind === "unknown")
|
|
192486
|
+
continue;
|
|
192487
|
+
const { fn, file, definingPath } = found;
|
|
192488
|
+
const helperSf = file.sf;
|
|
192489
|
+
const moduleBindings = file.moduleBindings;
|
|
192490
|
+
const det = detectReactiveFactory(fn, helperSf, definingPath);
|
|
192392
192491
|
if (!det) {
|
|
192393
192492
|
result.cleanFactoryImports.add(spec.local);
|
|
192394
192493
|
continue;
|
|
@@ -192413,11 +192512,15 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192413
192512
|
const required = [];
|
|
192414
192513
|
const pending = [];
|
|
192415
192514
|
let declinedEntry = null;
|
|
192416
|
-
|
|
192515
|
+
const allRefs = [
|
|
192516
|
+
...capture.importedRefs.map((r) => ({ ...r, isTypeOnly: false })),
|
|
192517
|
+
...capture.importedTypeRefs.map((r) => ({ ...r, isTypeOnly: true }))
|
|
192518
|
+
];
|
|
192519
|
+
for (const ref of allRefs) {
|
|
192417
192520
|
let specifier;
|
|
192418
192521
|
let targetKey;
|
|
192419
192522
|
if (ref.source.startsWith("./") || ref.source.startsWith("../")) {
|
|
192420
|
-
const abs = resolveRelativeImportToFile(ref.source,
|
|
192523
|
+
const abs = resolveRelativeImportToFile(ref.source, definingPath);
|
|
192421
192524
|
if (!abs) {
|
|
192422
192525
|
declinedEntry = {
|
|
192423
192526
|
code: "BF112",
|
|
@@ -192433,7 +192536,7 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192433
192536
|
targetKey = ref.source;
|
|
192434
192537
|
}
|
|
192435
192538
|
const existing = entryImportIndex.get(ref.localName);
|
|
192436
|
-
if (existing && existing.targetKey === targetKey && existing.exportedName === ref.exportedName) {
|
|
192539
|
+
if (existing && existing.targetKey === targetKey && existing.exportedName === ref.exportedName && (ref.isTypeOnly || !existing.isTypeOnly)) {
|
|
192437
192540
|
continue;
|
|
192438
192541
|
}
|
|
192439
192542
|
const planned = plannedInjections.get(ref.localName);
|
|
@@ -192447,7 +192550,7 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192447
192550
|
break;
|
|
192448
192551
|
}
|
|
192449
192552
|
pending.push([ref.localName, { targetKey, exportedName: ref.exportedName }]);
|
|
192450
|
-
required.push({ localName: ref.localName, exportedName: ref.exportedName, specifier });
|
|
192553
|
+
required.push({ localName: ref.localName, exportedName: ref.exportedName, specifier, isTypeOnly: ref.isTypeOnly || undefined });
|
|
192451
192554
|
}
|
|
192452
192555
|
if (declinedEntry) {
|
|
192453
192556
|
result.declined.set(spec.local, declinedEntry);
|
|
@@ -192455,7 +192558,7 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192455
192558
|
}
|
|
192456
192559
|
for (const [name, id] of pending)
|
|
192457
192560
|
plannedInjections.set(name, id);
|
|
192458
|
-
det.info.sourceFilePath =
|
|
192561
|
+
det.info.sourceFilePath = definingPath;
|
|
192459
192562
|
if (required.length > 0)
|
|
192460
192563
|
det.info.requiredImports = required;
|
|
192461
192564
|
result.factories.set(spec.local, det.info);
|
|
@@ -192467,6 +192570,8 @@ function prescanImportedReactiveFactories(entrySourceFile, filePath, result) {
|
|
|
192467
192570
|
}
|
|
192468
192571
|
function collectHelperModuleValueBindings(sf) {
|
|
192469
192572
|
const local = new Set;
|
|
192573
|
+
const localTypes = new Set;
|
|
192574
|
+
const importedTypes = new Map;
|
|
192470
192575
|
const imported = new Map;
|
|
192471
192576
|
for (const stmt of sf.statements) {
|
|
192472
192577
|
if (import_typescript8.default.isVariableStatement(stmt)) {
|
|
@@ -192482,35 +192587,41 @@ function collectHelperModuleValueBindings(sf) {
|
|
|
192482
192587
|
local.add(stmt.name.text);
|
|
192483
192588
|
continue;
|
|
192484
192589
|
}
|
|
192590
|
+
if ((import_typescript8.default.isTypeAliasDeclaration(stmt) || import_typescript8.default.isInterfaceDeclaration(stmt)) && stmt.name) {
|
|
192591
|
+
localTypes.add(stmt.name.text);
|
|
192592
|
+
continue;
|
|
192593
|
+
}
|
|
192485
192594
|
if (import_typescript8.default.isImportDeclaration(stmt)) {
|
|
192486
|
-
if (stmt.importClause?.isTypeOnly)
|
|
192487
|
-
continue;
|
|
192488
192595
|
if (!import_typescript8.default.isStringLiteral(stmt.moduleSpecifier))
|
|
192489
192596
|
continue;
|
|
192490
192597
|
const src = stmt.moduleSpecifier.text;
|
|
192491
192598
|
if (src === "@barefootjs/client" || src === "@barefootjs/client/runtime")
|
|
192492
192599
|
continue;
|
|
192600
|
+
const wholeTypeOnly = stmt.importClause?.isTypeOnly === true;
|
|
192493
192601
|
if (stmt.importClause?.name)
|
|
192494
|
-
local.add(stmt.importClause.name.text);
|
|
192602
|
+
(wholeTypeOnly ? localTypes : local).add(stmt.importClause.name.text);
|
|
192495
192603
|
const namedBindings = stmt.importClause?.namedBindings;
|
|
192496
192604
|
if (namedBindings && import_typescript8.default.isNamedImports(namedBindings)) {
|
|
192497
192605
|
for (const el of namedBindings.elements) {
|
|
192498
|
-
|
|
192499
|
-
|
|
192500
|
-
|
|
192606
|
+
const entry = { source: src, exportedName: (el.propertyName ?? el.name).text };
|
|
192607
|
+
if (wholeTypeOnly || el.isTypeOnly)
|
|
192608
|
+
importedTypes.set(el.name.text, entry);
|
|
192609
|
+
else
|
|
192610
|
+
imported.set(el.name.text, entry);
|
|
192501
192611
|
}
|
|
192502
192612
|
}
|
|
192503
192613
|
if (namedBindings && import_typescript8.default.isNamespaceImport(namedBindings)) {
|
|
192504
|
-
local.add(namedBindings.name.text);
|
|
192614
|
+
(wholeTypeOnly ? localTypes : local).add(namedBindings.name.text);
|
|
192505
192615
|
}
|
|
192506
192616
|
}
|
|
192507
192617
|
}
|
|
192508
|
-
return { local, imported };
|
|
192618
|
+
return { local, imported, localTypes, importedTypes };
|
|
192509
192619
|
}
|
|
192510
192620
|
function moduleCaptureCheck(fn, info, moduleBindings, selfName) {
|
|
192511
192621
|
if (!fn.body)
|
|
192512
|
-
return { captured: [], importedRefs: [] };
|
|
192622
|
+
return { captured: [], importedRefs: [], importedTypeRefs: [] };
|
|
192513
192623
|
const free = extractFreeIdentifiersFromNode(fn.body);
|
|
192624
|
+
const freeTypes = extractFreeTypeIdentifiersFromNode(fn.body);
|
|
192514
192625
|
const exclude = new Set(info.params);
|
|
192515
192626
|
for (const b of info.localBindings)
|
|
192516
192627
|
exclude.add(b);
|
|
@@ -192519,8 +192630,12 @@ function moduleCaptureCheck(fn, info, moduleBindings, selfName) {
|
|
|
192519
192630
|
for (const p of REACTIVE_PRIMITIVES)
|
|
192520
192631
|
exclude.add(p);
|
|
192521
192632
|
exclude.add(selfName);
|
|
192633
|
+
if (fn.typeParameters)
|
|
192634
|
+
for (const p of fn.typeParameters)
|
|
192635
|
+
exclude.add(p.name.text);
|
|
192522
192636
|
const captured = [];
|
|
192523
192637
|
const importedRefs = [];
|
|
192638
|
+
const importedTypeRefs = [];
|
|
192524
192639
|
for (const id of free) {
|
|
192525
192640
|
if (exclude.has(id))
|
|
192526
192641
|
continue;
|
|
@@ -192532,9 +192647,28 @@ function moduleCaptureCheck(fn, info, moduleBindings, selfName) {
|
|
|
192532
192647
|
if (imp)
|
|
192533
192648
|
importedRefs.push({ localName: id, source: imp.source, exportedName: imp.exportedName });
|
|
192534
192649
|
}
|
|
192650
|
+
for (const id of freeTypes) {
|
|
192651
|
+
if (exclude.has(id))
|
|
192652
|
+
continue;
|
|
192653
|
+
if (free.has(id))
|
|
192654
|
+
continue;
|
|
192655
|
+
if (moduleBindings.localTypes.has(id) || moduleBindings.local.has(id)) {
|
|
192656
|
+
captured.push(id);
|
|
192657
|
+
continue;
|
|
192658
|
+
}
|
|
192659
|
+
const typeImp = moduleBindings.importedTypes.get(id);
|
|
192660
|
+
if (typeImp) {
|
|
192661
|
+
importedTypeRefs.push({ localName: id, source: typeImp.source, exportedName: typeImp.exportedName });
|
|
192662
|
+
continue;
|
|
192663
|
+
}
|
|
192664
|
+
const valueImp = moduleBindings.imported.get(id);
|
|
192665
|
+
if (valueImp)
|
|
192666
|
+
importedRefs.push({ localName: id, source: valueImp.source, exportedName: valueImp.exportedName });
|
|
192667
|
+
}
|
|
192535
192668
|
captured.sort();
|
|
192536
192669
|
importedRefs.sort((a, b) => a.localName < b.localName ? -1 : 1);
|
|
192537
|
-
|
|
192670
|
+
importedTypeRefs.sort((a, b) => a.localName < b.localName ? -1 : 1);
|
|
192671
|
+
return { captured, importedRefs, importedTypeRefs };
|
|
192538
192672
|
}
|
|
192539
192673
|
function detectReactiveFactory(node, sourceFile, filePath) {
|
|
192540
192674
|
if (!node.body || !node.name)
|
|
@@ -192553,6 +192687,17 @@ function detectReactiveFactory(node, sourceFile, filePath) {
|
|
|
192553
192687
|
if (!hasReactiveCall)
|
|
192554
192688
|
return null;
|
|
192555
192689
|
const loc = getSourceLocation(node, sourceFile, filePath);
|
|
192690
|
+
let totalReturnCount = 0;
|
|
192691
|
+
function countReturns(n) {
|
|
192692
|
+
if (import_typescript8.default.isFunctionLike(n))
|
|
192693
|
+
return;
|
|
192694
|
+
if (import_typescript8.default.isReturnStatement(n)) {
|
|
192695
|
+
totalReturnCount++;
|
|
192696
|
+
return;
|
|
192697
|
+
}
|
|
192698
|
+
import_typescript8.default.forEachChild(n, countReturns);
|
|
192699
|
+
}
|
|
192700
|
+
import_typescript8.default.forEachChild(node.body, countReturns);
|
|
192556
192701
|
let returnExpr = null;
|
|
192557
192702
|
let returnCount = 0;
|
|
192558
192703
|
for (const stmt of node.body.statements) {
|
|
@@ -192570,7 +192715,7 @@ function detectReactiveFactory(node, sourceFile, filePath) {
|
|
|
192570
192715
|
expr = expr.expression;
|
|
192571
192716
|
returnExpr = expr;
|
|
192572
192717
|
}
|
|
192573
|
-
if (returnCount !== 1 || !returnExpr)
|
|
192718
|
+
if (totalReturnCount !== 1 || returnCount !== 1 || !returnExpr)
|
|
192574
192719
|
return { kind: "reactive-shaped" };
|
|
192575
192720
|
const returnTupleIdentifiers = [];
|
|
192576
192721
|
let returnKind;
|
|
@@ -192604,6 +192749,14 @@ function detectReactiveFactory(node, sourceFile, filePath) {
|
|
|
192604
192749
|
} else {
|
|
192605
192750
|
return { kind: "reactive-shaped" };
|
|
192606
192751
|
}
|
|
192752
|
+
const params = [];
|
|
192753
|
+
for (const p of node.parameters) {
|
|
192754
|
+
if (import_typescript8.default.isIdentifier(p.name)) {
|
|
192755
|
+
params.push(p.name.text);
|
|
192756
|
+
continue;
|
|
192757
|
+
}
|
|
192758
|
+
return { kind: "reactive-shaped" };
|
|
192759
|
+
}
|
|
192607
192760
|
const localBindings = [];
|
|
192608
192761
|
for (const stmt of node.body.statements) {
|
|
192609
192762
|
if (import_typescript8.default.isVariableStatement(stmt)) {
|
|
@@ -192614,15 +192767,95 @@ function detectReactiveFactory(node, sourceFile, filePath) {
|
|
|
192614
192767
|
localBindings.push(stmt.name.text);
|
|
192615
192768
|
}
|
|
192616
192769
|
}
|
|
192617
|
-
const
|
|
192770
|
+
const relevantNames = new Set([...params, ...localBindings, ...returnTupleIdentifiers]);
|
|
192771
|
+
const renameSites = [];
|
|
192772
|
+
let shadowedParam = null;
|
|
192773
|
+
function collectRenameSites(root, toBodyOffset) {
|
|
192774
|
+
function push(id, form) {
|
|
192775
|
+
renameSites.push({
|
|
192776
|
+
name: id.text,
|
|
192777
|
+
start: toBodyOffset(id.getStart(sourceFile)),
|
|
192778
|
+
end: toBodyOffset(id.getEnd()),
|
|
192779
|
+
form
|
|
192780
|
+
});
|
|
192781
|
+
}
|
|
192782
|
+
function classify(id) {
|
|
192783
|
+
if (!relevantNames.has(id.text))
|
|
192784
|
+
return;
|
|
192785
|
+
const p = id.parent;
|
|
192786
|
+
if (import_typescript8.default.isPropertyAccessExpression(p) && p.name === id)
|
|
192787
|
+
return;
|
|
192788
|
+
if (import_typescript8.default.isPropertyAssignment(p) && p.name === id)
|
|
192789
|
+
return;
|
|
192790
|
+
if (import_typescript8.default.isBindingElement(p) && p.propertyName === id)
|
|
192791
|
+
return;
|
|
192792
|
+
if ((import_typescript8.default.isMethodDeclaration(p) || import_typescript8.default.isGetAccessorDeclaration(p) || import_typescript8.default.isSetAccessorDeclaration(p) || import_typescript8.default.isPropertyDeclaration(p) || import_typescript8.default.isEnumMember(p)) && p.name === id)
|
|
192793
|
+
return;
|
|
192794
|
+
if (import_typescript8.default.isJsxAttribute(p) && p.name === id)
|
|
192795
|
+
return;
|
|
192796
|
+
if (import_typescript8.default.isLabeledStatement(p) && p.label === id || (import_typescript8.default.isBreakStatement(p) || import_typescript8.default.isContinueStatement(p)) && p.label === id)
|
|
192797
|
+
return;
|
|
192798
|
+
if ((import_typescript8.default.isJsxOpeningElement(p) || import_typescript8.default.isJsxSelfClosingElement(p) || import_typescript8.default.isJsxClosingElement(p)) && p.tagName === id && /^[a-z]/.test(id.text))
|
|
192799
|
+
return;
|
|
192800
|
+
if (import_typescript8.default.isShorthandPropertyAssignment(p) && p.name === id) {
|
|
192801
|
+
push(id, "shorthand");
|
|
192802
|
+
return;
|
|
192803
|
+
}
|
|
192804
|
+
if (import_typescript8.default.isBindingElement(p) && p.name === id && !p.propertyName && import_typescript8.default.isObjectBindingPattern(p.parent)) {
|
|
192805
|
+
if (params.includes(id.text))
|
|
192806
|
+
shadowedParam = id.text;
|
|
192807
|
+
push(id, "shorthand");
|
|
192808
|
+
return;
|
|
192809
|
+
}
|
|
192810
|
+
const isDecl = (import_typescript8.default.isVariableDeclaration(p) || import_typescript8.default.isParameter(p) || import_typescript8.default.isBindingElement(p) || import_typescript8.default.isFunctionDeclaration(p) || import_typescript8.default.isFunctionExpression(p) || import_typescript8.default.isClassDeclaration(p) || import_typescript8.default.isClassExpression(p)) && p.name === id;
|
|
192811
|
+
if (isDecl && params.includes(id.text))
|
|
192812
|
+
shadowedParam = id.text;
|
|
192813
|
+
push(id, "plain");
|
|
192814
|
+
}
|
|
192815
|
+
function visit2(n) {
|
|
192816
|
+
if (import_typescript8.default.isTypeNode(n) || import_typescript8.default.isTypeParameterDeclaration(n) || import_typescript8.default.isTypeAliasDeclaration(n) || import_typescript8.default.isInterfaceDeclaration(n))
|
|
192817
|
+
return;
|
|
192818
|
+
if (import_typescript8.default.isIdentifier(n)) {
|
|
192819
|
+
classify(n);
|
|
192820
|
+
return;
|
|
192821
|
+
}
|
|
192822
|
+
import_typescript8.default.forEachChild(n, visit2);
|
|
192823
|
+
}
|
|
192824
|
+
visit2(root);
|
|
192825
|
+
}
|
|
192826
|
+
const keptStatements = node.body.statements.filter((s) => !import_typescript8.default.isReturnStatement(s));
|
|
192827
|
+
const pieces = [];
|
|
192828
|
+
let base = 0;
|
|
192829
|
+
for (const stmt of keptStatements) {
|
|
192830
|
+
const text = stmt.getText(sourceFile);
|
|
192831
|
+
const stmtStart = stmt.getStart(sourceFile);
|
|
192832
|
+
collectRenameSites(stmt, (pos) => pos - stmtStart + base);
|
|
192833
|
+
pieces.push(text);
|
|
192834
|
+
base += text.length + 1;
|
|
192835
|
+
}
|
|
192836
|
+
const bodyStatements = pieces.join(`
|
|
192618
192837
|
`);
|
|
192619
|
-
|
|
192620
|
-
|
|
192621
|
-
|
|
192622
|
-
|
|
192623
|
-
|
|
192838
|
+
if (shadowedParam !== null) {
|
|
192839
|
+
return {
|
|
192840
|
+
kind: "declined",
|
|
192841
|
+
declined: {
|
|
192842
|
+
code: "BF114",
|
|
192843
|
+
detail: `parameter '${shadowedParam}' of '${node.name.text}' is shadowed by a nested declaration inside the factory body`,
|
|
192844
|
+
loc
|
|
192845
|
+
}
|
|
192846
|
+
};
|
|
192847
|
+
}
|
|
192848
|
+
for (const site of renameSites) {
|
|
192849
|
+
if (bodyStatements.slice(site.start, site.end) !== site.name) {
|
|
192850
|
+
return {
|
|
192851
|
+
kind: "declined",
|
|
192852
|
+
declined: {
|
|
192853
|
+
code: "BF111",
|
|
192854
|
+
detail: `internal rename-site offset mismatch for '${site.name}' — this is a compiler bug, ` + `please report it`,
|
|
192855
|
+
loc
|
|
192856
|
+
}
|
|
192857
|
+
};
|
|
192624
192858
|
}
|
|
192625
|
-
return { kind: "reactive-shaped" };
|
|
192626
192859
|
}
|
|
192627
192860
|
return {
|
|
192628
192861
|
kind: "factory",
|
|
@@ -192632,7 +192865,8 @@ function detectReactiveFactory(node, sourceFile, filePath) {
|
|
|
192632
192865
|
returnTupleIdentifiers,
|
|
192633
192866
|
returnKind,
|
|
192634
192867
|
localBindings,
|
|
192635
|
-
loc
|
|
192868
|
+
loc,
|
|
192869
|
+
renameSites
|
|
192636
192870
|
}
|
|
192637
192871
|
};
|
|
192638
192872
|
}
|
|
@@ -192736,24 +192970,31 @@ function rewriteFactoryCallsInSource(source, prescan) {
|
|
|
192736
192970
|
const argTexts = args.map((a) => a.getText(sourceFile));
|
|
192737
192971
|
const thisCallIndex = callSiteIndex++;
|
|
192738
192972
|
const suffix = `_bf${thisCallIndex}`;
|
|
192739
|
-
|
|
192740
|
-
const
|
|
192741
|
-
|
|
192742
|
-
|
|
192743
|
-
|
|
192744
|
-
|
|
192973
|
+
const renames = new Map;
|
|
192974
|
+
for (const name of factory.localBindings) {
|
|
192975
|
+
if (!excludeFromSuffixRename.has(name))
|
|
192976
|
+
renames.set(name, name + suffix);
|
|
192977
|
+
}
|
|
192978
|
+
if (renameReturnToCallerNames) {
|
|
192979
|
+
for (const [n, caller] of renameReturnToCallerNames) {
|
|
192980
|
+
if (caller !== n)
|
|
192981
|
+
renames.set(n, caller);
|
|
192982
|
+
}
|
|
192745
192983
|
}
|
|
192746
192984
|
const atomicArg = /^(?:[\w$.]+|'[^'\\]*'|"[^"\\]*"|-?\d+(?:\.\d+)?)$/;
|
|
192747
192985
|
for (let i2 = 0;i2 < factory.params.length; i2++) {
|
|
192748
192986
|
const p = factory.params[i2];
|
|
192749
|
-
const a = argTexts[i2] ?? "undefined";
|
|
192750
|
-
|
|
192751
|
-
body = body.replace(new RegExp(`\\b${escapeRegex(p)}\\b`, "g"), wrapped);
|
|
192987
|
+
const a = (argTexts[i2] ?? "undefined").trim();
|
|
192988
|
+
renames.set(p, atomicArg.test(a) ? a : `(${a})`);
|
|
192752
192989
|
}
|
|
192753
|
-
|
|
192754
|
-
|
|
192755
|
-
|
|
192756
|
-
|
|
192990
|
+
let body = factory.bodySource;
|
|
192991
|
+
for (let i2 = factory.renameSites.length - 1;i2 >= 0; i2--) {
|
|
192992
|
+
const site = factory.renameSites[i2];
|
|
192993
|
+
const repl = renames.get(site.name);
|
|
192994
|
+
if (repl === undefined)
|
|
192995
|
+
continue;
|
|
192996
|
+
const text = site.form === "shorthand" ? `${site.name}: ${repl}` : repl;
|
|
192997
|
+
body = body.slice(0, site.start) + text + body.slice(site.end);
|
|
192757
192998
|
}
|
|
192758
192999
|
edits.push({
|
|
192759
193000
|
start: stmt.getStart(sourceFile),
|
|
@@ -192766,20 +193007,44 @@ function rewriteFactoryCallsInSource(source, prescan) {
|
|
|
192766
193007
|
if (edits.length === 0)
|
|
192767
193008
|
return source;
|
|
192768
193009
|
const importsBySpecifier = new Map;
|
|
193010
|
+
const typeImportsBySpecifier = new Map;
|
|
192769
193011
|
for (const f of inlinedFactories) {
|
|
192770
193012
|
for (const r of f.requiredImports ?? []) {
|
|
192771
|
-
|
|
193013
|
+
const bySpecifier = r.isTypeOnly ? typeImportsBySpecifier : importsBySpecifier;
|
|
193014
|
+
let names = bySpecifier.get(r.specifier);
|
|
192772
193015
|
if (!names) {
|
|
192773
193016
|
names = new Map;
|
|
192774
|
-
|
|
193017
|
+
bySpecifier.set(r.specifier, names);
|
|
192775
193018
|
}
|
|
192776
193019
|
names.set(r.localName, r.exportedName);
|
|
192777
193020
|
}
|
|
192778
193021
|
}
|
|
192779
|
-
|
|
192780
|
-
const
|
|
193022
|
+
for (const [spec, typeNames] of typeImportsBySpecifier) {
|
|
193023
|
+
const valueNames = importsBySpecifier.get(spec);
|
|
193024
|
+
if (!valueNames)
|
|
193025
|
+
continue;
|
|
193026
|
+
for (const local of [...typeNames.keys()]) {
|
|
193027
|
+
if (valueNames.has(local))
|
|
193028
|
+
typeNames.delete(local);
|
|
193029
|
+
}
|
|
193030
|
+
if (typeNames.size === 0)
|
|
193031
|
+
typeImportsBySpecifier.delete(spec);
|
|
193032
|
+
}
|
|
193033
|
+
if (importsBySpecifier.size > 0 || typeImportsBySpecifier.size > 0) {
|
|
193034
|
+
const buildLine = (names, keyword, spec) => {
|
|
192781
193035
|
const specifiers = [...names].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([local, exported]) => exported === local ? local : `${exported} as ${local}`);
|
|
192782
|
-
return `import { ${specifiers.join(", ")} } from '${spec}'`;
|
|
193036
|
+
return `import ${keyword}{ ${specifiers.join(", ")} } from '${spec}'`;
|
|
193037
|
+
};
|
|
193038
|
+
const allSpecifiers = new Set([...importsBySpecifier.keys(), ...typeImportsBySpecifier.keys()]);
|
|
193039
|
+
const lines = [...allSpecifiers].sort().flatMap((spec) => {
|
|
193040
|
+
const out2 = [];
|
|
193041
|
+
const valueNames = importsBySpecifier.get(spec);
|
|
193042
|
+
if (valueNames)
|
|
193043
|
+
out2.push(buildLine(valueNames, "", spec));
|
|
193044
|
+
const typeNames = typeImportsBySpecifier.get(spec);
|
|
193045
|
+
if (typeNames)
|
|
193046
|
+
out2.push(buildLine(typeNames, "type ", spec));
|
|
193047
|
+
return out2;
|
|
192783
193048
|
});
|
|
192784
193049
|
const at = factoryImportInsertionOffset(sourceFile);
|
|
192785
193050
|
edits.push({ start: at, end: at, replacement: at === 0 ? lines.join(`
|
|
@@ -192818,9 +193083,6 @@ function isPascalCaseComponentFn(node) {
|
|
|
192818
193083
|
}
|
|
192819
193084
|
return false;
|
|
192820
193085
|
}
|
|
192821
|
-
function escapeRegex(s) {
|
|
192822
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
192823
|
-
}
|
|
192824
193086
|
function declinedFactoryMessage(callee, d) {
|
|
192825
193087
|
if (d.code === "BF112") {
|
|
192826
193088
|
return `Reactive factory '${callee}' references ${d.detail} from its own module ` + `scope and cannot be inlined. Move the referenced helper(s) into this file, ` + `pass them as factory arguments, or inline the factory here.`;
|
|
@@ -192836,6 +193098,8 @@ function declinedFactoryErrorCode(code2) {
|
|
|
192836
193098
|
return ErrorCodes.REACTIVE_FACTORY_MODULE_CAPTURE;
|
|
192837
193099
|
case "BF113":
|
|
192838
193100
|
return ErrorCodes.REACTIVE_FACTORY_IMPORT_COLLISION;
|
|
193101
|
+
case "BF114":
|
|
193102
|
+
return ErrorCodes.REACTIVE_FACTORY_PARAM_SHADOWED;
|
|
192839
193103
|
default:
|
|
192840
193104
|
return ErrorCodes.REACTIVE_FACTORY_RENAME_UNSUPPORTED;
|
|
192841
193105
|
}
|
|
@@ -193360,6 +193624,20 @@ function resolveFreeRefs(node, env) {
|
|
|
193360
193624
|
|
|
193361
193625
|
// ../jsx/src/to-locale-date-lowering.ts
|
|
193362
193626
|
var TO_LOCALE_TZ_RE = /^(?:UTC|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
|
|
193627
|
+
var tzProbeCache = new Map;
|
|
193628
|
+
function isBuildResolvableTimeZone(value) {
|
|
193629
|
+
const cached = tzProbeCache.get(value);
|
|
193630
|
+
if (cached !== undefined)
|
|
193631
|
+
return cached;
|
|
193632
|
+
let verified;
|
|
193633
|
+
try {
|
|
193634
|
+
verified = new Intl.DateTimeFormat("en-US", { timeZone: value }).resolvedOptions().timeZone === value;
|
|
193635
|
+
} catch {
|
|
193636
|
+
verified = false;
|
|
193637
|
+
}
|
|
193638
|
+
tzProbeCache.set(value, verified);
|
|
193639
|
+
return verified;
|
|
193640
|
+
}
|
|
193363
193641
|
var PROBE_UTC = new Date(Date.UTC(2001, 1, 3));
|
|
193364
193642
|
var formatCache = new Map;
|
|
193365
193643
|
var namesCache = new Map;
|
|
@@ -193598,7 +193876,7 @@ function matchToLocaleDateStringCall(callee, args, metadata) {
|
|
|
193598
193876
|
return null;
|
|
193599
193877
|
const value = String(prop.value.value);
|
|
193600
193878
|
if (prop.key === "timeZone") {
|
|
193601
|
-
if (!TO_LOCALE_TZ_RE.test(value))
|
|
193879
|
+
if (!TO_LOCALE_TZ_RE.test(value) && !isBuildResolvableTimeZone(value))
|
|
193602
193880
|
return null;
|
|
193603
193881
|
tz = value;
|
|
193604
193882
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/test",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.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.26.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.0.0"
|