HTML API: Close all elements at the end of a document.

When the model of breadcrumb generation in the HTML Processor and node
traversal was simplified, the change introduced a bug whereby unclosed
nodes at the end of a document would remain unvisited and unclosed.

In this patch, a fix is applied to ensure that all open elements close
while traversing a document. A couple of minor documentation typos are
fixed in the patch as well.

Developed in https://github.com/wordpress/wordpress-develop/pull/7085
Discussed in https://core.trac.wordpress.org/ticket/61576

Follow-up to [58713].

Props: dmsnell, gziolo, jonsurrell.
See #61576.

Built from https://develop.svn.wordpress.org/trunk@58828


git-svn-id: http://core.svn.wordpress.org/trunk@58224 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
dmsnell 2024-07-29 17:39:17 +00:00
parent 12991d53a4
commit d8ab99f84b
2 changed files with 12 additions and 7 deletions

View File

@ -609,25 +609,30 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor {
* until there are events or until there are no more * until there are events or until there are no more
* tokens works in the meantime and isn't obviously wrong. * tokens works in the meantime and isn't obviously wrong.
*/ */
while ( empty( $this->element_queue ) && $this->step() ) { if ( empty( $this->element_queue ) && $this->step() ) {
continue; return $this->next_token();
} }
// Process the next event on the queue. // Process the next event on the queue.
$this->current_element = array_shift( $this->element_queue ); $this->current_element = array_shift( $this->element_queue );
if ( ! isset( $this->current_element ) ) { if ( ! isset( $this->current_element ) ) {
return false; // There are no tokens left, so close all remaining open elements.
while ( $this->state->stack_of_open_elements->pop() ) {
continue;
}
return empty( $this->element_queue ) ? false : $this->next_token();
} }
$is_pop = WP_HTML_Stack_Event::POP === $this->current_element->operation; $is_pop = WP_HTML_Stack_Event::POP === $this->current_element->operation;
/* /*
* The root node only exists in the fragment parser, and closing it * The root node only exists in the fragment parser, and closing it
* indicates that the parse is complete. Stop before popping if from * indicates that the parse is complete. Stop before popping it from
* the breadcrumbs. * the breadcrumbs.
*/ */
if ( 'root-node' === $this->current_element->token->bookmark_name ) { if ( 'root-node' === $this->current_element->token->bookmark_name ) {
return ! $is_pop && $this->next_token(); return $this->next_token();
} }
// Adjust the breadcrumbs for this event. // Adjust the breadcrumbs for this event.
@ -638,7 +643,7 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor {
} }
// Avoid sending close events for elements which don't expect a closing. // Avoid sending close events for elements which don't expect a closing.
if ( $is_pop && ! static::expects_closer( $this->current_element->token ) ) { if ( $is_pop && ! $this->expects_closer( $this->current_element->token ) ) {
return $this->next_token(); return $this->next_token();
} }

View File

@ -16,7 +16,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '6.7-alpha-58827'; $wp_version = '6.7-alpha-58828';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.