@bamboocss/vite 1.46.0 → 1.46.1
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 +142 -38
- package/dist/index.mjs +142 -38
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -208,6 +208,23 @@ const bamboocssCss = (options) => {
|
|
|
208
208
|
* stylesheet twice over.
|
|
209
209
|
*/
|
|
210
210
|
let pending;
|
|
211
|
+
/**
|
|
212
|
+
* Which change the current `pending` was generated for, and the validated sheet it produced.
|
|
213
|
+
*
|
|
214
|
+
* Every environment loads the virtual stylesheet — a react-router dev server loads it once
|
|
215
|
+
* for the client graph and once for SSR — and each load used to run a complete extraction
|
|
216
|
+
* and optimization pass to produce byte-identical CSS. The sheet is a function of the source
|
|
217
|
+
* files alone, and the watcher below is the single point every event that can reach it
|
|
218
|
+
* passes through — Vite's own propagation only arrives via the watch edges `load` registers,
|
|
219
|
+
* over the same extracted files the watcher checks. A monotonic counter bumped there is
|
|
220
|
+
* therefore enough to know whether a build already reflects the world a load is asking about.
|
|
221
|
+
*
|
|
222
|
+
* Dev only. A production build has no dev watcher to advance the counter, so serving the
|
|
223
|
+
* memo there would hand `vite build --watch` a stale sheet; builds regenerate per load.
|
|
224
|
+
*/
|
|
225
|
+
let changeGeneration = 0;
|
|
226
|
+
let pendingGeneration = -1;
|
|
227
|
+
let servedCss;
|
|
211
228
|
const build = async () => {
|
|
212
229
|
const builder = await ensureBuilder();
|
|
213
230
|
await builder.setup({
|
|
@@ -245,6 +262,8 @@ const bamboocssCss = (options) => {
|
|
|
245
262
|
return css;
|
|
246
263
|
};
|
|
247
264
|
const generate = () => {
|
|
265
|
+
if (command === "serve" && pending && pendingGeneration === changeGeneration) return pending;
|
|
266
|
+
pendingGeneration = changeGeneration;
|
|
248
267
|
pending = Promise.resolve(pending).catch(() => void 0).then(build);
|
|
249
268
|
return pending;
|
|
250
269
|
};
|
|
@@ -393,6 +412,11 @@ const bamboocssCss = (options) => {
|
|
|
393
412
|
const query = queryOf(id);
|
|
394
413
|
if (id.slice(0, id.length - query.length) !== RESOLVED_ID) return null;
|
|
395
414
|
session.cssLoaded = true;
|
|
415
|
+
const generationAtStart = changeGeneration;
|
|
416
|
+
if (command === "serve" && servedCss?.generation === generationAtStart) {
|
|
417
|
+
if (this.addWatchFile) for (const file of extractedSourceFiles()) this.addWatchFile(file);
|
|
418
|
+
return servedCss.css;
|
|
419
|
+
}
|
|
396
420
|
let css;
|
|
397
421
|
try {
|
|
398
422
|
const validateDevCss = command === "serve" ? (await loadCssOutput()).pruneStaticCss : void 0;
|
|
@@ -403,6 +427,10 @@ const bamboocssCss = (options) => {
|
|
|
403
427
|
} catch (error) {
|
|
404
428
|
throw asError(error, `failed to generate ${VIRTUAL_CSS_ID}`);
|
|
405
429
|
}
|
|
430
|
+
if (command === "serve" && generationAtStart === changeGeneration) servedCss = {
|
|
431
|
+
generation: generationAtStart,
|
|
432
|
+
css
|
|
433
|
+
};
|
|
406
434
|
if (this.addWatchFile) for (const file of extractedSourceFiles()) this.addWatchFile(file);
|
|
407
435
|
return css;
|
|
408
436
|
},
|
|
@@ -427,6 +455,7 @@ const bamboocssCss = (options) => {
|
|
|
427
455
|
if (!ctx) return;
|
|
428
456
|
const absoluteFile = ctx.runtime.path.abs(ctx.config.cwd, file);
|
|
429
457
|
if (!session.extractedFiles.has(absoluteFile)) return;
|
|
458
|
+
changeGeneration++;
|
|
430
459
|
prebuilt = void 0;
|
|
431
460
|
const mod = server?.moduleGraph.getModuleById(RESOLVED_ID);
|
|
432
461
|
if (!mod) return;
|
|
@@ -694,6 +723,43 @@ const bamboocss = (options = {}) => {
|
|
|
694
723
|
return /* @__PURE__ */ new Error(`bamboocss: cached transform metadata for ${JSON.stringify(id)} in the ${JSON.stringify(environment)} environment ${problem}.\n\nBamboo cannot safely rebuild from this entry because cached JavaScript may still name CSS classes whose rules would be dropped. Restart Vite to invalidate its in-memory transform cache. If this persists, clear Vite's cache directory and rebuild.`);
|
|
695
724
|
};
|
|
696
725
|
const transformStateByEnvironment = /* @__PURE__ */ new Map();
|
|
726
|
+
/**
|
|
727
|
+
* One fold per file content per change event, shared across environments and hooks.
|
|
728
|
+
*
|
|
729
|
+
* A single edit folds the same bytes repeatedly: `hotUpdate` provisionally re-folds every
|
|
730
|
+
* dependent once per environment to decide what to invalidate, then `transform` folds the
|
|
731
|
+
* edited module for the client graph, again for SSR, and once more for each update a
|
|
732
|
+
* framework re-drives — react-router's server-change trigger calls `reloadModule` per pass.
|
|
733
|
+
* All of them read the same shared ts-morph project under the same config, so the result is
|
|
734
|
+
* a function of the bytes alone and the repeats were pure cost: on the app this was measured
|
|
735
|
+
* on, four transforms of a 46 kB route module per edit, ~10 ms each.
|
|
736
|
+
*
|
|
737
|
+
* `watchChange` clears it, which is the exact validity window: entries are correct until a
|
|
738
|
+
* file event changes what a fold could resolve, and `watchChange` is the one hook Vite calls
|
|
739
|
+
* for every such event before any update work begins. The per-environment resolution closure
|
|
740
|
+
* is deliberately not memoized — `withResolutionClosure` is recomputed per consumer against
|
|
741
|
+
* that environment's own recorded dependencies.
|
|
742
|
+
*
|
|
743
|
+
* Keyed by path *and* content digest, not path alone, because one physical file is served
|
|
744
|
+
* as more than one module shape in the same event — react-router clips a route module down
|
|
745
|
+
* to its route exports for the client graph while SSR gets the full file — and a last-write
|
|
746
|
+
* key would make the two shapes evict each other on every pass.
|
|
747
|
+
*
|
|
748
|
+
* Dev only, like the verdict memo it sits beside: a build transforms each module once per
|
|
749
|
+
* environment with no bracketing events, and holding every module's fold for the length of a
|
|
750
|
+
* build is memory a one-shot pass has no reason to spend.
|
|
751
|
+
*/
|
|
752
|
+
const foldMemoByContent = /* @__PURE__ */ new Map();
|
|
753
|
+
const foldMemoKey = (filePath, inputDigest) => `${filePath}\0${inputDigest}`;
|
|
754
|
+
/**
|
|
755
|
+
* The Project resolution walk `withResolutionClosure` runs, memoized per change event.
|
|
756
|
+
*
|
|
757
|
+
* The walk is the dominant per-dependent cost once the fold itself is memoized — it runs
|
|
758
|
+
* once per dependent per environment with identical inputs, since both environments record
|
|
759
|
+
* the same fold dependencies for byte-identical source. Same bracketing as the fold memo:
|
|
760
|
+
* `watchChange` clears it, so no entry outlives the project state it was computed against.
|
|
761
|
+
*/
|
|
762
|
+
const resolutionClosureMemo = /* @__PURE__ */ new Map();
|
|
697
763
|
/** The immutable generation currently occupying each configured output on disk. */
|
|
698
764
|
const liveOutputSlotsByEnvironment = /* @__PURE__ */ new Map();
|
|
699
765
|
/** Graphs which passed `buildEnd`, but whose output has not succeeded yet. */
|
|
@@ -1231,23 +1297,40 @@ const bamboocss = (options = {}) => {
|
|
|
1231
1297
|
if (!signature || !ctx || !foldSourceImpl || !runtimeCss || !styleCompiler) return false;
|
|
1232
1298
|
try {
|
|
1233
1299
|
const code = (0, node_fs.readFileSync)(signature.path, "utf8");
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
const
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1300
|
+
const inputDigest = digest(code);
|
|
1301
|
+
if (inputDigest !== signature.input) return false;
|
|
1302
|
+
let raw;
|
|
1303
|
+
let parserDependencies;
|
|
1304
|
+
const memoKey = foldMemoKey(signature.path, inputDigest);
|
|
1305
|
+
const memoized = foldMemoByContent.get(memoKey);
|
|
1306
|
+
if (memoized) {
|
|
1307
|
+
raw = memoized.result;
|
|
1308
|
+
parserDependencies = memoized.parserDependencies;
|
|
1309
|
+
} else {
|
|
1310
|
+
const sourceFile = ctx.project.addSourceFile(signature.path, code);
|
|
1311
|
+
const parserResult = ctx.project.parseSourceFile(signature.path);
|
|
1312
|
+
if (!parserResult) return false;
|
|
1313
|
+
raw = foldSourceImpl({
|
|
1314
|
+
ctx,
|
|
1315
|
+
code,
|
|
1316
|
+
parserResult,
|
|
1317
|
+
filePath: signature.path,
|
|
1318
|
+
runtimeCss,
|
|
1319
|
+
styleCompiler,
|
|
1320
|
+
maxRecipeStates,
|
|
1321
|
+
parseModule: (path) => ctx?.project.parseSourceFile(path),
|
|
1322
|
+
recipeConfigCache: state.recipeConfigCache,
|
|
1323
|
+
reportSurvivors: false,
|
|
1324
|
+
sourceFile
|
|
1325
|
+
});
|
|
1326
|
+
parserDependencies = parserResult.getDependencies();
|
|
1327
|
+
foldMemoByContent.set(memoKey, {
|
|
1328
|
+
result: raw,
|
|
1329
|
+
parserDependencies,
|
|
1330
|
+
reportedSurvivors: false
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
const result = withResolutionClosure(signature.path, raw, parserDependencies, state.dependenciesByModule.get(dependent));
|
|
1251
1334
|
const unchanged = digest(result.code) === signature.output;
|
|
1252
1335
|
/**
|
|
1253
1336
|
* Edges re-recorded exactly on the way to suppressing a module. A changed provisional
|
|
@@ -1397,7 +1480,14 @@ const bamboocss = (options = {}) => {
|
|
|
1397
1480
|
const targets = new Set(dependencies);
|
|
1398
1481
|
for (const dependency of previousDependencies ?? []) targets.add(dependency);
|
|
1399
1482
|
if (!targets.size) return result;
|
|
1400
|
-
|
|
1483
|
+
const targetList = [...targets];
|
|
1484
|
+
const closureKey = command === "serve" ? `${filePath}\0${targetList.slice().sort().join("|")}` : void 0;
|
|
1485
|
+
let reachable = closureKey ? resolutionClosureMemo.get(closureKey) : void 0;
|
|
1486
|
+
if (!reachable) {
|
|
1487
|
+
reachable = ctx.project.getDependencies(filePath, targetList);
|
|
1488
|
+
if (closureKey) resolutionClosureMemo.set(closureKey, reachable);
|
|
1489
|
+
}
|
|
1490
|
+
for (const dependency of reachable) if (!isGeneratedOutput(dependency, ctx)) dependencies.add(dependency);
|
|
1401
1491
|
const expanded = [...dependencies];
|
|
1402
1492
|
if (expanded.length === result.dependencies.length && expanded.every((dependency, index) => dependency === result.dependencies[index])) return result;
|
|
1403
1493
|
return {
|
|
@@ -1581,6 +1671,8 @@ const bamboocss = (options = {}) => {
|
|
|
1581
1671
|
* the parser still holds the file.
|
|
1582
1672
|
*/
|
|
1583
1673
|
watchChange(id, change) {
|
|
1674
|
+
foldMemoByContent.clear();
|
|
1675
|
+
resolutionClosureMemo.clear();
|
|
1584
1676
|
for (const state of transformStateByEnvironment.values()) {
|
|
1585
1677
|
state.unchangedFolds.clear();
|
|
1586
1678
|
state.changedRun = 0;
|
|
@@ -1650,27 +1742,39 @@ const bamboocss = (options = {}) => {
|
|
|
1650
1742
|
const previousDependencies = previousSignature && previousSignature.input === (inputDigest ??= digest(code)) ? state.dependenciesByModule.get(id) : void 0;
|
|
1651
1743
|
let result;
|
|
1652
1744
|
try {
|
|
1653
|
-
const
|
|
1654
|
-
const
|
|
1655
|
-
if (
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1745
|
+
const memoKey = command === "serve" ? foldMemoKey(filePath, inputDigest ??= digest(code)) : void 0;
|
|
1746
|
+
const memoized = memoKey ? foldMemoByContent.get(memoKey) : void 0;
|
|
1747
|
+
if (memoized?.reportedSurvivors) result = withResolutionClosure(filePath, memoized.result, memoized.parserDependencies, previousDependencies);
|
|
1748
|
+
else {
|
|
1749
|
+
const sourceFile = ctx.project.addSourceFile(filePath, code);
|
|
1750
|
+
const parserResult = ctx.project.parseSourceFile(filePath);
|
|
1751
|
+
if (!parserResult) {
|
|
1752
|
+
state.transformArtifactsByModule.delete(id);
|
|
1753
|
+
recordFoldDependencies(state, id, filePath, []);
|
|
1754
|
+
state.foldSignatures.delete(id);
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
const folded = foldSourceImpl({
|
|
1758
|
+
ctx,
|
|
1759
|
+
code,
|
|
1760
|
+
parserResult,
|
|
1761
|
+
filePath,
|
|
1762
|
+
runtimeCss,
|
|
1763
|
+
styleCompiler,
|
|
1764
|
+
maxRecipeStates,
|
|
1765
|
+
parseModule: (path) => ctx?.project.parseSourceFile(path),
|
|
1766
|
+
recipeConfigCache: state.recipeConfigCache,
|
|
1767
|
+
reportSurvivors: true,
|
|
1768
|
+
sourceFile
|
|
1769
|
+
});
|
|
1770
|
+
const parserDependencies = parserResult.getDependencies();
|
|
1771
|
+
if (memoKey) foldMemoByContent.set(memoKey, {
|
|
1772
|
+
result: folded,
|
|
1773
|
+
parserDependencies,
|
|
1774
|
+
reportedSurvivors: true
|
|
1775
|
+
});
|
|
1776
|
+
result = withResolutionClosure(filePath, folded, parserDependencies, previousDependencies);
|
|
1660
1777
|
}
|
|
1661
|
-
result = withResolutionClosure(filePath, foldSourceImpl({
|
|
1662
|
-
ctx,
|
|
1663
|
-
code,
|
|
1664
|
-
parserResult,
|
|
1665
|
-
filePath,
|
|
1666
|
-
runtimeCss,
|
|
1667
|
-
styleCompiler,
|
|
1668
|
-
maxRecipeStates,
|
|
1669
|
-
parseModule: (path) => ctx?.project.parseSourceFile(path),
|
|
1670
|
-
recipeConfigCache: state.recipeConfigCache,
|
|
1671
|
-
reportSurvivors: true,
|
|
1672
|
-
sourceFile
|
|
1673
|
-
}), parserResult.getDependencies(), previousDependencies);
|
|
1674
1778
|
} catch (error) {
|
|
1675
1779
|
_bamboocss_logger.logger.caughtError("vite:transform", `Failed to compile ${filePath}`, error);
|
|
1676
1780
|
const previousDependencies = [...state.dependenciesByModule.get(id) ?? []];
|
package/dist/index.mjs
CHANGED
|
@@ -203,6 +203,23 @@ const bamboocssCss = (options) => {
|
|
|
203
203
|
* stylesheet twice over.
|
|
204
204
|
*/
|
|
205
205
|
let pending;
|
|
206
|
+
/**
|
|
207
|
+
* Which change the current `pending` was generated for, and the validated sheet it produced.
|
|
208
|
+
*
|
|
209
|
+
* Every environment loads the virtual stylesheet — a react-router dev server loads it once
|
|
210
|
+
* for the client graph and once for SSR — and each load used to run a complete extraction
|
|
211
|
+
* and optimization pass to produce byte-identical CSS. The sheet is a function of the source
|
|
212
|
+
* files alone, and the watcher below is the single point every event that can reach it
|
|
213
|
+
* passes through — Vite's own propagation only arrives via the watch edges `load` registers,
|
|
214
|
+
* over the same extracted files the watcher checks. A monotonic counter bumped there is
|
|
215
|
+
* therefore enough to know whether a build already reflects the world a load is asking about.
|
|
216
|
+
*
|
|
217
|
+
* Dev only. A production build has no dev watcher to advance the counter, so serving the
|
|
218
|
+
* memo there would hand `vite build --watch` a stale sheet; builds regenerate per load.
|
|
219
|
+
*/
|
|
220
|
+
let changeGeneration = 0;
|
|
221
|
+
let pendingGeneration = -1;
|
|
222
|
+
let servedCss;
|
|
206
223
|
const build = async () => {
|
|
207
224
|
const builder = await ensureBuilder();
|
|
208
225
|
await builder.setup({
|
|
@@ -240,6 +257,8 @@ const bamboocssCss = (options) => {
|
|
|
240
257
|
return css;
|
|
241
258
|
};
|
|
242
259
|
const generate = () => {
|
|
260
|
+
if (command === "serve" && pending && pendingGeneration === changeGeneration) return pending;
|
|
261
|
+
pendingGeneration = changeGeneration;
|
|
243
262
|
pending = Promise.resolve(pending).catch(() => void 0).then(build);
|
|
244
263
|
return pending;
|
|
245
264
|
};
|
|
@@ -388,6 +407,11 @@ const bamboocssCss = (options) => {
|
|
|
388
407
|
const query = queryOf(id);
|
|
389
408
|
if (id.slice(0, id.length - query.length) !== RESOLVED_ID) return null;
|
|
390
409
|
session.cssLoaded = true;
|
|
410
|
+
const generationAtStart = changeGeneration;
|
|
411
|
+
if (command === "serve" && servedCss?.generation === generationAtStart) {
|
|
412
|
+
if (this.addWatchFile) for (const file of extractedSourceFiles()) this.addWatchFile(file);
|
|
413
|
+
return servedCss.css;
|
|
414
|
+
}
|
|
391
415
|
let css;
|
|
392
416
|
try {
|
|
393
417
|
const validateDevCss = command === "serve" ? (await loadCssOutput()).pruneStaticCss : void 0;
|
|
@@ -398,6 +422,10 @@ const bamboocssCss = (options) => {
|
|
|
398
422
|
} catch (error) {
|
|
399
423
|
throw asError(error, `failed to generate ${VIRTUAL_CSS_ID}`);
|
|
400
424
|
}
|
|
425
|
+
if (command === "serve" && generationAtStart === changeGeneration) servedCss = {
|
|
426
|
+
generation: generationAtStart,
|
|
427
|
+
css
|
|
428
|
+
};
|
|
401
429
|
if (this.addWatchFile) for (const file of extractedSourceFiles()) this.addWatchFile(file);
|
|
402
430
|
return css;
|
|
403
431
|
},
|
|
@@ -422,6 +450,7 @@ const bamboocssCss = (options) => {
|
|
|
422
450
|
if (!ctx) return;
|
|
423
451
|
const absoluteFile = ctx.runtime.path.abs(ctx.config.cwd, file);
|
|
424
452
|
if (!session.extractedFiles.has(absoluteFile)) return;
|
|
453
|
+
changeGeneration++;
|
|
425
454
|
prebuilt = void 0;
|
|
426
455
|
const mod = server?.moduleGraph.getModuleById(RESOLVED_ID);
|
|
427
456
|
if (!mod) return;
|
|
@@ -689,6 +718,43 @@ const bamboocss = (options = {}) => {
|
|
|
689
718
|
return /* @__PURE__ */ new Error(`bamboocss: cached transform metadata for ${JSON.stringify(id)} in the ${JSON.stringify(environment)} environment ${problem}.\n\nBamboo cannot safely rebuild from this entry because cached JavaScript may still name CSS classes whose rules would be dropped. Restart Vite to invalidate its in-memory transform cache. If this persists, clear Vite's cache directory and rebuild.`);
|
|
690
719
|
};
|
|
691
720
|
const transformStateByEnvironment = /* @__PURE__ */ new Map();
|
|
721
|
+
/**
|
|
722
|
+
* One fold per file content per change event, shared across environments and hooks.
|
|
723
|
+
*
|
|
724
|
+
* A single edit folds the same bytes repeatedly: `hotUpdate` provisionally re-folds every
|
|
725
|
+
* dependent once per environment to decide what to invalidate, then `transform` folds the
|
|
726
|
+
* edited module for the client graph, again for SSR, and once more for each update a
|
|
727
|
+
* framework re-drives — react-router's server-change trigger calls `reloadModule` per pass.
|
|
728
|
+
* All of them read the same shared ts-morph project under the same config, so the result is
|
|
729
|
+
* a function of the bytes alone and the repeats were pure cost: on the app this was measured
|
|
730
|
+
* on, four transforms of a 46 kB route module per edit, ~10 ms each.
|
|
731
|
+
*
|
|
732
|
+
* `watchChange` clears it, which is the exact validity window: entries are correct until a
|
|
733
|
+
* file event changes what a fold could resolve, and `watchChange` is the one hook Vite calls
|
|
734
|
+
* for every such event before any update work begins. The per-environment resolution closure
|
|
735
|
+
* is deliberately not memoized — `withResolutionClosure` is recomputed per consumer against
|
|
736
|
+
* that environment's own recorded dependencies.
|
|
737
|
+
*
|
|
738
|
+
* Keyed by path *and* content digest, not path alone, because one physical file is served
|
|
739
|
+
* as more than one module shape in the same event — react-router clips a route module down
|
|
740
|
+
* to its route exports for the client graph while SSR gets the full file — and a last-write
|
|
741
|
+
* key would make the two shapes evict each other on every pass.
|
|
742
|
+
*
|
|
743
|
+
* Dev only, like the verdict memo it sits beside: a build transforms each module once per
|
|
744
|
+
* environment with no bracketing events, and holding every module's fold for the length of a
|
|
745
|
+
* build is memory a one-shot pass has no reason to spend.
|
|
746
|
+
*/
|
|
747
|
+
const foldMemoByContent = /* @__PURE__ */ new Map();
|
|
748
|
+
const foldMemoKey = (filePath, inputDigest) => `${filePath}\0${inputDigest}`;
|
|
749
|
+
/**
|
|
750
|
+
* The Project resolution walk `withResolutionClosure` runs, memoized per change event.
|
|
751
|
+
*
|
|
752
|
+
* The walk is the dominant per-dependent cost once the fold itself is memoized — it runs
|
|
753
|
+
* once per dependent per environment with identical inputs, since both environments record
|
|
754
|
+
* the same fold dependencies for byte-identical source. Same bracketing as the fold memo:
|
|
755
|
+
* `watchChange` clears it, so no entry outlives the project state it was computed against.
|
|
756
|
+
*/
|
|
757
|
+
const resolutionClosureMemo = /* @__PURE__ */ new Map();
|
|
692
758
|
/** The immutable generation currently occupying each configured output on disk. */
|
|
693
759
|
const liveOutputSlotsByEnvironment = /* @__PURE__ */ new Map();
|
|
694
760
|
/** Graphs which passed `buildEnd`, but whose output has not succeeded yet. */
|
|
@@ -1226,23 +1292,40 @@ const bamboocss = (options = {}) => {
|
|
|
1226
1292
|
if (!signature || !ctx || !foldSourceImpl || !runtimeCss || !styleCompiler) return false;
|
|
1227
1293
|
try {
|
|
1228
1294
|
const code = readFileSync(signature.path, "utf8");
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1295
|
+
const inputDigest = digest(code);
|
|
1296
|
+
if (inputDigest !== signature.input) return false;
|
|
1297
|
+
let raw;
|
|
1298
|
+
let parserDependencies;
|
|
1299
|
+
const memoKey = foldMemoKey(signature.path, inputDigest);
|
|
1300
|
+
const memoized = foldMemoByContent.get(memoKey);
|
|
1301
|
+
if (memoized) {
|
|
1302
|
+
raw = memoized.result;
|
|
1303
|
+
parserDependencies = memoized.parserDependencies;
|
|
1304
|
+
} else {
|
|
1305
|
+
const sourceFile = ctx.project.addSourceFile(signature.path, code);
|
|
1306
|
+
const parserResult = ctx.project.parseSourceFile(signature.path);
|
|
1307
|
+
if (!parserResult) return false;
|
|
1308
|
+
raw = foldSourceImpl({
|
|
1309
|
+
ctx,
|
|
1310
|
+
code,
|
|
1311
|
+
parserResult,
|
|
1312
|
+
filePath: signature.path,
|
|
1313
|
+
runtimeCss,
|
|
1314
|
+
styleCompiler,
|
|
1315
|
+
maxRecipeStates,
|
|
1316
|
+
parseModule: (path) => ctx?.project.parseSourceFile(path),
|
|
1317
|
+
recipeConfigCache: state.recipeConfigCache,
|
|
1318
|
+
reportSurvivors: false,
|
|
1319
|
+
sourceFile
|
|
1320
|
+
});
|
|
1321
|
+
parserDependencies = parserResult.getDependencies();
|
|
1322
|
+
foldMemoByContent.set(memoKey, {
|
|
1323
|
+
result: raw,
|
|
1324
|
+
parserDependencies,
|
|
1325
|
+
reportedSurvivors: false
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
const result = withResolutionClosure(signature.path, raw, parserDependencies, state.dependenciesByModule.get(dependent));
|
|
1246
1329
|
const unchanged = digest(result.code) === signature.output;
|
|
1247
1330
|
/**
|
|
1248
1331
|
* Edges re-recorded exactly on the way to suppressing a module. A changed provisional
|
|
@@ -1392,7 +1475,14 @@ const bamboocss = (options = {}) => {
|
|
|
1392
1475
|
const targets = new Set(dependencies);
|
|
1393
1476
|
for (const dependency of previousDependencies ?? []) targets.add(dependency);
|
|
1394
1477
|
if (!targets.size) return result;
|
|
1395
|
-
|
|
1478
|
+
const targetList = [...targets];
|
|
1479
|
+
const closureKey = command === "serve" ? `${filePath}\0${targetList.slice().sort().join("|")}` : void 0;
|
|
1480
|
+
let reachable = closureKey ? resolutionClosureMemo.get(closureKey) : void 0;
|
|
1481
|
+
if (!reachable) {
|
|
1482
|
+
reachable = ctx.project.getDependencies(filePath, targetList);
|
|
1483
|
+
if (closureKey) resolutionClosureMemo.set(closureKey, reachable);
|
|
1484
|
+
}
|
|
1485
|
+
for (const dependency of reachable) if (!isGeneratedOutput(dependency, ctx)) dependencies.add(dependency);
|
|
1396
1486
|
const expanded = [...dependencies];
|
|
1397
1487
|
if (expanded.length === result.dependencies.length && expanded.every((dependency, index) => dependency === result.dependencies[index])) return result;
|
|
1398
1488
|
return {
|
|
@@ -1576,6 +1666,8 @@ const bamboocss = (options = {}) => {
|
|
|
1576
1666
|
* the parser still holds the file.
|
|
1577
1667
|
*/
|
|
1578
1668
|
watchChange(id, change) {
|
|
1669
|
+
foldMemoByContent.clear();
|
|
1670
|
+
resolutionClosureMemo.clear();
|
|
1579
1671
|
for (const state of transformStateByEnvironment.values()) {
|
|
1580
1672
|
state.unchangedFolds.clear();
|
|
1581
1673
|
state.changedRun = 0;
|
|
@@ -1645,27 +1737,39 @@ const bamboocss = (options = {}) => {
|
|
|
1645
1737
|
const previousDependencies = previousSignature && previousSignature.input === (inputDigest ??= digest(code)) ? state.dependenciesByModule.get(id) : void 0;
|
|
1646
1738
|
let result;
|
|
1647
1739
|
try {
|
|
1648
|
-
const
|
|
1649
|
-
const
|
|
1650
|
-
if (
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1740
|
+
const memoKey = command === "serve" ? foldMemoKey(filePath, inputDigest ??= digest(code)) : void 0;
|
|
1741
|
+
const memoized = memoKey ? foldMemoByContent.get(memoKey) : void 0;
|
|
1742
|
+
if (memoized?.reportedSurvivors) result = withResolutionClosure(filePath, memoized.result, memoized.parserDependencies, previousDependencies);
|
|
1743
|
+
else {
|
|
1744
|
+
const sourceFile = ctx.project.addSourceFile(filePath, code);
|
|
1745
|
+
const parserResult = ctx.project.parseSourceFile(filePath);
|
|
1746
|
+
if (!parserResult) {
|
|
1747
|
+
state.transformArtifactsByModule.delete(id);
|
|
1748
|
+
recordFoldDependencies(state, id, filePath, []);
|
|
1749
|
+
state.foldSignatures.delete(id);
|
|
1750
|
+
return null;
|
|
1751
|
+
}
|
|
1752
|
+
const folded = foldSourceImpl({
|
|
1753
|
+
ctx,
|
|
1754
|
+
code,
|
|
1755
|
+
parserResult,
|
|
1756
|
+
filePath,
|
|
1757
|
+
runtimeCss,
|
|
1758
|
+
styleCompiler,
|
|
1759
|
+
maxRecipeStates,
|
|
1760
|
+
parseModule: (path) => ctx?.project.parseSourceFile(path),
|
|
1761
|
+
recipeConfigCache: state.recipeConfigCache,
|
|
1762
|
+
reportSurvivors: true,
|
|
1763
|
+
sourceFile
|
|
1764
|
+
});
|
|
1765
|
+
const parserDependencies = parserResult.getDependencies();
|
|
1766
|
+
if (memoKey) foldMemoByContent.set(memoKey, {
|
|
1767
|
+
result: folded,
|
|
1768
|
+
parserDependencies,
|
|
1769
|
+
reportedSurvivors: true
|
|
1770
|
+
});
|
|
1771
|
+
result = withResolutionClosure(filePath, folded, parserDependencies, previousDependencies);
|
|
1655
1772
|
}
|
|
1656
|
-
result = withResolutionClosure(filePath, foldSourceImpl({
|
|
1657
|
-
ctx,
|
|
1658
|
-
code,
|
|
1659
|
-
parserResult,
|
|
1660
|
-
filePath,
|
|
1661
|
-
runtimeCss,
|
|
1662
|
-
styleCompiler,
|
|
1663
|
-
maxRecipeStates,
|
|
1664
|
-
parseModule: (path) => ctx?.project.parseSourceFile(path),
|
|
1665
|
-
recipeConfigCache: state.recipeConfigCache,
|
|
1666
|
-
reportSurvivors: true,
|
|
1667
|
-
sourceFile
|
|
1668
|
-
}), parserResult.getDependencies(), previousDependencies);
|
|
1669
1773
|
} catch (error) {
|
|
1670
1774
|
logger.caughtError("vite:transform", `Failed to compile ${filePath}`, error);
|
|
1671
1775
|
const previousDependencies = [...state.dependenciesByModule.get(id) ?? []];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bamboocss/vite",
|
|
3
|
-
"version": "1.46.
|
|
3
|
+
"version": "1.46.1",
|
|
4
4
|
"description": "Vite integration for Bamboo CSS",
|
|
5
5
|
"homepage": "https://bamboocss.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,18 +42,18 @@
|
|
|
42
42
|
"postcss": "8.5.26",
|
|
43
43
|
"postcss-selector-parser": "7.1.5",
|
|
44
44
|
"ts-morph": "28.0.0",
|
|
45
|
-
"@bamboocss/config": "1.46.
|
|
46
|
-
"@bamboocss/core": "1.46.
|
|
47
|
-
"@bamboocss/
|
|
48
|
-
"@bamboocss/
|
|
49
|
-
"@bamboocss/
|
|
50
|
-
"@bamboocss/
|
|
51
|
-
"@bamboocss/
|
|
45
|
+
"@bamboocss/config": "1.46.1",
|
|
46
|
+
"@bamboocss/core": "1.46.1",
|
|
47
|
+
"@bamboocss/node": "1.46.1",
|
|
48
|
+
"@bamboocss/shared": "1.46.1",
|
|
49
|
+
"@bamboocss/extractor": "1.46.1",
|
|
50
|
+
"@bamboocss/types": "1.46.1",
|
|
51
|
+
"@bamboocss/logger": "1.46.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
55
55
|
"vite": "7.2.6",
|
|
56
|
-
"@bamboocss/fixture": "1.46.
|
|
56
|
+
"@bamboocss/fixture": "1.46.1"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"vite": ">=5"
|