<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[58714] trunk/src/wp-includes/html-api: HTML API: Add context to Unsupported_Exception class for improved debugging.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/58714">58714</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/58714","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dmsnell</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2024-07-12 22:27:20 +0000 (Fri, 12 Jul 2024)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>HTML API: Add context to Unsupported_Exception class for improved 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 through a new
method, `get_unsupported_exception()`.

Developed in https://github.com/WordPress/wordpress-develop/pull/6985
Discussed in https://core.trac.wordpress.org/ticket/61646

Props bernhard-reiter, dmsnell, jonsurrell.
See <a href="https://core.trac.wordpress.org/ticket/61646">#61646</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludeshtmlapiclasswphtmlprocessorphp">trunk/src/wp-includes/html-api/class-wp-html-processor.php</a></li>
<li><a href="#trunksrcwpincludeshtmlapiclasswphtmlunsupportedexceptionphp">trunk/src/wp-includes/html-api/class-wp-html-unsupported-exception.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludeshtmlapiclasswphtmlprocessorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/html-api/class-wp-html-processor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/html-api/class-wp-html-processor.php        2024-07-12 22:18:16 UTC (rev 58713)
+++ trunk/src/wp-includes/html-api/class-wp-html-processor.php  2024-07-12 22:27:20 UTC (rev 58714)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -189,6 +189,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">        private $last_error = null;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Stores context for why the parser bailed on unsupported HTML, if it did.
+        *
+        * @see self::get_unsupported_exception
+        *
+        * @since 6.7.0
+        *
+        * @var WP_HTML_Unsupported_Exception|null
+        */
+       private $unsupported_exception = null;
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Releases a bookmark when PHP garbage-collects its wrapping WP_HTML_Token instance.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * This function is created inside the class constructor so that it can be passed to
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -385,6 +396,45 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Stops the parser and terminates its execution when encountering unsupported markup.
+        *
+        * @throws WP_HTML_Unsupported_Exception Halts execution of the parser.
+        *
+        * @since 6.7.0
+        *
+        * @param string $message Explains support is missing in order to parse the current node.
+        *
+        * @return mixed
+        */
+       private function bail( string $message ) {
+               $here  = $this->bookmarks[ $this->state->current_token->bookmark_name ];
+               $token = substr( $this->html, $here->start, $here->length );
+
+               $open_elements = array();
+               foreach ( $this->state->stack_of_open_elements->stack as $item ) {
+                       $open_elements[] = $item->node_name;
+               }
+
+               $active_formats = array();
+               foreach ( $this->state->active_formatting_elements->walk_down() as $item ) {
+                       $active_formats[] = $item->node_name;
+               }
+
+               $this->last_error = self::ERROR_UNSUPPORTED;
+
+               $this->unsupported_exception = new WP_HTML_Unsupported_Exception(
+                       $message,
+                       $this->state->current_token->node_name,
+                       $here->start,
+                       $token,
+                       $open_elements,
+                       $active_formats
+               );
+
+               throw $this->unsupported_exception;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Returns the last error, if any.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * Various situations lead to parsing failure but this class will
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -412,6 +462,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Returns context for why the parser aborted due to unsupported HTML, if it did.
+        *
+        * This is meant for debugging purposes, not for production use.
+        *
+        * @since 6.7.0
+        *
+        * @see self::$unsupported_exception
+        *
+        * @return WP_HTML_Unsupported_Exception|null
+        */
+       public function get_unsupported_exception() {
+               return $this->unsupported_exception;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Finds the next tag matching the $query.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @todo Support matching the class name and tag name.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -841,8 +906,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // This should be unreachable but PHP doesn't have total type checking on switch.
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $this->last_error = self::ERROR_UNSUPPORTED;
-                                       throw new WP_HTML_Unsupported_Exception( "Found unrecognized insertion mode '{$this->state->insertion_mode}'." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->bail( "Unaware of the requested parsing mode: '{$this->state->insertion_mode}'." );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                } catch ( WP_HTML_Unsupported_Exception $e ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        /*
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -922,8 +986,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_initial() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -942,8 +1005,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_before_html() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -962,8 +1024,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_before_head() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -982,8 +1043,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_head() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1002,8 +1062,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_head_noscript() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1022,8 +1081,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_after_head() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1445,8 +1503,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                         * >   than the end tag token that it actually is.
</span><span class="cx" style="display: block; padding: 0 10px">                         */
</span><span class="cx" style="display: block; padding: 0 10px">                        case '-BR':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->last_error = self::ERROR_UNSUPPORTED;
-                               throw new WP_HTML_Unsupported_Exception( 'Closing BR tags require unimplemented special handling.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->bail( 'Closing BR tags require unimplemented special handling.' );
+                               // This return required because PHPCS can't determine that the call to bail() throws.
+                               return false;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        /*
</span><span class="cx" style="display: block; padding: 0 10px">                         * > A start tag whose tag name is one of: "area", "br", "embed", "img", "keygen", "wbr"
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1602,8 +1661,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'TITLE':
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'TR':
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'XMP':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->last_error = self::ERROR_UNSUPPORTED;
-                               throw new WP_HTML_Unsupported_Exception( "Cannot process {$token_name} element." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->bail( "Cannot process {$token_name} element." );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! parent::is_tag_closer() ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1665,8 +1723,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_table() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1685,8 +1742,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_table_text() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1705,8 +1761,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_caption() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1725,8 +1780,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_column_group() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1745,8 +1799,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_table_body() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1765,8 +1818,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_row() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1785,8 +1837,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_cell() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1986,8 +2037,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_select_in_table() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2006,8 +2056,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_template() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2026,8 +2075,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_after_body() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2046,8 +2094,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_frameset() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2066,8 +2113,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_after_frameset() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2086,8 +2132,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_after_after_body() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2106,8 +2151,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_after_after_frameset() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2126,8 +2170,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether an element was found.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private function step_in_foreign_content() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /*
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2835,8 +2878,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( 'Cannot reconstruct active formatting elements when advancing and rewinding is required.' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3072,8 +3114,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // > If there is no such element, then return and instead act as described in the "any other end tag" entry above.
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( null === $formatting_element ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->last_error = self::ERROR_UNSUPPORTED;
-                               throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when "any other end tag" is required.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->bail( 'Cannot run adoption agency when "any other end tag" is required.' );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // > If formatting element is not in the stack of open elements, then this is a parse error; remove the element from the list, and return.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3125,12 +3166,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->last_error = self::ERROR_UNSUPPORTED;
-                       throw new WP_HTML_Unsupported_Exception( 'Cannot extract common ancestor in adoption agency algorithm.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->bail( 'Cannot extract common ancestor in adoption agency algorithm.' );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->last_error = self::ERROR_UNSUPPORTED;
-               throw new WP_HTML_Unsupported_Exception( 'Cannot run adoption agency when looping required.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->bail( 'Cannot run adoption agency when looping required.' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunksrcwpincludeshtmlapiclasswphtmlunsupportedexceptionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/html-api/class-wp-html-unsupported-exception.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/html-api/class-wp-html-unsupported-exception.php    2024-07-12 22:18:16 UTC (rev 58713)
+++ trunk/src/wp-includes/html-api/class-wp-html-unsupported-exception.php      2024-07-12 22:27:20 UTC (rev 58714)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -21,6 +21,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * operation and signify that the given HTML cannot be processed.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 6.4.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.7.0 Gained contextual information for use in debugging parse failures.
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @access private
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27,5 +28,88 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * @see WP_HTML_Processor
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> class WP_HTML_Unsupported_Exception extends Exception {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Name of the matched token when the exception was raised,
+        * if matched on a token.
+        *
+        * This does not imply that the token itself was unsupported, but it
+        * may have been the case that the token triggered part of the HTML
+        * parsing that isn't supported, such as the adoption agency algorithm.
+        *
+        * @since 6.7.0
+        *
+        * @var string
+        */
+       public $token_name;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Number of bytes into the input HTML document where the parser was
+        * parsing when the exception was raised.
+        *
+        * Use this to reconstruct context for the failure.
+        *
+        * @since 6.7.0
+        *
+        * @var int
+        */
+       public $token_at;
+
+       /**
+        * Full raw text of the matched token when the exception was raised,
+        * if matched on a token.
+        *
+        * Whereas the `$token_name` will be normalized, this contains the full
+        * raw text of the token, including original casing, duplicated attributes,
+        * and other syntactic variations that are normally abstracted in the HTML API.
+        *
+        * @since 6.7.0
+        *
+        * @var string
+        */
+       public $token;
+
+       /**
+        * Stack of open elements when the exception was raised.
+        *
+        * Use this to trace the parsing circumstances which led to the exception.
+        *
+        * @since 6.7.0
+        *
+        * @var string[]
+        */
+       public $stack_of_open_elements = array();
+
+       /**
+        * List of active formatting elements when the exception was raised.
+        *
+        * Use this to trace the parsing circumstances which led to the exception.
+        *
+        * @since 6.7.0
+        *
+        * @var string[]
+        */
+       public $active_formatting_elements = array();
+
+       /**
+        * Constructor function.
+        *
+        * @since 6.7.0
+        *
+        * @param string   $message                    Brief message explaining what is unsupported, the reason this exception was raised.
+        * @param string   $token_name                 Normalized name of matched token when this exception was raised.
+        * @param int      $token_at                   Number of bytes into source HTML document where matched token starts.
+        * @param string   $token                      Full raw text of matched token when this exception was raised.
+        * @param string[] $stack_of_open_elements     Stack of open elements when this exception was raised.
+        * @param string[] $active_formatting_elements List of active formatting elements when this exception was raised.
+        */
+       public function __construct( string $message, string $token_name, int $token_at, string $token, array $stack_of_open_elements, array $active_formatting_elements ) {
+               parent::__construct( $message );
+
+               $this->token_name = $token_name;
+               $this->token_at   = $token_at;
+               $this->token      = $token;
+
+               $this->stack_of_open_elements     = $stack_of_open_elements;
+               $this->active_formatting_elements = $active_formatting_elements;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>