Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idea: Alternative Ways to Control Registry Scoping #1058

Open
EisenbergEffect opened this issue May 3, 2024 · 3 comments
Open

Idea: Alternative Ways to Control Registry Scoping #1058

EisenbergEffect opened this issue May 3, 2024 · 3 comments

Comments

@EisenbergEffect
Copy link

EisenbergEffect commented May 3, 2024

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.

@sorvell
Copy link

sorvell commented May 3, 2024

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); 
}

@sorvell
Copy link

sorvell commented May 10, 2024

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.

@sorvell
Copy link

sorvell commented Sep 25, 2024

At TPAC2024, a similar suggestion was made to introduce the ability to make the default registry for a document settable. With this capability one could implement this API.

runWithScope = (registry, callback) => {
  const current = customElements.defaultRegistry;
  customElements.defaultRegistry = registry;
  callback();
  customElements.defaultRegistry = current;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants