webcomponents / polyfills

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

[scoped-custom-element-registry] proof of concept to fix stand-in element issues #568

Closed sorvell closed 1 month ago

sorvell commented 7 months ago

Description

prototype new polyfill

This is an alternate way to implement the custom elements registry polyfill. Instead of polyfilling CustomElementsRegistry completely and using a stand-in proxy element that delegates to the proper scope, real scopes are created via the CustomElementsRegistry available in an <iframe>, with one <iframe> per registry. This avoids the need to have a stand-in element proxy and the associated issues.

Motivation

Address issues that result from the stand-in element approach, e.g.

Caveats

pascalvos commented 7 months ago

@sorvell small sugestion what about making window.CustomElementRegistry bit more defensive so it doenst overwrite when the polyfill gets loaded more then once. i think this is also a problem with the legacy version if i read the code correctly

sorvell commented 7 months ago

I think this approach is looking viable. The POC version now passes the tests at https://github.com/open-wc/open-wc/blob/master/packages/scoped-elements.

The biggest known issues are:

filimon-danopoulos-stratsys commented 7 months ago

Fix: patch element constructors and squelch the spurious callbacks.

Would this affect all custom elements on a page or only those that opt in to scoped registries? Patching all custom elements is potentially problematic as that can have unintended consequences outside of Lit.

sorvell commented 7 months ago

Only scoped elements to be patched.

And, since this is intended as a polyfill, the goal is to patch in a way that does not rely on any library (e.g. Lit).

vospascal commented 7 months ago

if you would rely it on lit would that make things more easy or the end result be the same ? would the lit version have better optimization benefits if there was such a thing? i ask this cause of the existence of @lit-labs/scoped-registry-mixin package

sorvell commented 6 months ago

Since the spec is still likely in flux and the first implementation is in progress, work has started on making this into a ponyfill. There are some pros and cons to this, captured below:

Ponyfill v. Polyfill

Consideration Polyfill Ponyfill
Affects all elements Yes No
Performance concerns More Less
Requires bespoke API No Yes
Bespoke API for attachShadow No Yes
Bespoke API for innerHTML, etc. No Yes / Optional
Native feature interop Yes No
Removes seamlessly Yes No
Can differ from native feature No Yes
Better with 3rd party code Yes No

Approaches

Overview

Alternatives

Elements can applly manual scoping using only the global registry by ensuring all elements are registered with unique names. This would work as follows:

  1. import custom element classes
  2. create trivial subclasses for each (since a given class can only be defined once)
  3. define each element at a unique name, this would likely need to be version specific, e.g. md-button-1.0.1. This might be fine but to be 100% safe the name would have to be generated in-situ using customElements.get.
  4. adjust all usage to use the unique name.
    • In a library like Lit creating elements with static-html could make this relatively seamless, or even more bespoke support like a 1x template tag replacement could be provided.
    • other than in HTML, referencing elements by tag name in css or DOM API (e.g. querySelector) is best avoided.
sorvell commented 1 month ago

Approach was abandoned due to complexity related mostly to the need to do manual upgrades for late definitions.