diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php index 4a84835aff65b3..0f2eb65173673b 100644 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php +++ b/lib/compat/wordpress-6.4/html-api/class-wp-html-open-elements.php @@ -41,6 +41,17 @@ class WP_HTML_Open_Elements { */ public $stack = array(); + /** + * Holds functions added to be called after popping an element off the stack. + * + * Listeners are passed the WP_HTML_Token for the item that was removed. + * + * @since 6.4.0 + * + * @var array + */ + private $after_pop_listeners = array(); + /** * Whether a P element is in button scope currently. * @@ -119,6 +130,15 @@ public function has_element_in_specific_scope( $tag_name, $termination_list ) { if ( $node->node_name === $tag_name ) { return true; } + + switch ( $node->node_name ) { + case 'HTML': + return false; + } + + if ( in_array( $node->node_name, $termination_list, true ) ) { + return true; + } } return false; @@ -135,19 +155,7 @@ public function has_element_in_specific_scope( $tag_name, $termination_list ) { * @return bool Whether given element is in scope. */ public function has_element_in_scope( $tag_name ) { - return $this->has_element_in_specific_scope( - $tag_name, - array( - - /* - * Because it's not currently possible to encounter - * one of the termination elements, they don't need - * to be listed here. If they were, they would be - * unreachable and only waste CPU cycles while - * scanning through HTML. - */ - ) - ); + return $this->has_element_in_specific_scope( $tag_name, array( 'BUTTON' ) ); } /** @@ -398,6 +406,10 @@ public function after_element_push( $item ) { * cases where the precalculated value needs to change. */ switch ( $item->node_name ) { + case 'BUTTON': + $this->has_p_in_button_scope = false; + break; + case 'P': $this->has_p_in_button_scope = true; break; @@ -423,9 +435,46 @@ public function after_element_pop( $item ) { * cases where the precalculated value needs to change. */ switch ( $item->node_name ) { + case 'BUTTON': + $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); + break; + case 'P': $this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' ); break; } + + // Call any listeners that are registered. + foreach ( $this->after_pop_listeners as $listener ) { + call_user_func( $listener, $item ); + } + } + /** + * Creates a context in which a given listener is called after + * popping an element off of the stack of open elements. + * + * It's unlikely that you will need this function. It exists + * to aid an optimization in the `WP_HTML_Processor` and the + * strange form of calling a generator inside a `foreach` + * loop ensures that proper cleanup of the listener occurs. + * + * Example: + * + * $did_close = false; + * $closed_a_p = function ( $item ) use ( &$did_close ) { $did_close = 'P' === $item->node_name; }; + * foreach ( $stack_of_open_elements->with_pop_listener( $closed_a_p ) ) { + * while ( ! $did_close && $processor->next_tag() ) { + * // This loop executes until _any_ P element is closed. + * } + * } + * + * @since 6.4.0 + * + * @param callable $listener Called with the WP_HTML_Token for the item that was popped off of the stack. + */ + public function with_pop_listener( $listener ) { + $this->after_pop_listeners[] = $listener; + yield; + array_pop( $this->after_pop_listeners ); } } diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php index f845bffc3dda7f..6f73ea889dcf86 100644 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php +++ b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor-state.php @@ -111,6 +111,20 @@ class WP_HTML_Processor_State { */ public $context_node = null; + + /** + * The frameset-ok flag indicates if a `FRAMESET` element is allowed in the current state. + * + * > The frameset-ok flag is set to "ok" when the parser is created. It is set to "not ok" after certain tokens are seen. + * + * @since 6.4.0 + * + * @see https://html.spec.whatwg.org/#frameset-ok-flag + * + * @var bool + */ + public $frameset_ok = true; + /** * Constructor - creates a new and empty state value. * diff --git a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php index 593b3b7c27fc7a..4375dbb44369d6 100644 --- a/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php +++ b/lib/compat/wordpress-6.4/html-api/class-wp-html-processor.php @@ -7,10 +7,6 @@ * @since 6.4.0 */ -if ( class_exists( 'WP_HTML_Processor' ) ) { - return; -} - /** * Core class used to safely parse and modify an HTML document. * @@ -128,7 +124,7 @@ * @see WP_HTML_Tag_Processor * @see https://html.spec.whatwg.org/ */ -class WP_HTML_Processor extends WP_HTML_Tag_Processor { +class WP_HTML_Processor extends WP_HTML_Tag_Processor_Testing { /** * HTML processing requires more bookmarks than basic tag processing. * @@ -313,7 +309,7 @@ public function __construct( $html, $use_the_static_create_methods_instead = nul * failed it's possible to request the last error. This can be * helpful to know if it's possible to fix something or to give up. * - * Example + * Example: * * $p = WP_HTML_Processor::createFragment( '