From 6ec5ba361774bed3f6c12f2ce2b41d09aeedbc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Wed, 22 Oct 2025 16:33:56 +0200 Subject: [PATCH 1/5] Add declarative out-of-order streaming --- source | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/source b/source index 2d7effe1d68..9d9bfdda75d 100644 --- a/source +++ b/source @@ -67863,6 +67863,7 @@ not-slash = %x0000-002E / %x0030-10FFFF
Nothing (for clarification, see example).
Content attributes:
Global attributes
+
contentmethod
shadowrootmode
shadowrootdelegatesfocus
shadowrootclonable
@@ -67879,6 +67880,7 @@ interface HTMLTemplateElement : HTMLElement { [HTMLConstructor] constructor(); readonly attribute DocumentFragment content; + [CEReactions] attribute DOMString contentMethod; [CEReactions] attribute DOMString shadowRootMode; [CEReactions, Reflect] attribute boolean shadowRootDelegatesFocus; [CEReactions, Reflect] attribute boolean shadowRootClonable; @@ -67894,6 +67896,40 @@ interface HTMLTemplateElement : HTMLElement {

In a rendering, the template element represents nothing.

+

The contentmethod content attribute is an + enumerated attribute with the following keywords and states:

+ + + + + + + + + +
Keyword + State + Brief description +
replace + Replace + Replace the target element itself. +
replace-children + Replace Children + Replace the children of the target element. +
append + Append + Append after the target element. +
prepend + Prepend + Prepend before the target element. +
+ +

The contentmethod attribute's invalid value default and missing value default are both the None state.

+

The shadowrootmode content attribute is an enumerated attribute with the following keywords and states:

@@ -68075,6 +68111,13 @@ interface HTMLTemplateElement : HTMLElement { not a ShadowRoot node; otherwise null.

+
+

The contentMethod IDL attribute must + reflect the contentmethod content + attribute, limited to only known values.

+
+

The shadowRootMode IDL attribute must @@ -139403,6 +139446,10 @@ dictionary StorageEventInit : EventInit { element:

    + +
  1. Let the adjusted insertion location be the appropriate place for inserting a node.

  2. @@ -140196,6 +140243,10 @@ document.body.appendChild(text);

    If any of the following are false:

      +
    • templateStartTag's contentmethod is not in the None state;
    • +
    • templateStartTag's shadowrootmode is not in the None state;
    • @@ -140208,11 +140259,24 @@ document.body.appendChild(text); open elements,
    -

    then insert an HTML element for the token.

    +

    then insert an HTML element for the token and return.

  3. -

    Otherwise:

    +

    If templateStartTag's contentmethod is not in the None state:

    + +
      +
    1. TODO

    2. +
    +
  4. + +
  5. + +

    If templateStartTag's shadowrootmode is not in the None state:

    1. Let declarativeShadowHostElement be adjusted current @@ -152714,6 +152778,19 @@ interface External { Whether the element is editable "true"; "plaintext-only"; "false" + + contentmethod + template + Enables out-of-order streaming + "replace"; + "replace-children"; + "append"; + "prepend" + + contentname + HTML elements + Unique string to target what contentmethod affects + Text* controls audio; From 50a4491e34e2dccbab2883c37c1cddd4d5ca974d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Wed, 22 Oct 2025 16:58:23 +0200 Subject: [PATCH 2/5] Think out loud with TODOs and questions --- source | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/source b/source index 9d9bfdda75d..09d71f031bd 100644 --- a/source +++ b/source @@ -139449,6 +139449,27 @@ dictionary StorageEventInit : EventInit { +

    2. +

      contentmethod handling:

      + +
        +
      1. If element has a contentname attribute and is being inserted into a template + element with a valid contentmethod attribute, find the target element with the same namespace, + localName, and a contentname attribute with the same value.

      2. + +
      3. TODO: is there any whitespace stripping in contentname attribute values?

      4. + +
      5. If the template element is in body, instead search the whole document so + that things in head can be patched.

      6. + +
      7. Return if the target element wasn't found

      8. + +
      9. Depending on the contentmethod state, remove existing nodes and update the insertion point.

      10. + +
      11. Question: do we adjust the insertion point simply by setting adjusted insertion location, + or is there other bookkeeping that's needed here?

      12. +
      +
    3. Let the adjusted insertion location be the appropriate place for inserting a node.

    4. @@ -140268,7 +140289,9 @@ document.body.appendChild(text); data-x="attr-contentmethod-none-state">None state:

        -
      1. TODO

      2. +
      3. TODO: what to we need to do so that elements are inserted into the template element + and redirected by our pre-insertion steps? We need to undo whatever it is that causes nodes + to be inserted into the DocumentFragment normally.

      From 97d3cfd9addf8b72e7f80257d33068c6856fb7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Thu, 23 Oct 2025 17:03:39 +0200 Subject: [PATCH 3/5] Flesh things out more --- source | 111 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/source b/source index 09d71f031bd..dcd80abde4e 100644 --- a/source +++ b/source @@ -13894,6 +13894,7 @@ https://software.hixie.ch/utilities/js/live-dom-viewer/?%3C%21DOCTYPE%20HTML%3E%
    5. autocorrect
    6. autofocus
    7. contenteditable
    8. +
    9. contentname
    10. dir
    11. draggable
    12. enterkeyhint
    13. @@ -67930,6 +67931,17 @@ interface HTMLTemplateElement : HTMLElement { default">missing value default are both the None state.

      +

      The contentname + content points to the target for template contentmethod, like an ID attribute.

      + + +

      Should contentname work on only HTML elements, HTML+SVG+MathML, or any element?

      + +

      If specified, the contentname attribute value must equal + the contentname of another element in the same + tree.

      + +

      The shadowrootmode content attribute is an enumerated attribute with the following keywords and states:

      @@ -139294,6 +139306,13 @@ dictionary StorageEventInit : EventInit { parser.

      +
      If target is a template element whose "contentmethod target" is non-null:
      + +
      +

      Let adjusted insertion location be inside target's "contentmethod target", + after its last child (if any).

      +
      +
      Otherwise
      @@ -139305,8 +139324,31 @@ dictionary StorageEventInit : EventInit {
    14. If the adjusted insertion location is inside a template - element, let it instead be inside the template element's template - contents, after its last child (if any).

      + element:

      + +
        +
      1. If target is a template element whose "contentmethod target" is + non-null, let adjusted insertion location be inside target's + "contentmethod target", after its last child (if any).

      2. + +
      3. Otherwise, let adjusted insertion location be inside the + template element's template contents, after its last child (if + any).

      4. +
      + +

      We shouldn't handle contentmethod in both places above. But which is correct? + If we use the first place, should the above "Otherwise" be able to further update the + adjusted insertion location? The test case for this would be something like:

      + +
      
      +    <template contentname="regular-template">
      +    <template contentmethod="append">
      +     <template contentname="regular-template">
      +      <div class="where-does-this-end-up"></div>
      +     </template>
      +    </template>
      + +

      Also, does "inside" above mean any descendent, or only children?

    15. @@ -139446,40 +139488,54 @@ dictionary StorageEventInit : EventInit { element:

        - +
      1. Let the adjusted insertion location be the appropriate place for + inserting a node.

      2. + +
      3. If it is not possible to insert element at the adjusted insertion + location, abort these steps.

      4. + +
      5. If the parser was not created as part of the HTML fragment parsing + algorithm, then push a new element queue onto element's + relevant agent's custom element reactions stack.

      6. +
      7. -

        contentmethod handling:

        +

        If element's has a contentname attribute + specified and adjusted insertion location is inside a template element whose + contentmethod attribute is not in the None state:

          -
        1. If element has a contentname attribute and is being inserted into a template - element with a valid contentmethod attribute, find the target element with the same namespace, - localName, and a contentname attribute with the same value.

        2. +
        3. Let scope be the template element's parent.

        4. -
        5. TODO: is there any whitespace stripping in contentname attribute values?

        6. +
        7. If scope is a body element, set scope to its + parent.

        8. -
        9. If the template element is in body, instead search the whole document so - that things in head can be patched.

        10. +
        11. Let target be the first element in tree-order within scope with + a contentname attribute exactly matching that of + element.

        12. -
        13. Return if the target element wasn't found

        14. +
        15. If target is null, TODO and return.

        16. -
        17. Depending on the contentmethod state, remove existing nodes and update the insertion point.

        18. +
        19. If target doesn't have the same namespace and localName as element, + TODO and return.

        20. -
        21. Question: do we adjust the insertion point simply by setting adjusted insertion location, - or is there other bookkeeping that's needed here?

        22. -
        -
      8. +
      9. +

        Set the template element's "contentmethod target" to target.

        -
      10. Let the adjusted insertion location be the appropriate place for - inserting a node.

      11. +

        The "contentmethod target" will be used later when nodes are to be inserted + into the child of the template element that has a contentname attribute.

        + -
      12. If it is not possible to insert element at the adjusted insertion - location, abort these steps.

      13. +
      14. +

        Depending on the contentmethod attribute + state, potentially remove target or its children and adjust the + template element's "contentmethod target" and additionally keep track of the + element we should insert before for the "prepend" and "replace" modes.

        -
      15. If the parser was not created as part of the HTML fragment parsing - algorithm, then push a new element queue onto element's - relevant agent's custom element reactions stack.

      16. +

        Should we still insert the element in the following steps? Does it matter?

        + +
      +
    16. Insert element at the adjusted insertion location.

    17. @@ -140290,8 +140346,7 @@ document.body.appendChild(text);
      1. TODO: what to we need to do so that elements are inserted into the template element - and redirected by our pre-insertion steps? We need to undo whatever it is that causes nodes - to be inserted into the DocumentFragment normally.

      2. + and redirected by our pre-insertion steps?

      @@ -152811,7 +152866,7 @@ interface External { "prepend" contentname - HTML elements + HTML elements Unique string to target what contentmethod affects Text* From 8739f8b5c0c21271eebed621f9704a42c9d049dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Mon, 27 Oct 2025 12:11:42 +0100 Subject: [PATCH 4/5] Let shadowrootmode take precedent over contentmethod --- source | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/source b/source index dcd80abde4e..a2990837a18 100644 --- a/source +++ b/source @@ -140322,11 +140322,11 @@ document.body.appendChild(text);
      • templateStartTag's contentmethod is not in the None state;
      • + data-x="attr-contentmethod-none-state">None state; or
      • templateStartTag's shadowrootmode is not in the None state;
      • + data-x="attr-shadowrootmode-none-state">None state; or
      • document's allow declarative shadow @@ -140340,18 +140340,6 @@ document.body.appendChild(text);
      • -

        If templateStartTag's contentmethod is not in the None state:

        - -
          -
        1. TODO: what to we need to do so that elements are inserted into the template element - and redirected by our pre-insertion steps?

        2. -
        -
      • - -
      • -

        If templateStartTag's shadowrootmode is not in the None state:

        @@ -140431,6 +140419,17 @@ document.body.appendChild(text);
  6. + +
  7. +

    Otherwise, if templateStartTag's contentmethod is not in the None state:

    + +
      +
    1. TODO: what to we need to do so that elements are inserted into the template element + and redirected by our pre-insertion steps?

    2. +
    +
From 00872de452efa1451eaeb0e44f736398f79b0204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20J=C3=A4genstedt?= Date: Mon, 27 Oct 2025 16:09:59 +0100 Subject: [PATCH 5/5] Add a note about scope's type --- source | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source b/source index a2990837a18..5b195202a53 100644 --- a/source +++ b/source @@ -139505,7 +139505,12 @@ dictionary StorageEventInit : EventInit { data-x="attr-contentmethod-none-state">None state:

    -
  1. Let scope be the template element's parent.

  2. +
  3. +

    Let scope be the template element's parent.

    + +

    The template element's parent will often be an element, but can + be a DocumentFragment in the fragment case.

    +
  4. If scope is a body element, set scope to its parent.