Skip to content

Commit 6962fa2

Browse files
committed
HTML API: Expand Unsupported class and make it available for debugging.
The HTML Processor internally throws an exception when it reaches HTML that it knows it cannot process, but this exception is not made available to calling code. It can be useful to extract more knowledge about why it gave up, especially for debugging purposes. In this patch, more context is added to the WP_HTML_Unsupported_Exception and the last exception is made available to calling code, if it asks.
1 parent 2b2d6fe commit 6962fa2

2 files changed

Lines changed: 82 additions & 1 deletion

File tree

src/wp-includes/html-api/class-wp-html-processor.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,17 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor {
188188
*/
189189
private $last_error = null;
190190

191+
/**
192+
* Stores context for why the parser bailed on unsupported HTML, if it did.
193+
*
194+
* @see self::get_unsupported_exception
195+
*
196+
* @since 6.7.0
197+
*
198+
* @var WP_HTML_Unsupported_Exception|null
199+
*/
200+
private $unsupported_exception = null;
201+
191202
/**
192203
* Releases a bookmark when PHP garbage-collects its wrapping WP_HTML_Token instance.
193204
*
@@ -384,6 +395,45 @@ function ( WP_HTML_Token $token ) {
384395
};
385396
}
386397

398+
/**
399+
* Stops the parser and terminates its execution when encountering unsupported markup.
400+
*
401+
* @throws WP_HTML_Unsupported_Exception Halts execution of the parser.
402+
*
403+
* @since 6.7.0
404+
*
405+
* @param string $message Explains support is missing in order to parse the current node.
406+
*
407+
* @return mixed
408+
*/
409+
private function bail( string $message ) {
410+
$here = $this->bookmarks[ $this->state->current_token->bookmark_name ];
411+
$token = substr( $this->html, $here->start, $here->length );
412+
413+
$open_elements = array();
414+
foreach ( $this->state->stack_of_open_elements->stack as $item ) {
415+
$open_elements[] = $item->node_name;
416+
}
417+
418+
$active_formats = array();
419+
foreach ( $this->state->active_formatting_elements->walk_down() as $item ) {
420+
$active_formats[] = $item->node_name;
421+
}
422+
423+
$this->last_error = self::ERROR_UNSUPPORTED;
424+
425+
$this->unsupported_exception = new WP_HTML_Unsupported_Exception(
426+
$message,
427+
$this->state->current_token->node_name,
428+
$here->start,
429+
$token,
430+
$open_elements,
431+
$active_formats
432+
);
433+
434+
throw $this->unsupported_exception;
435+
}
436+
387437
/**
388438
* Returns the last error, if any.
389439
*
@@ -411,6 +461,21 @@ public function get_last_error() {
411461
return $this->last_error;
412462
}
413463

464+
/**
465+
* Returns context for why the parser aborted due to unsupported HTML, if it did.
466+
*
467+
* This is meant for debugging purposes, not for production use.
468+
*
469+
* @since 6.7.0
470+
*
471+
* @see self::$unsupported_exception
472+
*
473+
* @return WP_HTML_Unsupported_Exception|null
474+
*/
475+
public function get_unsupported_exception() {
476+
return $this->unsupported_exception;
477+
}
478+
414479
/**
415480
* Finds the next tag matching the $query.
416481
*

src/wp-includes/html-api/class-wp-html-unsupported-exception.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare( strict_types=1 );
22
/**
33
* HTML API: WP_HTML_Unsupported_Exception class
44
*
@@ -27,5 +27,21 @@
2727
* @see WP_HTML_Processor
2828
*/
2929
class WP_HTML_Unsupported_Exception extends Exception {
30+
public $token_name;
31+
public $token_at;
3032

33+
public $token;
34+
public $stack_of_open_elements = array();
35+
public $active_formatting_elements = array();
36+
37+
public function __construct( string $message, string $token_name, int $token_at, string $token, array $stack_of_open_elements, array $active_formatting_elements ) {
38+
parent::__construct( $message );
39+
40+
$this->token_name = $token_name;
41+
$this->token_at = $token_at;
42+
$this->token = $token;
43+
44+
$this->stack_of_open_elements = $stack_of_open_elements;
45+
$this->active_formatting_elements = $active_formatting_elements;
46+
}
3147
}

0 commit comments

Comments
 (0)