@@ -76,4 +76,94 @@ public function test_full_processor_seek_forward() {
7676 $ this ->assertSame ( 'DIV ' , $ processor ->get_tag () );
7777 $ this ->assertTrue ( $ processor ->get_attribute ( 'two ' ) );
7878 }
79+
80+ /**
81+ * Seeking into and out of foreign content requires updating the parsing namespace correctly.
82+ *
83+ * @ticket 62290
84+ */
85+ public function test_full_processor_seek_back_from_foreign_content () {
86+ $ processor = WP_HTML_Processor::create_full_parser ( '<html><body><custom-element /><svg><rect /> ' );
87+ $ this ->assertTrue ( $ processor ->next_tag ( 'CUSTOM-ELEMENT ' ) );
88+ $ this ->assertTrue ( $ processor ->set_bookmark ( 'mark ' ), 'Failed to set bookmark "mark". ' );
89+ $ this ->assertTrue ( $ processor ->has_bookmark ( 'mark ' ), 'Failed "mark" has_bookmark check. ' );
90+
91+ /*
92+ * <custom-element /> has self-closing flag, but HTML elements (that are not void elements) cannot self-close,
93+ * they must be closed by some means, usually a closing tag.
94+ *
95+ * If the div were interpreted as foreign content, it would self-close.
96+ */
97+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
98+ $ this ->assertTrue ( $ processor ->expects_closer (), 'Incorrectly interpreted custom-element with self-closing flag as self-closing element. ' );
99+
100+ // Proceed into foreign content.
101+ $ this ->assertTrue ( $ processor ->next_tag ( 'RECT ' ) );
102+ $ this ->assertSame ( 'svg ' , $ processor ->get_namespace () );
103+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
104+ $ this ->assertFalse ( $ processor ->expects_closer () );
105+ $ this ->assertSame ( array ( 'HTML ' , 'BODY ' , 'CUSTOM-ELEMENT ' , 'SVG ' , 'RECT ' ), $ processor ->get_breadcrumbs () );
106+
107+ // Seek back.
108+ $ this ->assertTrue ( $ processor ->seek ( 'mark ' ), 'Failed to seek to bookmark "mark". ' );
109+ $ this ->assertSame ( 'CUSTOM-ELEMENT ' , $ processor ->get_tag () );
110+ // If the parsing namespace were not correct here (html),
111+ // then the self-closing flag would be misinterpreted.
112+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
113+ $ this ->assertTrue ( $ processor ->expects_closer (), 'Incorrectly interpreted custom-element with self-closing flag as self-closing element. ' );
114+
115+ // Proceed into foreign content again.
116+ $ this ->assertTrue ( $ processor ->next_tag ( 'RECT ' ) );
117+ $ this ->assertSame ( 'svg ' , $ processor ->get_namespace () );
118+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
119+ $ this ->assertFalse ( $ processor ->expects_closer () );
120+
121+ // The RECT should still descend from the CUSTOM-ELEMENT despite its self-closing flag.
122+ $ this ->assertSame ( array ( 'HTML ' , 'BODY ' , 'CUSTOM-ELEMENT ' , 'SVG ' , 'RECT ' ), $ processor ->get_breadcrumbs () );
123+ }
124+
125+ /**
126+ * Seeking into and out of foreign content requires updating the parsing namespace correctly.
127+ *
128+ * @ticket 62290
129+ */
130+ public function test_pragment_processor_seek_back_from_foreign_content () {
131+ $ processor = WP_HTML_Processor::create_fragment ( '<custom-element /><svg><rect /> ' );
132+ $ this ->assertTrue ( $ processor ->next_tag ( 'CUSTOM-ELEMENT ' ) );
133+ $ this ->assertTrue ( $ processor ->set_bookmark ( 'mark ' ), 'Failed to set bookmark "mark". ' );
134+ $ this ->assertTrue ( $ processor ->has_bookmark ( 'mark ' ), 'Failed "mark" has_bookmark check. ' );
135+
136+ /*
137+ * <custom-element /> has self-closing flag, but HTML elements (that are not void elements) cannot self-close,
138+ * they must be closed by some means, usually a closing tag.
139+ *
140+ * If the div were interpreted as foreign content, it would self-close.
141+ */
142+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
143+ $ this ->assertTrue ( $ processor ->expects_closer (), 'Incorrectly interpreted custom-element with self-closing flag as self-closing element. ' );
144+
145+ // Proceed into foreign content.
146+ $ this ->assertTrue ( $ processor ->next_tag ( 'RECT ' ) );
147+ $ this ->assertSame ( 'svg ' , $ processor ->get_namespace () );
148+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
149+ $ this ->assertFalse ( $ processor ->expects_closer () );
150+ $ this ->assertSame ( array ( 'HTML ' , 'BODY ' , 'CUSTOM-ELEMENT ' , 'SVG ' , 'RECT ' ), $ processor ->get_breadcrumbs () );
151+
152+ // Seek back.
153+ $ this ->assertTrue ( $ processor ->seek ( 'mark ' ), 'Failed to seek to bookmark "mark". ' );
154+ $ this ->assertSame ( 'CUSTOM-ELEMENT ' , $ processor ->get_tag () );
155+ // If the parsing namespace were not correct here (html),
156+ // then the self-closing flag would be misinterpreted.
157+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
158+ $ this ->assertTrue ( $ processor ->expects_closer (), 'Incorrectly interpreted custom-element with self-closing flag as self-closing element. ' );
159+
160+ // Proceed into foreign content again.
161+ $ this ->assertTrue ( $ processor ->next_tag ( 'RECT ' ) );
162+ $ this ->assertSame ( 'svg ' , $ processor ->get_namespace () );
163+ $ this ->assertTrue ( $ processor ->has_self_closing_flag () );
164+ $ this ->assertFalse ( $ processor ->expects_closer () );
165+
166+ // The RECT should still descend from the CUSTOM-ELEMENT despite its self-closing flag.
167+ $ this ->assertSame ( array ( 'HTML ' , 'BODY ' , 'CUSTOM-ELEMENT ' , 'SVG ' , 'RECT ' ), $ processor ->get_breadcrumbs () );
168+ }
79169}
0 commit comments