From ef055d790b5728de5c796ef75d846bd01065e12e Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Tue, 17 Dec 2024 18:32:24 +0100 Subject: [PATCH 1/5] Add Scoped Custom Element Registries DOM PR: https://github.com/whatwg/dom/pull/1341. Tests: ... Closes #10854. --- source | 331 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 261 insertions(+), 70 deletions(-) diff --git a/source b/source index 5caba469479..67700c429d7 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
      +
      shadowrootcustomelements
      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 shadowRootCustomElements; };
      Uses HTMLTemplateElement.
      @@ -64717,6 +64738,10 @@ interface HTMLTemplateElement : HTMLElement { data-x="attr-template-shadowrootserializable">shadowrootserializable content attribute is a boolean attribute.

      +

      The shadowrootcustomelements + 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 shadowRootCustomElements IDL attribute + must reflect the shadowrootcustomelements 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,17 @@ 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);
        +
        +  [CEReactions, NewObject] HTMLElement createElement(DOMString name);
        +  [CEReactions, NewObject] Node cloneSubtree(Node root);
        +  undefined initializeSubtree((Element or ShadowRoot) root);
         };
         
         callback CustomElementConstructor = HTMLElement ();
        @@ -73455,6 +73496,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 parentNode: + +

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

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

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

        4. + +
        5. Return parentNode'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.createElement(name)
      +
      +

      Returns an HTML element with name as its local + name and registry as its registry.

      + +

      If name does not match the Name production an + "InvalidCharacterError" DOMException will be thrown.

      +
      + +
      registry.cloneSubtree(root)
      +
      Returns a copy of root, changing the registry from root's inclusive + descendants from null (if any) to registry in the process.
      + +
      registry.initializeSubtree(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 +73780,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 +73901,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 +73935,59 @@ console.assert(el instanceof SpiderMan); // upgraded!

        +

        The createElement(name) + method steps are:

        + +
          +
        1. If name does not match the XML Name production, + then throw an "InvalidCharacterError" + DOMException.

        2. + +
        3. Return the result of creating an element given + this's relevant global object's associated Document, name, the + HTML namespace, null, null, true, and this.

        4. +
        + +

        The cloneSubtree(root) + method steps are:

        + +
          +
        1. If root is a Document or ShadowRoot object, then + throw a "NotSupportedError" DOMException.

        2. + +
        3. Return the result of cloning a node given + root with subtree set to true + and fallbackRegistry set + this.

        4. +
        + +

        The initializeSubtree(root) + method steps are:

        + +
          +
        1. +

          For each inclusive descendant inclusiveDescendant of + root:

          + +
            +
          1. If inclusiveDescendant is an Element node whose custom element registry is null, then set + inclusiveDescendant's custom element + registry to this.

          2. + +
          3. Otherwise, if inclusiveDescendant is a ShadowRoot node whose + custom element registry is null, set + inclusiveDescendant's custom + element registry to this.

          4. +
          +
        2. +
        + +

        Upgrades

        To upgrade an element, given as input a @@ -73904,8 +74059,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 +74108,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 +74175,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 +74538,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 +130546,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 @@ -131281,7 +131455,8 @@ document.body.appendChild(text);

        15. 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 +131480,10 @@ document.body.appendChild(text); shadow.

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

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

      @@ -135109,6 +135288,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 + " shadowrootcustomelements=""".

    14. +
    15. Append ">".

    16. Append the value of running the HTML fragment serialization algorithm with @@ -135522,8 +135706,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 +142964,8 @@ interface External { shadowrootmode; shadowrootdelegatesfocus; shadowrootclonable; - shadowrootserializable + shadowrootserializable; + shadowrootcustomelements HTMLTemplateElement @@ -144263,6 +144449,11 @@ interface External { template Sets clonable on a declarative shadow root Boolean attribute + + shadowrootcustomelements + template + Enables declarative shadow roots to indicate they will use a custom element registry + Boolean attribute shadowrootdelegatesfocus template From 0c9a957da416d50bffca3ae87c347f14d5e69135 Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Fri, 21 Feb 2025 10:41:57 +0100 Subject: [PATCH 2/5] Remove createElement and cloneSubtree, rename initializeSubtree to initialize Also refactor initialize and pass registry to create an element. --- source | 79 +++++++++++----------------------------------------------- 1 file changed, 14 insertions(+), 65 deletions(-) diff --git a/source b/source index 67700c429d7..5ddaab6d583 100644 --- a/source +++ b/source @@ -73484,10 +73484,7 @@ interface CustomElementRegistry { DOMString? getName(CustomElementConstructor constructor); Promise<CustomElementConstructor> whenDefined(DOMString name); [CEReactions] undefined upgrade(Node root); - - [CEReactions, NewObject] HTMLElement createElement(DOMString name); - [CEReactions, NewObject] Node cloneSubtree(Node root); - undefined initializeSubtree((Element or ShadowRoot) root); + undefined initialize((Element or ShadowRoot) root); }; callback CustomElementConstructor = HTMLElement (); @@ -73580,20 +73577,7 @@ dictionary ElementDefinitionOptions { inclusive descendant elements of root, even if they are not connected. -
      registry.createElement(name)
      -
      -

      Returns an HTML element with name as its local - name and registry as its registry.

      - -

      If name does not match the Name production an - "InvalidCharacterError" DOMException will be thrown.

      -
      - -
      registry.cloneSubtree(root)
      -
      Returns a copy of root, changing the registry from root's inclusive - descendants from null (if any) to registry in the process.
      - -
      registry.initializeSubtree(root)
      +
      registry.initialize(root)
      Each inclusive descendant of root with a null registry will have it updated to this CustomElementRegistry object.
      @@ -73936,55 +73920,20 @@ console.assert(el instanceof SpiderMan); // upgraded!

      The createElement(name) - method steps are:

      - -
        -
      1. If name does not match the XML Name production, - then throw an "InvalidCharacterError" - DOMException.

      2. - -
      3. Return the result of creating an element given - this's relevant global object's associated Document, name, the - HTML namespace, null, null, true, and this.

      4. -
      - -

      The cloneSubtree(root) - method steps are:

      - -
        -
      1. If root is a Document or ShadowRoot object, then - throw a "NotSupportedError" DOMException.

      2. - -
      3. Return the result of cloning a node given - root with subtree set to true - and fallbackRegistry set - this.

      4. -
      - -

      The initializeSubtree(root) - method steps are:

      + data-x="dom-CustomElementRegistry-initialize">initialize(root) method + steps are:

        -
      1. -

        For each inclusive descendant inclusiveDescendant of - root:

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

      3. -
          -
        1. If inclusiveDescendant is an Element node whose custom element registry is null, then set - inclusiveDescendant's custom element - registry to this.

        2. - -
        3. Otherwise, if inclusiveDescendant is a ShadowRoot node whose - custom element registry is null, set - inclusiveDescendant's custom - element registry to this.

        4. -
        - +
      4. For each inclusive descendant inclusiveDescendant of + root: if inclusiveDescendant is an Element node whose custom element registry is null, then set + inclusiveDescendant's custom element + registry to this.

      @@ -130575,7 +130524,7 @@ dictionary StorageEventInit : EventInit {
    21. 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 From d1461d70c94e6d1386fae18c6510b64ba1dfd68d Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Fri, 21 Feb 2025 15:39:28 +0100 Subject: [PATCH 3/5] Make sure initialize() updates the scoped document set --- source | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/source b/source index 5ddaab6d583..a9f4e1f0a7d 100644 --- a/source +++ b/source @@ -73929,11 +73929,21 @@ console.assert(el instanceof SpiderMan); // upgraded! root's custom element registry to this.

    22. -
    23. For each inclusive descendant inclusiveDescendant of - root: if inclusiveDescendant is an Element node whose custom element registry is null, then set - inclusiveDescendant's custom element - registry to this.

    24. +
    25. +

      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. +
      +
    From 98b171ebe7b477be4a58b4bd2afc53bf3fd8208b Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Thu, 6 Mar 2025 12:36:05 +0100 Subject: [PATCH 4/5] Polyfill rename --- source | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/source b/source index a9f4e1f0a7d..503bec335ec 100644 --- a/source +++ b/source @@ -64673,7 +64673,7 @@ not-slash = %x0000-002E / %x0030-10FFFF
    shadowrootdelegatesfocus
    shadowrootclonable
    shadowrootserializable
    -
    shadowrootcustomelements
    +
    shadowrootcustomelementregistry
    Accessibility considerations:
    For authors.
    @@ -64689,7 +64689,7 @@ interface HTMLTemplateElement : HTMLElement { [CEReactions] attribute boolean shadowRootDelegatesFocus; [CEReactions] attribute boolean shadowRootClonable; [CEReactions] attribute boolean shadowRootSerializable; - [CEReactions] attribute DOMString shadowRootCustomElements; + [CEReactions] attribute DOMString shadowRootCustomElementRegistry; };
    Uses HTMLTemplateElement.
    @@ -64739,7 +64739,7 @@ interface HTMLTemplateElement : HTMLElement { attribute is a boolean attribute.

    The shadowrootcustomelements + data-x="attr-template-shadowrootcustomelementregistry">shadowrootcustomelementregistry content attribute is a boolean attribute.

    The template contents of a template element HTMLTemplateElement : HTMLElement { data-x="attr-template-shadowrootserializable">shadowrootserializable content attribute.

    The shadowRootCustomElements IDL attribute - must reflect the shadowrootcustomelements content - attribute.

    + data-x="dom-template-shadowRootCustomElementRegistry">shadowRootCustomElementRegistry + IDL attribute must reflect the shadowrootcustomelementregistry + content attribute.

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

    @@ -131441,8 +131441,9 @@ document.body.appendChild(text);
  • Set shadow's available to element internals to true.

  • If template start tag has a shadowrootcustomelements attribute, - then set shadow's keep custom element registry null to true.

  • + data-x="attr-template-shadowrootcustomelementregistry">shadowrootcustomelementregistry + attribute, then set shadow's keep custom element registry null to + true.

    @@ -135250,7 +135251,7 @@ document.body.appendChild(text);
  • If current node's custom element registry is not shadow's custom element registry, then append - " shadowrootcustomelements=""".

  • + " shadowrootcustomelementregistry=""".

  • Append ">".

  • @@ -142924,7 +142925,7 @@ interface External { shadowrootdelegatesfocus; shadowrootclonable; shadowrootserializable; - shadowrootcustomelements + shadowrootcustomelementregistry HTMLTemplateElement @@ -144409,8 +144410,8 @@ interface External { Sets clonable on a declarative shadow root Boolean attribute - shadowrootcustomelements - template + shadowrootcustomelementregistry + template Enables declarative shadow roots to indicate they will use a custom element registry Boolean attribute From 8ef7c76028dbdd375ee78d3a5f7e51f3072dc35a Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Thu, 6 Mar 2025 12:58:11 +0100 Subject: [PATCH 5/5] Rename argument to look up a custom element registry --- source | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/source b/source index 503bec335ec..4c6c60b2ff9 100644 --- a/source +++ b/source @@ -73516,21 +73516,20 @@ dictionary ElementDefinitionOptions { data-x="dom-CustomElementRegistry-whenDefined">whenDefined() method.

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

      -
    1. If parentNode is an Element object, then return +

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

    3. If parentNode is a ShadowRoot object, then return - parentNode's custom element - registry. +

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

    5. If parentNode's browsing context is - null, then return null.

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

    8. -
    9. Return parentNode's relevant global object's

      Return node's relevant global object's custom element registry.