Make WordPress Core


Ignore:
Timestamp:
10/09/2026 04:55:54 AM (32 hours ago)
Author:
westonruter
Message:

HTML API: Remove unreachable code from HTML Processor.

The bail() method in WP_HTML_Processor always throws, and it has been documented as returning never since r61699. The return false; sentinels added after its calls in r59001, the break statements following a goto, and the trailing bail() calls at the end of methods whose every path already returns could therefore never run, and PHPStan reported them as unreachable. They are removed. Where a sentinel guarded against a future code path falling off the end of a method, PHPStan now catches that case instead by reporting a missing return.

In step_in_foreign_content(), end tags are now handled in an else branch rather than by re-checking is_tag_closer(), which was always true at that point. This lets both PHPStan and IDEs see that every path returns, so the trailing bail() is no longer needed.

The remaining break statements after a bail() call in a switch are kept. PHPCS cannot tell that bail() never returns, so without a break it treats the case as falling through and misreports the indentation of the comment above the next case. They remain in the baseline, along with two other unreachable statements which mirror steps of the HTML specification.

The outer loop of the adoption agency algorithm is likewise kept, along with its safety budget, as scaffolding for the parts of the algorithm which are not yet supported. Since r64237 PHPStan has reported the loop's two comparisons as constant. Rather than leaving them in baselines that are meant to be emptied, they are now ignored in phpstan.neon.dist with an explanation, and the two baseline files are deleted.

Developed in ​https://github.com/WordPress/wordpress-develop/pull/14090.
Follow-up to r58836, r59001, r61699, r63023, r64237.

