Make WordPress Core

Changeset 62689


Ignore:
Timestamp:
07/10/2026 05:22:53 PM (4 weeks ago)
Author:
jonsurrell
Message:

HTML API: Update SELECT element parsing according to specification.

The HTML standard was updated to support customizable SELECT elements. Update HTML API parsing accordingly.

Developed in https://github.com/WordPress/wordpress-develop/pull/9298.

Props jonsurrell, dmsnell.
Fixes #63736.

Location:
trunk
Files:
1 added
5 edited

Legend:

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

    r62575 r62689  
    282282         * >   - marquee
    283283         * >   - object
     284         * >   - select
    284285         * >   - template
    285286         * >   - MathML mi
     
    313314                                'MARQUEE',
    314315                                'OBJECT',
     316                                'SELECT',
    315317                                'TEMPLATE',
    316318
     
    363365                                'OBJECT',
    364366                                'OL',
     367                                'SELECT',
    365368                                'TEMPLATE',
    366369                                'UL',
     
    411414                                'MARQUEE',
    412415                                'OBJECT',
     416                                'SELECT',
    413417                                'TEMPLATE',
    414418
     
    460464         * Returns whether a particular element is in select scope.
    461465         *
    462          * This test differs from the others like it, in that its rules are inverted.
    463          * Instead of arriving at a match when one of any tag in a termination group
    464          * is reached, this one terminates if any other tag is reached.
     466         * The "select scope" concept was removed from the HTML standard along with the
     467         * customizable `<select>` changes, so nothing is ever in select scope.
    465468         *
    466469         * > The stack of open elements is said to have a particular element in select scope when it has
     
    472475         * @since 6.7.0 Full implementation.
    473476         *
    474          * @see https://html.spec.whatwg.org/#has-an-element-in-select-scope
     477         * @deprecated 7.1.0 This method is no longer part of the HTML standard.
     478         * @ignore
    475479         *
    476480         * @param string $tag_name Name of tag to check.
    477          * @return bool Whether the given element is in SELECT scope.
     481         * @return bool Always false; select scope no longer exists.
    478482         */
    479483        public function has_element_in_select_scope( string $tag_name ): bool {
    480                 foreach ( $this->walk_up() as $node ) {
    481                         if ( $node->node_name === $tag_name ) {
    482                                 return true;
    483                         }
    484 
    485                         if (
    486                                 'OPTION' !== $node->node_name &&
    487                                 'OPTGROUP' !== $node->node_name
    488                         ) {
    489                                 return false;
    490                         }
    491                 }
     484                _deprecated_function( __METHOD__, '7.1.0' );
    492485
    493486                return false;
     
    698691                        case 'MARQUEE':
    699692                        case 'OBJECT':
     693                        case 'SELECT':
    700694                        case 'TEMPLATE':
    701695                        case 'math MI':
     
    754748                        case 'MARQUEE':
    755749                        case 'OBJECT':
     750                        case 'SELECT':
    756751                        case 'TEMPLATE':
    757752                        case 'math MI':
  • trunk/src/wp-includes/html-api/class-wp-html-processor-state.php

    r61793 r62689  
    210210         * @since 6.7.0
    211211         *
    212          * @see https://html.spec.whatwg.org/#parsing-main-inselect
     212         * @deprecated 7.1.0 The "in select" insertion mode was removed from the standard.
     213         * @ignore
     214         *
    213215         * @see WP_HTML_Processor_State::$insertion_mode
    214216         *
     
    222224         * @since 6.7.0
    223225         *
    224          * @see https://html.spec.whatwg.org/#parsing-main-inselectintable
     226         * @deprecated 7.1.0 The "in select in table" insertion mode was removed from the standard.
     227         * @ignore
     228         *
    225229         * @see WP_HTML_Processor_State::$insertion_mode
    226230         *
  • trunk/src/wp-includes/html-api/class-wp-html-processor.php

    r62687 r62689  
    136136 * these situations and will bail.
    137137 *
     138 * The parser does not implement the "maybe clone an option into selectedcontent" algorithm.
     139 * SELECTEDCONTENT elements may not reflect the actual selected content.
     140 *
    138141 * @since 6.4.0
    139142 *
    140143 * @see WP_HTML_Tag_Processor
    141  * @see https://html.spec.whatwg.org/
     144 * @link https://html.spec.whatwg.org/
    142145 * @phpstan-consistent-constructor
    143146 */
     
    11431146                                case WP_HTML_Processor_State::INSERTION_MODE_IN_CELL:
    11441147                                        return $this->step_in_cell();
    1145 
    1146                                 case WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT:
    1147                                         return $this->step_in_select();
    1148 
    1149                                 case WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT_IN_TABLE:
    1150                                         return $this->step_in_select_in_table();
    11511148
    11521149                                case WP_HTML_Processor_State::INSERTION_MODE_IN_TEMPLATE:
     
    26822679                         * > "button", "center", "details", "dialog", "dir", "div", "dl", "fieldset",
    26832680                         * > "figcaption", "figure", "footer", "header", "hgroup", "listing", "main",
    2684                          * > "menu", "nav", "ol", "pre", "search", "section", "summary", "ul"
     2681                         * > "menu", "nav", "ol", "pre", "search", "section", "select", "summary", "ul"
    26852682                         */
    26862683                        case '-ADDRESS':
     
    27092706                        case '-SEARCH':
    27102707                        case '-SECTION':
     2708                        case '-SELECT':
    27112709                        case '-SUMMARY':
    27122710                        case '-UL':
     
    30273025                         */
    30283026                        case '+INPUT':
     3027                                /*
     3028                                 * > If the parser was created as part of the HTML fragment parsing algorithm
     3029                                 * > (fragment case) and the context element passed to that algorithm is a
     3030                                 * > select element:
     3031                                 * >   1. Parse error.
     3032                                 * >   2. Ignore the token.
     3033                                 * >   3. Return.
     3034                                 */
     3035                                if ( isset( $this->context_node ) && 'SELECT' === $this->context_node->node_name ) {
     3036                                        return $this->step();
     3037                                }
     3038
     3039                                /*
     3040                                 * > If the stack of open elements has a select element in scope:
     3041                                 * >   1. Parse error.
     3042                                 * >   2. Pop elements from the stack of open elements until a select element
     3043                                 * >      has been popped from the stack.
     3044                                 */
     3045                                if ( $this->state->stack_of_open_elements->has_element_in_scope( 'SELECT' ) ) {
     3046                                        $this->state->stack_of_open_elements->pop_until( 'SELECT' );
     3047                                }
     3048
    30293049                                $this->reconstruct_active_formatting_elements();
    30303050                                $this->insert_html_element( $this->state->current_token );
     
    30583078                                        $this->close_a_p_element();
    30593079                                }
     3080
     3081                                if ( $this->state->stack_of_open_elements->has_element_in_scope( 'SELECT' ) ) {
     3082                                        $this->generate_implied_end_tags();
     3083                                        /*
     3084                                         * > If the stack of open elements has an option element in scope or has
     3085                                         * > an optgroup element in scope, then this is a parse error.
     3086                                         *
     3087                                         * @todo Indicate a parse error once it's possible.
     3088                                         */
     3089                                }
     3090
    30603091                                $this->insert_html_element( $this->state->current_token );
    30613092                                $this->state->frameset_ok = false;
     
    31443175                         */
    31453176                        case '+SELECT':
     3177                                /*
     3178                                 * > If the parser was created as part of the HTML fragment parsing algorithm
     3179                                 * > (fragment case) and the context element passed to that algorithm is a
     3180                                 * > select element:
     3181                                 * >   1. Parse error.
     3182                                 * >   2. Ignore the token.
     3183                                 */
     3184                                if ( isset( $this->context_node ) && 'SELECT' === $this->context_node->node_name ) {
     3185                                        // @todo Indicate a parse error once it's possible.
     3186                                        return $this->step();
     3187                                }
     3188                                /*
     3189                                 * > Otherwise, if the stack of open elements has a select element in scope:
     3190                                 * >   1. Parse error.
     3191                                 * >   2. Ignore the token.
     3192                                 * >   3. Pop elements from the stack of open elements until a select element
     3193                                 * >      has been popped from the stack.
     3194                                 */
     3195                                if ( $this->state->stack_of_open_elements->has_element_in_scope( 'SELECT' ) ) {
     3196                                        // @todo Indicate a parse error once it's possible.
     3197                                        $this->state->stack_of_open_elements->pop_until( 'SELECT' );
     3198                                        return $this->step();
     3199                                }
     3200
    31463201                                $this->reconstruct_active_formatting_elements();
    31473202                                $this->insert_html_element( $this->state->current_token );
    31483203                                $this->state->frameset_ok = false;
    3149 
    3150                                 switch ( $this->state->insertion_mode ) {
     3204                                return true;
     3205
     3206                        /*
     3207                         * > A start tag whose tag name is "option"
     3208                         */
     3209                        case '+OPTION':
     3210                                if ( $this->state->stack_of_open_elements->has_element_in_scope( 'SELECT' ) ) {
     3211                                        $this->generate_implied_end_tags( 'OPTGROUP' );
    31513212                                        /*
    3152                                          * > If the insertion mode is one of "in table", "in caption", "in table body", "in row",
    3153                                          * > or "in cell", then switch the insertion mode to "in select in table".
     3213                                         * > If the stack of open elements has an option element in scope, then this
     3214                                         * > is a parse error.
     3215                                         * @todo Indicate a parse error once it's possible.
    31543216                                         */
    3155                                         case WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE:
    3156                                         case WP_HTML_Processor_State::INSERTION_MODE_IN_CAPTION:
    3157                                         case WP_HTML_Processor_State::INSERTION_MODE_IN_TABLE_BODY:
    3158                                         case WP_HTML_Processor_State::INSERTION_MODE_IN_ROW:
    3159                                         case WP_HTML_Processor_State::INSERTION_MODE_IN_CELL:
    3160                                                 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT_IN_TABLE;
    3161                                                 break;
    3162 
     3217                                } elseif ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) {
     3218                                        $this->state->stack_of_open_elements->pop();
     3219                                }
     3220
     3221                                $this->reconstruct_active_formatting_elements();
     3222                                $this->insert_html_element( $this->state->current_token );
     3223                                return true;
     3224
     3225                        /*
     3226                         * > A start tag whose tag name is "optgroup"
     3227                         */
     3228                        case '+OPTGROUP':
     3229                                if ( $this->state->stack_of_open_elements->has_element_in_scope( 'SELECT' ) ) {
     3230                                        $this->generate_implied_end_tags();
    31633231                                        /*
    3164                                          * > Otherwise, switch the insertion mode to "in select".
     3232                                         * > If the stack of open elements has an option element in scope or has an
     3233                                         * > optgroup element in scope, then this is a parse error.
     3234                                         * @todo Indicate a parse error once it's possible.
    31653235                                         */
    3166                                         default:
    3167                                                 $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT;
    3168                                                 break;
    3169                                 }
    3170                                 return true;
    3171 
    3172                         /*
    3173                          * > A start tag whose tag name is one of: "optgroup", "option"
    3174                          */
    3175                         case '+OPTGROUP':
    3176                         case '+OPTION':
    3177                                 if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) {
     3236                                } elseif ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) {
    31783237                                        $this->state->stack_of_open_elements->pop();
    31793238                                }
     3239
    31803240                                $this->reconstruct_active_formatting_elements();
    31813241                                $this->insert_html_element( $this->state->current_token );
     
    41334193                 */
    41344194                return $this->step_in_body();
    4135         }
    4136 
    4137         /**
    4138          * Parses next element in the 'in select' insertion mode.
    4139          *
    4140          * This internal function performs the 'in select' insertion mode
    4141          * logic for the generalized WP_HTML_Processor::step() function.
    4142          *
    4143          * @since 6.7.0
    4144          * @ignore
    4145          *
    4146          * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input.
    4147          *
    4148          * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inselect
    4149          * @see WP_HTML_Processor::step
    4150          *
    4151          * @return bool Whether an element was found.
    4152          */
    4153         private function step_in_select(): bool {
    4154                 $token_name = $this->get_token_name();
    4155                 $token_type = $this->get_token_type();
    4156                 $op_sigil   = '#tag' === $token_type ? ( parent::is_tag_closer() ? '-' : '+' ) : '';
    4157                 $op         = "{$op_sigil}{$token_name}";
    4158 
    4159                 switch ( $op ) {
    4160                         /*
    4161                          * > Any other character token
    4162                          */
    4163                         case '#text':
    4164                                 /*
    4165                                  * > A character token that is U+0000 NULL
    4166                                  *
    4167                                  * If a text node only comprises null bytes then it should be
    4168                                  * entirely ignored and should not return to calling code.
    4169                                  */
    4170                                 if ( parent::TEXT_IS_NULL_SEQUENCE === $this->text_node_classification ) {
    4171                                         // Parse error: ignore the token.
    4172                                         return $this->step();
    4173                                 }
    4174 
    4175                                 $this->insert_html_element( $this->state->current_token );
    4176                                 return true;
    4177 
    4178                         /*
    4179                          * > A comment token
    4180                          * > A processing instruction token
    4181                          */
    4182                         case '#comment':
    4183                         case '#funky-comment':
    4184                         case '#presumptuous-tag':
    4185                         case '#processing-instruction':
    4186                                 $this->insert_html_element( $this->state->current_token );
    4187                                 return true;
    4188 
    4189                         /*
    4190                          * > A DOCTYPE token
    4191                          */
    4192                         case 'html':
    4193                                 // Parse error: ignore the token.
    4194                                 return $this->step();
    4195 
    4196                         /*
    4197                          * > A start tag whose tag name is "html"
    4198                          */
    4199                         case '+HTML':
    4200                                 return $this->step_in_body();
    4201 
    4202                         /*
    4203                          * > A start tag whose tag name is "option"
    4204                          */
    4205                         case '+OPTION':
    4206                                 if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) {
    4207                                         $this->state->stack_of_open_elements->pop();
    4208                                 }
    4209                                 $this->insert_html_element( $this->state->current_token );
    4210                                 return true;
    4211 
    4212                         /*
    4213                          * > A start tag whose tag name is "optgroup"
    4214                          * > A start tag whose tag name is "hr"
    4215                          *
    4216                          * These rules are identical except for the treatment of the self-closing flag and
    4217                          * the subsequent pop of the HR void element, all of which is handled elsewhere in the processor.
    4218                          */
    4219                         case '+OPTGROUP':
    4220                         case '+HR':
    4221                                 if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) {
    4222                                         $this->state->stack_of_open_elements->pop();
    4223                                 }
    4224 
    4225                                 if ( $this->state->stack_of_open_elements->current_node_is( 'OPTGROUP' ) ) {
    4226                                         $this->state->stack_of_open_elements->pop();
    4227                                 }
    4228 
    4229                                 $this->insert_html_element( $this->state->current_token );
    4230                                 return true;
    4231 
    4232                         /*
    4233                          * > An end tag whose tag name is "optgroup"
    4234                          */
    4235                         case '-OPTGROUP':
    4236                                 $current_node = $this->state->stack_of_open_elements->current_node();
    4237                                 if ( $current_node && 'OPTION' === $current_node->node_name ) {
    4238                                         foreach ( $this->state->stack_of_open_elements->walk_up( $current_node ) as $parent ) {
    4239                                                 break;
    4240                                         }
    4241                                         if ( $parent && 'OPTGROUP' === $parent->node_name ) {
    4242                                                 $this->state->stack_of_open_elements->pop();
    4243                                         }
    4244                                 }
    4245 
    4246                                 if ( $this->state->stack_of_open_elements->current_node_is( 'OPTGROUP' ) ) {
    4247                                         $this->state->stack_of_open_elements->pop();
    4248                                         return true;
    4249                                 }
    4250 
    4251                                 // Parse error: ignore the token.
    4252                                 return $this->step();
    4253 
    4254                         /*
    4255                          * > An end tag whose tag name is "option"
    4256                          */
    4257                         case '-OPTION':
    4258                                 if ( $this->state->stack_of_open_elements->current_node_is( 'OPTION' ) ) {
    4259                                         $this->state->stack_of_open_elements->pop();
    4260                                         return true;
    4261                                 }
    4262 
    4263                                 // Parse error: ignore the token.
    4264                                 return $this->step();
    4265 
    4266                         /*
    4267                          * > An end tag whose tag name is "select"
    4268                          * > A start tag whose tag name is "select"
    4269                          *
    4270                          * > It just gets treated like an end tag.
    4271                          */
    4272                         case '-SELECT':
    4273                         case '+SELECT':
    4274                                 if ( ! $this->state->stack_of_open_elements->has_element_in_select_scope( 'SELECT' ) ) {
    4275                                         // Parse error: ignore the token.
    4276                                         return $this->step();
    4277                                 }
    4278                                 $this->state->stack_of_open_elements->pop_until( 'SELECT' );
    4279                                 $this->reset_insertion_mode_appropriately();
    4280                                 return true;
    4281 
    4282                         /*
    4283                          * > A start tag whose tag name is one of: "input", "keygen", "textarea"
    4284                          *
    4285                          * All three of these tags are considered a parse error when found in this insertion mode.
    4286                          */
    4287                         case '+INPUT':
    4288                         case '+KEYGEN':
    4289                         case '+TEXTAREA':
    4290                                 if ( ! $this->state->stack_of_open_elements->has_element_in_select_scope( 'SELECT' ) ) {
    4291                                         // Ignore the token.
    4292                                         return $this->step();
    4293                                 }
    4294                                 $this->state->stack_of_open_elements->pop_until( 'SELECT' );
    4295                                 $this->reset_insertion_mode_appropriately();
    4296                                 return $this->step( self::REPROCESS_CURRENT_NODE );
    4297 
    4298                         /*
    4299                          * > A start tag whose tag name is one of: "script", "template"
    4300                          * > An end tag whose tag name is "template"
    4301                          */
    4302                         case '+SCRIPT':
    4303                         case '+TEMPLATE':
    4304                         case '-TEMPLATE':
    4305                                 return $this->step_in_head();
    4306                 }
    4307 
    4308                 /*
    4309                  * > Anything else
    4310                  * >   Parse error: ignore the token.
    4311                  */
    4312                 return $this->step();
    4313         }
    4314 
    4315         /**
    4316          * Parses next element in the 'in select in table' insertion mode.
    4317          *
    4318          * This internal function performs the 'in select in table' insertion mode
    4319          * logic for the generalized WP_HTML_Processor::step() function.
    4320          *
    4321          * @since 6.7.0
    4322          * @ignore
    4323          *
    4324          * @throws WP_HTML_Unsupported_Exception When encountering unsupported HTML input.
    4325          *
    4326          * @see https://html.spec.whatwg.org/#parsing-main-inselectintable
    4327          * @see WP_HTML_Processor::step
    4328          *
    4329          * @return bool Whether an element was found.
    4330          */
    4331         private function step_in_select_in_table(): bool {
    4332                 $token_name = $this->get_token_name();
    4333                 $token_type = $this->get_token_type();
    4334                 $op_sigil   = '#tag' === $token_type ? ( parent::is_tag_closer() ? '-' : '+' ) : '';
    4335                 $op         = "{$op_sigil}{$token_name}";
    4336 
    4337                 switch ( $op ) {
    4338                         /*
    4339                          * > A start tag whose tag name is one of: "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"
    4340                          */
    4341                         case '+CAPTION':
    4342                         case '+TABLE':
    4343                         case '+TBODY':
    4344                         case '+TFOOT':
    4345                         case '+THEAD':
    4346                         case '+TR':
    4347                         case '+TD':
    4348                         case '+TH':
    4349                                 // @todo Indicate a parse error once it's possible.
    4350                                 $this->state->stack_of_open_elements->pop_until( 'SELECT' );
    4351                                 $this->reset_insertion_mode_appropriately();
    4352                                 return $this->step( self::REPROCESS_CURRENT_NODE );
    4353 
    4354                         /*
    4355                          * > An end tag whose tag name is one of: "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"
    4356                          */
    4357                         case '-CAPTION':
    4358                         case '-TABLE':
    4359                         case '-TBODY':
    4360                         case '-TFOOT':
    4361                         case '-THEAD':
    4362                         case '-TR':
    4363                         case '-TD':
    4364                         case '-TH':
    4365                                 // @todo Indicate a parse error once it's possible.
    4366                                 if ( ! $this->state->stack_of_open_elements->has_element_in_table_scope( $token_name ) ) {
    4367                                         return $this->step();
    4368                                 }
    4369                                 $this->state->stack_of_open_elements->pop_until( 'SELECT' );
    4370                                 $this->reset_insertion_mode_appropriately();
    4371                                 return $this->step( self::REPROCESS_CURRENT_NODE );
    4372                 }
    4373 
    4374                 /*
    4375                  * > Anything else
    4376                  */
    4377                 return $this->step_in_select();
    43784195        }
    43794196
     
    52365053                                        return $this->step_in_cell();
    52375054
    5238                                 case WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT:
    5239                                         return $this->step_in_select();
    5240 
    5241                                 case WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT_IN_TABLE:
    5242                                         return $this->step_in_select_in_table();
    5243 
    52445055                                case WP_HTML_Processor_State::INSERTION_MODE_IN_TEMPLATE:
    52455056                                        return $this->step_in_template();
     
    61395950                        switch ( $node->node_name ) {
    61405951                                /*
    6141                                  * > 4. If node is a `select` element, run these substeps:
    6142                                  * >   1. If _last_ is true, jump to the step below labeled done.
    6143                                  * >   2. Let _ancestor_ be _node_.
    6144                                  * >   3. _Loop_: If _ancestor_ is the first node in the stack of open elements,
    6145                                  * >      jump to the step below labeled done.
    6146                                  * >   4. Let ancestor be the node before ancestor in the stack of open elements.
    6147                                  * >   …
    6148                                  * >   7. Jump back to the step labeled _loop_.
    6149                                  * >   8. _Done_: Switch the insertion mode to "in select" and return.
    6150                                  */
    6151                                 case 'SELECT':
    6152                                         if ( ! $last ) {
    6153                                                 foreach ( $this->state->stack_of_open_elements->walk_up( $node ) as $ancestor ) {
    6154                                                         if ( 'html' !== $ancestor->namespace ) {
    6155                                                                 continue;
    6156                                                         }
    6157 
    6158                                                         switch ( $ancestor->node_name ) {
    6159                                                                 /*
    6160                                                                  * > 5. If _ancestor_ is a `template` node, jump to the step below
    6161                                                                  * >    labeled _done_.
    6162                                                                  */
    6163                                                                 case 'TEMPLATE':
    6164                                                                         break 2;
    6165 
    6166                                                                 /*
    6167                                                                  * > 6. If _ancestor_ is a `table` node, switch the insertion mode to
    6168                                                                  * >    "in select in table" and return.
    6169                                                                  */
    6170                                                                 case 'TABLE':
    6171                                                                         $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT_IN_TABLE;
    6172                                                                         return;
    6173                                                         }
    6174                                                 }
    6175                                         }
    6176                                         $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_SELECT;
    6177                                         return;
    6178 
    6179                                 /*
    6180                                  * > 5. If _node_ is a `td` or `th` element and _last_ is false, then switch the
     5952                                 * > 4. If _node_ is a `td` or `th` element and _last_ is false, then switch the
    61815953                                 * >    insertion mode to "in cell" and return.
    61825954                                 */
     
    61895961                                        break;
    61905962
    6191                                         /*
    6192                                         * > 6. If _node_ is a `tr` element, then switch the insertion mode to "in row"
    6193                                         * >    and return.
    6194                                         */
     5963                                /*
     5964                                * > 5. If _node_ is a `tr` element, then switch the insertion mode to "in row"
     5965                                * >    and return.
     5966                                */
    61955967                                case 'TR':
    61965968                                        $this->state->insertion_mode = WP_HTML_Processor_State::INSERTION_MODE_IN_ROW;
     
    61985970
    61995971                                /*
    6200                                  * > 7. If _node_ is a `tbody`, `thead`, or `tfoot` element, then switch the
     5972                                 * > 6. If _node_ is a `tbody`, `thead`, or `tfoot` element, then switch the
    62015973                                 * >    insertion mode to "in table body" and return.
    62025974                                 */
     
    62085980
    62095981                                /*
    6210                                  * > 8. If _node_ is a `caption` element, then switch the insertion mode to
     5982                                 * > 7. If _node_ is a `caption` element, then switch the insertion mode to
    62115983                                 * >    "in caption" and return.
    62125984                                 */
     
    62165988
    62175989                                /*
    6218                                  * > 9. If _node_ is a `colgroup` element, then switch the insertion mode to
     5990                                 * > 8. If _node_ is a `colgroup` element, then switch the insertion mode to
    62195991                                 * >    "in column group" and return.
    62205992                                 */
     
    62245996
    62255997                                /*
    6226                                  * > 10. If _node_ is a `table` element, then switch the insertion mode to
    6227                                  * >     "in table" and return.
     5998                                 * > 9. If _node_ is a `table` element, then switch the insertion mode to
     5999                                 * >    "in table" and return.
    62286000                                 */
    62296001                                case 'TABLE':
     
    62326004
    62336005                                /*
    6234                                  * > 11. If _node_ is a `template` element, then switch the insertion mode to the
     6006                                 * > 10. If _node_ is a `template` element, then switch the insertion mode to the
    62356007                                 * >     current template insertion mode and return.
    62366008                                 */
     
    62406012
    62416013                                /*
    6242                                  * > 12. If _node_ is a `head` element and _last_ is false, then switch the
     6014                                 * > 11. If _node_ is a `head` element and _last_ is false, then switch the
    62436015                                 * >     insertion mode to "in head" and return.
    62446016                                 */
     
    62516023
    62526024                                /*
    6253                                  * > 13. If _node_ is a `body` element, then switch the insertion mode to "in body"
     6025                                 * > 12. If _node_ is a `body` element, then switch the insertion mode to "in body"
    62546026                                 * >     and return.
    62556027                                 */
     
    62596031
    62606032                                /*
    6261                                  * > 14. If _node_ is a `frameset` element, then switch the insertion mode to
     6033                                 * > 13. If _node_ is a `frameset` element, then switch the insertion mode to
    62626034                                 * >     "in frameset" and return. (fragment case)
    62636035                                 */
     
    62676039
    62686040                                /*
    6269                                  * > 15. If _node_ is an `html` element, run these substeps:
     6041                                 * > 14. If _node_ is an `html` element, run these substeps:
    62706042                                 * >     1. If the head element pointer is null, switch the insertion mode to
    62716043                                 * >        "before head" and return. (fragment case)
     
    62826054
    62836055                /*
    6284                  * > 16. If _last_ is true, then switch the insertion mode to "in body"
     6056                 * > 15. If _last_ is true, then switch the insertion mode to "in body"
    62856057                 * >     and return. (fragment case)
    62866058                 *
  • trunk/tests/phpunit/tests/html-api/wpHtmlProcessor-serialize.php

    r62687 r62689  
    4242                        '<div></div>',
    4343                        'Should have provided the explicit closer to the un-closed DIV element.'
     44                );
     45        }
     46
     47        /**
     48         * Ensures that SELECTEDCONTENT is parsed like an ordinary element.
     49         *
     50         * @ticket 63736
     51         */
     52        public function test_selectedcontent_is_not_unsupported() {
     53                $this->assertSame(
     54                        WP_HTML_Processor::normalize( '<select><button><selectedcontent></button><option selected>Y' ),
     55                        '<select><button><selectedcontent></selectedcontent></button><option selected>Y</option></select>',
     56                        'Should not bail on SELECTEDCONTENT when selected OPTION cloning would be needed.'
    4457                );
    4558        }
  • trunk/tests/phpunit/tests/html-api/wpHtmlProcessorWebPlatformTests.php

    r62687 r62689  
    2828         */
    2929        const SKIP_TESTS = array(
    30                 'noscript01/line0014'       => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    31                 'tests14/line0022'          => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    32                 'tests14/line0055'          => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    33                 'tests19/line0488'          => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    34                 'tests19/line0500'          => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    35                 'tests19/line1079'          => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    36                 'tests2/line0207'           => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    37                 'tests2/line0686'           => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    38                 'tests2/line0697'           => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    39                 'tests2/line0709'           => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    40                 'menuitem-element/line0161' => 'Unimplemented: This parser does not support customizable SELECT element content.',
    41                 'tests9/line0048'           => 'Unimplemented: This parser does not support customizable SELECT element content.',
    42                 'tests9/line0059'           => 'Unimplemented: This parser does not support customizable SELECT element content.',
    43                 'tests9/line0299'           => 'Unimplemented: This parser does not support customizable SELECT element content.',
    44                 'tests10/line0035'          => 'Unimplemented: This parser does not support customizable SELECT element content.',
    45                 'tests10/line0046'          => 'Unimplemented: This parser does not support customizable SELECT element content.',
    46                 'tests10/line0259'          => 'Unimplemented: This parser does not support customizable SELECT element content.',
    47                 'tests18/line0227'          => 'Unimplemented: This parser does not support customizable SELECT element content.',
    48                 'webkit01/line0231'         => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
    49                 'webkit02/line0557'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    50                 'webkit02/line0590'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    51                 'webkit02/line0611'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    52                 'webkit02/line0624'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    53                 'webkit02/line0637'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    54                 'webkit02/line0652'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    55                 'webkit02/line0666'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    56                 'webkit02/line0692'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    57                 'webkit02/line0706'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    58                 'webkit02/line0732'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
    59                 'webkit02/line0748'         => 'Unimplemented: This parser does not support customizable SELECT element content.',
     30                'noscript01/line0014' => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     31                'tests14/line0022'    => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     32                'tests14/line0055'    => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     33                'tests19/line0488'    => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     34                'tests19/line0500'    => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     35                'tests19/line1079'    => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     36                'tests2/line0207'     => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     37                'tests2/line0686'     => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     38                'tests2/line0697'     => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     39                'tests2/line0709'     => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     40                'webkit01/line0231'   => 'Unimplemented: This parser does not add missing attributes to existing HTML or BODY tags.',
     41                'webkit02/line0692'   => 'Unimplemented: The parser does not implement the "maybe clone an option into selectedcontent" algorithm.',
     42                'webkit02/line0732'   => 'Unimplemented: The parser does not implement the "maybe clone an option into selectedcontent" algorithm.',
     43                'webkit02/line0748'   => 'Unimplemented: The parser does not implement the "maybe clone an option into selectedcontent" algorithm.',
    6044        );
    6145
Note: See TracChangeset for help on using the changeset viewer.