webcomponents / polyfills

Web Components Polyfills
BSD 3-Clause "New" or "Revised" License
1.13k stars 165 forks source link

[scoped-custom-element-registry] Elements can lose registry when removed from DOM #569

Open sorvell opened 7 months ago

sorvell commented 7 months ago

Description

If a nested element is removed from a shadowRoot using a registry and then innerHTML is called on it with html containing a scoped element, the element will not customize.

Example

Playground example

Expected behavior

Both elements in the example should customize.

Actual behavior

The 2nd scoped element fails to customize.

sorvell commented 7 months ago

Here are 3 possible ways to fix this issue:

  1. When trees of elements are created inside scoped roots (via innerHTML, insertAdjacentHtml, importNode, and maybe cloneNode?), stamp the entire subtree of elements with the creating registry. Currently only the top-most element is stamped.

    Preferred This will be a small perf hit but is robust and simple.

  2. Patch all DOM modification APIs to "pass along" the registry before mutating the DOM. This would involve patching a lot of the API surface area, e.g. all append's, all replaceWith..., all remove/removeChild, all setters textContent, innerHTML, innerText, outerText.

    Issues There's a lot to maintain and get right here and a large amount of code to add.

  3. Use a MutationObserver to detect DOM changes. This seems straightforward, but it would need to observe disconnected nodes as well, and likely would want to un-observe them when re-connection.

    Issues This is also a lot to get just right, validate, and maintain.