mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
fix(css): restore handler context after minifying nested rules (#25997)
## Summary - Fixes handler context not being restored after minifying nested CSS rules - Adds regression test for the issue ## Test plan - [x] Test fails with `USE_SYSTEM_BUN=1 bun test test/regression/issue/25794.test.ts` - [x] Test passes with `bun bd test test/regression/issue/25794.test.ts` Fixes #25794 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
86
test/regression/issue/25794.test.ts
Normal file
86
test/regression/issue/25794.test.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
||||
|
||||
test("CSS logical properties should not be stripped when nested rules are present", async () => {
|
||||
// Test for regression of issue #25794: CSS logical properties (e.g., inset-inline-end)
|
||||
// are stripped from bundler output when they appear in a nested selector that also
|
||||
// contains further nested rules (like pseudo-elements).
|
||||
|
||||
const dir = tempDirWithFiles("css-logical-properties-nested", {
|
||||
"input.css": `.test-longform {
|
||||
background-color: teal;
|
||||
|
||||
&.test-longform--end {
|
||||
inset-inline-end: 20px;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "build", "input.css", "--outdir", "out"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
// Verify the output CSS contains the logical property fallbacks
|
||||
const outputContent = await Bun.file(`${dir}/out/input.css`).text();
|
||||
|
||||
// Helper function to normalize CSS output for snapshots
|
||||
function normalizeCSSOutput(output: string): string {
|
||||
return output
|
||||
.replace(/\/\*.*?\*\//g, "/* [path] */") // Replace comment paths
|
||||
.trim();
|
||||
}
|
||||
|
||||
// The output should contain LTR/RTL fallback rules for inset-inline-end
|
||||
// inset-inline-end: 20px should generate:
|
||||
// - right: 20px for LTR languages
|
||||
// - left: 20px for RTL languages
|
||||
// The bundler generates vendor-prefixed variants for browser compatibility
|
||||
expect(normalizeCSSOutput(outputContent)).toMatchInlineSnapshot(`
|
||||
"/* [path] */
|
||||
.test-longform {
|
||||
background-color: teal;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:not(:-moz-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:-moz-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.test-longform.test-longform--end:after {
|
||||
content: "";
|
||||
}"
|
||||
`);
|
||||
|
||||
// Should exit successfully
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
Reference in New Issue
Block a user