Introduce customelementregistry global attribute
Introduce customelementregistry global attribute for elements as discussed in https://github.com/whatwg/dom/issues/1413
- [x] At least two implementers are interested (and none opposed):
- Chromium
- Webkit
- [x] Tests are written and can be reviewed and commented upon at:
- https://github.com/web-platform-tests/wpt/commit/cc1c056521abd0ff97456455dbebe113617a2bc1
- [x] Implementation bugs are filed:
- Chromium: https://issues.chromium.org/issues/399124619
- Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=1874414
- WebKit: https://bugs.webkit.org/show_bug.cgi?id=302970
- [x] Corresponding HTML AAM & ARIA in HTML issues & PRs: N/A
- [x] MDN issue is filed: N/A
- [x] The top of this comment includes a clear commit message to use.
(See WHATWG Working Mode: Changes for more details.)
/custom-elements.html ( diff ) /dom.html ( diff ) /index.html ( diff ) /indices.html ( diff ) /infrastructure.html ( diff ) /parsing.html ( diff )
@annevk Here's the PR for the new custom element registry attribute.
This should probably have serialization steps similar to shouldAppendRegistryAttribute for shadowrootcustomelementregistry as well.
@Jamesernator @annevk I thought about the serialization steps, but when I read through these lines in serializing an element, I thought all attributes are serialized automatically. Am I missing something here?
For each attribute that the element has, append a U+0020 SPACE character, the attribute's serialized name as described below, a U+003D EQUALS SIGN character (=), a U+0022 QUOTATION MARK character ("), the attribute's value, escaped as described below in attribute mode, and a second U+0022 QUOTATION MARK character (").
I thought about the serialization steps, but when I read through these lines in serializing an element, I thought all attributes are serialized automatically. Am I missing something here?
Sure, but calling .createElement('x-foo', { customElementRegistry: nonGlobalRegistry }) doesn't actually set that attribute (besides it could just be removed after as well).
This actually pretty similar to the is attribute in element serialization steps too, in that an element's "is" value is not actually reflected as an attribute. Also like the is attribute we might opt not to emit it if there is already a customelementregistry attribute.
I see what you mean. Then here's an open question on serialization if we expect the attribute to be serialized on element using scoped registry I want to verify here:
<div customelementregistry><foo><bar></bar></foo></div>
const host = document.querySelector('div');
const registry = new CustomElementRegistry();
registry.initialize(host);
In this case, initialize will give foo and bar scoped registry. When we're serializing host, are we expecting to see customelementregistry attribute on foo and bar as well? It feels a bit odd since they didn't have those attribute at the first place.
In this case, initialize will give foo and bar scoped registry.
That depends how foo and bar were created, if they were parsed from the main document then their custom element registry would be the global one anyway so .initialize would be an effective no-op on them.
However if they didn't have a registry then yes I'd expect the change in registry would result in a change in serialization (just like any other DOM change).
I believe the intended behavior of cusomelementregistry attribute is that the element with such attribute and the subtree of the element should all get null registry. The foo and bar in above example should get scoped registry, and it sounds like we do want the attribute serialized for foo and bar.
What if we don’t do the initialize and left foo and bar’s registry null? Should they get the attribute during serialization as well in this case?
I believe the intended behavior of cusomelementregistry attribute is that the element with such attribute and the subtree of the element should all get null registry.
Actually that makes sense, it seems fine to avoid serializing the attribute if the registry is the same as the parent element.
What if we don’t do the initialize and left foo and bar’s registry null? Should they get the attribute during serialization as well in this case?
So I think the serialization is somewhat non-trivial, and we should also carefully consider the possibility of some kind of "declarative custom element registry" in future, with that in mind I think we should go along some lines of:
| ↓parent \ child→ | global registry | custom registry 1 | custom registry 2 | null |
| global registry | no attribute | attribute | attribute | |
| custom registry 1 | ??? | no attribute | !!!attribute | !!!attribute |
| null | ??? | !!!attribute | !!!no attribute | |
Ideally we should have some story for global registry as a child of a scoped registry (??? in the table), as both it's not clear how to serialize it, and people transitioning to scoped registries will likely come across places where they need to opt-out.
As a bikeshed perhaps just:
<div customelementregistry="">
<x-foo></x-foo>
<div customelementregisty="global">
<x-foo></x-foo>
</div>
</div>
Now in the chart I've put !!! in front of entries that, while all could be omitted, may have impacts on a possible future declarative custom element registries. e.g. If in future we have something like:
<customelementregistry specifier="named">
<define>....</define>
</customelementregistry>
<div customelementregistry="named">
<div customelementregistry=""></div>
</div>
then those entries with !!! may need special consideration for how it would interact with such a possible feature.