Props westonruter, dmsnell, jonsurrell.
See #65817.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/html-api/class-wp-html-processor.php

    r63790 r64250  
    15861586                                }
    15871587                                goto initial_anything_else;
    1588                                 break;
    15891588
    15901589                        /*
    … …  
    16791678                                }
    16801679                                goto before_html_anything_else;
    1681                                 break;
    16821680
    16831681                        /*
    … …  
    17011699                                 */
    17021700                                goto before_html_anything_else;
    1703                                 break;
    17041701                }
    17051702
    … …  
    17611758                                }
    17621759                                goto before_head_anything_else;
    1763                                 break;
    17641760
    17651761                        /*
    … …  
    18061802                        case '-HTML':
    18071803                                goto before_head_anything_else;
    1808                                 break;
    18091804                }
    18101805
    … …  
    18621857
    18631858                                goto in_head_anything_else;
    1864                                 break;
    18651859
    18661860                        /*
    … …  
    19941988                                 */
    19951989                                goto in_head_anything_else;
    1996                                 break;
    19971990
    19981991                        /*
    … …  
    20872080
    20882081                                goto in_head_noscript_anything_else;
    2089                                 break;
    20902082
    20912083                        /*
    … …  
    21912183                                }
    21922184                                goto after_head_anything_else;
    2193                                 break;
    21942185
    21952186                        /*
    … …  
    22802271                                 */
    22812272                                goto after_head_anything_else;
    2282                                 break;
    22832273                }
    22842274
    … …  
    27842774                                        $this->state->stack_of_open_elements->remove_node( $node );
    27852775                                        return true;
    2786                                 } else {
    2787                                         /*
    2788                                          * > If the stack of open elements does not have a form element in scope,
    2789                                          * > then this is a parse error; return and ignore the token.
    2790                                          *
    2791                                          * Note that unlike in the clause above, this is checking for any FORM in scope.
    2792                                          */
    2793                                         if ( ! $this->state->stack_of_open_elements->has_element_in_scope( 'FORM' ) ) {
    2794                                                 // Parse error: ignore the token.
    2795                                                 return $this->step();
    2796                                         }
    2797 
    2798                                         $this->generate_implied_end_tags();
    2799 
    2800                                         if ( ! $this->state->stack_of_open_elements->current_node_is( 'FORM' ) ) {
    2801                                                 // @todo Indicate a parse error once it's possible. This error does not impact the logic here.
    2802                                         }
    2803 
    2804                                         $this->state->stack_of_open_elements->pop_until( 'FORM' );
    2805                                         return true;
    2806                                 }
    2807                                 break;
     2776                                }
     2777
     2778                                /*
     2779                                 * > If the stack of open elements does not have a form element in scope,
     2780                                 * > then this is a parse error; return and ignore the token.
     2781                                 *
     2782                                 * Note that unlike in the clause above, this is checking for any FORM in scope.
     2783                                 */
     2784                                if ( ! $this->state->stack_of_open_elements->has_element_in_scope( 'FORM' ) ) {
     2785                                        // Parse error: ignore the token.
     2786                                        return $this->step();
     2787                                }
     2788
     2789                                $this->generate_implied_end_tags();
     2790
     2791                                if ( ! $this->state->stack_of_open_elements->current_node_is( 'FORM' ) ) {
     2792                                        // @todo Indicate a parse error once it's possible. This error does not impact the logic here.
     2793                                }
     2794
     2795                                $this->state->stack_of_open_elements->pop_until( 'FORM' );
     2796                                return true;
    28082797
    28092798                        /*
    … …  
    33673356                        return $this->in_body_any_other_end_tag();
    33683357                }
    3369 
    3370                 $this->bail( 'Should not have been able to reach end of IN BODY processing. Check HTML API code.' );
    3371                 // This unnecessary return prevents tools from inaccurately reporting type errors.
    3372                 return false;
    33733358        }
    33743359
    … …  
    34193404
    34203405                $this->bail( 'Should not have been able to reach end of "any other end tag" IN BODY processing. Check HTML API code.' );
    3421                 // This unnecessary return prevents tools from inaccurately reporting type errors.
    3422                 return false;
    34233406        }
    34243407
    … …  
    34973480                                        // Non-whitespace would trigger fostering, unsupported at this time.
    34983481                                        $this->bail( 'Foster parenting is not supported.' );
    3499                                         break;
    35003482                                }
    35013483                                break;
    … …  
    38223804
    38233805                                goto in_column_group_anything_else;
    3824                                 break;
    38253806
    38263807                        /*
    … …  
    43834364                                }
    43844365                                goto after_body_anything_else;
    4385                                 break;
    43864366
    43874367                        /*
    … …  
    47064686                                }
    47074687                                goto after_after_body_anything_else;
    4708                                 break;
    47094688                }
    47104689
    … …  
    49854964                        }
    49864965                        return true;
    4987                 }
    4988 
    4989                 /*
    4990                  * > An end tag whose name is "script", if the current node is an SVG script element.
    4991                  */
    4992                 if ( $this->is_tag_closer() && 'SCRIPT' === $this->state->current_token->node_name && 'svg' === $this->state->current_token->namespace ) {
    4993                         $this->state->stack_of_open_elements->pop();
    4994                         return true;
    4995                 }
    4996 
    4997                 /*
    4998                  * > Any other end tag
    4999                  */
    5000                 if ( $this->is_tag_closer() ) {
     4966                } else {
     4967                        /*
     4968                         * > An end tag whose name is "script", if the current node is an SVG script element.
     4969                         */
     4970                        if ( 'SCRIPT' === $this->state->current_token->node_name && 'svg' === $this->state->current_token->namespace ) {
     4971                                $this->state->stack_of_open_elements->pop();
     4972                                return true;
     4973                        }
     4974
     4975                        /*
     4976                         * > Any other end tag
     4977                         */
    50014978                        $node = $this->state->stack_of_open_elements->current_node();
    50024979                        if ( $tag_name !== $node->node_name ) {
    … …  
    50985075                        }
    50995076                }
    5100 
    5101                 $this->bail( 'Should not have been able to reach end of IN FOREIGN CONTENT processing. Check HTML API code.' );
    5102                 // This unnecessary return prevents tools from inaccurately reporting type errors.
    5103                 return false;
    51045077        }
    51055078
    … …  
    63896362
    63906363                $this->bail( 'Should not have reached end of HTML Integration Point detection: check HTML API code.' );
    6391                 // This unnecessary return prevents tools from inaccurately reporting type errors.
    6392                 return false;
    63936364        }
    63946365
Note: See TracChangeset for help on using the changeset viewer.