Skip to content

Self-closing tag on void elements shouldn't be a parse error/warning in \Dom\HTMLDocument #17485

Closed

Description

@xPaw

Description

The following code:

<?php
$Data = "<!DOCTYPE HTML>\n<br />\n<input />";
$Document = \Dom\HTMLDocument::createFromString( $Data );
echo $Document->saveHTML();

Resulted in this output:

Warning: Dom\HTMLDocument::createFromString(): tree error non-void-html-element-start-tag-with-trailing-solidus in Entity, line: 2, column: 2-3 in test.php on line 3
Warning: Dom\HTMLDocument::createFromString(): tree error non-void-html-element-start-tag-with-trailing-solidus in Entity, line: 3, column: 2-6 in test.php on line 3

I believe the html standard specifically allows this on void elements: ref

Then, if the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/), which on foreign elements marks the start tag as self-closing. On void elements, it does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.

it doesn't warn for tags like <div /> and simply opens it as normal.

relevant code:

bool is_void = lxb_html_tag_is_void(token->tag_id);
if (is_void) {
lxb_html_tree_parse_error(tree, token,
LXB_HTML_RULES_ERROR_NOVOHTELSTTAWITRSO);
}

PHP Version

8.4.3

Operating System

No response

Activity

  1. xPaw commented on Jan 16, 2025

    @xPaw
    ContributorAuthor

    @lexborisov should I have opened this in your repo?

  2. lexborisov commented on Jan 16, 2025

    @lexborisov
    Contributor

    @xPaw

    It looks like it to me.

    This is where you have to look at the tree construction specification. It is written there:

    https://html.spec.whatwg.org/multipage/parsing.html#acknowledge-self-closing-flag

    When a start tag token is emitted with its self-closing flag set, if the flag is not acknowledged when it is processed by the tree construction stage, that is a non-void-html-element-start-tag-with-trailing-solidus parse error.
    
  3. xPaw commented on Jan 16, 2025

    @xPaw
    ContributorAuthor

    Hmm, that seems confusing to me as to what's the correct implementation for a parser. Browsers obviously accept this.

    Edit: actually that appears to be correct, since void elements should be acceptable with the slash? Even the error string implies non-void.

  4. lexborisov commented on Jan 16, 2025

    @lexborisov
    Contributor

    @xPaw

    Hmm, that seems confusing to me as to what's the correct implementation for a parser. Browsers obviously accept this.

    Edit: actually that appears to be correct, since void elements should be acceptable with the slash?

    After reading the spec sheet again,
    The problem seems to be solved by changing the condition in the code, to negation.
    https://github.com/lexbor/lexbor/blob/58c88147db7342aefbc45d5e5621a974c210106a/source/lexbor/html/tree.h#L333

    if (!is_void) {
  5. xPaw commented on Jan 16, 2025

    @xPaw
    ContributorAuthor

    This is how I read it too, but assumed it was too simple of a fix.

  6. ndossche commented on Jan 16, 2025

    @ndossche
    Member

    I also think the check should probably be negated.

  7. lexborisov commented on Jan 16, 2025

    @lexborisov
    Contributor

    @xPaw @nielsdos

    Yeah, it all adds up. I had doubts, because in the code the <param> tag used to be void, but then it was excluded and I didn't notice it, unfortunately.

    I'll get the patch ready.

  8. lexborisov commented on Jan 16, 2025

    @lexborisov
    Contributor
  9. ndossche commented on Jan 16, 2025

    @ndossche
    Member

    @lexborisov Thanks a lot! I'm not sure this is entirely correctly fixed however. After cherry-picking your commits into PHP I get a new warning for this line in this test:

    It's a foreign element (in SVG) and I believe it shouldn't warn here based on the spec comments.

  10. xPaw commented on Jan 16, 2025

    @xPaw
    ContributorAuthor

    Just to add about svgs (before the fix at least), I've noticed that <path /> would turn into <path></path> when calling saveHtml.

  11. ndossche commented on Jan 16, 2025

    @ndossche
    Member

    @xPaw that is at least consistent with my browser. Try this JS:

    html = `<!DOCTYPE html>
    <html>
    <body>
        <svg width="100" height="100">
            <path />
        </svg>
    </body>
    </html>`;
    dom = (new DOMParser).parseFromString(html, 'text/html');
    dom.body.innerHTML
  12. lexborisov commented on Jan 16, 2025

    @lexborisov
    Contributor

    @nielsdos

    @lexborisov Thanks a lot! I'm not sure this is entirely correctly fixed however. After cherry-picking your commits into PHP I get a new warning for this line in this test:

    php-src/ext/dom/tests/modern/html/interactions/HTMLDocument_getElementsByTagName.phpt

    Line 18 in a4fa1e7

         <circle cx="0" cy="0" r="10"/> 
    

    It's a foreign element (in SVG) and I believe it shouldn't warn here based on the spec comments.

    I figured it out, void elements are only checked in the HTML namespace, in other cases it's always false.
    But I didn't find any direct text about it. It just comes out of the references in the specification.

    https://html.spec.whatwg.org/multipage/syntax.html#elements-2
    https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign "Any other start tag"

  13. 2 remaining items

  14. xPaw commented on Jan 16, 2025

    @xPaw
    ContributorAuthor

    Seems like acknowledge disables the error:

    When a start tag token is emitted with its self-closing flag set, if the flag is not acknowledged when it is processed by the tree construction stage, that is a non-void-html-element-start-tag-with-trailing-solidus parse error.

  15. lexborisov commented on Jan 16, 2025

    @lexborisov
    Contributor

    Seems like acknowledge disables the error:

    When a start tag token is emitted with its self-closing flag set, if the flag is not acknowledged when it is processed by the tree construction stage, that is a non-void-html-element-start-tag-with-trailing-solidus parse error.

    It seems to be, but it would seem that it will always be false for Foreign elements. What's the point of calling it in then?
    Ok, I'll reread the spec sheet again and if anything, I'll contact the folks at WATHWG.

  16. xPaw commented on Jan 16, 2025

    @xPaw
    ContributorAuthor

    The spec is kind of all over the place, but this would imply that it gets set to true during tag name parse:

    U+002F SOLIDUS (/)
    Switch to the self-closing start tag state.

    3.2.5.40 Self-closing start tag state
    Consume the next input character:

    U+003E GREATER-THAN SIGN (>)
    Set the self-closing flag of the current tag token. Switch to the data state. Emit the current tag token.

  17. changed the title [-]Self-closing tag on void elements shouldn't be a parse error/warning in Dom\HTMLParser[/-] [+]Self-closing tag on void elements shouldn't be a parse error/warning in `\Dom\HTMLDocument`[/+] on Jan 17, 2025
  18. lexborisov commented on Jan 17, 2025

    @lexborisov
    Contributor

    @xPaw @nielsdos

    Thanks for help! Fixed in lexbor/lexbor@e58e1e8.

  19. ndossche commented on Jan 17, 2025

    @ndossche
    Member

    Thanks both, merged into PHP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions