Skip to content

Convert generated css compat table to a data table#31999

Open
alii wants to merge 6 commits into
mainfrom
claude/split/css
Open

Convert generated css compat table to a data table#31999
alii wants to merge 6 commits into
mainfrom
claude/split/css

Conversation

@alii

@alii alii commented Jun 8, 2026

Copy link
Copy Markdown
Member

What this does

Split from #31912 (whole-repo simplification pass, closed in favor of module-scoped splits). Moves and removes code with zero intended behavior change, and makes src/css/compat.rs regenerable.

  • src/css/compat.rs: replaces the generated 5.4k-line match (one arm of version checks per feature) with a per-feature minimum-version table consumed by generic is_compatible / is_partially_compatible checks.
  • src/css/css_parser.rs: gives AtRuleParser and QualifiedRuleParser default method implementations that reject the rule, and deletes the copy-pasted reject-all impls from declaration.rs, font_face.rs, font_palette_values.rs, keyframes.rs, page.rs, property.rs.
  • src/css/properties/custom.rs: drops the inlined url_to_css shim and calls Url::to_css directly (now un-gated in values/url.rs and already used by font_face.rs, image.rs, syntax.rs). The shared fn checks flags.is_internal exactly like the Zig reference; the shim had deviated to tag.is_internal().
  • src/css/build-prefixes.js: now emits the table-form compat.rs alongside compat.zig, resolving the regenerability question this PR originally left open. Also restores the allBrowsers definition that remove all usingnamespace in css #19067 deleted while the script still references it (the script could not run at all without it), and maps BCD's webview_ios agent to null the same way oculus already is (newer BCD data otherwise crashes the script).
  • The one feature variant whose name carried consecutive capitals is renamed to Rust acronym casing (Feature::FontSizeXxxLarge, matching the existing AbsoluteFontSize::XxxLarge in properties/font.rs); the generator's name derivation collapses single-letter segment runs accordingly.

Verification

  • Mechanical equivalence audit of the table against the old match form on main: all 215 features x 9 browsers produce identical min-version/unsupported data, and table row order matches enum declaration order.
  • Generator emission: fed generateCompatRs the data parsed out of the checked-in compat.zig (generated from the same original dataset); the output is byte-identical to the checked-in compat.rs, so the file is exactly what regeneration produces.
  • Full end-to-end generator run in a scratch tree with data deps pinned to Sept 2024 (autoprefixer@10.4.20, caniuse-lite@1.0.30001663, @mdn/browser-compat-data@5.6.0): completes, output is rustfmt-idempotent, and differs from the checked-in file only in 24 rows of data values that moved between dataset snapshots. Running against current @mdn/browser-compat-data 8.x additionally needs schema adaptations (css.types.image.gradient moved, etc.); that predates this PR and is left alone.
  • cargo check -p bun_css clean. bun bd test test/js/bun/css/ and bun bd test test/bundler/css/ pass, except the css-fuzz and fuzz ansi256 timeouts, which fail identically at the merge base under a debug+ASAN build (pre-existing debug slowness, verified by running them on main).

No test changes: this is a behavior-preserving refactor, and the existing CSS suites (2300+ tests) are the regression net.

Tests

test/js/bun/css/css.test.ts gains two blocks pinning the refactored surfaces:

  • browser compat feature table: for three features spread across the table (MediaRangeSyntax, HexAlphaColors, FontFamilySystemUi), one target just below the minimum browser version (must lower) and one at the minimum (must preserve), driven through cssInternals targets. These catch table row/enum misalignment or wrong minimums.
  • at-rule and qualified-rule rejection defaults: unknown at-rules and qualified rules inside @font-face, @keyframes, @font-palette-values, @property, and style attributes hit the new trait defaults; tests pin the recovery output and the Unknown at-rule @bogus error message.

Since this PR is a behavior-preserving refactor, these tests pass both before and after by construction: a test that failed on the merge base would contradict the equivalence this PR claims. They were run against both the merge base and this branch to confirm identical output, and they pin the refactored surfaces so any future regression in the table data, row ordering, or the trait defaults fails loudly.

@robobun

robobun commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator
Updated 2:13 PM PT - Jun 12th, 2026

@robobun, your commit 35b133a has 3 failures in Build #61622 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 31999

That installs a local version of the PR into your bun-31999 executable, so you can run:

bun-31999 --bun

@alii alii marked this pull request as ready for review June 9, 2026 20:18
@alii

