Make WordPress Core

Changeset 58588


Ignore:
Timestamp:
06/27/2024 08:47:38 PM (3 months ago)
Author:
dmsnell
Message:

HTML API: Report breadcrumbs properly when visiting virtual nodes.

When [58304] introduced the abililty to visit virtual nodes in the HTML document,
those being the nodes which are implied by the HTML but no explicitly present in
the raw text, a bug was introduced in the get_breadcrumbs() method because it
wasn't updated to be aware of the virtual nodes. Therefore it would report the
wrong breadcrumbs for virtual nodes. Since the new get_depth() method is based
on the same logic it was also broken for virtual nodes.

In this patch, the breadcrumbs have been updated to account for the virtual nodes
and the depth method has been updated to rely on the fixed breadcrumb logic.

Developed in https://github.com/WordPress/wordpress-develop/pull/6914
Discussed in https://core.trac.wordpress.org/ticket/61348

Follow-up to [58304].

Props dmsnell, jonsurrell, zieladam.
See #61348.

Location:
trunk/src/wp-includes/html-api
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/html-api/class-wp-html-open-elements.php

    r58441 r58588  
    309309    public function pop() {
    310310        $item = array_pop( $this->stack );
    311 
    312311        if ( null === $item ) {
    313312            return false;
    314313        }
    315314
     315        if ( 'context-node' === $item->bookmark_name ) {
     316            $this->stack[] = $item;
     317            return false;
     318        }
     319
    316320        $this->after_element_pop( $item );
    317321        return true;
     
    330334    public function pop_until( $tag_name ) {
    331335        foreach ( $this->walk_up() as $item ) {
     336            if ( 'context-node' === $item->bookmark_name ) {
     337                return true;
     338            }
     339
    332340            $this->pop();
    333341
     
    370378     */
    371379    public function remove_node( $token ) {
     380        if ( 'context-node' === $token->bookmark_name ) {
     381            return false;
     382        }
     383
    372384        foreach ( $this->walk_up() as $position_from_end => $item ) {
    373385            if ( $token->bookmark_name !== $item->bookmark_name ) {
  • trunk/src/wp-includes/html-api/class-wp-html-processor.php

    r58558 r58588  
    520520        }
    521521
    522         if ( 0 === count( $this->element_queue ) && ! $this->step() ) {
    523             while ( $this->state->stack_of_open_elements->pop() ) {
     522        if ( 'done' !== $this->has_seen_context_node && 0 === count( $this->element_queue ) && ! $this->step() ) {
     523            while ( 'context-node' !== $this->state->stack_of_open_elements->current_node()->bookmark_name && $this->state->stack_of_open_elements->pop() ) {
    524524                continue;
    525525            }
     526            $this->has_seen_context_node = 'done';
     527            return $this->next_token();
    526528        }
    527529
     
    538540
    539541        if ( ! isset( $this->current_element ) ) {
    540             return $this->next_token();
     542            if ( 'done' === $this->has_seen_context_node ) {
     543                return false;
     544            } else {
     545                return $this->next_token();
     546            }
    541547        }
    542548
     
    783789     * @since 6.4.0
    784790     *
    785      * @todo make aware of queue of elements, because stack operations have already been done by now.
    786      *
    787791     * @return string[]|null Array of tag names representing path to matched node, if matched, otherwise NULL.
    788792     */
    789793    public function get_breadcrumbs() {
    790794        $breadcrumbs = array();
     795
    791796        foreach ( $this->state->stack_of_open_elements->walk_down() as $stack_item ) {
    792797            $breadcrumbs[] = $stack_item->node_name;
     798        }
     799
     800        if ( ! $this->is_virtual() ) {
     801            return $breadcrumbs;
     802        }
     803
     804        foreach ( $this->element_queue as $queue_item ) {
     805            if ( $this->current_element->token->bookmark_name === $queue_item->token->bookmark_name ) {
     806                break;
     807            }
     808
     809            if ( 'context-node' === $queue_item->token->bookmark_name ) {
     810                break;
     811            }
     812
     813            if ( 'real' === $queue_item->provenance ) {
     814                break;
     815            }
     816
     817            if ( WP_HTML_Stack_Event::PUSH === $queue_item->operation ) {
     818                $breadcrumbs[] = $queue_item->token->node_name;
     819            } else {
     820                array_pop( $breadcrumbs );
     821            }
     822        }
     823
     824        if ( null !== parent::get_token_name() && ! parent::is_tag_closer() ) {
     825            array_pop( $breadcrumbs );
     826        }
     827
     828        // Add the virtual node we're at.
     829        if ( WP_HTML_Stack_Event::PUSH === $this->current_element->operation ) {
     830            $breadcrumbs[] = $this->current_element->token->node_name;
    793831        }
    794832
     
    822860     */
    823861    public function get_current_depth() {
    824         return $this->state->stack_of_open_elements->count();
     862        return $this->is_virtual()
     863            ? count( $this->get_breadcrumbs() )
     864            : $this->state->stack_of_open_elements->count();
    825865    }
    826866
Note: See TracChangeset for help on using the changeset viewer.