Skip to content

feat(css): four more value-level minify transforms - #21629

Merged
alexander-akait merged 15 commits into
mainfrom
feat/css-minify-selector-and-value-transforms
Aug 7, 2026
Merged

alexander-akait merged 15 commits into
mainfrom
feat/css-minify-selector-and-value-transforms

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Aug 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Four more minify transforms, each one a spelling change that leaves the computed style identical: a <position> written as edge keywords becomes the percentages it resolves to (background-position:left bottom → 0%100%), a <transform-list> drops the whitespace between two functions the ) already parts, a font-stretch keyword becomes the percentage it names (condensed → 75%), and a shorthand slot holding the value it already defaults to is dropped (transition:height .35s ease → height.35s).

Every table is derived: the position axes are read off <position>'s own […] || […] branch, and the droppable shorthand keywords off each shorthand's top-level || of slots, so generation fails if either grammar moves. Only the percentages are stated in SUPPLEMENT, since no dataset carries them.

The shorthand drop needs three conditions together, and each one is a rewrite that would otherwise turn a declaration the engine drops into one it accepts: exactly one slot may name the keyword (animation's none is both a name and a fill mode), that slot must take keywords and nothing else (mask:url(a.svg) none fills <mask-reference> twice and is dropped, so unwriting the none would revive it), and it must not be reached through a /. A sibling out of the same slot's keywords declines it at print time for the same reason.

Measured on the benchmark fixtures: Bootstrap 230,290 → 230,187, Tailwind app 125,657 → 125,542. Rejected on the evidence: background-position:left center → 0 (cssnano and lightningcss both emit it, but left computes to 0% and 0 to 0px), flex:0 1 auto → 0 auto (safe here, but flex:0 1 0 → 0 0 is not, and the dropped token is a number rather than a keyword), and folding color-mix() to a hex (Chrome computes color(srgb …), so lightningcss's #fb2c3680 is a different colour from color(srgb 0.982628 0.171899 0.21316 / 0.5)).

What kind of change does this PR introduce?

feat

Did you add tests for your changes?

Yes — test/CssSyntax.unittest.js gains four describes covering each transform and the cases it declines (500 tests in the file); the configCases/css/minimize-values and minimize-timing-functions snapshots were updated in both ConfigTest and ConfigCacheTest.

Does this PR introduce a breaking change?

No. Minified output changes; every transform preserves the computed style.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a — no option or public API changes.

Use of AI

Claude Code was used throughout: to diff webpack's output against cssnano's and lightningcss's to find where the bytes were going, to write the generator collectors and the printer, and to write the tests. Every equivalence was checked in headless Chromium by comparing the element's whole computed style rather than the one property written, and each candidate was measured before and after — three were dropped on the evidence rather than shipped, as described above.


Generated by Claude Code


Note

Medium Risk
Minified CSS output changes across many properties; mistakes could alter rendering, though transforms are guarded and heavily tested for cases that would revive dropped declarations.

Overview
Extends webpack’s CSS minifier with four output-only transforms that keep computed styles the same while shrinking bytes.

<position> edge keywords on properties whose value is purely a position (e.g. background-position, object-position) rewrite to shorter percentages when that saves length (left top → 0%0%), with guards for offsets, shorthands, and ambiguous cases.

<transform-list> values join adjacent functions without extra space between ) and the next function name.

font-stretch named widths map to their spec percentages when shorter (condensed → 75%).

Shorthand values drop tokens that only restate a slot’s initial keyword (e.g. transition:height .35s ease → height .35s), using a generated SHORTHAND_INITIAL_KEYWORDS map and strict rules so invalid “double slot” declarations are not revived.

Lookup data is generated from mdn-data grammars in tooling/generate-css-data.js into lib/css/data.js; logic lives in lib/css/syntax.js. Unit tests and minimize config snapshots are updated accordingly.

Reviewed by Cursor Bugbot for commit 425c742. Bugbot is set up for automated code reviews on this repo. Configure here.

@changeset-bot

changeset-bot Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a1a0ba2

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes changesets to release 1 package
Name Type
webpack Minor

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 28df2fb. Configure here.

Comment thread lib/css/syntax.js Resolved
@codecov

codecov Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.11399% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.23%. Comparing base (21af4f5) to head (a1a0ba2).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
tooling/generate-css-data.js 93.71% 13 Missing ⚠️
lib/css/syntax.js 98.78% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             main   #21629    +/-   ##
========================================
  Coverage   94.22%   94.23%            
========================================
  Files         628      628            
  Lines       79590    79952   +362     
  Branches    23548    23676   +128     
========================================
+ Hits        74997    75345   +348     
- Misses       4593     4607    +14     
Flag Coverage Δ
css-parsing 25.94% <12.29%> (-0.04%) ⬇️
html5lib 27.37% <ø> (ø)
integration 88.83% <25.69%> (-0.14%) ⬇️
test262 49.16% <ø> (-0.04%) ⬇️
unit 52.15% <96.11%> (+0.22%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (d0a9320).

Install it locally:

  • npm
npm i -D webpack@https://pkg.pr.new/webpack@d0a9320
  • yarn
yarn add -D webpack@https://pkg.pr.new/webpack@d0a9320
  • pnpm
pnpm add -D webpack@https://pkg.pr.new/webpack@d0a9320

@github-actions

github-actions Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Generated code size

Comparing a1a0ba2 against 21af4f5. Merging this PR will change the code webpack generates.

Changed New Deleted Unchanged Raw change
Cases 14 0 0 1490 🔴 ↑ +1.45 KiB
Assets 17 0 0 5884 🔴 ↑ +1.45 KiB
Runtimes 0 0 0 1858 —
17 asset(s) changed size
Asset Before After Change Gzip (9) Brotli (11) Zstd (19)
🔴 ↑ css/minimize-shorthands bundle0.css 6.46 KiB 8.84 KiB +2.38 KiB (+36.93%) +40.82% +42.80% +40.47%
🟢 ↓ css/large 1/961.bundle1.css 1.28 MiB 1.28 MiB -531 B (-0.04%) -0.06% -0.00% -0.04%
🟢 ↓ css/large 1/382.bundle1.css 1.87 MiB 1.87 MiB -531 B (-0.03%) -0.08% +0.05% -0.16%
🔴 ↑ css/minimize-calc bundle0.css 10.26 KiB 10.51 KiB +249 B (+2.37%) +2.89% +2.30% +2.64%
🟢 ↓ css/css-modules web-production/652.bundle1.css 27.61 KiB 27.57 KiB -42 B (-0.15%) -0.09% -0.04% -0.05%
🟢 ↓ css/css-modules web-production-global/244.bundle5.css 30.21 KiB 30.17 KiB -42 B (-0.14%) -0.12% -0.09% -0.12%
🟢 ↓ module/import-meta-parser-options bundle0.mjs 20.68 KiB 20.65 KiB -30 B (-0.14%) — -0.29% +0.04%
🟢 ↓ css/minimize-lightningcss-values bundle0.css 12.23 KiB 12.22 KiB -19 B (-0.15%) +0.67% +0.61% +0.75%
🟢 ↓ css/minimize-timing-functions bundle0.css 3.40 KiB 3.40 KiB -5 B (-0.14%) +0.40% +0.47% +0.27%
🟢 ↓ css/minimize-strings main.css 3.50 KiB 3.50 KiB -4 B (-0.11%) +0.19% +0.23% +0.38%
🟢 ↓ css/external-in-web 1/dynamic_css.bundle1.css 233 B 232 B -1 B (-0.43%) +0.68% — —
🟢 ↓ css/external-in-web 0/dynamic_css.bundle0.css 233 B 232 B -1 B (-0.43%) +0.68% — —
🟢 ↓ css/case-insensitive 1/bundle1.css 391 B 390 B -1 B (-0.26%) -0.32% -0.41% -0.33%
🟢 ↓ css/counter-scoping 1/bundle1.css 853 B 852 B -1 B (-0.12%) -0.30% +0.34% -0.31%
🟢 ↓ css/minimize-urls bundle0.css 2.34 KiB 2.34 KiB -1 B (-0.04%) — -0.16% -0.26%
🟢 ↓ css/minimize-esbuild bundle0.css 6.88 KiB 6.88 KiB -1 B (-0.01%) — +0.10% +0.18%
🟢 ↓ css/minimize-values bundle0.css 14.88 KiB 14.88 KiB -1 B (-0.01%) +0.04% +0.26% -0.02%

No runtime gained or lost a runtime module.

Built test/configCases with the defaults a user gets: 1504 case(s), 5901 asset(s), 35 emitted nothing.

@codspeed

codspeed Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 1 benchmark

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 3 improved benchmarks
❌ 1 regressed benchmark
✅ 216 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Memory benchmark "devtool-eval", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 507.3 KB 877.8 KB -42.2%
⚡ Memory benchmark "many-modules-interop-runtime", scenario '{"name":"mode-production","mode":"production"}', measure 'exec' 26.9 KB 20.6 KB +30.38%
⚡ Memory benchmark "devtool-eval", scenario '{"name":"mode-production","mode":"production"}' 16.5 MB 12.6 MB +30.35%
⚡ Memory benchmark "many-chunks-commonjs", scenario '{"name":"mode-production","mode":"production"}' 10.9 MB 8.8 MB +23.73%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing feat/css-minify-selector-and-value-transforms (a1a0ba2) with main (21af4f5)

Open in CodSpeed

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

8 similar comments
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

… tail

A comma parts a `transition` into layers, each with its own set of slots, so
the initial-keyword drop and the slot order now run per layer instead of
declining the whole value. A `<position>` whose second value names the centre
drops it, which the percentage rewrite could not reach past an offset.
`transform-origin` states both axes longhand and takes a z `<length>` after
them, so naming `<position>` never reaches it. Derive those properties from
everything the grammar accepts — the five edge keywords and an offset — which
a third component keeps clear of the depth.
Grammar matching skips whitespace and a `)` fuses with nothing, so between
two calls it separates the same tokens either way. Reading that off the value's
shape rather than a property table reaches the prefixed spellings no dataset
names, `filter`, a track list and an `@font-face` `src` — and retires the
table, which held one name.
…lengths

A generic family is one identifier, so only a lone word can be read as one —
`Apple Color Emoji` is three, whatever the last of them spells. A shadow states
its offsets as `<length>{MIN,MAX}`, and the ones past MIN default to zero, so a
trailing `0` says nothing; the grammar states MIN, so the generator reads it.
Filter Effects 1 states, per function, the amount an omitted argument means, so
writing that amount says nothing. The grammar marks which arguments are
omittable, so the set is derived and only the amounts are stated.

Also drops the shadow zero-length collapse: it saved raw bytes but cost more
after gzip, which is what ships.
`import/order` sorts the generated exports, and `FILTER_FUNCTION_OMITTED`
belongs before `FLEX_KEYWORDS`.
A shadow states its offsets as `<length>{MIN,MAX}`, and the ones past MIN
default to zero, so a trailing `0` says nothing; the grammar states MIN, so the
generator reads it. Also rewords the filter table's `omittable` to `optional`,
which cspell rejected.
A comma with nothing either side is a layer no shadow fills, so the value is
kept as written.
Restarting a jest worker thread because it tripped --workerIdleMemoryLimit
segfaults Bun 1.3.14 in thread teardown, a different wild address each time and
workers_terminated short of workers_spawned. The runner's heaps sit at the
512MB the other runtimes use, so it fired constantly and the job died ~150s in.
Reproduced locally: 30MB and 100MB crash, 4096MB and no limit pass.
@alexander-akait
alexander-akait force-pushed the feat/css-minify-selector-and-value-transforms branch from 9afb58a to a1a0ba2 Compare August 7, 2026 14:15
@cursor

cursor Bot commented Aug 7, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your team's free trial on GitHub.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging feat/css-minify-selector-and-value-transforms into main will be
99.29%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.82%100%100%98.82%103
examples
   build-common.js100%100%100%100%
   buildAll.js100%100%100%100%
   examples.js100%100%100%100%
   template-common.js98.21%100%100%98.21%72
examples/custom-javascript-parser
   test.filter.js100%100%100%100%
examples/custom-javascript-parser/internals
   acorn-parse.js100%100%100%100%
   meriyah-parse.js100%100%100%100%
   oxc-parse.js100%100%100%100%
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/module-federation
   test.filter.js100%100%100%100%
examples/reexport-components
   test.filter.js100%100%100%100%
examples/typescript
   test.filter.js100%100%100%100%
examples/typescript-non-erasable
   test.filter.js50%100%100%50%5
examples/virtual-modules
   test.filter.js100%100%100%100%
examples/wasm-bindgen-esm
   test.filter.js100%100%100%100%
examples/wasm-complex
   test.filter.js100%100%100%100%
examples/wasm-emscripten
   test.filter.js100%100%100%100%
examples/wasm-simple
   test.filter.js100%100%100%100%
examples/wasm-simple-source-phase
   test.filter.js100%100%100%100%
lib
   APIPlugin.js100%100%100%100%
   AsyncDependenciesBlock.js100%100%100%100%
   AutomaticPrefetchPlugin.js100%100%100%100%
   BannerPlugin.js100%100%100%100%
   Cache.js98.21%100%100%98.21%101
   CacheFacade.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%39
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CircularModulesPlugin.js98.81%100%100%98.81%136
   CleanPlugin.js99.13%100%100%99.13%214, 234
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.42%100%100%98.42%1648, 1967, 1974, 1982, 2004, 2007, 2946, 3425–3426, 3458, 4162, 4192, 4245–4246, 4250, 4255, 4271–4272, 4286–4287, 4292–4293, 4773, 4799, 527, 532, 5607, 5639, 5656, 5672, 5688, 5703, 5728–5729, 5731, 6061, 6066, 6072, 6075, 6082, 6094, 6096, 6100, 6116, 6131, 6163, 6217, 6241, 6356, 778–779
   Compiler.js99.56%100%100%99.56%1159–1160, 1168
   ConcatenationScope.js99.12%100%100%99.12%300
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js99.88%100%100%99.88%1461
   ContextModuleFactory.js97.20%100%100%97.20%266, 435, 456, 461, 501, 512, 514, 518, 527–528
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js99.08%100%100%99.08%1080, 176–177, 193, 212, 286
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.51%100%100%98.51%480, 527
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DotenvPlugin.js98.41%100%100%98.41%378, 391–392
   DynamicEntryPlugin.js100%100%100%100%
   EntryOptionPlugin.js100%100%100%100%
   EntryPlugin.js100%100%100%100%
   Entrypoint.js100%100%100%100%
   EnvironmentPlugin.js97.14%100%100%97.14%49
   ErrorHelpers.js100%100%100%100%
   EvalDevToolModulePlugin.js100%100%100%100%
   EvalSourceMapDevToolPlugin.js100%100%100%100%
   ExportsInfo.js100%100%100%100%
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.67%100%100%98.67%1216, 1219, 515–519, 521, 667
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.16%100%100%99.16%1267, 1269–1274, 1281, 1284, 182, 2502–2503, 2506, 2517, 2528, 2539, 280, 3976, 3991, 4015
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.21%100%100%98.21%448, 457, 460, 464, 476
   FlagDependencyUsagePlugin.js100%100%100%100%
   FlagEntryExportAsUsedPlugin.js100%100%100%100%
   Generator.js100%100%100%100%
   HotModuleReplacementPlugin.js100%100%100%100%
   HotUpdateChunk.js100%100%100%100%
   IgnorePlugin.js100%100%100%100%
   IgnoreWarningsPlugin.js100%100%100%100%
   InitFragment.js100%100%100%100%
   JavascriptMetaInfoPlugin.js100%100%100%100%
   LazyBarrel.js100%100%100%100%
   LibraryTemplatePlugin.js100%100%100%100%
   LoaderOptionsPlugin.js100%100%100%100%
   LoaderTargetPlugin.js100%100%100%100%
   MainTemplate.js100%100%100%100%
   ManifestPlugin.js100%100%100%100%
   Module.js98.51%100%100%98.51%1303, 1308, 1368, 1382, 1444, 1453
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.90%100%100%98.90%111, 113
   ModuleGraph.js99.78%100%100%99.78%1170
   ModuleGraphConnection.js100%100%100%100%
   ModuleInfoHeaderPlugin.js100%100%100%100%
   ModuleNotFoundError.js100%100%100%100%
   ModuleProfile.js100%100%100%100%
   ModuleSourceTypeConstants.js100%100%100%100%
   ModuleTemplate.js100%100%100%100%
   ModuleTypeConstants.js100%100%100%100%
   MultiCompiler.js99.71%100%100%99.71%692
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.98%100%100%97.98%1020, 1023, 1040, 1057, 1305, 1339, 1355, 1803, 2100, 2105–2115, 34
   NormalModuleFactory.js98.72%100%100%98.72%1123, 1391, 1402, 1412, 1463–1465, 1472, 526, 538
   NormalModuleReplacementPlugin.js100%100%100%100%
   NullFactory.js100%100%100%100%
   OptimizationStages.js100%100%100%100%
   OptionsApply.js100%100%100%100%
   Parser.js100%100%100%100%
   PlatformPlugin.js100%100%100%100%
   PrefetchPlugin.js100%100%100%100%
   ProgressPlugin.js99.80%100%100%99.80%691
   ProvidePlugin.js100%100%100%100%
   RawModule.js100%100%100%100%
   RecordIdsPlugin.js100%100%100%100%
   RequestShortener.js100%100%100%100%
   ResolverFactory.js100%100%100%100%
   RuntimeGlobals.js100%100%100%100%
   RuntimeModule.js100%100%100%100%
   RuntimePlugin.js100%100%100%100%
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js98.63%100%100%98.63%220, 224, 226, 420, 431, 890
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.47%100%100%99.47%352–353
   UseStrictPlugin.js100%100%100%100%
   WarnCaseSensitiveModulesPlugin.js100%100%100%100%
   WarnDeprecatedOptionPlugin.js100%100%100%100%
   WarnNoModeSetPlugin.js100%100%100%100%
   WatchIgnorePlugin.js100%100%100%100%
   Watching.js100%100%100%100%
   WebpackError.js100%100%100%100%
   WebpackIsIncludedPlugin.js100%100%100%100%
   WebpackOptionsApply.js100%100%100%100%
   WebpackOptionsDefaulter.js100%100%100%100%
   buildChunkGraph.js99.87%100%100%99.87%371
   cli.js98.63%100%100%98.63%10, 119, 549, 581, 631, 905
   index.js99.73%100%100%99.73%184
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js97.10%100%100%97.10%10, 263, 285, 287
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.95%100%100%97.95%295, 319, 322, 42, 452, 47
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
   WebManifestGenerator.js100%100%100%100%
   WebManifestParser.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
   isGeneratorLowered.js100%100%100%100%
lib/bun
   BunTargetPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%75, 87, 95
   MemoryCachePlugin.js92%100%100%92%34, 43
   MemoryWithGcCachePlugin.js93.42%100%100%93.42%108, 122–123, 132, 90
   PackFileCacheStrategy.js96.52%100%100%96.52%1310, 1410, 1414, 1476, 1712, 1796, 1819, 1851, 675, 694, 704–706, 708, 724–725, 730, 733, 735, 740, 745, 770, 776, 810, 816, 822, 827, 838, 847, 852–853, 855, 872, 878–879, 881
   ResolverCachePlugin.js100%100%100%100%
   

@alexander-akait
alexander-akait merged commit d0a9320 into main Aug 7, 2026
63 checks passed
@alexander-akait
alexander-akait deleted the feat/css-minify-selector-and-value-transforms branch August 7, 2026 15:19
alexander-akait added a commit that referenced this pull request Aug 9, 2026
The limit bounds each worker thread's heap; without it the suite grows until the
runner is out of memory. Dropping it in #21629 traded Bun's segfault for an OOM.
alexander-akait added a commit that referenced this pull request Aug 9, 2026
…om itself (#21646)

* ci(bun): restore the worker idle memory limit

The limit bounds each worker thread's heap; without it the suite grows until the
runner is out of memory. Dropping it in #21629 traded Bun's segfault for an OOM.

* ci(bun): end a Bun worker from itself instead of terminating it

Bun segfaults when jest terminates a worker thread from the parent on an
idle-memory restart, a different wild address each time and workers_terminated
short of workers_spawned. Sending the end message jest already uses for shutdown
lets the worker leave on its own. Guarded on Bun, so Node and Deno still
terminate. Reproduced with a low limit: terminate crashes 5/5, ending 3/3 passes.

* ci(bun): exit a Bun worker once it has ended, so the pool replaces it

Ending a worker only removes its message listener; the thread leaves only if
that was its last handle. A jest worker that leaked one therefore stayed alive
in the RESTARTING state forever — reproduced with a worker holding a timer:
the idle-memory limit tripped (1.63 MB over a 1 MB limit), the restart was
requested, and the next task still ran on the same thread. The limit had
become a no-op for that worker, which is the one thing it exists to do.

The worker now exits itself after teardown, on Bun only. Same reproduction:
the state returns to `ok` and the next task runs on a new thread.
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.

1 participant