fix(canonicalize): handle utilities with empty property maps in collapse#19727
fix(canonicalize): handle utilities with empty property maps in collapse#19727kirkouimet wants to merge 1 commit intotailwindlabs:mainfrom
Conversation
When `canonicalizeCandidates` is called with `collapse: true`, the
`collapseGroup` function builds an `otherUtilities` array by mapping
each candidate's property values. If a utility generates CSS but has
no standard declaration properties (e.g. shadow utilities that use
`@property` rules and CSS custom properties), the inner loop over
`propertyValues.keys()` never executes, leaving `result` as `null`.
The non-null assertion `result!` then returns `null` into the array,
causing downstream code to crash with "X is not iterable" or "Cannot
read properties of null (reading 'has')" when iterating or calling
methods on the null entry.
Fix: return an empty Set instead of null when a utility has no
property keys. This is semantically correct -- a utility with no
standard properties cannot be linked to or collapsed with any other
utility, which is exactly what an empty Set represents.
Reproduction: `canonicalizeCandidates(['shadow-sm', 'border'], { collapse: true })`
crashes on vanilla Tailwind CSS with no custom configuration.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Repository UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
WalkthroughThis change addresses a null reference issue in the collapse canonicalization logic and adds corresponding test coverage. The production code modification updates the 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request. ### What changed? #### ✳️ eslint (9.27.0 → 9.29.0) · [Repo](https://github.com/eslint/eslint) · [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) <details> <summary>Release Notes</summary> <h4><a href="https://github.com/eslint/eslint/releases/tag/v9.29.0">9.29.0</a></h4> <blockquote><h2 dir="auto">Features</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/f686fcb51e47cf53b891ae595684afe8a0ef584d"><code class="notranslate">f686fcb</code></a> feat: add <code class="notranslate">ecmaVersion: 2026</code>, parsing <code class="notranslate">using</code> and <code class="notranslate">await using</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19832">#19832</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/19cdd226bb5957f8f7e8cb4e92d38aafe47f8ff4"><code class="notranslate">19cdd22</code></a> feat: prune suppressions for non-existent files (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19825">#19825</a>) (TKDev7)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b3d720f82f08022a33b10f0437111e7d270b8e3c"><code class="notranslate">b3d720f</code></a> feat: add ES2025 globals (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19835">#19835</a>) (fisker Cheung)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/677a2837a17320f54a8869682af128a2a7d77579"><code class="notranslate">677a283</code></a> feat: add auto-accessor fields support to class-methods-use-this (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19789">#19789</a>) (sethamus)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/dbba0589f5509223658b73de6eb721f659bcec47"><code class="notranslate">dbba058</code></a> feat: allow global type declaration in <code class="notranslate">no-var</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19714">#19714</a>) (Remco Haszing)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/342bd29e1a10a4b521ed0dbb6d889dcfc137e863"><code class="notranslate">342bd29</code></a> feat: ignore type annotations in no-restricted-globals (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19781">#19781</a>) (sethamus)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/786bcd13652b90c5bd0c7201610b856ad1b87542"><code class="notranslate">786bcd1</code></a> feat: add allowProperties option to no-restricted-properties (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19772">#19772</a>) (sethamus)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/05b66d05bd68214f2fa1ab53fb2734c9d9e5348a"><code class="notranslate">05b66d0</code></a> feat: add <code class="notranslate">sourceCode.isGlobalReference(node)</code> method (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19695">#19695</a>) (Nitin Kumar)</li> </ul> <h2 dir="auto">Bug Fixes</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/85c082c54bd42ad818f5938b8fb1fb2aa0a1912f"><code class="notranslate">85c082c</code></a> fix: explicit matching behavior with negated patterns and arrays (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19845">#19845</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/9bda4a9bf18c9fef91cdd93921a0935ffcf9a9fc"><code class="notranslate">9bda4a9</code></a> fix: fix <code class="notranslate">LintOptions.filterCodeBlock</code> types (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19837">#19837</a>) (ntnyq)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/7ab77a2c7605126daaa7e7f7ab75b5c252677d12"><code class="notranslate">7ab77a2</code></a> fix: correct breaking deprecation of FlatConfig type (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19826">#19826</a>) (Logicer)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/1ba33181ab300588a803434884c054ed003f0bbd"><code class="notranslate">1ba3318</code></a> fix: add <code class="notranslate">language</code> and <code class="notranslate">dialects</code> to <code class="notranslate">no-use-before-define</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19808">#19808</a>) (Francesco Trotta)</li> </ul> <h2 dir="auto">Documentation</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/00e3e6ad1357df7d46be51d3f305efecb90244a7"><code class="notranslate">00e3e6a</code></a> docs: add support for custom name parameter to <code class="notranslate">includeIgnoreFile</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19795">#19795</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/3aed0756ed3669ac27fc243c81fd82e3d0e6973b"><code class="notranslate">3aed075</code></a> docs: Update README (GitHub Actions Bot)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a2f888d679e2a44964da596a4158911819e1d31d"><code class="notranslate">a2f888d</code></a> docs: enhance documentation with links and fix typos (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19761">#19761</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/53c3235ba1c90a85a44f0abd18998ccc4e0445bf"><code class="notranslate">53c3235</code></a> docs: update to clarify prompt usage (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19748">#19748</a>) (Jennifer Davis)</li> </ul> <h2 dir="auto">Chores</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/5c114c962f29d0b33e6439e9ab0985014af06b9f"><code class="notranslate">5c114c9</code></a> chore: upgrade @eslint/js@9.29.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19851">#19851</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/acf2201a067d062e007b1b7b164b8e96fa1af50f"><code class="notranslate">acf2201</code></a> chore: package.json update for @eslint/js release (Jenkins)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a806994263e54e4bc1481736b1c0626c8b770808"><code class="notranslate">a806994</code></a> refactor: Remove eslintrc from flat config functionality (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19833">#19833</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/152ed51329d82c6e7375f41a105e01b31750e17f"><code class="notranslate">152ed51</code></a> test: switch to flat config mode in code path analysis tests (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19824">#19824</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b647239272931e0a947500b2f554fc8ccdf8adfd"><code class="notranslate">b647239</code></a> chore: Update first-party dependencies faster with Renovate (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19822">#19822</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/7abe42e2de931289e19e34e390d16936cf6faf64"><code class="notranslate">7abe42e</code></a> refactor: SafeEmitter -> SourceCodeVisitor (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19708">#19708</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e39289596757702b6c8d747d5ab9c1a7820c108f"><code class="notranslate">e392895</code></a> perf: improve time complexity of <code class="notranslate">getLocFromIndex</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19782">#19782</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0ed289c5ceed1c10b599b22c8b9374a5a3a144dd"><code class="notranslate">0ed289c</code></a> chore: remove accidentally committed file (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19807">#19807</a>) (Francesco Trotta)</li> </ul></blockquote> <h4><a href="https://github.com/eslint/eslint/releases/tag/v9.28.0">9.28.0</a></h4> <blockquote><h2 dir="auto">Features</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b0674be94e4394401b4f668453a473572c321023"><code class="notranslate">b0674be</code></a> feat: Customization of serialization for languageOptions (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19760">#19760</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a95721f1064fdbfe0e392b955ce3053a24551f80"><code class="notranslate">a95721f</code></a> feat: Add <code class="notranslate">--pass-on-unpruned-suppressions</code> CLI option (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19773">#19773</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/bfd0e7a39535b3c1ddc742dfffa6bdcdc93079e2"><code class="notranslate">bfd0e7a</code></a> feat: support TypeScript syntax in <code class="notranslate">no-use-before-define</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19566">#19566</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/68c61c093a885623e48f38026e3f3a05bfa403de"><code class="notranslate">68c61c0</code></a> feat: support TS syntax in <code class="notranslate">no-shadow</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19565">#19565</a>) (Nitin Kumar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0f773ef248af0301a410fee11e1b22174100cf6a"><code class="notranslate">0f773ef</code></a> feat: support TS syntax in <code class="notranslate">no-magic-numbers</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19561">#19561</a>) (Nitin Kumar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/c4a6b6051889b1cb668d4d2ae29e9c27c74993d6"><code class="notranslate">c4a6b60</code></a> feat: add allowTypeAnnotation to func-style (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19754">#19754</a>) (sethamus)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/b03ad176f158afdd921f0af5126c398012b10559"><code class="notranslate">b03ad17</code></a> feat: add TypeScript support to <code class="notranslate">prefer-arrow-callback</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19678">#19678</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/bc3c3313ce2719062805b6849d29f9a375cf23f2"><code class="notranslate">bc3c331</code></a> feat: ignore overloaded function declarations in func-style rule (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19755">#19755</a>) (sethamus)</li> </ul> <h2 dir="auto">Bug Fixes</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/eea3e7eb1ca84f9e8870e1190d65d5235d9d8429"><code class="notranslate">eea3e7e</code></a> fix: Remove configured global variables from <code class="notranslate">GlobalScope#implicit</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19779">#19779</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/a467de39f6e509af95a7963904326635c1bf7116"><code class="notranslate">a467de3</code></a> fix: update context.report types (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19751">#19751</a>) (Nitin Kumar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/fd467bb892d735a4a8863beabd181a3f3152689a"><code class="notranslate">fd467bb</code></a> fix: remove interopDefault to use jiti's default (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19697">#19697</a>) (sethamus)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/72d16e3066aac2f1c74f4150ba43dfa8cf532584"><code class="notranslate">72d16e3</code></a> fix: avoid false positive in <code class="notranslate">no-unassigned-vars</code> for declare module (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19746">#19746</a>) (Azat S.)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/81c3c936266474c2081f310098084bd0eb1768d2"><code class="notranslate">81c3c93</code></a> fix: curly types (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19750">#19750</a>) (Eli)</li> </ul> <h2 dir="auto">Documentation</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/3ec208233f29c161aae8f99f9f091e371fe83a62"><code class="notranslate">3ec2082</code></a> docs: Nested arrays in files config entry (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19799">#19799</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/89a65b07f6171a860284b62d97c8b3edf312b98c"><code class="notranslate">89a65b0</code></a> docs: clarify how config arrays can apply to subsets of files (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19788">#19788</a>) (Shais Ch)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/2ba8a0d75c7a8e6aa4798275126698be40391d37"><code class="notranslate">2ba8a0d</code></a> docs: Add description of meta.namespace to plugin docs (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19798">#19798</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/59dd7e6b28507053bde985ea2311dca8ec0db681"><code class="notranslate">59dd7e6</code></a> docs: update <code class="notranslate">func-style</code> with examples (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19793">#19793</a>) (Tanuj Kanti)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e9129e0799d068c377d63d59a0a800e7d1fea8dd"><code class="notranslate">e9129e0</code></a> docs: add global scope's <code class="notranslate">implicit</code> field to Scope Manager docs (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19770">#19770</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/52f5b7a0af48a2f143f0bccfd4e036025b08280d"><code class="notranslate">52f5b7a</code></a> docs: fix minor typos and add links (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19743">#19743</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/00716a339ede24ed5a76aceed833f38a6c4e8d3a"><code class="notranslate">00716a3</code></a> docs: upfront recommend against using the no-return-await rule (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19727">#19727</a>) (Mike DiDomizio)</li> </ul> <h2 dir="auto">Chores</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/175b7b83fcdc8f3f84821510dd7e04d120402317"><code class="notranslate">175b7b8</code></a> chore: upgrade to <code class="notranslate">@eslint/js@9.28.0</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19802">#19802</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/844f5a69dc78ca38f856c137e061e8facc9d00ba"><code class="notranslate">844f5a6</code></a> chore: package.json update for @eslint/js release (Jenkins)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/62b1c1bc7981798c3aec2dd430c200c797a25629"><code class="notranslate">62b1c1b</code></a> chore: update globals to v16 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19791">#19791</a>) (Nitin Kumar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/e8a1cb8f7fbc18efa589bfedea5326de636b4868"><code class="notranslate">e8a1cb8</code></a> chore: ignore jiti-v2.0 & jiti-v2.1 for renovate (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19786">#19786</a>) (Nitin Kumar)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/43d39754b6d315954f46a70dbd53d1fa0eea1619"><code class="notranslate">43d3975</code></a> chore: Add Copilot Instructions file (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19753">#19753</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/2dfb5ebef4c14d552d10a6c7c2c2ce376e63654a"><code class="notranslate">2dfb5eb</code></a> test: update <code class="notranslate">SourceCodeTraverser</code> tests (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19763">#19763</a>) (Milos Djermanovic)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/5bc21f9e8e00f9e49442d1b6520b307ce94f3518"><code class="notranslate">5bc21f9</code></a> chore: add <code class="notranslate">*.code-workspace</code> to <code class="notranslate">.gitignore</code> (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19771">#19771</a>) (루밀LuMir)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/f4fa40eb4bd6f4dba3b2e7fff259d0780ef6becf"><code class="notranslate">f4fa40e</code></a> refactor: NodeEventGenerator -> SourceCodeTraverser (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19679">#19679</a>) (Nicholas C. Zakas)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/0f49329b4a7f91714f2cd1e9ce532d32202c47f4"><code class="notranslate">0f49329</code></a> refactor: use a service to emit warnings (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19725">#19725</a>) (Francesco Trotta)</li> <li> <a href="https://bounce.depfu.com/github.com/eslint/eslint/commit/20a9e59438fde3642ab058cc55ee1b9fa02b6391"><code class="notranslate">20a9e59</code></a> chore: update dependency shelljs to ^0.10.0 (<a href="https://bounce.depfu.com/github.com/eslint/eslint/pull/19740">#19740</a>) (renovate[bot])</li> </ul></blockquote> <p><em>Does any of this look wrong? <a href="https://depfu.com/packages/npm/eslint/feedback">Please let us know.</a></em></p> </details> <details> <summary>Commits</summary> <p><a href="https://github.com/eslint/eslint/compare/b9080cf28d88f934941a545a033eb960eceeadbd...edf232b680390013c68f081a5e41843bcf2dd18f">See the full diff on Github</a>. The new version differs by 58 commits:</p> <ul> <li><a href="https://github.com/eslint/eslint/commit/edf232b680390013c68f081a5e41843bcf2dd18f"><code>9.29.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/c2414b647baaa75303ef647e134b2520c10bf6e0"><code>Build: changelog update for 9.29.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/5c114c962f29d0b33e6439e9ab0985014af06b9f"><code>chore: upgrade @eslint/js@9.29.0 (#19851)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/acf2201a067d062e007b1b7b164b8e96fa1af50f"><code>chore: package.json update for @eslint/js release</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/f686fcb51e47cf53b891ae595684afe8a0ef584d"><code>feat: add `ecmaVersion: 2026`, parsing `using` and `await using` (#19832)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/85c082c54bd42ad818f5938b8fb1fb2aa0a1912f"><code>fix: explicit matching behavior with negated patterns and arrays (#19845)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/00e3e6ad1357df7d46be51d3f305efecb90244a7"><code>docs: add support for custom name parameter to `includeIgnoreFile` (#19795)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/9bda4a9bf18c9fef91cdd93921a0935ffcf9a9fc"><code>fix: fix `LintOptions.filterCodeBlock` types (#19837)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a806994263e54e4bc1481736b1c0626c8b770808"><code>refactor: Remove eslintrc from flat config functionality (#19833)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/19cdd226bb5957f8f7e8cb4e92d38aafe47f8ff4"><code>feat: prune suppressions for non-existent files (#19825)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b3d720f82f08022a33b10f0437111e7d270b8e3c"><code>feat: add ES2025 globals (#19835)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/677a2837a17320f54a8869682af128a2a7d77579"><code>feat: add auto-accessor fields support to class-methods-use-this (#19789)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/3aed0756ed3669ac27fc243c81fd82e3d0e6973b"><code>docs: Update README</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/7ab77a2c7605126daaa7e7f7ab75b5c252677d12"><code>fix: correct breaking deprecation of FlatConfig type (#19826)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a2f888d679e2a44964da596a4158911819e1d31d"><code>docs: enhance documentation with links and fix typos (#19761)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/dbba0589f5509223658b73de6eb721f659bcec47"><code>feat: allow global type declaration in `no-var` (tailwindlabs#19714)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/152ed51329d82c6e7375f41a105e01b31750e17f"><code>test: switch to flat config mode in code path analysis tests (#19824)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b647239272931e0a947500b2f554fc8ccdf8adfd"><code>chore: Update first-party dependencies faster with Renovate (#19822)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/7abe42e2de931289e19e34e390d16936cf6faf64"><code>refactor: SafeEmitter -> SourceCodeVisitor (tailwindlabs#19708)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/342bd29e1a10a4b521ed0dbb6d889dcfc137e863"><code>feat: ignore type annotations in no-restricted-globals (#19781)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e39289596757702b6c8d747d5ab9c1a7820c108f"><code>perf: improve time complexity of `getLocFromIndex` (#19782)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/1ba33181ab300588a803434884c054ed003f0bbd"><code>fix: add `language` and `dialects` to `no-use-before-define` (#19808)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/786bcd13652b90c5bd0c7201610b856ad1b87542"><code>feat: add allowProperties option to no-restricted-properties (#19772)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/05b66d05bd68214f2fa1ab53fb2734c9d9e5348a"><code>feat: add `sourceCode.isGlobalReference(node)` method (tailwindlabs#19695)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/53c3235ba1c90a85a44f0abd18998ccc4e0445bf"><code>docs: update to clarify prompt usage (tailwindlabs#19748)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/0ed289c5ceed1c10b599b22c8b9374a5a3a144dd"><code>chore: remove accidentally committed file (#19807)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/f341f21e024388e602cfccee06e11b9113a2d298"><code>9.28.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/779dda93a25a0e9da934a96311e5f97985e4401c"><code>Build: changelog update for 9.28.0</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/175b7b83fcdc8f3f84821510dd7e04d120402317"><code>chore: upgrade to `@eslint/js@9.28.0` (#19802)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/844f5a69dc78ca38f856c137e061e8facc9d00ba"><code>chore: package.json update for @eslint/js release</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b0674be94e4394401b4f668453a473572c321023"><code>feat: Customization of serialization for languageOptions (#19760)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/3ec208233f29c161aae8f99f9f091e371fe83a62"><code>docs: Nested arrays in files config entry (#19799)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/89a65b07f6171a860284b62d97c8b3edf312b98c"><code>docs: clarify how config arrays can apply to subsets of files (#19788)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/2ba8a0d75c7a8e6aa4798275126698be40391d37"><code>docs: Add description of meta.namespace to plugin docs (#19798)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/eea3e7eb1ca84f9e8870e1190d65d5235d9d8429"><code>fix: Remove configured global variables from `GlobalScope#implicit` (#19779)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a95721f1064fdbfe0e392b955ce3053a24551f80"><code>feat: Add `--pass-on-unpruned-suppressions` CLI option (#19773)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/a467de39f6e509af95a7963904326635c1bf7116"><code>fix: update context.report types (tailwindlabs#19751)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/59dd7e6b28507053bde985ea2311dca8ec0db681"><code>docs: update `func-style` with examples (#19793)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/62b1c1bc7981798c3aec2dd430c200c797a25629"><code>chore: update globals to v16 (#19791)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/bfd0e7a39535b3c1ddc742dfffa6bdcdc93079e2"><code>feat: support TypeScript syntax in `no-use-before-define` (tailwindlabs#19566)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/68c61c093a885623e48f38026e3f3a05bfa403de"><code>feat: support TS syntax in `no-shadow` (tailwindlabs#19565)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e8a1cb8f7fbc18efa589bfedea5326de636b4868"><code>chore: ignore jiti-v2.0 & jiti-v2.1 for renovate (#19786)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/0f773ef248af0301a410fee11e1b22174100cf6a"><code>feat: support TS syntax in `no-magic-numbers` (tailwindlabs#19561)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/43d39754b6d315954f46a70dbd53d1fa0eea1619"><code>chore: Add Copilot Instructions file (#19753)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/c4a6b6051889b1cb668d4d2ae29e9c27c74993d6"><code>feat: add allowTypeAnnotation to func-style (#19754)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/fd467bb892d735a4a8863beabd181a3f3152689a"><code>fix: remove interopDefault to use jiti&tailwindlabs#39;s default (tailwindlabs#19697)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/2dfb5ebef4c14d552d10a6c7c2c2ce376e63654a"><code>test: update `SourceCodeTraverser` tests (#19763)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/b03ad176f158afdd921f0af5126c398012b10559"><code>feat: add TypeScript support to `prefer-arrow-callback` (tailwindlabs#19678)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/e9129e0799d068c377d63d59a0a800e7d1fea8dd"><code>docs: add global scope&tailwindlabs#39;s `implicit` field to Scope Manager docs (#19770)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/bc3c3313ce2719062805b6849d29f9a375cf23f2"><code>feat: ignore overloaded function declarations in func-style rule (#19755)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/5bc21f9e8e00f9e49442d1b6520b307ce94f3518"><code>chore: add `*.code-workspace` to `.gitignore` (#19771)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/72d16e3066aac2f1c74f4150ba43dfa8cf532584"><code>fix: avoid false positive in `no-unassigned-vars` for declare module (tailwindlabs#19746)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/f4fa40eb4bd6f4dba3b2e7fff259d0780ef6becf"><code>refactor: NodeEventGenerator -> SourceCodeTraverser (tailwindlabs#19679)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/81c3c936266474c2081f310098084bd0eb1768d2"><code>fix: curly types (tailwindlabs#19750)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/52f5b7a0af48a2f143f0bccfd4e036025b08280d"><code>docs: fix minor typos and add links (tailwindlabs#19743)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/0f49329b4a7f91714f2cd1e9ce532d32202c47f4"><code>refactor: use a service to emit warnings (tailwindlabs#19725)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/20a9e59438fde3642ab058cc55ee1b9fa02b6391"><code>chore: update dependency shelljs to ^0.10.0 (tailwindlabs#19740)</code></a></li> <li><a href="https://github.com/eslint/eslint/commit/00716a339ede24ed5a76aceed833f38a6c4e8d3a"><code>docs: upfront recommend against using the no-return-await rule (tailwindlabs#19727)</code></a></li> </ul> </details> ---  [Depfu](https://depfu.com) will automatically keep this PR conflict-free, as long as you don't add any commits to this branch yourself. You can also trigger a rebase manually by commenting with `@depfu rebase`. <details><summary>All Depfu comment commands</summary> <blockquote><dl> <dt>@depfu rebase</dt><dd>Rebases against your default branch and redoes this update</dd> <dt>@depfu recreate</dt><dd>Recreates this PR, overwriting any edits that you've made to it</dd> <dt>@depfu merge</dt><dd>Merges this PR once your tests are passing and conflicts are resolved</dd> <dt>@depfu cancel merge</dt><dd>Cancels automatic merging of this PR</dd> <dt>@depfu close</dt><dd>Closes this PR and deletes the branch</dd> <dt>@depfu reopen</dt><dd>Restores the branch and reopens this PR (if it's closed)</dd> <dt>@depfu pause</dt><dd>Ignores all future updates for this dependency and closes this PR</dd> <dt>@depfu pause [minor|major]</dt><dd>Ignores all future minor/major updates for this dependency and closes this PR</dd> <dt>@depfu resume</dt><dd>Future versions of this dependency will create PRs again (leaves this PR as is)</dd> </dl></blockquote> </details> Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Problem
canonicalizeCandidatescrashes when called withcollapse: trueand the candidate list includes utilities whose CSS output contains no standard declaration properties (only@propertyrules and CSS custom properties).This is reproducible with vanilla Tailwind CSS and no custom configuration:
All shadow utilities (
shadow-sm,shadow-md,shadow-lg,shadow-xl) crash when combined with any other utility andcollapse: true.This was discovered via
eslint-plugin-better-tailwindcss, which callscanonicalizeCandidateswithcollapse: truefor itsenforce-canonical-classesrule. The crash brings down ESLint entirely.Root cause
In
collapseGroup, theotherUtilitiesarray is built by mapping over each candidate's property values:When a utility like
shadow-smgenerates CSS with@propertyrules and custom property declarations but no standard CSS properties,propertyValues.keys()is empty, the loop never executes, andresultstaysnull. The non-null assertionresult!returnsnullinto the array.Downstream code then crashes when iterating or calling
.has()on the null entry:Fix
Return an empty
Setinstead ofnullwhen a utility has no property keys:This is semantically correct: a utility with no standard properties cannot be linked to or collapsed with any other utility, which is exactly what an empty Set represents in the linking algorithm. It won't cause false collapses or suppress valid collapses of other utilities.
Test plan
collapse does not crash when utilities with no standard properties are presentshadow-sm + border,shadow-md + p-4, andshadow-sm + shadow-mddon't throw