Skip to content

Commit

Permalink
HTML API: Test and fix SVG script handling.
Browse files Browse the repository at this point in the history
When support was added for foreign content, an ambiguity in the HTML specification led to code that followed the wrong path when encountering a self-closing SCRIPT element in the SVG namespace. Further, a fallthrough was discovered during manual testing.

This patch adds a new test to assert the proper behaviors and fixes these issues. In the case of the SCRIPT element, the outcome was the same with the wrong code path, making the defect benign. In the case of the fallthrough, the wrong behavior would occur.

The updates in this patch also resolves a todo relating to the spec ambiguity.

Developed in WordPress#7164
Discussed in https://core.trac.wordpress.org/ticket/61576

Follow-up to [58868].

Props: dmsnell, jonsurrell.
See #61576.


git-svn-id: https://develop.svn.wordpress.org/trunk@58871 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
dmsnell committed Aug 8, 2024
1 parent b9014d6 commit 7ceb839
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
29 changes: 15 additions & 14 deletions src/wp-includes/html-api/class-wp-html-processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4239,21 +4239,22 @@ private function step_in_foreign_content(): bool {
/*
* > If the token has its self-closing flag set, then run
* > the appropriate steps from the following list:
* >
* > ↪ the token's tag name is "script", and the new current node is in the SVG namespace
* > Acknowledge the token's self-closing flag, and then act as
* > described in the steps for a "script" end tag below.
* >
* > ↪ Otherwise
* > Pop the current node off the stack of open elements and
* > acknowledge the token's self-closing flag.
*
* Since the rules for SCRIPT below indicate to pop the element off of the stack of
* open elements, which is the same for the Otherwise condition, there's no need to
* separate these checks. The difference comes when a parser operates with the scripting
* flag enabled, and executes the script, which this parser does not support.
*/
if ( $this->state->current_token->has_self_closing_flag ) {
if ( 'SCRIPT' === $this->state->current_token->node_name && 'svg' === $this->state->current_token->namespace ) {
/*
* > Acknowledge the token's self-closing flag, and then act as
* > described in the steps for a "script" end tag below.
*
* @todo Verify that this shouldn't be handled by the rule for
* "An end tag whose name is 'script', if the current node
* is an SVG script element."
*/
goto in_foreign_content_any_other_end_tag;
} else {
$this->state->stack_of_open_elements->pop();
}
$this->state->stack_of_open_elements->pop();
}
return true;
}
Expand All @@ -4263,13 +4264,13 @@ private function step_in_foreign_content(): bool {
*/
if ( $this->is_tag_closer() && 'SCRIPT' === $this->state->current_token->node_name && 'svg' === $this->state->current_token->namespace ) {
$this->state->stack_of_open_elements->pop();
return true;
}

/*
* > Any other end tag
*/
if ( $this->is_tag_closer() ) {
in_foreign_content_any_other_end_tag:
$node = $this->state->stack_of_open_elements->current_node();
if ( $tag_name !== $node->node_name ) {
// @todo Indicate a parse error once it's possible.
Expand Down
10 changes: 10 additions & 0 deletions tests/phpunit/tests/html-api/wpHtmlProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -521,4 +521,14 @@ public function test_expects_closer_foreign_content_self_closing() {
$this->assertSame( 'MATH', $processor->get_tag() );
$this->assertTrue( $processor->expects_closer() );
}

/**
* Ensures that self-closing foreign SCRIPT elements are properly found.
*
* @ticket 61576
*/
public function test_foreign_content_script_self_closing() {
$processor = WP_HTML_Processor::create_fragment( '<svg><script />' );
$this->assertTrue( $processor->next_tag( 'script' ) );
}
}

0 comments on commit 7ceb839

Please sign in to comment.