Commit activity
Last 12 weeks · 79 commits
Community health
4 of 6 standards met
Recent PRs & issues
Summary and are missing from in . The list has every other CSS Values 4 math function, and both places that use it skip these two: No whitespace is added around operators inside them. A delay that grows from the middle item, , generates . The browser can't read as a subtraction, so every item gets (instead of for ). generates , which is dropped as invalid. doesn't see them, so the value is not inferred as a length. generates instead of , while already generates . This adds both names to the list. I found this while reading , not in a project. Both functions are Baseline 2025 (Chrome 138, Firefox 118, Safari 15.4). Test plan Added and cases, alone and nested in , to the math operator table in , and to the existing test in . All five fail on (e.g. , and in the snapshot) and pass with this change. : 45 files, 5405 tests passed. Compiled the classes above on and on this branch, and loaded the CSS in Chrome 156. On the delay is and the is dropped. On this branch the delay is , the width is , and the font size is for . on the changed files, and . Not run: and the integration tests, since I don't have the Rust toolchain set up here. The change is in the TypeScript core only.
Summary Fixes #20470. Scanning with Oxide only inside a Node worker can crash the Windows process with when the worker exits. The captured original build failure executed an address in the unloaded Oxide addon. A standalone reproduction is available at https://github.com/bompus/oxide-worker-unload-repro. During Windows Node-API module registration, retain the containing library with . This prevents worker teardown from unmapping native code while Rayon threads may still use it. A failed pin returns an initialization error. Registration runs after library loading, rather than from a DLL load-time constructor. Non-Windows builds exclude the hook, and no dependency or JavaScript export is added. Tradeoff for maintainer review: the native library intentionally remains mapped until process termination, including in long-lived Node processes. This is a targeted retention fix, not a thread-pool shutdown implementation. The dump proves unloaded-code execution; it does not identify the precise native thread/function responsible. Related thread-pool lifetime discussion: rayon-rs/rayon#1101 and rayon-rs/rayon#1242. Extend the existing worker integration test to scan content, check worker success, and keep the parent alive briefly. On Windows, also assert that the native library is still present in . This assertion detects unloading even when the access violation does not reproduce on that particular run. Test plan Validated locally on Windows 11 Pro build 26200, Node 24.13.1 x64, Rust 1.95.0, with ESET enabled and no parent-retention preload: succeeded for both upstream and this patch. Each DLL was copied to a separate file for comparison. Original isolated worker reproduction, 20 sequential pairs with reversed arm order on alternate pairs: unmodified 18 passes / 2 access violations; patched 20 passes / 0 access violations. Executed the exact and fixture bodies from the changed integration test against those binaries: unmodified failed the library-retention assertion 20/20; patched passed 20/20**, including expected output. These fixture runs were direct Node executions, not the full packaged Vitest integration harness. passed. Prettier 3.9.6 checked the changed TypeScript file with the repository's basic formatting settings; the embedded-template/import plugins were not run. passed the preceding unit suites but failed eight scanner symlink tests (63 scanner tests passed). on an untouched checkout at reproduced the same eight failures. No scanner code is changed here. Full JavaScript/integration suites and non-Windows execution remain unverified locally. Opening as a draft for the retention-policy review and CI validation. [ci-all] Existing scanner failures on both checkouts:
What version of Tailwind CSS are you using? and 4.3.3. What build tool (or framework if it abstracts the build tool) are you using? The reproduction uses only Node's built-in and Oxide. Originally encountered during Expo/Metro Android release builds using UniWind 1.11.0, but those tools are not required to reproduce it. What version of Node.js are you using? v24.13.1, win32 x64. The original build also failed on v24.20.0; the isolated results below are specifically from v24.13.1. What browser are you using? N/A. What operating system are you using? Windows 11 Pro, build 26200, x64. ESET remained enabled during the isolated comparison; no antivirus exclusions or diagnostic preloads were used. Reproduction URL https://github.com/bompus/oxide-worker-unload-repro runs a single baseline trial. first loads the same Oxide package in the main thread. Clear any diagnostic/preload before comparing. Describe your issue A Node worker creates a Scanner and scans 100 in-memory HTML strings, then exits naturally. The parent stays alive for another 500 ms. Expected: the scanner produces , the worker exits successfully, and the parent exits 0. Actual: the process intermittently exits with rather than a JavaScript exception. The fresh minimal project produced these results from 20 sequential pairs, reversing baseline/retention order on alternate pairs: Failing baseline trials were 7 and 19, both with process status (), no stdout, and no stderr. This is intermittent: one passing run does not exclude the bug, and these counts are not a general failure-rate claim. Native evidence from the original build A locally captured dump of the failing Expo update-resource subprocess yielded: The dump came from the original build, not the minimal reproduction. It establishes an attempt to execute unloaded Oxide code. The remaining stack was not reliable enough to identify a specific Rust function or thread owner. No dump is uploaded here. Workaround and possible direction** Requiring UniWind's resolved Oxide dependency in the main thread before worker creation passed ten earlier small trials and three alternating full APK builds; one of those three full-build baseline trials crashed. The newly isolated comparison above independently reproduced the same baseline/workaround distinction. Oxide's scanner uses Rayon's parallel iterators. Native thread lifetime versus library unloading is a plausible mechanism, not yet a symbolically proven identification of the faulting thread. Related discussion: https://github.com/rayon-rs/rayon/issues/1101 and https://github.com/rayon-rs/rayon/issues/1242. A proposed Windows library-retention fix and regression test are in draft PR #20471. Comparing release binaries built from upstream and the patch in another 20 alternating pairs reproduced two baseline access violations and zero patched failures. The regression fixture's explicit library-retention assertion failed 20/20 unmodified runs and passed 20/20 patched runs. The PR documents validation limits, including eight scanner symlink test failures also reproduced on untouched upstream. A process-lifetime pin intentionally keeps the native library mapped until Node exits; it does not implement native thread-pool shutdown.
Recent fixes
Summary The build plugin's caches a compiler for as long as the plugin instance lives, but that compiler holds onto the from the call that first created it, through the callback passed to . Nothing ever released that captured context. In a plain this never shows up because the process exits right after, but if the same plugin instance is reused afterward (Astro's static build runs the SSR/prerender build and then generates every page in the same process) the finished build's context, and the native Rolldown arena behind it, stay alive while the next phase starts allocating on top of it. This clears the cached roots for an environment as soon as its bundle closes, so the reference is dropped before anything else gets a chance to run. Fixes #20501 Test plan Added a test that wraps the build plugin's handler to grab a on the from the first call, runs a Vite 8 (Rolldown) build, forces a few GCs, and checks the context was collected. It fails on the old code and passes with the fix (only reproduces under Rolldown, not Rollup). Ran the full suite locally and it passes.
Repository: tailwindlabs/tailwindcss. Description: A utility-first CSS framework for rapid UI development. Stars: 98604, Forks: 6399. Primary language: TypeScript. Languages: TypeScript (80.4%), Rust (17.4%), JavaScript (0.8%), CSS (0.6%), HTML (0.6%). License: MIT. Homepage: https://tailwindcss.com/ Topics: css, css-framework, functional-css, postcss, responsive, tailwindcss, utility-classes. Latest release: v4.3.5 (1w ago). Open PRs: 83, open issues: 47. Last activity: 3d ago. Community health: 62%. Top contributors: adamwathan, RobinMalfait, depfu[bot], thecrypticace, dependabot-preview[bot], reinink, philipp-spiess, bradlc, dependabot-support, MichaelDeBoey and others.