diff --git a/src/wp-includes/interactivity-api/class-wp-interactivity-api.php b/src/wp-includes/interactivity-api/class-wp-interactivity-api.php index fdde5d429aa6b..f771912f326e7 100644 --- a/src/wp-includes/interactivity-api/class-wp-interactivity-api.php +++ b/src/wp-includes/interactivity-api/class-wp-interactivity-api.php @@ -439,7 +439,12 @@ private function _process_directives( string $html ) { array_pop( $tag_stack ); } } else { - if ( 0 !== count( $p->get_attribute_names_with_prefix( 'data-wp-each-child' ) ) ) { + $each_child_attrs = $p->get_attribute_names_with_prefix( 'data-wp-each-child' ); + if ( null === $each_child_attrs ) { + continue; + } + + if ( 0 !== count( $each_child_attrs ) ) { /* * If the tag has a `data-wp-each-child` directive, jump to its closer * tag because those tags have already been processed. diff --git a/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php b/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php index 1aa9a7238e104..f9e52f6c8cea4 100644 --- a/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php +++ b/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php @@ -833,6 +833,31 @@ public static function data_html_with_unbalanced_tags() { ); } + /** + * Tests that the `process_directives` handles self-closing BR tags without + * causing fatal errors and processes directives correctly. + * + * @ticket 63891 + * @covers ::process_directives + */ + public function test_process_directives_handles_br_self_closing_tags_with_invalid_closers() { + $this->interactivity->state( + 'myPlugin', + array( + 'id' => 'some-id', + ) + ); + + $html = '