From 4cce311f5540bf8c6495c6406ff5ff0260c635ae Mon Sep 17 00:00:00 2001 From: Mason Freed Date: Thu, 4 Apr 2024 03:02:49 -0700 Subject: [PATCH] Add getHTML() and serializable shadow roots Corresponding DOM PR: https://github.com/whatwg/dom/pull/1256. Closes #8867. Co-authored-by: Domenic Denicola --- source | 192 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 37 deletions(-) diff --git a/source b/source index d2f3a21ea4a..4a7c1fcd47d 100644 --- a/source +++ b/source @@ -3156,7 +3156,7 @@ 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, and clonable.
  • +
  • The shadow root concept, and its delegates focus, available to element internals, clonable, and serializable.
  • The shadow host concept
  • HTMLCollection interface, its length attribute, and its @@ -17164,9 +17164,9 @@ people expect to have work and what is necessary.

    For meta elements with an http-equiv attribute in the Encoding declaration state, the content attribute must have a value - that is an ASCII case-insensitive match for a string that consists of: the literal - string "text/html;", optionally followed by any number of ASCII - whitespace, followed by the literal string "charset=utf-8".

    + that is an ASCII case-insensitive match for a string that consists of: + "text/html;", optionally followed by any number of ASCII + whitespace, followed by "charset=utf-8".

    A document must not contain both a meta element with an http-equiv attribute in the shadowrootmode

    shadowrootdelegatesfocus
    shadowrootclonable
    +
    shadowrootserializable
    Accessibility considerations:
    For authors.
    @@ -63491,6 +63492,7 @@ interface HTMLTemplateElement : HTMLElement { [CEReactions] attribute DOMString shadowRootMode; [CEReactions] attribute boolean shadowRootDelegatesFocus; [CEReactions] attribute boolean shadowRootClonable; + [CEReactions] attribute boolean shadowRootSerializable; };
    Uses HTMLTemplateElement.
    @@ -63535,6 +63537,10 @@ interface HTMLTemplateElement : HTMLElement { data-x="attr-template-shadowrootclonable">shadowrootclonable content attribute is a boolean attribute.

    +

    The shadowrootserializable content + attribute is a boolean attribute.

    +

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

    @@ -63680,6 +63686,10 @@ interface HTMLTemplateElement : HTMLElement { attribute must reflect the shadowrootclonable content attribute.

    +

    The shadowRootSerializable + IDL attribute must reflect the shadowrootserializable content attribute.

    +

    The cloning steps for a template @@ -67844,7 +67854,7 @@ try { and the last two digits representing the blue component, the digits being ASCII lower hex digits. Otherwise, the color value has alpha less than 1.0, and the string is the color value in the CSS rgba() - functional-notation format: the literal string "rgba" (U+0072 U+0067 U+0062 + functional-notation format: "rgba" (U+0072 U+0067 U+0062 U+0061) followed by a U+0028 LEFT PARENTHESIS, a base-ten integer in the range 0-255 representing the red component (using ASCII digits in the shortest form possible), a literal U+002C COMMA and U+0020 SPACE, an integer for the green component, a comma and a space, an integer @@ -81302,9 +81312,8 @@ body { display:none } attribute, and therefore might not reflect the actual spellchecking state.

    On setting, if the new value is true, then the element's spellcheck content attribute must be set to the literal string - "true", otherwise it must be set to the literal string "false". + data-x="attr-spellcheck">spellcheck content attribute must be set to + "true", otherwise it must be set to "false".


    @@ -112676,10 +112685,22 @@ document.body.appendChild(frame) - -

    DOM parsing

    +

    DOM parsing and serialization APIs

    + +
    partial interface Element {
    +  [CEReactions] undefined setHTMLUnsafe(HTMLString html);
    +  DOMString getHTML(optional GetHTMLOptions options = {});
    +};
    +
    +partial interface ShadowRoot {
    +  [CEReactions] undefined setHTMLUnsafe(HTMLString html);
    +  DOMString getHTML(optional GetHTMLOptions options = {});
    +};
    +
    +dictionary GetHTMLOptions {
    +  boolean serializableShadowRoots = false;
    +  sequence<ShadowRoot> shadowRoots = [];
    +};

    The DOMParser interface

    @@ -112871,14 +112892,6 @@ enum DOMParserSupportedType {

    These methods perform no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

    -
    partial interface Element {
    -  [CEReactions] undefined setHTMLUnsafe(HTMLString html);
    -};
    -
    -partial interface ShadowRoot {
    -  [CEReactions] undefined setHTMLUnsafe(HTMLString html);
    -};
    -

    Element's ShadowRoot {

    +

    HTML serialization methods

    + +
    +
    html = element.getHTML({ serializableShadowRoots, shadowRoots })
    +
    +

    Returns the result of serializing element to HTML. Shadow roots within element are serialized according to the provided options:

    + +
      +
    • If serializableShadowRoots is true, then all open shadow roots marked as serializable are serialized.

    • + +
    • If the shadowRoots array is provided, then all shadow roots specified in the array are serialized, regardless of whether or not they are marked as serializable.

    • +
    + +

    If neither option is provided, then no shadow roots are serialized.

    +
    + +
    html = shadowRoot.getHTML({ serializableShadowRoots, shadowRoots })
    +
    +

    Returns the result of serializing shadowRoot to HTML, using its shadow host as the context element. Shadow roots within shadowRoot are serialized according to the provided options, as above.

    +
    +
    + +
    + +

    Element's getHTML(options) method steps + are to return the result of HTML fragment serialization algorithm with + this, options["serializableShadowRoots"], + and options["shadowRoots"].

    + +

    ShadowRoot's getHTML(options) method steps + are to return the result of HTML fragment serialization algorithm with + this, options["serializableShadowRoots"], + and options["shadowRoots"].

    + +

    Timers

    @@ -127685,6 +127737,10 @@ document.body.appendChild(text); data-x="attr-template-shadowrootclonable">shadowrootclonable
    attribute; otherwise false.

  • +
  • Let serializable be true if template start tag has a shadowrootserializable attribute; + otherwise false.

  • +
  • Let delegatesFocus be true if template start tag has a shadowrootdelegatesfocus attribute; otherwise false.

  • @@ -127699,9 +127755,10 @@ document.body.appendChild(text);
    1. Attach a shadow root with declarative shadow host element, mode, clonable, - delegatesFocus, and "named". If an exception is thrown, - then catch it, report the exception, insert an element at the adjusted - insertion location with template, and return.

    2. + serializable, delegatesFocus, and "named". + If an exception is thrown, then catch it, report the exception, + insert an element at the adjusted insertion location with + template, and return.

    3. Let shadow be declarative shadow host element's shadow root.

    4. @@ -131462,7 +131519,8 @@ document.body.appendChild(text);

      The following steps form the HTML fragment serialization algorithm. The algorithm takes as input a DOM Element, Document, or DocumentFragment referred to as - the node, and returns a string.

      + the node, a boolean serializableShadowRoots, and a + sequence<ShadowRoot> shadowRoots, and returns a string.

      This algorithm serializes the children of the node being serialized, not the node itself.

      @@ -131476,9 +131534,60 @@ document.body.appendChild(text);
    5. If the node is a template element, then let the node instead be the template element's template contents (a DocumentFragment node).

    6. +
    7. +

      If current node is a shadow host, then:

      + +
        +
      1. Let shadow be current node's + shadow root.

      2. + +
      3. +

        If one of the following is true:

        + +
          +
        • serializableShadowRoots is true, shadow's + serializable is true, and shadow's + mode is "open"; + or

        • + +
        • shadowRoots contains shadow,

        • +
        + +

        then:

        + +
          +
        1. Append "<template shadowrootmode="".

        2. + +
        3. If shadow's mode + is "open", then append "open". + Otherwise, append "closed".

        4. + +
        5. Append """.

        6. + +
        7. If shadow's delegates focus is set, then append + " shadowrootdelegatesfocus=""".

        8. + +
        9. If shadow's serializable is set, then append + " shadowrootserializable=""".

        10. + +
        11. If shadow's clonable is set, then append + " shadowrootclonable=""".

        12. + +
        13. Append ">".

        14. + +
        15. Append the value of running the HTML fragment serialization algorithm with + shadow, serializableShadowRoots, and shadowRoots (thus recursing + into this algorithm for that element).

        16. + +
        17. Append "</template>".

        18. +
        +
      4. +
      +
    8. +
    9. For each child node of the node, in tree order, run the - following steps: + following steps:

      1. Let current node be the child node being processed.

      2. @@ -131571,11 +131680,11 @@ document.body.appendChild(text);

        If current node serializes as void, then continue on to the next child node at this point.

        -

        Append the value of running the HTML fragment serialization algorithm on the - current node element (thus recursing into this algorithm for that - element), followed by a U+003C LESS-THAN SIGN character (<), a U+002F SOLIDUS character - (/), tagname again, and finally a U+003E GREATER-THAN SIGN character - (>).

        +

        Append the value of running the HTML fragment serialization algorithm with + current node, serializableShadowRoots, and shadowRoots (thus + recursing into this algorithm for that node), followed by a U+003C LESS-THAN SIGN character (<), a + U+002F SOLIDUS character (/), tagname again, and finally a U+003E GREATER-THAN SIGN + character (>).

        @@ -131597,7 +131706,7 @@ document.body.appendChild(text);
        If current node is a Comment
        -

        Append the literal string "<!--" (U+003C LESS-THAN SIGN, U+0021 +

        Append "<!--" (U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS, U+002D HYPHEN-MINUS), followed by the value of current node's data, followed by the literal string "-->" (U+002D HYPHEN-MINUS, U+002D HYPHEN-MINUS, @@ -131608,7 +131717,7 @@ document.body.appendChild(text);

        If current node is a ProcessingInstruction
        -

        Append the literal string "<?" (U+003C LESS-THAN SIGN, U+003F +

        Append "<?" (U+003C LESS-THAN SIGN, U+003F QUESTION MARK), followed by the value of current node's target IDL attribute, followed by a single U+0020 SPACE character, followed by the value of current node's data, @@ -131619,13 +131728,13 @@ document.body.appendChild(text);

        If current node is a DocumentType
        -

        Append the literal string "<!DOCTYPE" (U+003C LESS-THAN SIGN, U+0021 +

        Append "<!DOCTYPE" (U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+0044 LATIN CAPITAL LETTER D, U+004F LATIN CAPITAL LETTER O, U+0043 LATIN CAPITAL LETTER C, U+0054 LATIN CAPITAL LETTER T, U+0059 LATIN CAPITAL LETTER Y, U+0050 LATIN CAPITAL LETTER P, U+0045 LATIN CAPITAL LETTER E), followed by a space (U+0020 SPACE), followed by the value of current node's name, followed by the literal string ">" (U+003E GREATER-THAN SIGN).

        + data-x="concept-doctype-name">name, followed by ">" + (U+003E GREATER-THAN SIGN).

        @@ -131646,7 +131755,7 @@ document.body.appendChild(text);

        For instance, if a textarea element to which a Comment node has been appended is serialized and the output is then reparsed, the comment will end up being displayed in the text control. Similarly, if, as a result of DOM manipulation, an element - contains a comment that contains the literal string "-->", then when + contains a comment that contains "-->", then when the result of serializing the element is parsed, the comment will be truncated at that point and the rest of the comment will be interpreted as markup. More examples would be making a script element contain a Text node with the text string "External { script-supporting; colgroup* empty - globals + globals; + shadowrootmode; + shadowrootdelegatesfocus; + shadowrootclonable; + shadowrootserializable HTMLTemplateElement @@ -140597,6 +140710,11 @@ interface External { template Sets clonable on a declarative shadow root Boolean attribute + + shadowrootserializable + template + Sets serializable on a declarative shadow root + Boolean attribute shape area