Skip to content

Commit

Permalink
Remove bail depth since we can't track a negative-sized stack
Browse files Browse the repository at this point in the history
For sibling navigation we have to continue
processing outside of balanced_next().
  • Loading branch information
dmsnell committed Dec 22, 2022
1 parent 1b99f7c commit 3920a01
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 49 deletions.
19 changes: 3 additions & 16 deletions lib/experimental/html/class-wp-html-attribute-sourcer.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,6 @@ function array_is_list( $array ) {
}
}

class Selector {
public $element = null;
public $class = null;
public $hash = null;
public $has_attribute = null;
public $then = null;
}

class ParseResult {
public $last_index;
public $selector = null;
}

class WP_HTML_Attribute_Sourcer {
/**
* Attributes definitions, typically from `block.json`.
Expand Down Expand Up @@ -208,7 +195,7 @@ public static function select( $selectors, $html ) {
'tag' => $tags->get_tag(),
'selector' => $next
] );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
while ( $tags->balanced_next( $state ) ) {
continue;
}
Expand All @@ -234,7 +221,7 @@ public static function select( $selectors, $html ) {
'tag' => $tags->get_tag(),
'selector' => $next
] );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
$state->match_depth = 1;
while ( $tags->balanced_next( $state ) ) {
if ( null === self::select_match( $tags, $next ) ) {
Expand All @@ -260,7 +247,7 @@ public static function select( $selectors, $html ) {
'tag' => $tags->get_tag(),
'selector' => $next
] );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
while ( $tags->balanced_next( $state ) ) {
if ( null === self::select_match( $tags, $next ) ) {
continue;
Expand Down
26 changes: 12 additions & 14 deletions lib/experimental/html/class-wp-html-processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@
class WP_HTML_Processor_Scan_State {
public $budget = 1000;
public $open_tags = array();
public $bail_depth = 0;
public $match_depth = null;

public function relative_depth() {
return count( $this->open_tags );
}

public function also_scan_siblings() {
$this->bail_depth = -1;
}
}


class WP_HTML_Processor extends WP_HTML_Tag_Processor {
public static function new_state() {
return new WP_HTML_Processor_Scan_State();
public function new_state() {
$state = new WP_HTML_Processor_Scan_State();
$tag_name = $this->get_tag();

if ( ! self::is_html_void_element( $tag_name ) && ! $this->is_tag_closer() ) {
$state->open_tags[] = $tag_name;
}

return $state;
}

public function balanced_next( WP_HTML_Processor_Scan_State $state, $query = null ) {
Expand Down Expand Up @@ -98,13 +100,9 @@ public function balanced_next( WP_HTML_Processor_Scan_State $state, $query = nul
: $state->relative_depth();

/*
* Step 2. If we've reached the depth at which we want to stop searching,
* then bail at the current tag. This is mostly used to stop at the end
* of the opening tag's closing tag, but if set negative can continue
* scanning sibling elements (-1) or parents (-2) and so on.
* Step 2. Bail if we've reached the end of the tag in which we started.
*/

if ( $state->bail_depth === $depth ) {
if ( 0 === $depth ) {
return false;
}

Expand All @@ -119,7 +117,7 @@ public function balanced_next( WP_HTML_Processor_Scan_State $state, $query = nul
* searching once we've exited the tag on which we started, or reach its parent.
*/

if ( ! isset( $state->match_depth ) || $state->match_depth === $depth ) {
if ( ! isset( $state->match_depth ) || $state->match_depth + 1 === $depth ) {
$this->parse_query( $query );
if ( $this->matches() ) {
return true;
Expand Down
29 changes: 10 additions & 19 deletions phpunit/html/wp-html-processor-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
require_once __DIR__ . '/../../lib/experimental/html/class-wp-html-processor.php';

/**
* @group html-proc
* @group html-processor
*
* @coversDefaultClass WP_HTML_Processor
*/
Expand All @@ -19,47 +19,38 @@ public function test_find_descendant_tag() {
$tags = new WP_HTML_Processor( '<div>outside</div><section><div><img>inside</div></section>' );

$tags->next_tag( 'div' );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
$this->assertFalse( $tags->balanced_next( $state, 'img' ) );

$this->assertTrue( $tags->next_tag( 'div' ) );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
$this->assertTrue( $tags->balanced_next( $state, 'img' ) );
}

public function test_find_immediate_child_tag() {
$tags = new WP_HTML_Processor( '<div><div><div><img></div></div></div>' );

$tags->next_tag( 'div' );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
$state->match_depth = 1;
$this->assertFalse( $tags->balanced_next( $state, 'img' ) );
}

public function test_find_immediate_child_of_fails_when_inside_sibling_of_current_tag() {
$tags = new WP_HTML_Processor( '<div><div><div><img></div></div><img></div>' );
public function test_find_immediate_child_tag2() {
$tags = new WP_HTML_Processor( '<div><div><div><img></div></div><img wanted></div>' );

$tags->next_tag( 'div' );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
$state->match_depth = 1;
$this->assertFalse( $tags->balanced_next( $state, 'img' ) );
}

public function test_find_immediate_child_succeeds_when_inside_sibling_of_current_tag_and_searchign_siblings() {
$tags = new WP_HTML_Processor( '<div><div><div><img></div></div><img></div>' );

$tags->next_tag( 'div' );
$state = WP_HTML_Processor::new_state();
$state->also_scan_siblings();
$state->match_depth = 1;
$this->assertTrue( $tags->balanced_next( $state, 'img' ) );
$this->assertTrue( $tags->balanced_next( $state, 'img' ), 'Did not find the wanted <img>' );
$this->assertTrue( $tags->get_attribute( 'wanted' ), 'Found the wrong <img>' );
}

public function test_find_child_tag() {
$tags = new WP_HTML_Processor( '<div><div><div><img></div></div></div>' );

$tags->next_tag( 'div' );
$state = WP_HTML_Processor::new_state();
$state = $tags->new_state();
$state->match_depth = 3;
$this->assertTrue( $tags->balanced_next( $state, 'img' ) );
}
Expand Down

1 comment on commit 3920a01

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/3754012181
📝 Reported issues:

Please sign in to comment.