@bamboocss/vite 1.37.9 → 1.37.11
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 +47 -16
- package/dist/index.mjs +47 -16
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -751,10 +751,33 @@ const collectModuleScopeNames = (sourceFile) => {
|
|
|
751
751
|
* while under-reporting ships an element whose class has no rule behind it and says nothing.
|
|
752
752
|
* Shadowing a recipe binding is rare; silently shipping unstyled markup is not recoverable.
|
|
753
753
|
*/
|
|
754
|
-
|
|
755
|
-
|
|
754
|
+
/**
|
|
755
|
+
* Every identifier in the module, grouped by the name it spells.
|
|
756
|
+
*
|
|
757
|
+
* Built once per pass and handed to each lookup, because walking the whole tree per binding
|
|
758
|
+
* made that O(bindings x identifiers): a module declaring ten recipes walked its identifiers
|
|
759
|
+
* ten times.
|
|
760
|
+
*
|
|
761
|
+
* Deliberately *not* memoized across passes, unlike the module-scope names beside it. That
|
|
762
|
+
* cache holds strings, which outlive anything; this one holds nodes, and a node does not
|
|
763
|
+
* survive its source file being replaced — `addSourceFile` overwrites, which forgets every
|
|
764
|
+
* node previously taken from it. Keying on the source text does not help, because identical
|
|
765
|
+
* text re-parsed is a fresh tree: the cache hits and returns nodes that throw
|
|
766
|
+
* `Attempted to get information from a node that was removed or forgotten` on the next read.
|
|
767
|
+
*/
|
|
768
|
+
const identifierIndex = (sourceFile) => {
|
|
769
|
+
const index = /* @__PURE__ */ new Map();
|
|
756
770
|
for (const identifier of sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.Identifier)) {
|
|
757
|
-
|
|
771
|
+
const text = identifier.getText();
|
|
772
|
+
const known = index.get(text);
|
|
773
|
+
if (known) known.push(identifier);
|
|
774
|
+
else index.set(text, [identifier]);
|
|
775
|
+
}
|
|
776
|
+
return index;
|
|
777
|
+
};
|
|
778
|
+
const localReferencesTo = (index, name, declaration) => {
|
|
779
|
+
const references = [];
|
|
780
|
+
for (const identifier of index.get(name) ?? []) {
|
|
758
781
|
if (identifier === declaration) continue;
|
|
759
782
|
const parent = identifier.getParent();
|
|
760
783
|
if (!parent) continue;
|
|
@@ -2539,6 +2562,7 @@ const foldSource = (options) => {
|
|
|
2539
2562
|
const sourceFile = ownSourceFile ?? candidates[0]?.node.getSourceFile() ?? recipeDefinitions[0]?.call.getSourceFile();
|
|
2540
2563
|
if (!sourceFile) return;
|
|
2541
2564
|
const importedRecipeBindings = new Set(parserResult.importedRecipes?.keys() ?? []);
|
|
2565
|
+
const identifiers = identifierIndex(sourceFile);
|
|
2542
2566
|
for (const binding of new Set([...recipeConfigs.keys(), ...importedRecipeBindings])) {
|
|
2543
2567
|
const entry = recipeConfigs.get(binding);
|
|
2544
2568
|
if (entry === AMBIGUOUS) continue;
|
|
@@ -2546,7 +2570,7 @@ const foldSource = (options) => {
|
|
|
2546
2570
|
const definition = entry?.box?.getNode?.();
|
|
2547
2571
|
const nameNode = definition?.getSourceFile() === sourceFile ? definition?.getFirstAncestorByKind(ts_morph.SyntaxKind.VariableDeclaration)?.getNameNode() : importSpecifierFor(sourceFile, binding);
|
|
2548
2572
|
if (!nameNode || !ts_morph.Node.isIdentifier(nameNode)) continue;
|
|
2549
|
-
const references = localReferencesTo(
|
|
2573
|
+
const references = localReferencesTo(identifiers, binding, nameNode);
|
|
2550
2574
|
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;
|
|
2551
2575
|
const survivor = references.find((ref) => !applied.some(([from, to]) => ref.getStart() >= from && ref.getStart() < to));
|
|
2552
2576
|
if (!survivor) continue;
|
|
@@ -2839,18 +2863,24 @@ const bamboocss = (options = {}) => {
|
|
|
2839
2863
|
skipped: /* @__PURE__ */ new Map()
|
|
2840
2864
|
};
|
|
2841
2865
|
const staticSession = createStaticCompilationSession();
|
|
2842
|
-
|
|
2843
|
-
|
|
2866
|
+
/**
|
|
2867
|
+
* Indexed by file, because the only bulk operation on it is "forget this one's".
|
|
2868
|
+
*
|
|
2869
|
+
* A flat array meant every transform scanned every survivor and then rebuilt the dedupe key
|
|
2870
|
+
* set from scratch — O(modules x survivors) across a build, and worst exactly when a build is
|
|
2871
|
+
* already failing and the user is iterating on it. One project had 736 of them across 9,461
|
|
2872
|
+
* modules, which is seven million string builds to discard.
|
|
2873
|
+
*/
|
|
2874
|
+
const survivorsByFile = /* @__PURE__ */ new Map();
|
|
2875
|
+
const allSurvivors = () => [...survivorsByFile.values()].flat();
|
|
2844
2876
|
const addSurvivor = (entry) => {
|
|
2845
|
-
const
|
|
2846
|
-
if (
|
|
2847
|
-
|
|
2848
|
-
|
|
2877
|
+
const forFile = survivorsByFile.get(entry.file) ?? [];
|
|
2878
|
+
if (forFile.some((seen) => seen.line === entry.line && seen.name === entry.name && seen.reason === entry.reason)) return;
|
|
2879
|
+
forFile.push(entry);
|
|
2880
|
+
survivorsByFile.set(entry.file, forFile);
|
|
2849
2881
|
};
|
|
2850
2882
|
const clearSurvivorsFor = (file) => {
|
|
2851
|
-
|
|
2852
|
-
survivorKeys.clear();
|
|
2853
|
-
for (const entry of survivors) survivorKeys.add(`${entry.file}:${entry.line}:${entry.name}:${entry.reason}`);
|
|
2883
|
+
survivorsByFile.delete(file);
|
|
2854
2884
|
};
|
|
2855
2885
|
const createSurvivorError = (entries) => {
|
|
2856
2886
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -2909,8 +2939,7 @@ const bamboocss = (options = {}) => {
|
|
|
2909
2939
|
totals.files = 0;
|
|
2910
2940
|
totals.filesWithFolds = 0;
|
|
2911
2941
|
totals.skipped.clear();
|
|
2912
|
-
|
|
2913
|
-
survivorKeys.clear();
|
|
2942
|
+
survivorsByFile.clear();
|
|
2914
2943
|
recipeConfigCache.clear();
|
|
2915
2944
|
resetStaticCompilationSession(staticSession);
|
|
2916
2945
|
}
|
|
@@ -3013,7 +3042,8 @@ const bamboocss = (options = {}) => {
|
|
|
3013
3042
|
}
|
|
3014
3043
|
if (reportSkipped && result.skipped.length) _bamboocss_logger.logger.info("vite:transform", formatSkipped(filePath, result.skipped));
|
|
3015
3044
|
for (const dependency of result.dependencies) this.addWatchFile?.(dependency);
|
|
3016
|
-
|
|
3045
|
+
const forFile = survivorsByFile.get(filePath);
|
|
3046
|
+
if (command === "serve" && forFile?.length) throw createSurvivorError(forFile);
|
|
3017
3047
|
if (!result.folded.length) return null;
|
|
3018
3048
|
_bamboocss_logger.logger.debug("vite:transform", `Compiled ${result.folded.length} call(s) in ${filePath}`);
|
|
3019
3049
|
return {
|
|
@@ -3022,6 +3052,7 @@ const bamboocss = (options = {}) => {
|
|
|
3022
3052
|
};
|
|
3023
3053
|
},
|
|
3024
3054
|
buildEnd() {
|
|
3055
|
+
const survivors = allSurvivors();
|
|
3025
3056
|
if (survivors.length) throw createSurvivorError(survivors);
|
|
3026
3057
|
if (typeof this.getModuleInfo === "function") {
|
|
3027
3058
|
if (!staticSession.cssLoaded) throw new Error(`bamboocss: compiled class values were produced, but ${JSON.stringify(VIRTUAL_CSS_ID)} was not imported. Add \`import ${JSON.stringify(VIRTUAL_CSS_ID)}\` once, from a JavaScript or TypeScript module in the application entry graph.\n\nIt has to be a JS import. \`@import\` from a stylesheet does not reach it: the id names a virtual module resolved by this plugin, and Vite resolves CSS \`@import\` before plugin resolution, so it fails as an unresolvable path. A project that ships one preloaded stylesheet imports this from its entry module instead, and lets Vite emit the CSS asset.`);
|
package/dist/index.mjs
CHANGED
|
@@ -721,10 +721,33 @@ const collectModuleScopeNames = (sourceFile) => {
|
|
|
721
721
|
* while under-reporting ships an element whose class has no rule behind it and says nothing.
|
|
722
722
|
* Shadowing a recipe binding is rare; silently shipping unstyled markup is not recoverable.
|
|
723
723
|
*/
|
|
724
|
-
|
|
725
|
-
|
|
724
|
+
/**
|
|
725
|
+
* Every identifier in the module, grouped by the name it spells.
|
|
726
|
+
*
|
|
727
|
+
* Built once per pass and handed to each lookup, because walking the whole tree per binding
|
|
728
|
+
* made that O(bindings x identifiers): a module declaring ten recipes walked its identifiers
|
|
729
|
+
* ten times.
|
|
730
|
+
*
|
|
731
|
+
* Deliberately *not* memoized across passes, unlike the module-scope names beside it. That
|
|
732
|
+
* cache holds strings, which outlive anything; this one holds nodes, and a node does not
|
|
733
|
+
* survive its source file being replaced — `addSourceFile` overwrites, which forgets every
|
|
734
|
+
* node previously taken from it. Keying on the source text does not help, because identical
|
|
735
|
+
* text re-parsed is a fresh tree: the cache hits and returns nodes that throw
|
|
736
|
+
* `Attempted to get information from a node that was removed or forgotten` on the next read.
|
|
737
|
+
*/
|
|
738
|
+
const identifierIndex = (sourceFile) => {
|
|
739
|
+
const index = /* @__PURE__ */ new Map();
|
|
726
740
|
for (const identifier of sourceFile.getDescendantsOfKind(SyntaxKind.Identifier)) {
|
|
727
|
-
|
|
741
|
+
const text = identifier.getText();
|
|
742
|
+
const known = index.get(text);
|
|
743
|
+
if (known) known.push(identifier);
|
|
744
|
+
else index.set(text, [identifier]);
|
|
745
|
+
}
|
|
746
|
+
return index;
|
|
747
|
+
};
|
|
748
|
+
const localReferencesTo = (index, name, declaration) => {
|
|
749
|
+
const references = [];
|
|
750
|
+
for (const identifier of index.get(name) ?? []) {
|
|
728
751
|
if (identifier === declaration) continue;
|
|
729
752
|
const parent = identifier.getParent();
|
|
730
753
|
if (!parent) continue;
|
|
@@ -2509,6 +2532,7 @@ const foldSource = (options) => {
|
|
|
2509
2532
|
const sourceFile = ownSourceFile ?? candidates[0]?.node.getSourceFile() ?? recipeDefinitions[0]?.call.getSourceFile();
|
|
2510
2533
|
if (!sourceFile) return;
|
|
2511
2534
|
const importedRecipeBindings = new Set(parserResult.importedRecipes?.keys() ?? []);
|
|
2535
|
+
const identifiers = identifierIndex(sourceFile);
|
|
2512
2536
|
for (const binding of new Set([...recipeConfigs.keys(), ...importedRecipeBindings])) {
|
|
2513
2537
|
const entry = recipeConfigs.get(binding);
|
|
2514
2538
|
if (entry === AMBIGUOUS) continue;
|
|
@@ -2516,7 +2540,7 @@ const foldSource = (options) => {
|
|
|
2516
2540
|
const definition = entry?.box?.getNode?.();
|
|
2517
2541
|
const nameNode = definition?.getSourceFile() === sourceFile ? definition?.getFirstAncestorByKind(SyntaxKind.VariableDeclaration)?.getNameNode() : importSpecifierFor(sourceFile, binding);
|
|
2518
2542
|
if (!nameNode || !Node.isIdentifier(nameNode)) continue;
|
|
2519
|
-
const references = localReferencesTo(
|
|
2543
|
+
const references = localReferencesTo(identifiers, binding, nameNode);
|
|
2520
2544
|
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;
|
|
2521
2545
|
const survivor = references.find((ref) => !applied.some(([from, to]) => ref.getStart() >= from && ref.getStart() < to));
|
|
2522
2546
|
if (!survivor) continue;
|
|
@@ -2809,18 +2833,24 @@ const bamboocss = (options = {}) => {
|
|
|
2809
2833
|
skipped: /* @__PURE__ */ new Map()
|
|
2810
2834
|
};
|
|
2811
2835
|
const staticSession = createStaticCompilationSession();
|
|
2812
|
-
|
|
2813
|
-
|
|
2836
|
+
/**
|
|
2837
|
+
* Indexed by file, because the only bulk operation on it is "forget this one's".
|
|
2838
|
+
*
|
|
2839
|
+
* A flat array meant every transform scanned every survivor and then rebuilt the dedupe key
|
|
2840
|
+
* set from scratch — O(modules x survivors) across a build, and worst exactly when a build is
|
|
2841
|
+
* already failing and the user is iterating on it. One project had 736 of them across 9,461
|
|
2842
|
+
* modules, which is seven million string builds to discard.
|
|
2843
|
+
*/
|
|
2844
|
+
const survivorsByFile = /* @__PURE__ */ new Map();
|
|
2845
|
+
const allSurvivors = () => [...survivorsByFile.values()].flat();
|
|
2814
2846
|
const addSurvivor = (entry) => {
|
|
2815
|
-
const
|
|
2816
|
-
if (
|
|
2817
|
-
|
|
2818
|
-
|
|
2847
|
+
const forFile = survivorsByFile.get(entry.file) ?? [];
|
|
2848
|
+
if (forFile.some((seen) => seen.line === entry.line && seen.name === entry.name && seen.reason === entry.reason)) return;
|
|
2849
|
+
forFile.push(entry);
|
|
2850
|
+
survivorsByFile.set(entry.file, forFile);
|
|
2819
2851
|
};
|
|
2820
2852
|
const clearSurvivorsFor = (file) => {
|
|
2821
|
-
|
|
2822
|
-
survivorKeys.clear();
|
|
2823
|
-
for (const entry of survivors) survivorKeys.add(`${entry.file}:${entry.line}:${entry.name}:${entry.reason}`);
|
|
2853
|
+
survivorsByFile.delete(file);
|
|
2824
2854
|
};
|
|
2825
2855
|
const createSurvivorError = (entries) => {
|
|
2826
2856
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -2879,8 +2909,7 @@ const bamboocss = (options = {}) => {
|
|
|
2879
2909
|
totals.files = 0;
|
|
2880
2910
|
totals.filesWithFolds = 0;
|
|
2881
2911
|
totals.skipped.clear();
|
|
2882
|
-
|
|
2883
|
-
survivorKeys.clear();
|
|
2912
|
+
survivorsByFile.clear();
|
|
2884
2913
|
recipeConfigCache.clear();
|
|
2885
2914
|
resetStaticCompilationSession(staticSession);
|
|
2886
2915
|
}
|
|
@@ -2983,7 +3012,8 @@ const bamboocss = (options = {}) => {
|
|
|
2983
3012
|
}
|
|
2984
3013
|
if (reportSkipped && result.skipped.length) logger.info("vite:transform", formatSkipped(filePath, result.skipped));
|
|
2985
3014
|
for (const dependency of result.dependencies) this.addWatchFile?.(dependency);
|
|
2986
|
-
|
|
3015
|
+
const forFile = survivorsByFile.get(filePath);
|
|
3016
|
+
if (command === "serve" && forFile?.length) throw createSurvivorError(forFile);
|
|
2987
3017
|
if (!result.folded.length) return null;
|
|
2988
3018
|
logger.debug("vite:transform", `Compiled ${result.folded.length} call(s) in ${filePath}`);
|
|
2989
3019
|
return {
|
|
@@ -2992,6 +3022,7 @@ const bamboocss = (options = {}) => {
|
|
|
2992
3022
|
};
|
|
2993
3023
|
},
|
|
2994
3024
|
buildEnd() {
|
|
3025
|
+
const survivors = allSurvivors();
|
|
2995
3026
|
if (survivors.length) throw createSurvivorError(survivors);
|
|
2996
3027
|
if (typeof this.getModuleInfo === "function") {
|
|
2997
3028
|
if (!staticSession.cssLoaded) throw new Error(`bamboocss: compiled class values were produced, but ${JSON.stringify(VIRTUAL_CSS_ID)} was not imported. Add \`import ${JSON.stringify(VIRTUAL_CSS_ID)}\` once, from a JavaScript or TypeScript module in the application entry graph.\n\nIt has to be a JS import. \`@import\` from a stylesheet does not reach it: the id names a virtual module resolved by this plugin, and Vite resolves CSS \`@import\` before plugin resolution, so it fails as an unresolvable path. A project that ships one preloaded stylesheet imports this from its entry module instead, and lets Vite emit the CSS asset.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/vite",
|
|
3
|
-
"version": "1.37.
|
|
3
|
+
"version": "1.37.11",
|
|
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/
|
|
44
|
-
"@bamboocss/
|
|
45
|
-
"@bamboocss/extractor": "1.37.
|
|
46
|
-
"@bamboocss/
|
|
47
|
-
"@bamboocss/
|
|
48
|
-
"@bamboocss/
|
|
49
|
-
"@bamboocss/
|
|
43
|
+
"@bamboocss/logger": "1.37.11",
|
|
44
|
+
"@bamboocss/node": "1.37.11",
|
|
45
|
+
"@bamboocss/extractor": "1.37.11",
|
|
46
|
+
"@bamboocss/core": "1.37.11",
|
|
47
|
+
"@bamboocss/config": "1.37.11",
|
|
48
|
+
"@bamboocss/shared": "1.37.11",
|
|
49
|
+
"@bamboocss/types": "1.37.11"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
53
53
|
"vite": "7.2.6",
|
|
54
|
-
"@bamboocss/fixture": "1.37.
|
|
54
|
+
"@bamboocss/fixture": "1.37.11"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"vite": ">=5"
|