WICG / webcomponents

Web Components specifications

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Idea: Alternative Ways to Control Registry Scoping

EisenbergEffect opened this issue · comments

Background

Recently, the community has been exploring practical uses of scoped element registries more. A number of situations have arisen that seem to indicate a potential deficiency in the current API surface. Some scenarios include:

  • Setting innerHTML on a detached element, where a specific registry should apply.
  • Integrating with a 3rd party framework (e.g. React) that creates elements without knowledge of the appropriate registry.
  • Existing web components, libraries, and frameworks that don't/can't easily plumb through custom registries into their systems.

The consensus seems to be that none of these scenarios are blockers to the current proposal, but that they do represent key use cases that we should have a reasonable solution for.

Strawman

One potential solution is to provide additional APIs that explicitly control the registry scope in which code runs. For example, we could add something like:

  • document.runWithScope(registry, callback) - Synchronously invokes the callback, ensuring that all element creation and upgrades use the specified registry.
  • document.runWithoutScope(callback) - Synchronously invokes the callback, ensuring that no element created will be upgraded, regardless of whether it is defined in the global registry.

Feedback Request

I'd love to get feedback on the use cases and applicability of an API like this. Let's try to avoid bike shedding on the name and where the API lives (I'm not super happy with that myself actually). I think we can figure that out later if we determine first that we want something like this, how it would work, and whether it's feasible for browser implementors.

For the 3rd party framework case, this seems possibly more powerful than would would strictly be needed since: (1) the main issue is interaction with the global registry not arbitrary ones, and (2) it might be feasible to limit special behavior to disconnected elements.

Here's a strawperson of what conceptually might mostly work:

runWithScope = (registry, callback) => {
  const {document} = window;
  const {content} = document.createElement('template');
  window.document = content.ownerDocument;
  callback();
  window.document = document;
  registry.upgrade(content); 
}

This seemed worth capturing after discussion with @justinfagnani. I believe the idea here would essentially additionally augment the steps to lookup a custom element definition similar to how the scoped registry proposal does so when shadowRoot creation methods are called.

And in the strawperson-ing spirit, this would be something like:

3. Let registry be document's relevant global object's CustomElementRegistry object.

3. Let registry be...
  a. the last registry on the `runWithScope` registry stack
  b. or if that is null, the creating context node's root node's registry
  c. or if that is null, the document's relevant global object's CustomElementRegistry object.