Skip to content

WIP: CSS cascade-order dependency fuzzer for component fixtures#321062

Draft
hediet wants to merge 1 commit into
mainfrom
hediet/component-explorer-css-order-fuzzer
Draft

WIP: CSS cascade-order dependency fuzzer for component fixtures#321062
hediet wants to merge 1 commit into
mainfrom
hediet/component-explorer-css-order-fuzzer

Conversation

@hediet

@hediet hediet commented Jun 12, 2026

Copy link
Copy Markdown
Member

Work in progress. Tooling to detect and localize CSS cascade-order dependencies in component fixtures, which render through @vscode/component-explorer over an rspack serve-out build that concatenates all CSS into one native-CSS bundle.

Done in this branch

  • Input-driven stylesheet reversalinstallGlobalStyles accepts a reverseStylesheets option (true = reverse all documents, or { fromIndex, toIndex } = reverse only that window). Driven per-run via the render --input flag (parseStyleOptions), not via global state.
  • @css-source marker loaderbuild/rspack/cssSourceMarkerLoader.ts prepends each CSS module's repo-relative source path as a comment that native CSS preserves, so tooling can map concatenated bundle documents back to source files. Wired into the .css rule in rspack.serve-out.config.mts.

Remaining work

See src/vs/workbench/test/browser/componentFixtures/CSS_ORDER_FUZZER_TODO.md for the full list:

  1. Verify the .ts loader runs (blocker) — confirm @rspack/cli loads a .ts loader directly; fall back to inlining in the .mts config if not.
  2. Apply the known specificity fix (validation case) — aiCustomizationManagement.css vs codicon.css (0,2,0) tie on display.
  3. Bisection driver — in-page binary search against the live serve (no rebuilds) to localize order-dependent document pairs.
  4. CI guardbuild/lib/checkStylesheetOrder.ts + daily workflow diffing manifest imageHash of normal vs. reversed render.
  5. Component-explorer CLI feature request — render input-matrix and/or --server-url attach mode so bisection reuses a running serve.

Adds input-driven stylesheet reversal and @CSS-Source marker loader; see CSS_ORDER_FUZZER_TODO.md for remaining work.
Copilot AI review requested due to automatic review settings June 12, 2026 00:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds WIP tooling to help detect and localize CSS cascade-order dependencies in component fixtures by (1) optionally reversing bundled stylesheet “documents” at runtime, and (2) tagging concatenated CSS with per-source markers so order-dependent conflicts can be mapped back to originating files.

Changes:

  • Introduces a new installGlobalStyles helper that can build an adopted stylesheet with optionally reversed “document” order (by banner-delimited segments).
  • Threads a render --input option (reverseStylesheets) through fixtureUtils.ts to control reversal per render.
  • Adds an rspack CSS loader to inject @css-source marker comments into bundled CSS for later attribution/bisection tooling.
Show a summary per file
File Description
src/vs/workbench/test/browser/componentFixtures/fixtureUtilsCss.ts New stylesheet installation helper with optional banner-delimited “document” reversal.
src/vs/workbench/test/browser/componentFixtures/fixtureUtils.ts Uses the new helper and derives reversal options from context.input.
src/vs/workbench/test/browser/componentFixtures/CSS_ORDER_FUZZER_TODO.md Tracks remaining implementation/validation steps for the fuzzer workflow.
build/rspack/rspack.serve-out.config.mts Wires a CSS loader to tag CSS modules with source markers.
build/rspack/cssSourceMarkerLoader.ts Implements the @css-source marker injection loader.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 4

Comment on lines +20 to +23
export default function cssSourceMarkerLoader(this: { resourcePath: string; rootContext: string }, source: string): string {
const rel = path.relative(this.rootContext, this.resourcePath).replace(/\\/g, '/');
return `/* @css-source: ${rel} */\n${source}`;
}
Comment on lines +325 to +331
if (value && typeof value === 'object') {
const range = value as Record<string, unknown>;
if (typeof range.fromIndex === 'number' && typeof range.toIndex === 'number') {
return { reverseStylesheets: { fromIndex: range.fromIndex, toIndex: range.toIndex } };
}
}
return undefined;
Comment on lines +182 to +195
export function installGlobalStyles(themes: readonly ColorThemeData[], options?: InstallGlobalStylesOptions): Promise<void> {
if (!globalStylesPromise) {
const reverse = options?.reverseStylesheets ?? false;
globalStylesPromise = (async () => {
const globalSheet = await getGlobalStyleSheet(reverse);
document.adoptedStyleSheets = [
...document.adoptedStyleSheets,
globalSheet,
getIconsStyleSheetCached(),
...themes.map(getThemeStyleSheet),
];
})();
}
return globalStylesPromise;
Comment on lines 66 to 73
{
test: /\.css$/,
type: 'css',
// Tag every CSS module with its repo-relative source path (as a
// comment that native CSS preserves) so tooling reading the
// bundled stylesheet can map concatenated documents back to files.
use: [path.join(__dirname, 'cssSourceMarkerLoader.ts')],
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants