@bamboocss/vite 1.35.4 → 1.36.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.cjs +70 -20
- package/dist/index.mjs +70 -20
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -635,6 +635,54 @@ const collectModuleScopeNames = (sourceFile) => {
|
|
|
635
635
|
}
|
|
636
636
|
return names;
|
|
637
637
|
};
|
|
638
|
+
/**
|
|
639
|
+
* Every identifier in this module that reads the binding `name` declared at `declaration`.
|
|
640
|
+
*
|
|
641
|
+
* Replaces `nameNode.findReferencesAsNodes()`, which is a TypeScript *language-service*
|
|
642
|
+
* query. The first such query forces `synchronizeHostData` -> `createProgram`, binding the
|
|
643
|
+
* whole transitive `.d.ts` closure of the project — the exact cost `createTsProject`'s
|
|
644
|
+
* `skipAddingFilesFromTsConfig`, `skipFileDependencyResolution` and `skipLoadingLibFiles`
|
|
645
|
+
* exist to avoid, and which none of them govern. On a 2,278-file app it loaded 24,081 source
|
|
646
|
+
* files and 4.4 GB of AST and symbols, 80% of the heap, and OOMed the build. The retained
|
|
647
|
+
* strings were `googleapis` and `typescript`; none of it can reference a recipe binding.
|
|
648
|
+
*
|
|
649
|
+
* A recipe binding is module-scoped or imported, so every read of it is in this file. A
|
|
650
|
+
* syntactic walk answers the same question over one AST the parser has already built.
|
|
651
|
+
*
|
|
652
|
+
* ## Where this deliberately over-reports
|
|
653
|
+
*
|
|
654
|
+
* Shadowing is not resolved. If any nested scope declares the same name, every matching
|
|
655
|
+
* identifier is returned rather than only the ones that bind to `declaration`. That direction
|
|
656
|
+
* is chosen on purpose: over-reporting fails the build with a diagnostic naming a real line,
|
|
657
|
+
* while under-reporting ships an element whose class has no rule behind it and says nothing.
|
|
658
|
+
* Shadowing a recipe binding is rare; silently shipping unstyled markup is not recoverable.
|
|
659
|
+
*/
|
|
660
|
+
const localReferencesTo = (sourceFile, name, declaration) => {
|
|
661
|
+
const references = [];
|
|
662
|
+
for (const identifier of sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.Identifier)) {
|
|
663
|
+
if (identifier.getText() !== name) continue;
|
|
664
|
+
if (identifier === declaration) continue;
|
|
665
|
+
const parent = identifier.getParent();
|
|
666
|
+
if (!parent) continue;
|
|
667
|
+
if (ts_morph.Node.isPropertyAccessExpression(parent) && parent.getNameNode() === identifier) continue;
|
|
668
|
+
if (ts_morph.Node.isPropertyAssignment(parent) && parent.getNameNode() === identifier) continue;
|
|
669
|
+
if (ts_morph.Node.isBindingElement(parent) && parent.getPropertyNameNode() === identifier) continue;
|
|
670
|
+
if ((ts_morph.Node.isJsxOpeningElement(parent) || ts_morph.Node.isJsxSelfClosingElement(parent) || ts_morph.Node.isJsxClosingElement(parent)) && parent.getTagNameNode() === identifier) continue;
|
|
671
|
+
if (ts_morph.Node.isJsxAttribute(parent) && parent.getNameNode() === identifier) continue;
|
|
672
|
+
if ((ts_morph.Node.isMethodDeclaration(parent) || ts_morph.Node.isPropertyDeclaration(parent) || ts_morph.Node.isGetAccessorDeclaration(parent) || ts_morph.Node.isSetAccessorDeclaration(parent) || ts_morph.Node.isMethodSignature(parent) || ts_morph.Node.isPropertySignature(parent) || ts_morph.Node.isEnumMember(parent)) && parent.getNameNode() === identifier) continue;
|
|
673
|
+
if ((ts_morph.Node.isVariableDeclaration(parent) || ts_morph.Node.isParameterDeclaration(parent) || ts_morph.Node.isFunctionDeclaration(parent) || ts_morph.Node.isClassDeclaration(parent) || ts_morph.Node.isBindingElement(parent)) && parent.getNameNode() === identifier) continue;
|
|
674
|
+
if (ts_morph.Node.isImportSpecifier(parent) || ts_morph.Node.isExportSpecifier(parent)) {
|
|
675
|
+
if (parent.getNameNode() !== identifier) continue;
|
|
676
|
+
if (ts_morph.Node.isExportSpecifier(parent)) {
|
|
677
|
+
references.push(identifier);
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
references.push(identifier);
|
|
683
|
+
}
|
|
684
|
+
return references;
|
|
685
|
+
};
|
|
638
686
|
//#endregion
|
|
639
687
|
//#region src/fold-recipe.ts
|
|
640
688
|
/**
|
|
@@ -2383,29 +2431,36 @@ const foldSource = (options) => {
|
|
|
2383
2431
|
* also allowed to remain when it joins an arbitrary external class; only fully analyzable
|
|
2384
2432
|
* arguments receive Bamboo's semantic composition guarantee.
|
|
2385
2433
|
*/
|
|
2434
|
+
/** The specifier this module imported `binding` through, if it did. */
|
|
2435
|
+
function importSpecifierFor(sourceFile, binding) {
|
|
2436
|
+
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
2437
|
+
if (declaration.isTypeOnly()) continue;
|
|
2438
|
+
for (const named of declaration.getNamedImports()) {
|
|
2439
|
+
if (named.isTypeOnly()) continue;
|
|
2440
|
+
if ((named.getAliasNode() ?? named.getNameNode()).getText() === binding) return named.getAliasNode() ?? named.getNameNode();
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2386
2444
|
function reportRuntimeBindings() {
|
|
2387
2445
|
const sourceFile = ownSourceFile ?? candidates[0]?.node.getSourceFile() ?? recipeDefinitions[0]?.call.getSourceFile();
|
|
2388
2446
|
if (!sourceFile) return;
|
|
2389
|
-
|
|
2447
|
+
const importedRecipeBindings = new Set(parserResult.importedRecipes?.keys() ?? []);
|
|
2448
|
+
for (const binding of new Set([...recipeConfigs.keys(), ...importedRecipeBindings])) {
|
|
2449
|
+
const entry = recipeConfigs.get(binding);
|
|
2390
2450
|
if (entry === AMBIGUOUS) continue;
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
const nameNode = definition
|
|
2451
|
+
if (!entry && !importedRecipeBindings.has(binding)) continue;
|
|
2452
|
+
const definition = entry?.box?.getNode?.();
|
|
2453
|
+
const nameNode = definition?.getSourceFile() === sourceFile ? definition?.getFirstAncestorByKind(ts_morph.SyntaxKind.VariableDeclaration)?.getNameNode() : importSpecifierFor(sourceFile, binding);
|
|
2394
2454
|
if (!nameNode || !ts_morph.Node.isIdentifier(nameNode)) continue;
|
|
2395
|
-
|
|
2396
|
-
|
|
2455
|
+
const references = localReferencesTo(sourceFile, binding, nameNode);
|
|
2456
|
+
if (skipped.filter((item) => SURVIVES_TO_RUNTIME.has(item.reason) && item.end > item.start).some((item) => references.some((ref) => ref.getStart() >= item.start && ref.getStart() < item.end))) continue;
|
|
2457
|
+
const survivor = references.find((ref) => !applied.some(([from, to]) => ref.getStart() >= from && ref.getStart() < to));
|
|
2397
2458
|
if (!survivor) continue;
|
|
2398
|
-
const survivorFile = survivor.getSourceFile();
|
|
2399
|
-
const foreign = survivorFile !== sourceFile;
|
|
2400
2459
|
skipped.push({
|
|
2401
2460
|
name: binding,
|
|
2402
2461
|
reason: "runtime-binding",
|
|
2403
|
-
start:
|
|
2404
|
-
end:
|
|
2405
|
-
...foreign ? { origin: {
|
|
2406
|
-
filePath: survivorFile.getFilePath(),
|
|
2407
|
-
line: survivor.getStartLineNumber()
|
|
2408
|
-
} } : {}
|
|
2462
|
+
start: survivor.getStart(),
|
|
2463
|
+
end: survivor.getEnd()
|
|
2409
2464
|
});
|
|
2410
2465
|
}
|
|
2411
2466
|
const bambooModules = [
|
|
@@ -2869,12 +2924,7 @@ const bamboocss = (options = {}) => {
|
|
|
2869
2924
|
for (const entry of result.skipped) {
|
|
2870
2925
|
if (entry.reason === "not-imported" || entry.reason === "overlapping") continue;
|
|
2871
2926
|
if (entry.name === "cx" && entry.reason === "dynamic") continue;
|
|
2872
|
-
addSurvivor(
|
|
2873
|
-
file: entry.origin.filePath,
|
|
2874
|
-
line: entry.origin.line,
|
|
2875
|
-
name: entry.name,
|
|
2876
|
-
reason: entry.reason
|
|
2877
|
-
} : {
|
|
2927
|
+
addSurvivor({
|
|
2878
2928
|
file: filePath,
|
|
2879
2929
|
line: lineAt(code, entry.start),
|
|
2880
2930
|
name: entry.name,
|
package/dist/index.mjs
CHANGED
|
@@ -605,6 +605,54 @@ const collectModuleScopeNames = (sourceFile) => {
|
|
|
605
605
|
}
|
|
606
606
|
return names;
|
|
607
607
|
};
|
|
608
|
+
/**
|
|
609
|
+
* Every identifier in this module that reads the binding `name` declared at `declaration`.
|
|
610
|
+
*
|
|
611
|
+
* Replaces `nameNode.findReferencesAsNodes()`, which is a TypeScript *language-service*
|
|
612
|
+
* query. The first such query forces `synchronizeHostData` -> `createProgram`, binding the
|
|
613
|
+
* whole transitive `.d.ts` closure of the project — the exact cost `createTsProject`'s
|
|
614
|
+
* `skipAddingFilesFromTsConfig`, `skipFileDependencyResolution` and `skipLoadingLibFiles`
|
|
615
|
+
* exist to avoid, and which none of them govern. On a 2,278-file app it loaded 24,081 source
|
|
616
|
+
* files and 4.4 GB of AST and symbols, 80% of the heap, and OOMed the build. The retained
|
|
617
|
+
* strings were `googleapis` and `typescript`; none of it can reference a recipe binding.
|
|
618
|
+
*
|
|
619
|
+
* A recipe binding is module-scoped or imported, so every read of it is in this file. A
|
|
620
|
+
* syntactic walk answers the same question over one AST the parser has already built.
|
|
621
|
+
*
|
|
622
|
+
* ## Where this deliberately over-reports
|
|
623
|
+
*
|
|
624
|
+
* Shadowing is not resolved. If any nested scope declares the same name, every matching
|
|
625
|
+
* identifier is returned rather than only the ones that bind to `declaration`. That direction
|
|
626
|
+
* is chosen on purpose: over-reporting fails the build with a diagnostic naming a real line,
|
|
627
|
+
* while under-reporting ships an element whose class has no rule behind it and says nothing.
|
|
628
|
+
* Shadowing a recipe binding is rare; silently shipping unstyled markup is not recoverable.
|
|
629
|
+
*/
|
|
630
|
+
const localReferencesTo = (sourceFile, name, declaration) => {
|
|
631
|
+
const references = [];
|
|
632
|
+
for (const identifier of sourceFile.getDescendantsOfKind(SyntaxKind.Identifier)) {
|
|
633
|
+
if (identifier.getText() !== name) continue;
|
|
634
|
+
if (identifier === declaration) continue;
|
|
635
|
+
const parent = identifier.getParent();
|
|
636
|
+
if (!parent) continue;
|
|
637
|
+
if (Node.isPropertyAccessExpression(parent) && parent.getNameNode() === identifier) continue;
|
|
638
|
+
if (Node.isPropertyAssignment(parent) && parent.getNameNode() === identifier) continue;
|
|
639
|
+
if (Node.isBindingElement(parent) && parent.getPropertyNameNode() === identifier) continue;
|
|
640
|
+
if ((Node.isJsxOpeningElement(parent) || Node.isJsxSelfClosingElement(parent) || Node.isJsxClosingElement(parent)) && parent.getTagNameNode() === identifier) continue;
|
|
641
|
+
if (Node.isJsxAttribute(parent) && parent.getNameNode() === identifier) continue;
|
|
642
|
+
if ((Node.isMethodDeclaration(parent) || Node.isPropertyDeclaration(parent) || Node.isGetAccessorDeclaration(parent) || Node.isSetAccessorDeclaration(parent) || Node.isMethodSignature(parent) || Node.isPropertySignature(parent) || Node.isEnumMember(parent)) && parent.getNameNode() === identifier) continue;
|
|
643
|
+
if ((Node.isVariableDeclaration(parent) || Node.isParameterDeclaration(parent) || Node.isFunctionDeclaration(parent) || Node.isClassDeclaration(parent) || Node.isBindingElement(parent)) && parent.getNameNode() === identifier) continue;
|
|
644
|
+
if (Node.isImportSpecifier(parent) || Node.isExportSpecifier(parent)) {
|
|
645
|
+
if (parent.getNameNode() !== identifier) continue;
|
|
646
|
+
if (Node.isExportSpecifier(parent)) {
|
|
647
|
+
references.push(identifier);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
references.push(identifier);
|
|
653
|
+
}
|
|
654
|
+
return references;
|
|
655
|
+
};
|
|
608
656
|
//#endregion
|
|
609
657
|
//#region src/fold-recipe.ts
|
|
610
658
|
/**
|
|
@@ -2353,29 +2401,36 @@ const foldSource = (options) => {
|
|
|
2353
2401
|
* also allowed to remain when it joins an arbitrary external class; only fully analyzable
|
|
2354
2402
|
* arguments receive Bamboo's semantic composition guarantee.
|
|
2355
2403
|
*/
|
|
2404
|
+
/** The specifier this module imported `binding` through, if it did. */
|
|
2405
|
+
function importSpecifierFor(sourceFile, binding) {
|
|
2406
|
+
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
2407
|
+
if (declaration.isTypeOnly()) continue;
|
|
2408
|
+
for (const named of declaration.getNamedImports()) {
|
|
2409
|
+
if (named.isTypeOnly()) continue;
|
|
2410
|
+
if ((named.getAliasNode() ?? named.getNameNode()).getText() === binding) return named.getAliasNode() ?? named.getNameNode();
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2356
2414
|
function reportRuntimeBindings() {
|
|
2357
2415
|
const sourceFile = ownSourceFile ?? candidates[0]?.node.getSourceFile() ?? recipeDefinitions[0]?.call.getSourceFile();
|
|
2358
2416
|
if (!sourceFile) return;
|
|
2359
|
-
|
|
2417
|
+
const importedRecipeBindings = new Set(parserResult.importedRecipes?.keys() ?? []);
|
|
2418
|
+
for (const binding of new Set([...recipeConfigs.keys(), ...importedRecipeBindings])) {
|
|
2419
|
+
const entry = recipeConfigs.get(binding);
|
|
2360
2420
|
if (entry === AMBIGUOUS) continue;
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
const nameNode = definition
|
|
2421
|
+
if (!entry && !importedRecipeBindings.has(binding)) continue;
|
|
2422
|
+
const definition = entry?.box?.getNode?.();
|
|
2423
|
+
const nameNode = definition?.getSourceFile() === sourceFile ? definition?.getFirstAncestorByKind(SyntaxKind.VariableDeclaration)?.getNameNode() : importSpecifierFor(sourceFile, binding);
|
|
2364
2424
|
if (!nameNode || !Node.isIdentifier(nameNode)) continue;
|
|
2365
|
-
|
|
2366
|
-
|
|
2425
|
+
const references = localReferencesTo(sourceFile, binding, nameNode);
|
|
2426
|
+
if (skipped.filter((item) => SURVIVES_TO_RUNTIME.has(item.reason) && item.end > item.start).some((item) => references.some((ref) => ref.getStart() >= item.start && ref.getStart() < item.end))) continue;
|
|
2427
|
+
const survivor = references.find((ref) => !applied.some(([from, to]) => ref.getStart() >= from && ref.getStart() < to));
|
|
2367
2428
|
if (!survivor) continue;
|
|
2368
|
-
const survivorFile = survivor.getSourceFile();
|
|
2369
|
-
const foreign = survivorFile !== sourceFile;
|
|
2370
2429
|
skipped.push({
|
|
2371
2430
|
name: binding,
|
|
2372
2431
|
reason: "runtime-binding",
|
|
2373
|
-
start:
|
|
2374
|
-
end:
|
|
2375
|
-
...foreign ? { origin: {
|
|
2376
|
-
filePath: survivorFile.getFilePath(),
|
|
2377
|
-
line: survivor.getStartLineNumber()
|
|
2378
|
-
} } : {}
|
|
2432
|
+
start: survivor.getStart(),
|
|
2433
|
+
end: survivor.getEnd()
|
|
2379
2434
|
});
|
|
2380
2435
|
}
|
|
2381
2436
|
const bambooModules = [
|
|
@@ -2839,12 +2894,7 @@ const bamboocss = (options = {}) => {
|
|
|
2839
2894
|
for (const entry of result.skipped) {
|
|
2840
2895
|
if (entry.reason === "not-imported" || entry.reason === "overlapping") continue;
|
|
2841
2896
|
if (entry.name === "cx" && entry.reason === "dynamic") continue;
|
|
2842
|
-
addSurvivor(
|
|
2843
|
-
file: entry.origin.filePath,
|
|
2844
|
-
line: entry.origin.line,
|
|
2845
|
-
name: entry.name,
|
|
2846
|
-
reason: entry.reason
|
|
2847
|
-
} : {
|
|
2897
|
+
addSurvivor({
|
|
2848
2898
|
file: filePath,
|
|
2849
2899
|
line: lineAt(code, entry.start),
|
|
2850
2900
|
name: entry.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/vite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.0",
|
|
4
4
|
"description": "Vite integration for Bamboo CSS",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,18 +40,18 @@
|
|
|
40
40
|
"postcss": "8.5.26",
|
|
41
41
|
"postcss-selector-parser": "7.1.5",
|
|
42
42
|
"ts-morph": "28.0.0",
|
|
43
|
-
"@bamboocss/config": "1.
|
|
44
|
-
"@bamboocss/core": "1.
|
|
45
|
-
"@bamboocss/extractor": "1.
|
|
46
|
-
"@bamboocss/logger": "1.
|
|
47
|
-
"@bamboocss/node": "1.
|
|
48
|
-
"@bamboocss/
|
|
49
|
-
"@bamboocss/
|
|
43
|
+
"@bamboocss/config": "1.36.0",
|
|
44
|
+
"@bamboocss/core": "1.36.0",
|
|
45
|
+
"@bamboocss/extractor": "1.36.0",
|
|
46
|
+
"@bamboocss/logger": "1.36.0",
|
|
47
|
+
"@bamboocss/node": "1.36.0",
|
|
48
|
+
"@bamboocss/shared": "1.36.0",
|
|
49
|
+
"@bamboocss/types": "1.36.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
53
53
|
"vite": "7.2.6",
|
|
54
|
-
"@bamboocss/fixture": "1.
|
|
54
|
+
"@bamboocss/fixture": "1.36.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"vite": ">=5"
|