Fix CSS color fallback panic for oklab() in unparsed values (#31269)
### Problem
Found by fuzzing (`panic: internal error: entered unreachable code:
Expected RGBA, P3, LAB fallback`), but reachable through the public API.
Any CSS that contains an `oklab()` color inside an *unparsed* value — a
`var()` fallback, or a declaration whose value fails to parse as a color
— panics the CSS minifier whenever the browser targets don't require
compiling oklab (including the default of no targets):
```sh
# app.css: .foo { color: var(--x, oklab(40% 0.1 0.1)) }
bun build --target=bun app.css
# panic: internal error: entered unreachable code: Expected RGBA, P3, LAB fallback. This is a bug in Bun.
```
Original fuzz repro (minimized):
```sh
BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING=1 bun -e 'require("bun:internal-for-testing").cssInternals.minifyTest("{\n\tcolor: \"o \"oklab(10% 08 0/ .0", "")'
```
### Cause
`CssColor::get_possible_fallbacks` in `src/css/values/color.rs`
mistranslated lightningcss's match guards. Upstream the guard applies to
both variants of each pattern:
```rust
LABColor::LAB(..) | LABColor::LCH(..) if should_compile!(targets, LabColors) => ...
LABColor::OKLAB(..) | LABColor::OKLCH(..) if should_compile!(targets, OklabColors) => ...
```
The port (carried over verbatim from the Zig) applied it only to the
second variant, i.e. `lab == .oklab or (lab == .oklch and
shouldCompileSame(.oklab_colors))`. So an `oklab()` color with targets
that don't require compiling it returned an OKLAB-only fallback set
instead of an empty one. `TokenList::get_fallbacks` then picked that
single OKLAB bit as the "lowest" fallback and passed it to
`CssColor::get_fallback`, which only accepts RGB, P3, and LAB and hits
the `unreachable!`.
Parsed color properties never hit this because `get_necessary_fallbacks`
subtracts the highest kind; only the unparsed/token-list path passes the
raw set through.
### Fix
Apply the `should_compile_same` guard to both variants of each pair
(`lab`/`lch`, `oklab`/`oklch`), matching lightningcss. When no targets
require compilation the fallback set is empty and the color is left
untouched.
### Verification
- New tests in `test/js/bun/css/css.test.ts` (`edge cases > unparsed
oklab color fallbacks`): `var()` fallbacks and string-prefixed
declarations with `oklab`/`oklch`/`lab`/`lch`.
- `USE_SYSTEM_BUN=1 bun test test/js/bun/css/css.test.ts -t "unparsed
oklab"` → panics with the fuzz signature (bug present)
- `bun bd test test/js/bun/css/css.test.ts` → 1038 pass, 0 fail (fix
works, no regressions)
- `bun build --target=bun` on the CSS above now emits `color: var(--x,
oklab(40% .1 .1))` instead of crashing; the original fuzz input minifies
without panicking.
- `doesnt_crash.test.ts`, `color.test.ts`, `small-list-grow.test.ts`,
`nested-function-backtracking.test.ts` pass with the debug build. R
robobun committed
3c92be850ac3ddb5b2ac020838b6b603f9e724cd
Parent: ffd67d8
Committed by GitHub <noreply@github.com>
on 5/23/2026, 7:14:22 AM