@@ -670,21 +670,6 @@ static GumboInsertionMode get_appropriate_insertion_mode (
670
670
}
671
671
672
672
switch (node -> v .element .tag ) {
673
- case GUMBO_TAG_SELECT : {
674
- if (is_last ) {
675
- return GUMBO_INSERTION_MODE_IN_SELECT ;
676
- }
677
- for (int i = index ; i > 0 ; -- i ) {
678
- const GumboNode * ancestor = open_elements -> data [i ];
679
- if (node_html_tag_is (ancestor , GUMBO_TAG_TEMPLATE )) {
680
- return GUMBO_INSERTION_MODE_IN_SELECT ;
681
- }
682
- if (node_html_tag_is (ancestor , GUMBO_TAG_TABLE )) {
683
- return GUMBO_INSERTION_MODE_IN_SELECT_IN_TABLE ;
684
- }
685
- }
686
- return GUMBO_INSERTION_MODE_IN_SELECT ;
687
- }
688
673
case GUMBO_TAG_TD :
689
674
case GUMBO_TAG_TH :
690
675
if (!is_last ) return GUMBO_INSERTION_MODE_IN_CELL ;
@@ -1610,6 +1595,7 @@ static bool has_open_element(const GumboParser* parser, GumboTag tag) {
1610
1595
TAG(TH), \
1611
1596
TAG(MARQUEE), \
1612
1597
TAG(OBJECT), \
1598
+ TAG(SELECT), \
1613
1599
TAG(TEMPLATE), \
1614
1600
TAG_MATHML(MI), \
1615
1601
TAG_MATHML(MO), \
@@ -1694,12 +1680,6 @@ static bool has_an_element_in_table_scope(const GumboParser* parser, GumboTag ta
1694
1680
return has_an_element_in_specific_scope (parser , 1 , & tag , false, & tags );
1695
1681
}
1696
1682
1697
- // https://html.spec.whatwg.org/multipage/parsing.html#has-an-element-in-select-scope
1698
- static bool has_an_element_in_select_scope (const GumboParser * parser , GumboTag tag ) {
1699
- static const TagSet tags = {TAG (OPTGROUP ), TAG (OPTION )};
1700
- return has_an_element_in_specific_scope (parser , 1 , & tag , true, & tags );
1701
- }
1702
-
1703
1683
// https://html.spec.whatwg.org/multipage/parsing.html#generate-implied-end-tags
1704
1684
// "exception" is the "element to exclude from the process" listed in the spec.
1705
1685
// Pass GUMBO_TAG_LAST to not exclude any of them.
@@ -1804,18 +1784,6 @@ static void close_current_cell(GumboParser* parser, const GumboToken* token) {
1804
1784
close_table_cell (parser , token , cell_tag );
1805
1785
}
1806
1786
1807
- // This factors out the "act as if an end tag of tag name 'select' had been
1808
- // seen" clause of the spec, since it's referenced in several places. It pops
1809
- // all nodes from the stack until the current <select> has been closed, then
1810
- // resets the insertion mode appropriately.
1811
- static void close_current_select (GumboParser * parser ) {
1812
- GumboNode * node = pop_current_node (parser );
1813
- while (!node_html_tag_is (node , GUMBO_TAG_SELECT )) {
1814
- node = pop_current_node (parser );
1815
- }
1816
- reset_insertion_mode_appropriately (parser );
1817
- }
1818
-
1819
1787
// The list of nodes in the "special" category:
1820
1788
// https://html.spec.whatwg.org/multipage/parsing.html#special
1821
1789
static bool is_special_node (const GumboNode * node ) {
@@ -3310,6 +3278,10 @@ static void handle_in_body(GumboParser* parser, GumboToken* token) {
3310
3278
}
3311
3279
if (tag_is (token , kStartTag , GUMBO_TAG_HR )) {
3312
3280
maybe_implicitly_close_p_tag (parser , token );
3281
+ generate_implied_end_tags (parser , GUMBO_TAG_OPTGROUP , NULL );
3282
+ if (has_an_element_in_scope (parser , GUMBO_TAG_OPTION )) {
3283
+ parser_add_parse_error (parser , token );
3284
+ }
3313
3285
insert_element_from_token (parser , token );
3314
3286
pop_current_node (parser );
3315
3287
acknowledge_self_closing_tag (parser );
@@ -3342,30 +3314,45 @@ static void handle_in_body(GumboParser* parser, GumboToken* token) {
3342
3314
return ;
3343
3315
}
3344
3316
if (tag_is (token , kStartTag , GUMBO_TAG_SELECT )) {
3317
+ if (has_an_element_in_scope (parser , GUMBO_TAG_SELECT )) {
3318
+ parser_add_parse_error (parser , token );
3319
+ while (!node_html_tag_is (pop_current_node (parser ), GUMBO_TAG_SELECT ))
3320
+ ;
3321
+ }
3345
3322
reconstruct_active_formatting_elements (parser );
3346
3323
insert_element_from_token (parser , token );
3347
3324
set_frameset_not_ok (parser );
3348
- GumboInsertionMode state = parser -> _parser_state -> _insertion_mode ;
3349
- if (
3350
- state == GUMBO_INSERTION_MODE_IN_TABLE
3351
- || state == GUMBO_INSERTION_MODE_IN_CAPTION
3352
- || state == GUMBO_INSERTION_MODE_IN_TABLE_BODY
3353
- || state == GUMBO_INSERTION_MODE_IN_ROW
3354
- || state == GUMBO_INSERTION_MODE_IN_CELL
3355
- ) {
3356
- set_insertion_mode (parser , GUMBO_INSERTION_MODE_IN_SELECT_IN_TABLE );
3325
+ return ;
3326
+ }
3327
+ if (tag_is (token , kStartTag , GUMBO_TAG_OPTION )) {
3328
+ if (has_an_element_in_scope (parser , GUMBO_TAG_SELECT )) {
3329
+ generate_implied_end_tags (parser , GUMBO_TAG_OPTGROUP , NULL );
3330
+ if (has_an_element_in_scope (parser , GUMBO_TAG_OPTION )) {
3331
+ parser_add_parse_error (parser , token );
3332
+ }
3357
3333
} else {
3358
- set_insertion_mode (parser , GUMBO_INSERTION_MODE_IN_SELECT );
3334
+ if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
3335
+ pop_current_node (parser );
3336
+ }
3337
+ reconstruct_active_formatting_elements (parser );
3359
3338
}
3339
+ insert_element_from_token (parser , token );
3360
3340
return ;
3361
3341
}
3362
- if (
3363
- tag_in (token , kStartTag , & (const TagSet ){TAG (OPTGROUP ), TAG (OPTION )})
3364
- ) {
3365
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
3366
- pop_current_node (parser );
3342
+ if (tag_is (token , kStartTag , GUMBO_TAG_OPTGROUP )) {
3343
+ if (has_an_element_in_scope (parser , GUMBO_TAG_SELECT )) {
3344
+ generate_implied_end_tags (parser , GUMBO_TAG_LAST , NULL );
3345
+ if (has_an_element_in_scope_with_tagname (parser , 2 , (GumboTag []) {
3346
+ GUMBO_TAG_OPTION , GUMBO_TAG_OPTGROUP
3347
+ })) {
3348
+ parser_add_parse_error (parser , token );
3349
+ }
3350
+ } else {
3351
+ if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
3352
+ pop_current_node (parser );
3353
+ }
3354
+ reconstruct_active_formatting_elements (parser );
3367
3355
}
3368
- reconstruct_active_formatting_elements (parser );
3369
3356
insert_element_from_token (parser , token );
3370
3357
return ;
3371
3358
}
@@ -3944,159 +3931,6 @@ static void handle_in_cell(GumboParser* parser, GumboToken* token) {
3944
3931
handle_in_body (parser , token );
3945
3932
}
3946
3933
3947
- // https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inselect
3948
- static void handle_in_select (GumboParser * parser , GumboToken * token ) {
3949
- if (token -> type == GUMBO_TOKEN_NULL ) {
3950
- parser_add_parse_error (parser , token );
3951
- ignore_token (parser );
3952
- return ;
3953
- }
3954
- if (
3955
- token -> type == GUMBO_TOKEN_CHARACTER
3956
- || token -> type == GUMBO_TOKEN_WHITESPACE
3957
- ) {
3958
- insert_text_token (parser , token );
3959
- return ;
3960
- }
3961
- if (token -> type == GUMBO_TOKEN_COMMENT ) {
3962
- append_comment_node (parser , get_current_node (parser ), token );
3963
- return ;
3964
- }
3965
- if (token -> type == GUMBO_TOKEN_DOCTYPE ) {
3966
- parser_add_parse_error (parser , token );
3967
- ignore_token (parser );
3968
- return ;
3969
- }
3970
- if (tag_is (token , kStartTag , GUMBO_TAG_HTML )) {
3971
- handle_in_body (parser , token );
3972
- return ;
3973
- }
3974
- if (tag_is (token , kStartTag , GUMBO_TAG_OPTION )) {
3975
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
3976
- pop_current_node (parser );
3977
- }
3978
- insert_element_from_token (parser , token );
3979
- return ;
3980
- }
3981
- if (tag_is (token , kStartTag , GUMBO_TAG_OPTGROUP )) {
3982
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
3983
- pop_current_node (parser );
3984
- }
3985
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTGROUP )) {
3986
- pop_current_node (parser );
3987
- }
3988
- insert_element_from_token (parser , token );
3989
- return ;
3990
- }
3991
- if (tag_is (token , kStartTag , GUMBO_TAG_HR )) {
3992
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
3993
- pop_current_node (parser );
3994
- }
3995
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTGROUP )) {
3996
- pop_current_node (parser );
3997
- }
3998
- insert_element_from_token (parser , token );
3999
- pop_current_node (parser );
4000
- acknowledge_self_closing_tag (parser );
4001
- return ;
4002
- }
4003
- if (tag_is (token , kEndTag , GUMBO_TAG_OPTGROUP )) {
4004
- GumboVector * open_elements = & parser -> _parser_state -> _open_elements ;
4005
- if (
4006
- node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )
4007
- && node_html_tag_is (
4008
- open_elements -> data [open_elements -> length - 2 ],
4009
- GUMBO_TAG_OPTGROUP
4010
- )
4011
- ) {
4012
- pop_current_node (parser );
4013
- }
4014
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTGROUP )) {
4015
- pop_current_node (parser );
4016
- return ;
4017
- }
4018
- parser_add_parse_error (parser , token );
4019
- ignore_token (parser );
4020
- return ;
4021
- }
4022
- if (tag_is (token , kEndTag , GUMBO_TAG_OPTION )) {
4023
- if (node_html_tag_is (get_current_node (parser ), GUMBO_TAG_OPTION )) {
4024
- pop_current_node (parser );
4025
- return ;
4026
- }
4027
- parser_add_parse_error (parser , token );
4028
- ignore_token (parser );
4029
- return ;
4030
- }
4031
- if (tag_is (token , kEndTag , GUMBO_TAG_SELECT )) {
4032
- if (!has_an_element_in_select_scope (parser , GUMBO_TAG_SELECT )) {
4033
- parser_add_parse_error (parser , token );
4034
- ignore_token (parser );
4035
- return ;
4036
- }
4037
- close_current_select (parser );
4038
- return ;
4039
- }
4040
- if (tag_is (token , kStartTag , GUMBO_TAG_SELECT )) {
4041
- parser_add_parse_error (parser , token );
4042
- ignore_token (parser );
4043
- if (has_an_element_in_select_scope (parser , GUMBO_TAG_SELECT )) {
4044
- close_current_select (parser );
4045
- }
4046
- return ;
4047
- }
4048
- if (
4049
- tag_in (token , kStartTag , & (const TagSet ) {TAG (INPUT ), TAG (KEYGEN ), TAG (TEXTAREA )})
4050
- ) {
4051
- parser_add_parse_error (parser , token );
4052
- if (!has_an_element_in_select_scope (parser , GUMBO_TAG_SELECT )) {
4053
- ignore_token (parser );
4054
- } else {
4055
- close_current_select (parser );
4056
- parser -> _parser_state -> _reprocess_current_token = true;
4057
- }
4058
- return ;
4059
- }
4060
- if (
4061
- tag_in (token , kStartTag , & (const TagSet ){TAG (SCRIPT ), TAG (TEMPLATE )})
4062
- || tag_is (token , kEndTag , GUMBO_TAG_TEMPLATE )
4063
- ) {
4064
- handle_in_head (parser , token );
4065
- return ;
4066
- }
4067
- if (token -> type == GUMBO_TOKEN_EOF ) {
4068
- handle_in_body (parser , token );
4069
- return ;
4070
- }
4071
- parser_add_parse_error (parser , token );
4072
- ignore_token (parser );
4073
- }
4074
-
4075
- // https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inselectintable
4076
- static void handle_in_select_in_table (GumboParser * parser , GumboToken * token ) {
4077
- static const TagSet tags = {
4078
- TAG (CAPTION ), TAG (TABLE ), TAG (TBODY ), TAG (TFOOT ), TAG (THEAD ),
4079
- TAG (TR ), TAG (TD ), TAG (TH )
4080
- };
4081
- if (tag_in (token , kStartTag , & tags )) {
4082
- parser_add_parse_error (parser , token );
4083
- close_current_select (parser );
4084
- parser -> _parser_state -> _reprocess_current_token = true;
4085
- return ;
4086
- }
4087
- if (tag_in (token , kEndTag , & tags )) {
4088
- parser_add_parse_error (parser , token );
4089
- if (!has_an_element_in_table_scope (parser , token -> v .end_tag .tag )) {
4090
- ignore_token (parser );
4091
- return ;
4092
- }
4093
- close_current_select (parser );
4094
- parser -> _parser_state -> _reprocess_current_token = true;
4095
- return ;
4096
- }
4097
- handle_in_select (parser , token );
4098
- }
4099
-
4100
3934
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-intemplate
4101
3935
static void handle_in_template (GumboParser * parser , GumboToken * token ) {
4102
3936
GumboParserState * state = parser -> _parser_state ;
@@ -4395,8 +4229,6 @@ static const TokenHandler kTokenHandlers[] = {
4395
4229
handle_in_table_body ,
4396
4230
handle_in_row ,
4397
4231
handle_in_cell ,
4398
- handle_in_select ,
4399
- handle_in_select_in_table ,
4400
4232
handle_in_template ,
4401
4233
handle_after_body ,
4402
4234
handle_in_frameset ,
0 commit comments