alii commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

@robobun adopt

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR adds default rejecting implementations to CSS parser traits, simplifies many rule parser implementations to use those defaults, extends browser mapping data (adds webview_ios), generates a Rust compat module from the compatibility table, and removes an inline URL-to-css shim in custom properties.

Changes

Parser trait defaults and implementation cleanup

Layer / File(s) Summary
Trait default implementations
src/css/css_parser.rs
QualifiedRuleParser and AtRuleParser now provide default implementations for parse_prelude, parse_block, and rule_without_block that reject unsupported rule types with appropriate parse errors.
PropertyDeclarationParser simplified
src/css/declaration.rs
Remove explicit error-returning parse method bodies for PropertyDeclarationParser's AtRuleParser and QualifiedRuleParser impls; associated types remain.
Rule parser implementations simplified
src/css/rules/font_face.rs, src/css/rules/font_palette_values.rs, src/css/rules/keyframes.rs, src/css/rules/page.rs, src/css/rules/property.rs
Drop duplicated explicit rejection method bodies and unused imports across multiple rule parsers so they rely on the trait defaults.

CSS browser compatibility and Rust code generation

Layer / File(s) Summary
Browser mapping configuration
src/css/build-prefixes.js
BROWSER_MAPPING and MDN_BROWSER_MAPPING gain webview_ios: null entries; allBrowsers is computed from caniuse-lite agents (excluding mapped keys) to detect missing browser fields.
Rust compat code generation
src/css/build-prefixes.js
New generateCompatRs creates Rust source (Feature enum and is_compatible/is_partially_compatible) from compatibility entries, writes src/css/compat.rs, and runs rustfmt.
Browser compat tests
test/js/bun/css/css.test.ts
Add tests covering browser min-version rewriting for selected features and tests asserting default rejection behavior for unknown nested at-rules (including style-attribute cases).

Custom properties URL serialization refactoring

Layer / File(s) Summary
Direct URL::to_css invocation
src/css/properties/custom.rs
Remove the inline Url::to_css shim from the ext module and update TokenList::to_css to call url.to_css(dest) directly; adjust comments about inlined leaf functions.

Tests and minor fixes

Layer / File(s) Summary
Compat and rejection tests
test/js/bun/css/css.test.ts
Import attrTest and add tests for browser compat min-version handling and default nested at-rule rejection.
Font feature flag fix
src/css/properties/font.rs
Use Feature::FontSizeXxxLarge in AbsoluteFontSize::XxxLarge compatibility check.

Suggested reviewers

  • RiskyMH
  • dylan-conway
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: converting CSS compat match logic to a data table, which is the core refactor across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The pull request description provides comprehensive detail on changes, verification methods, and test additions, covering both required template sections.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@alii alii force-pushed the claude/split/css branch from e0533a1 to a31d011 Compare June 9, 2026 20:19
@robobun

robobun commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Adopted and ready for review. The open question in the description is resolved: build-prefixes.js now emits the table-form compat.rs (verified byte-identical when driven with the same dataset it was generated from), and regression tests pin the compat table boundaries and the at-rule parser defaults.

CI on the merged head (build 61622): all CSS tests pass on every lane. After retries the single remaining red is darwin 14 aarch64, where two timing-sensitive fetch tests flaked (fetch-abort-slow-connect, a 50ms AbortSignal race, and fetch-leak, an RSS-threshold probe); unrelated to this diff.

@alii

alii commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@robobun does anything get faster because of this table?

@robobun

robobun commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Runtime: no. is_compatible only runs during CSS transforms with browser targets set, and per call both forms are a handful of predictable compares (the old dense match compiled to a jump table), all of it a rounding error next to parse/print. I would not expect any benchmark to move.

Binary size: yes. The CI size check on this build compares against main exactly at the merge point (build 61606 = 09703da), so the delta is this diff alone: -16 KB darwin-x64, -32 KB linux-x64 and x64-baseline, -48 KB darwin-aarch64, -64 KB linux-aarch64. The bigger aarch64 savings fit deleting ~5.2k lines of compare-and-branch codegen (fixed-width instructions make branchy code larger there), replaced by a 7.6 KB static table.

Compile time of bun_css: I timed old vs new on this container (3 runs each, dev and release) and the difference is within run-to-run noise, so no claim there.

So the honest answer is smaller, not faster; the motivation remains the -5.2k lines and build-prefixes.js being able to regenerate the file.

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