lwc icon indicating copy to clipboard operation
lwc copied to clipboard

[HMR] `swapStyle()` API does not account for stylesheet collisions

Open nolanlawson opened this issue 4 months ago • 0 comments

In the current implementation of swapStyle, unrendering stylesheets does not work correctly if there is a chance collision of CSS content between two separate .css files.

For example, let's say we have two identical CSS files:

/* a.css */
div { color: red }
/* b.css */
div { color: red }

And a third, different CSS file:

/* c.css */
div { color: blue }

And say we render two components, one with A and the other with B. Now we run:

swapStyle(a, c)

This will correctly replace A with C in the first component. However, it will incorrectly also replace B with C in the second component, since the contents for A and B have happened to collide.

Note this only occurs in cases where it's possible for the exact CSS content to collide in the same target DocumentOrShadowRoot, e.g.:

  • top-level light DOM components with non-scoped style
  • native shadow DOM components with non-scoped style

The reason for this is that style scoping / synthetic shadow scoping defeats the collision by appending generated attributes/classes to the CSS selectors inside the CSS content.

Minimal repro: https://github.com/nolanlawson/lwc-1/commit/43e3d9b39d6cfa68929b8036a45d54b0fd337b6c (passes for scoped light, fails for native shadow and global light)

nolanlawson avatar Apr 16 '24 19:04 nolanlawson