diff --git a/source b/source index 5caba469479..4c6c60b2ff9 100644 --- a/source +++ b/source @@ -3181,7 +3181,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • node document concept
  • document type concept
  • host concept
  • -
  • The shadow root concept, and its delegates focus, available to element internals, clonable, and serializable.
  • +
  • The shadow root concept, and its delegates focus, available to element internals, clonable, serializable, custom element registry, and keep custom element registry null.
  • +
  • The shadow host concept
  • HTMLCollection interface, its length attribute, and its @@ -3297,8 +3298,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute no-quirks mode
  • The algorithm clone a node with its arguments document, - subtree, and - parent, and the concept of + subtree, + parent, and + fallbackRegistry, and the concept of cloning steps
  • The concept of base URL change steps and the definition of what happens when an element is affected by a base URL change
  • The concept of an element's unique identifier (ID)
  • @@ -3319,6 +3321,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • An element's namespace, namespace prefix, local name, + custom element registry, + custom element definition, and is value
  • @@ -12034,9 +12038,6 @@ console.assert(el.constructor === Element); overridden constructor steps:

      -
    1. Let registry be current global object's custom element registry.

    2. -
    3. If NewTarget is equal to the active function object, then throw a TypeError.

      @@ -12057,6 +12058,24 @@ document.createElement("bad-1"); // (2)
    4. +
    5. Let registry be null.

    6. + +
    7. +

      If the surrounding agent's active custom element constructor + map[NewTarget] exists:

      + +
        +
      1. Set registry to the surrounding agent's active custom + element constructor map[NewTarget].

      2. + +
      3. Remove the surrounding agent's + active custom element constructor map[NewTarget].

      4. +
      + +
    8. If registry is null, then set registry to current global + object's custom element + registry.

    9. +
    10. Let definition be the item in registry's custom element definition set with shadowrootdelegatesfocus

      shadowrootclonable
      shadowrootserializable
      +
      shadowrootcustomelementregistry
      Accessibility considerations:
      For authors.
      @@ -64669,6 +64689,7 @@ interface HTMLTemplateElement : HTMLElement { [CEReactions] attribute boolean shadowRootDelegatesFocus; [CEReactions] attribute boolean shadowRootClonable; [CEReactions] attribute boolean shadowRootSerializable; + [CEReactions] attribute DOMString shadowRootCustomElementRegistry; };
      Uses HTMLTemplateElement.
      @@ -64717,6 +64738,10 @@ interface HTMLTemplateElement : HTMLElement { data-x="attr-template-shadowrootserializable">shadowrootserializable content attribute is a boolean attribute.

      +

      The shadowrootcustomelementregistry + content attribute is a boolean attribute.

      +

      The template contents of a template element are not children of the element itself.

      @@ -64869,6 +64894,15 @@ interface HTMLTemplateElement : HTMLElement { must reflect the shadowrootserializable content attribute.

      +

      The shadowRootCustomElementRegistry + IDL attribute must reflect the shadowrootcustomelementregistry + content attribute.

      + +

      The IDL attribute does intentionally not have a boolean type so it can be + extended.

      +

      The cloning steps for template @@ -73336,8 +73370,8 @@ document.body.append(parent);

      -

      A custom element definition describes a custom element and consists - of:

      +

      A custom element definition describes a custom element and + consists of:

      A Controls attachShadow().
      -

      To look up a custom element definition, given a document, - namespace, localName, and is, perform the following steps. They - will return either a custom element definition or null:

      +

      To look up a custom element definition, given null or a + CustomElementRegistry object registry, string-or-null + namespace, string localName, and string-or-null is, perform the + following steps. They will return either a custom element definition or null:

        -
      1. If namespace is not the HTML namespace, then return null.

      2. - -
      3. If document's browsing context is - null, then return null.

      4. +
      5. If registry is null, then return null.

      6. -
      7. Let registry be document's relevant global object's - custom element registry.

      8. +
      9. If namespace is not the HTML namespace, then return null.

      10. If registry's custom element definition set contains an item with +

        Each similar-origin window agent has an associated active custom element constructor map, which is a map of constructors to CustomElementRegistry objects.

        +

        The customElements attribute of the Window interface must return the CustomElementRegistry object for that @@ -73442,11 +73477,14 @@ document.body.append(parent);

        [Exposed=Window]
         interface CustomElementRegistry {
        -  [CEReactions] undefined define(DOMString name, CustomElementConstructor constructor, optional ElementDefinitionOptions options = {});
        -  (CustomElementConstructor or undefined) get(DOMString name);
        -  DOMString? getName(CustomElementConstructor constructor);
        -  Promise<CustomElementConstructor> whenDefined(DOMString name);
        -  [CEReactions] undefined upgrade(Node root);
        +  constructor();
        +
        +  [CEReactions] undefined define(DOMString name, CustomElementConstructor constructor, optional ElementDefinitionOptions options = {});
        +  (CustomElementConstructor or undefined) get(DOMString name);
        +  DOMString? getName(CustomElementConstructor constructor);
        +  Promise<CustomElementConstructor> whenDefined(DOMString name);
        +  [CEReactions] undefined upgrade(Node root);
        +  undefined initialize((Element or ShadowRoot) root);
         };
         
         callback CustomElementConstructor = HTMLElement ();
        @@ -73455,6 +73493,12 @@ dictionary ElementDefinitionOptions {
           DOMString extends;
         };
        +

        Every CustomElementRegistry has an is + scoped, a boolean, initially false.

        + +

        Every CustomElementRegistry has a scoped + document set, a set of Document objects, initially « ».

        +

        Every CustomElementRegistry has a custom element definition set, a set of custom element definitions, initially « ». Lookup of items in this set uses their ElementDefinitionOptions { element names to promises. It is used to implement the whenDefined() method.

        +

        To look up a custom element registry, given an Element object, + ShadowRoot object, or Document object node: + +

          +
        1. If node is an Element object, then return + parentNode's custom element + registry. + +

        2. If node is a ShadowRoot object, then return node's + custom element registry. + +

        3. If node's browsing context is null, + then return null.

        4. + +
        5. Return node's relevant global object's custom element registry.

        6. +
        +
      -
      window.customElements.define(name, - constructor)
      +
      registry = window.customElements
      +
      Returns the global CustomElementRegistry object.
      + +
      registry = new CustomElementRegistry()
      +
      Constructs a new CustomElementRegistry object, for scoped usage.
      +
      registry.define(name, + constructor)
      Defines a new custom element, mapping the given name to the given constructor as an autonomous custom element.
      - -
      window.customElements.define(name, constructor, +
      registry.define(name, constructor, { extends: baseLocalName })
      -
      Defines a new custom element, mapping the given name to the given constructor as a customized built-in element for the element type identified by the supplied baseLocalName. A "NotSupportedError" DOMException will be thrown upon trying to extend a custom element or - an unknown element.
      - -
      window.customElements.get(name)
      + an unknown element, or when registry is not a global + CustomElementRegistry object. +
      registry.get(name)
      Retrieves the custom element constructor defined for the given name. Returns undefined if there is no custom element definition with the given name.
      -
      window.customElements.getName(constructor)
      - +
      registry.getName(constructor)
      Retrieves the given name for a custom element defined for the given constructor. Returns null if there is no custom element definition with the given constructor.
      -
      window.customElements.whenDefined(name)
      - +
      registry.whenDefined(name)
      Returns a promise that will be fulfilled with the custom element's constructor when a custom element becomes defined with the given name. (If such a custom element is already defined, the returned promise will be immediately fulfilled.) Returns a promise rejected with a "SyntaxError" DOMException if not given a valid custom element name.
      -
      window.customElements.upgrade(root)
      - +
      registry.upgrade(root)
      Tries to upgrade all shadow-including inclusive descendant elements of root, even if they are not connected.
      + +
      registry.initialize(root)
      +
      Each inclusive descendant of root with a null registry will have it + updated to this CustomElementRegistry object.
      +

      The new CustomElementRegistry() constructor + steps are to set this's is scoped to true.

      +

      Element definition is a process of adding a custom element definition to the CustomElementRegistry. This is accomplished by the define() method. The ElementDefinitionOptions {

      If extends is not null:

        +
      1. If this is not this's relevant global object's + custom element registry, then throw a + "NotSupportedError" DOMException.

      2. +
      3. If extends is a valid custom element name, then throw a "NotSupportedError" DOMException.

      4. @@ -73689,22 +73763,14 @@ dictionary ElementDefinitionOptions {
      5. Append definition to this's custom element definition set.

      6. -
      7. Let document be this's relevant global object's associated Document.

      8. - -
      9. Let upgradeCandidates be all elements that are shadow-including descendants of document, whose namespace - is the HTML namespace and whose local name is localName, in - shadow-including tree order. Additionally, if extends is non-null, only - include elements whose is - value is equal to name.

      10. - -
      11. For each element element of upgradeCandidates, enqueue a - custom element upgrade reaction given element and - definition.

      12. +
      13. If this's is scoped is true, then for each document + of this's scoped document set: upgrade particular elements within + a document given document and localName. - +

      14. Otherwise, upgrade particular elements within a document given + this's relevant global object's associated Document, localName, + and name.

      15. If this's when-defined promise map[name] shadow-including descendants of document, whose namespace + is the HTML namespace and whose local name is localName, in + shadow-including tree order. Additionally, if name is not + localName, only include elements whose is value is equal to name.

      16. + +
      17. For each element element of upgradeCandidates: enqueue a + custom element upgrade reaction given element and + definition.

      18. +
      + +

      The get(name) method steps are:

      @@ -73799,9 +73884,9 @@ fetch(articleURL)
      -

      When invoked, the upgrade(root) method must run - these steps:

      +

      The upgrade(root) method steps + are:

      1. Let candidates be a list of all of root's @@ -73833,6 +73918,34 @@ console.assert(el instanceof SpiderMan); // upgraded!

        +

        The initialize(root) method + steps are:

        + +
          +
        1. If root is a ShadowRoot node whose custom element registry is null, then set + root's custom element + registry to this.

        2. + +
        3. +

          For each inclusive descendant inclusiveDescendant of root: + if inclusiveDescendant is an Element node whose custom element registry is null:

          + +
            +
          1. Set inclusiveDescendant's custom element registry to + this.

          2. + +
          3. If this's is scoped is true, then append inclusiveDescendant's node document to + this's scoped document set.

          4. +
          +
        4. +
        + +

        Upgrades

        To upgrade an element, given as input a @@ -73904,8 +74017,14 @@ customElements.define("x-foo", class extends HTMLElement {

      2. Let C be definition's constructor.

      3. +
      4. Let registry be element's custom element registry.

      5. + +
      6. Set the surrounding agent's active custom + element constructor map[C] to registry.

      7. +
      8. -

        Run the following substeps while catching any exceptions:

        +

        Run the following steps while catching any exceptions:

        1. @@ -73947,10 +74066,18 @@ customElements.define("x-foo", class extends HTMLElement {
        -

        Then, perform the following substep, regardless of whether the above steps threw an exception +

        Then, perform the following steps, regardless of whether the above steps threw an exception or not:

          +
        1. +

          Remove registry's relevant global + object's active custom element constructor map[C].

          + +

          This is a no-op if C immediately calls super() as it ought to do.

          +
        2. +
        3. Remove the last entry from the end of definition's construction stack.

          @@ -74006,15 +74133,16 @@ customElements.define("x-foo", class extends HTMLElement { element state to "custom".

        -

        To try to upgrade an element, given as input an - element element, run the following steps:

        +

        To try to upgrade an element given an element + element:

        1. Let definition be the result of looking up a custom element definition given element's node - document, element's namespace, element's local name, and - element's is - value.

        2. + definition">looking up a custom element definition given element's custom element registry, element's + namespace, element's local name, and element's is value.

        3. If definition is not null, then enqueue a custom element upgrade reaction given element and definition.

        4. @@ -74368,9 +74496,10 @@ customElements.define("x-foo", class extends HTMLElement { DOMException.

        5. Let definition be the result of looking up a custom element definition given this's node - document, its namespace, its local name, and null as the is value.

        6. + definition">looking up a custom element definition given this's custom element registry, this's + namespace, this's local name, and null.

        7. If definition is null, then throw an "NotSupportedError" DOMException.

        8. @@ -130375,8 +130504,11 @@ dictionary StorageEventInit : EventInit {
        9. Let is be the value of the "is" attribute in the given token, if such an attribute exists, or null otherwise.

        10. +
        11. Let registry be the result of looking up a custom element registry given intended parent.

        12. +
        13. Let definition be the result of looking up a custom element definition given document, given + definition">looking up a custom element definition given registry, given namespace, local name, and is.

        14. Let willExecuteScript be true if definition is non-null and the @@ -130401,7 +130533,7 @@ dictionary StorageEventInit : EventInit {

        15. Let element be the result of creating an element given document, localName, given namespace, - null, is, and willExecuteScript.

          + null, is, willExecuteScript, and registry.

          This will cause custom element constructors to run, if willExecuteScript is true. However, since we @@ -131281,7 +131413,8 @@ document.body.appendChild(text);

        16. Attach a shadow root with declarative shadow host element, mode, clonable, - serializable, delegatesFocus, and "named".

          + serializable, delegatesFocus, "named", and + registry.

          If an exception is thrown, then catch it and:

          @@ -131305,6 +131438,11 @@ document.body.appendChild(text); shadow.

        17. Set shadow's available to element internals to true.

        18. + +
        19. If template start tag has a shadowrootcustomelementregistry + attribute, then set shadow's keep custom element registry null to + true.

      @@ -135109,6 +135247,11 @@ document.body.appendChild(text);
    11. If shadow's clonable is set, then append " shadowrootclonable=""".

    12. +
    13. If current node's custom + element registry is not shadow's custom element registry, then append + " shadowrootcustomelementregistry=""".

    14. +
    15. Append ">".

    16. Append the value of running the HTML fragment serialization algorithm with @@ -135522,8 +135665,9 @@ console.assert(container.firstChild instanceof SuperP);

    17. Let root be the result of creating an - element given document, "html", and the HTML - namespace.

    18. + element given document, "html", the HTML + namespace, null, null, false, and context's custom element registry.

    19. Append root to document.

    20. @@ -142779,7 +142923,8 @@ interface External { shadowrootmode; shadowrootdelegatesfocus; shadowrootclonable; - shadowrootserializable + shadowrootserializable; + shadowrootcustomelementregistry HTMLTemplateElement @@ -144263,6 +144408,11 @@ interface External { template Sets clonable on a declarative shadow root Boolean attribute + + shadowrootcustomelementregistry + template + Enables declarative shadow roots to indicate they will use a custom element registry + Boolean attribute shadowrootdelegatesfocus template