diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 35d91fad3129c..1c1499c298a33 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -1493,9 +1493,6 @@ public function serialize_token(): string { case 'IFRAME': case 'NOEMBED': case 'NOFRAMES': - $text = ''; - break; - case 'SCRIPT': case 'STYLE': break; diff --git a/tests/phpunit/tests/html-api/wpHtmlProcessor-serialize.php b/tests/phpunit/tests/html-api/wpHtmlProcessor-serialize.php index e516addb6c314..053d8023d4929 100644 --- a/tests/phpunit/tests/html-api/wpHtmlProcessor-serialize.php +++ b/tests/phpunit/tests/html-api/wpHtmlProcessor-serialize.php @@ -281,10 +281,108 @@ public static function data_tokens_with_null_bytes() { 'Foreign content text' => array( "one\x00two", "one\u{FFFD}two" ), 'SCRIPT content' => array( "", "" ), 'STYLE content' => array( "", "" ), + 'IFRAME content' => array( "", "" ), + 'NOEMBED content' => array( "a\x00b", "a\u{FFFD}b" ), + 'NOFRAMES content' => array( "a\x00b", "a\u{FFFD}b" ), 'Comment text' => array( "", "" ), ); } + /** + * Ensures that the contents of IFRAME, NOEMBED, and NOFRAMES elements are + * preserved when serializing. + * + * These elements contain raw text which is part of the parsed document. + * Dropping it would change the document's contents across a serialize and + * re-parse cycle. + * + * @ticket 65372 + * + * @dataProvider data_rawtext_elements_with_contents + * + * @param string $html Normalized HTML containing a rawtext element with contents. + */ + public function test_rawtext_element_contents_are_preserved_when_normalizing( string $html ) { + $this->assertSame( + $html, + WP_HTML_Processor::normalize( $html ), + 'Should have preserved the rawtext element contents.' + ); + } + + /** + * Data provider. + * + * @return array[] + */ + public static function data_rawtext_elements_with_contents() { + return array( + 'IFRAME with following text' => array( 'y' ), + 'NOEMBED with following text' => array( 'xy' ), + 'NOFRAMES with following text' => array( '
xy
' ), + 'NOFRAMES before comment' => array( '
x
' ), + 'IFRAME with markup-like contents' => array( '' ), + 'NOEMBED with character reference' => array( '&' ), + 'NOFRAMES with character reference' => array( '<' ), + ); + } + + /** + * Ensures that the contents of IFRAME, NOEMBED, and NOFRAMES elements are + * preserved when serializing full documents, including NOFRAMES elements + * in the HEAD or after a FRAMESET. + * + * @ticket 65372 + * + * @dataProvider data_full_documents_with_rawtext_elements + * + * @param string $html Input HTML document. + * @param string $expected Expected serialization of the full document. + */ + public function test_rawtext_element_contents_are_preserved_in_full_documents( string $html, string $expected ) { + $processor = WP_HTML_Processor::create_full_parser( $html ); + + $this->assertSame( + $expected, + $processor->serialize(), + 'Should have preserved the rawtext element contents.' + ); + } + + /** + * Data provider. + * + * @return array[] + */ + public static function data_full_documents_with_rawtext_elements() { + return array( + 'IFRAME in BODY' => array( + 'y', + 'y', + ), + 'NOEMBED in BODY' => array( + 'ax', + 'ax', + ), + 'NOFRAMES in BODY' => array( + 'ax', + 'ax', + ), + 'NOFRAMES in HEAD' => array( + 'xz', + 'xz', + ), + 'NOFRAMES in FRAMESET' => array( + 'x', + 'x', + ), + 'IFRAME before a comment' => array( + '

', + '

', + ), + ); + } + /** * @ticket 62396 *