From c6e339d33173d085e7ac0076e94687a65732f8e3 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Tue, 25 Aug 2026 12:08:22 +0800 Subject: [PATCH 1/3] fix(vite): clear a component's styles when it loses its last one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A component that lost its last style kept the old CSS applied until a full reload. The generated HMR module opens with `...ClassName.ɵcmp`, so every key it does not emit keeps its previous value — and `styles` was omitted for every "no styles" answer. `styles` is now three-valued, end to end: non-empty these are the component's styles [] it definitively has none — emit `styles: []` and clear null unknown — omit the key, whatever it has survives Four places collapsed the first two into one value. `index.ts:734` turned an empty result into null before the call; `lib.rs:555` merged `None` and `Some([])` with `unwrap_or_default`; `lib.rs:561`/`:577` mapped an empty list back to `None`; and `update_module.rs:182` guarded the emit a second time. Fixing only the generator changes nothing, because nothing ever handed it a `Some([])`. `null` was also overloaded in the plugin. Clearing on an unreadable decorator would wipe live CSS, so the distinction that matters is whether the answer is KNOWN, not whether it is empty. `readStyles` now reports a failed read instead of swallowing it in a `catch`: a stylesheet read successfully but holding nothing is definitively styleless and clears, while one that could not be read at all stays unknown and is left alone. An editor's atomic write leaves exactly that window. The file-level fallback branch keeps its old semantics and can never clear. Verified against the pinned Angular v22.0.0: `ɵɵreplaceMetadata` → `recreateLView` → `destroyLView` → `sharedStylesHost.removeStyles`, which is ref-counted per CSS string. Today the removed and re-added strings are identical, so the count dips and returns and the `