/[suikacvs]/markup/html/whatpm/Whatpm/HTML.pm.src
Suika

Diff of /markup/html/whatpm/Whatpm/HTML.pm.src

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.77 by wakaba, Mon Mar 3 10:20:19 2008 UTC revision 1.101 by wakaba, Sun Mar 9 05:12:05 2008 UTC
# Line 303  sub TABLE_IMS ()      { 0b1000000 } Line 303  sub TABLE_IMS ()      { 0b1000000 }
303  sub ROW_IMS ()        { 0b10000000 }  sub ROW_IMS ()        { 0b10000000 }
304  sub BODY_AFTER_IMS () { 0b100000000 }  sub BODY_AFTER_IMS () { 0b100000000 }
305  sub FRAME_IMS ()      { 0b1000000000 }  sub FRAME_IMS ()      { 0b1000000000 }
306    sub SELECT_IMS ()     { 0b10000000000 }
307    
308    ## NOTE: "initial" and "before html" insertion modes have no constants.
309    
310    ## NOTE: "after after body" insertion mode.
311  sub AFTER_HTML_BODY_IM () { AFTER_HTML_IMS | BODY_AFTER_IMS }  sub AFTER_HTML_BODY_IM () { AFTER_HTML_IMS | BODY_AFTER_IMS }
312    
313    ## NOTE: "after after frameset" insertion mode.
314  sub AFTER_HTML_FRAMESET_IM () { AFTER_HTML_IMS | FRAME_IMS }  sub AFTER_HTML_FRAMESET_IM () { AFTER_HTML_IMS | FRAME_IMS }
315    
316  sub IN_HEAD_IM () { HEAD_IMS | 0b00 }  sub IN_HEAD_IM () { HEAD_IMS | 0b00 }
317  sub IN_HEAD_NOSCRIPT_IM () { HEAD_IMS | 0b01 }  sub IN_HEAD_NOSCRIPT_IM () { HEAD_IMS | 0b01 }
318  sub AFTER_HEAD_IM () { HEAD_IMS | 0b10 }  sub AFTER_HEAD_IM () { HEAD_IMS | 0b10 }
# Line 319  sub IN_TABLE_IM () { TABLE_IMS } Line 326  sub IN_TABLE_IM () { TABLE_IMS }
326  sub AFTER_BODY_IM () { BODY_AFTER_IMS }  sub AFTER_BODY_IM () { BODY_AFTER_IMS }
327  sub IN_FRAMESET_IM () { FRAME_IMS | 0b01 }  sub IN_FRAMESET_IM () { FRAME_IMS | 0b01 }
328  sub AFTER_FRAMESET_IM () { FRAME_IMS | 0b10 }  sub AFTER_FRAMESET_IM () { FRAME_IMS | 0b10 }
329  sub IN_SELECT_IM () { 0b01 }  sub IN_SELECT_IM () { SELECT_IMS | 0b01 }
330    sub IN_SELECT_IN_TABLE_IM () { SELECT_IMS | 0b10 }
331  sub IN_COLUMN_GROUP_IM () { 0b10 }  sub IN_COLUMN_GROUP_IM () { 0b10 }
332    
333  ## Implementations MUST act as if state machine in the spec  ## Implementations MUST act as if state machine in the spec
# Line 656  sub _get_next_token ($) { Line 664  sub _get_next_token ($) {
664            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
665          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
666            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
667            if ($self->{current_token}->{attributes}) {            #if ($self->{current_token}->{attributes}) {
668              !!!cp (36);            #  ## NOTE: This should never be reached.
669              !!!parse-error (type => 'end tag attribute');            #  !!! cp (36);
670            } else {            #  !!! parse-error (type => 'end tag attribute');
671              #} else {
672              !!!cp (37);              !!!cp (37);
673            }            #}
674          } else {          } else {
675            die "$0: $self->{current_token}->{type}: Unknown token type";            die "$0: $self->{current_token}->{type}: Unknown token type";
676          }          }
# Line 688  sub _get_next_token ($) { Line 697  sub _get_next_token ($) {
697            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
698          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
699            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
700            if ($self->{current_token}->{attributes}) {            #if ($self->{current_token}->{attributes}) {
701              !!!cp (40);            #  ## NOTE: This state should never be reached.
702              !!!parse-error (type => 'end tag attribute');            #  !!! cp (40);
703            } else {            #  !!! parse-error (type => 'end tag attribute');
704              #} else {
705              !!!cp (41);              !!!cp (41);
706            }            #}
707          } else {          } else {
708            die "$0: $self->{current_token}->{type}: Unknown token type";            die "$0: $self->{current_token}->{type}: Unknown token type";
709          }          }
# Line 912  sub _get_next_token ($) { Line 922  sub _get_next_token ($) {
922              !!!cp (67);              !!!cp (67);
923              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
924            } else {            } else {
925                ## NOTE: This state should never be reached.
926              !!!cp (68);              !!!cp (68);
927            }            }
928          } else {          } else {
# Line 963  sub _get_next_token ($) { Line 974  sub _get_next_token ($) {
974              !!!cp (74);              !!!cp (74);
975              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
976            } else {            } else {
977                ## NOTE: This state should never be reached.
978              !!!cp (75);              !!!cp (75);
979            }            }
980          } else {          } else {
# Line 1011  sub _get_next_token ($) { Line 1023  sub _get_next_token ($) {
1023              !!!cp (80);              !!!cp (80);
1024              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1025            } else {            } else {
1026                ## NOTE: This state should never be reached.
1027              !!!cp (81);              !!!cp (81);
1028            }            }
1029          } else {          } else {
# Line 1067  sub _get_next_token ($) { Line 1080  sub _get_next_token ($) {
1080              !!!cp (88);              !!!cp (88);
1081              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1082            } else {            } else {
1083                ## NOTE: This state should never be reached.
1084              !!!cp (89);              !!!cp (89);
1085            }            }
1086          } else {          } else {
# Line 1091  sub _get_next_token ($) { Line 1105  sub _get_next_token ($) {
1105              !!!cp (91);              !!!cp (91);
1106              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1107            } else {            } else {
1108                ## NOTE: This state should never be reached.
1109              !!!cp (92);              !!!cp (92);
1110            }            }
1111          } else {          } else {
# Line 1139  sub _get_next_token ($) { Line 1154  sub _get_next_token ($) {
1154              !!!cp (98);              !!!cp (98);
1155              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1156            } else {            } else {
1157                ## NOTE: This state should never be reached.
1158              !!!cp (99);              !!!cp (99);
1159            }            }
1160          } else {          } else {
# Line 1182  sub _get_next_token ($) { Line 1198  sub _get_next_token ($) {
1198              !!!cp (104);              !!!cp (104);
1199              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1200            } else {            } else {
1201                ## NOTE: This state should never be reached.
1202              !!!cp (105);              !!!cp (105);
1203            }            }
1204          } else {          } else {
# Line 1228  sub _get_next_token ($) { Line 1245  sub _get_next_token ($) {
1245              !!!cp (110);              !!!cp (110);
1246              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1247            } else {            } else {
1248                ## NOTE: This state should never be reached.
1249              !!!cp (111);              !!!cp (111);
1250            }            }
1251          } else {          } else {
# Line 1252  sub _get_next_token ($) { Line 1270  sub _get_next_token ($) {
1270              !!!cp (113);              !!!cp (113);
1271              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1272            } else {            } else {
1273                ## NOTE: This state should never be reached.
1274              !!!cp (114);              !!!cp (114);
1275            }            }
1276          } else {          } else {
# Line 1323  sub _get_next_token ($) { Line 1342  sub _get_next_token ($) {
1342              !!!cp (120);              !!!cp (120);
1343              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1344            } else {            } else {
1345                ## NOTE: This state should never be reached.
1346              !!!cp (121);              !!!cp (121);
1347            }            }
1348          } else {          } else {
# Line 2190  sub _tokenize_attempt_to_consume_an_enti Line 2210  sub _tokenize_attempt_to_consume_an_enti
2210         0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, & # 0x000D # CR         0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, & # 0x000D # CR
2211         $additional => 1,         $additional => 1,
2212        }->{$self->{next_char}}) {        }->{$self->{next_char}}) {
2213        !!!cp (1001);
2214      ## Don't consume      ## Don't consume
2215      ## No error      ## No error
2216      return undef;      return undef;
# Line 2203  sub _tokenize_attempt_to_consume_an_enti Line 2224  sub _tokenize_attempt_to_consume_an_enti
2224          !!!next-input-character;          !!!next-input-character;
2225          if (0x0030 <= $self->{next_char} and          if (0x0030 <= $self->{next_char} and
2226              $self->{next_char} <= 0x0039) { # 0..9              $self->{next_char} <= 0x0039) { # 0..9
2227              !!!cp (1002);
2228            $code ||= 0;            $code ||= 0;
2229            $code *= 0x10;            $code *= 0x10;
2230            $code += $self->{next_char} - 0x0030;            $code += $self->{next_char} - 0x0030;
2231            redo X;            redo X;
2232          } elsif (0x0061 <= $self->{next_char} and          } elsif (0x0061 <= $self->{next_char} and
2233                   $self->{next_char} <= 0x0066) { # a..f                   $self->{next_char} <= 0x0066) { # a..f
2234              !!!cp (1003);
2235            $code ||= 0;            $code ||= 0;
2236            $code *= 0x10;            $code *= 0x10;
2237            $code += $self->{next_char} - 0x0060 + 9;            $code += $self->{next_char} - 0x0060 + 9;
2238            redo X;            redo X;
2239          } elsif (0x0041 <= $self->{next_char} and          } elsif (0x0041 <= $self->{next_char} and
2240                   $self->{next_char} <= 0x0046) { # A..F                   $self->{next_char} <= 0x0046) { # A..F
2241              !!!cp (1004);
2242            $code ||= 0;            $code ||= 0;
2243            $code *= 0x10;            $code *= 0x10;
2244            $code += $self->{next_char} - 0x0040 + 9;            $code += $self->{next_char} - 0x0040 + 9;
2245            redo X;            redo X;
2246          } elsif (not defined $code) { # no hexadecimal digit          } elsif (not defined $code) { # no hexadecimal digit
2247              !!!cp (1005);
2248            !!!parse-error (type => 'bare hcro');            !!!parse-error (type => 'bare hcro');
2249            !!!back-next-input-character ($x_char, $self->{next_char});            !!!back-next-input-character ($x_char, $self->{next_char});
2250            $self->{next_char} = 0x0023; # #            $self->{next_char} = 0x0023; # #
2251            return undef;            return undef;
2252          } elsif ($self->{next_char} == 0x003B) { # ;          } elsif ($self->{next_char} == 0x003B) { # ;
2253              !!!cp (1006);
2254            !!!next-input-character;            !!!next-input-character;
2255          } else {          } else {
2256              !!!cp (1007);
2257            !!!parse-error (type => 'no refc');            !!!parse-error (type => 'no refc');
2258          }          }
2259    
2260          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
2261              !!!cp (1008);
2262            !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);            !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);
2263            $code = 0xFFFD;            $code = 0xFFFD;
2264          } elsif ($code > 0x10FFFF) {          } elsif ($code > 0x10FFFF) {
2265              !!!cp (1009);
2266            !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);            !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);
2267            $code = 0xFFFD;            $code = 0xFFFD;
2268          } elsif ($code == 0x000D) {          } elsif ($code == 0x000D) {
2269              !!!cp (1010);
2270            !!!parse-error (type => 'CR character reference');            !!!parse-error (type => 'CR character reference');
2271            $code = 0x000A;            $code = 0x000A;
2272          } elsif (0x80 <= $code and $code <= 0x9F) {          } elsif (0x80 <= $code and $code <= 0x9F) {
2273              !!!cp (1011);
2274            !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);            !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);
2275            $code = $c1_entity_char->{$code};            $code = $c1_entity_char->{$code};
2276          }          }
# Line 2254  sub _tokenize_attempt_to_consume_an_enti Line 2285  sub _tokenize_attempt_to_consume_an_enti
2285                
2286        while (0x0030 <= $self->{next_char} and        while (0x0030 <= $self->{next_char} and
2287                  $self->{next_char} <= 0x0039) { # 0..9                  $self->{next_char} <= 0x0039) { # 0..9
2288            !!!cp (1012);
2289          $code *= 10;          $code *= 10;
2290          $code += $self->{next_char} - 0x0030;          $code += $self->{next_char} - 0x0030;
2291                    
# Line 2261  sub _tokenize_attempt_to_consume_an_enti Line 2293  sub _tokenize_attempt_to_consume_an_enti
2293        }        }
2294    
2295        if ($self->{next_char} == 0x003B) { # ;        if ($self->{next_char} == 0x003B) { # ;
2296            !!!cp (1013);
2297          !!!next-input-character;          !!!next-input-character;
2298        } else {        } else {
2299            !!!cp (1014);
2300          !!!parse-error (type => 'no refc');          !!!parse-error (type => 'no refc');
2301        }        }
2302    
2303        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
2304            !!!cp (1015);
2305          !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);          !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);
2306          $code = 0xFFFD;          $code = 0xFFFD;
2307        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
2308            !!!cp (1016);
2309          !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);          !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);
2310          $code = 0xFFFD;          $code = 0xFFFD;
2311        } elsif ($code == 0x000D) {        } elsif ($code == 0x000D) {
2312            !!!cp (1017);
2313          !!!parse-error (type => 'CR character reference');          !!!parse-error (type => 'CR character reference');
2314          $code = 0x000A;          $code = 0x000A;
2315        } elsif (0x80 <= $code and $code <= 0x9F) {        } elsif (0x80 <= $code and $code <= 0x9F) {
2316            !!!cp (1018);
2317          !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);          !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);
2318          $code = $c1_entity_char->{$code};          $code = $c1_entity_char->{$code};
2319        }        }
2320                
2321        return {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1};        return {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1};
2322      } else {      } else {
2323          !!!cp (1019);
2324        !!!parse-error (type => 'bare nero');        !!!parse-error (type => 'bare nero');
2325        !!!back-next-input-character ($self->{next_char});        !!!back-next-input-character ($self->{next_char});
2326        $self->{next_char} = 0x0023; # #        $self->{next_char} = 0x0023; # #
# Line 2311  sub _tokenize_attempt_to_consume_an_enti Line 2350  sub _tokenize_attempt_to_consume_an_enti
2350        $entity_name .= chr $self->{next_char};        $entity_name .= chr $self->{next_char};
2351        if (defined $EntityChar->{$entity_name}) {        if (defined $EntityChar->{$entity_name}) {
2352          if ($self->{next_char} == 0x003B) { # ;          if ($self->{next_char} == 0x003B) { # ;
2353              !!!cp (1020);
2354            $value = $EntityChar->{$entity_name};            $value = $EntityChar->{$entity_name};
2355            $match = 1;            $match = 1;
2356            !!!next-input-character;            !!!next-input-character;
2357            last;            last;
2358          } else {          } else {
2359              !!!cp (1021);
2360            $value = $EntityChar->{$entity_name};            $value = $EntityChar->{$entity_name};
2361            $match = -1;            $match = -1;
2362            !!!next-input-character;            !!!next-input-character;
2363          }          }
2364        } else {        } else {
2365            !!!cp (1022);
2366          $value .= chr $self->{next_char};          $value .= chr $self->{next_char};
2367          $match *= 2;          $match *= 2;
2368          !!!next-input-character;          !!!next-input-character;
# Line 2328  sub _tokenize_attempt_to_consume_an_enti Line 2370  sub _tokenize_attempt_to_consume_an_enti
2370      }      }
2371            
2372      if ($match > 0) {      if ($match > 0) {
2373          !!!cp (1023);
2374        return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};        return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};
2375      } elsif ($match < 0) {      } elsif ($match < 0) {
2376        !!!parse-error (type => 'no refc');        !!!parse-error (type => 'no refc');
2377        if ($in_attr and $match < -1) {        if ($in_attr and $match < -1) {
2378            !!!cp (1024);
2379          return {type => CHARACTER_TOKEN, data => '&'.$entity_name};          return {type => CHARACTER_TOKEN, data => '&'.$entity_name};
2380        } else {        } else {
2381            !!!cp (1025);
2382          return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};          return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};
2383        }        }
2384      } else {      } else {
2385          !!!cp (1026);
2386        !!!parse-error (type => 'bare ero');        !!!parse-error (type => 'bare ero');
2387        ## NOTE: "No characters are consumed" in the spec.        ## NOTE: "No characters are consumed" in the spec.
2388        return {type => CHARACTER_TOKEN, data => '&'.$value};        return {type => CHARACTER_TOKEN, data => '&'.$value};
2389      }      }
2390    } else {    } else {
2391        !!!cp (1027);
2392      ## no characters are consumed      ## no characters are consumed
2393      !!!parse-error (type => 'bare ero');      !!!parse-error (type => 'bare ero');
2394      return undef;      return undef;
# Line 2381  sub _construct_tree ($) { Line 2428  sub _construct_tree ($) {
2428        
2429    !!!next-token;    !!!next-token;
2430    
   $self->{insertion_mode} = BEFORE_HEAD_IM;  
2431    undef $self->{form_element};    undef $self->{form_element};
2432    undef $self->{head_element};    undef $self->{head_element};
2433    $self->{open_elements} = [];    $self->{open_elements} = [];
2434    undef $self->{inner_html_node};    undef $self->{inner_html_node};
2435    
2436      ## NOTE: The "initial" insertion mode.
2437    $self->_tree_construction_initial; # MUST    $self->_tree_construction_initial; # MUST
2438    
2439      ## NOTE: The "before html" insertion mode.
2440    $self->_tree_construction_root_element;    $self->_tree_construction_root_element;
2441      $self->{insertion_mode} = BEFORE_HEAD_IM;
2442    
2443      ## NOTE: The "before head" insertion mode and so on.
2444    $self->_tree_construction_main;    $self->_tree_construction_main;
2445  } # _construct_tree  } # _construct_tree
2446    
2447  sub _tree_construction_initial ($) {  sub _tree_construction_initial ($) {
2448    my $self = shift;    my $self = shift;
2449    
2450      ## NOTE: "initial" insertion mode
2451    
2452    INITIAL: {    INITIAL: {
2453      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
2454        ## NOTE: Conformance checkers MAY, instead of reporting "not HTML5"        ## NOTE: Conformance checkers MAY, instead of reporting "not HTML5"
# Line 2405  sub _tree_construction_initial ($) { Line 2460  sub _tree_construction_initial ($) {
2460        if (not defined $token->{name} or # <!DOCTYPE>        if (not defined $token->{name} or # <!DOCTYPE>
2461            defined $token->{public_identifier} or            defined $token->{public_identifier} or
2462            defined $token->{system_identifier}) {            defined $token->{system_identifier}) {
2463            !!!cp ('t1');
2464          !!!parse-error (type => 'not HTML5');          !!!parse-error (type => 'not HTML5');
2465        } elsif ($doctype_name ne 'HTML') {        } elsif ($doctype_name ne 'HTML') {
2466            !!!cp ('t2');
2467          ## ISSUE: ASCII case-insensitive? (in fact it does not matter)          ## ISSUE: ASCII case-insensitive? (in fact it does not matter)
2468          !!!parse-error (type => 'not HTML5');          !!!parse-error (type => 'not HTML5');
2469          } else {
2470            !!!cp ('t3');
2471        }        }
2472                
2473        my $doctype = $self->{document}->create_document_type_definition        my $doctype = $self->{document}->create_document_type_definition
# Line 2422  sub _tree_construction_initial ($) { Line 2481  sub _tree_construction_initial ($) {
2481        $self->{document}->append_child ($doctype);        $self->{document}->append_child ($doctype);
2482                
2483        if ($token->{quirks} or $doctype_name ne 'HTML') {        if ($token->{quirks} or $doctype_name ne 'HTML') {
2484            !!!cp ('t4');
2485          $self->{document}->manakai_compat_mode ('quirks');          $self->{document}->manakai_compat_mode ('quirks');
2486        } elsif (defined $token->{public_identifier}) {        } elsif (defined $token->{public_identifier}) {
2487          my $pubid = $token->{public_identifier};          my $pubid = $token->{public_identifier};
# Line 2500  sub _tree_construction_initial ($) { Line 2560  sub _tree_construction_initial ($) {
2560            "-/W3C/DTD HTML 4.0 TRANSITIONAL/EN" => 1,            "-/W3C/DTD HTML 4.0 TRANSITIONAL/EN" => 1,
2561            "HTML" => 1,            "HTML" => 1,
2562          }->{$pubid}) {          }->{$pubid}) {
2563              !!!cp ('t5');
2564            $self->{document}->manakai_compat_mode ('quirks');            $self->{document}->manakai_compat_mode ('quirks');
2565          } elsif ($pubid eq "-//W3C//DTD HTML 4.01 FRAMESET//EN" or          } elsif ($pubid eq "-//W3C//DTD HTML 4.01 FRAMESET//EN" or
2566                   $pubid eq "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN") {                   $pubid eq "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN") {
2567            if (defined $token->{system_identifier}) {            if (defined $token->{system_identifier}) {
2568                !!!cp ('t6');
2569              $self->{document}->manakai_compat_mode ('quirks');              $self->{document}->manakai_compat_mode ('quirks');
2570            } else {            } else {
2571                !!!cp ('t7');
2572              $self->{document}->manakai_compat_mode ('limited quirks');              $self->{document}->manakai_compat_mode ('limited quirks');
2573            }            }
2574          } elsif ($pubid eq "-//W3C//DTD XHTML 1.0 Frameset//EN" or          } elsif ($pubid eq "-//W3C//DTD XHTML 1.0 FRAMESET//EN" or
2575                   $pubid eq "-//W3C//DTD XHTML 1.0 Transitional//EN") {                   $pubid eq "-//W3C//DTD XHTML 1.0 TRANSITIONAL//EN") {
2576              !!!cp ('t8');
2577            $self->{document}->manakai_compat_mode ('limited quirks');            $self->{document}->manakai_compat_mode ('limited quirks');
2578            } else {
2579              !!!cp ('t9');
2580          }          }
2581          } else {
2582            !!!cp ('t10');
2583        }        }
2584        if (defined $token->{system_identifier}) {        if (defined $token->{system_identifier}) {
2585          my $sysid = $token->{system_identifier};          my $sysid = $token->{system_identifier};
2586          $sysid =~ tr/A-Z/a-z/;          $sysid =~ tr/A-Z/a-z/;
2587          if ($sysid eq "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") {          if ($sysid eq "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") {
2588              ## TODO: Check the spec: PUBLIC "(limited quirks)" "(quirks)"
2589            $self->{document}->manakai_compat_mode ('quirks');            $self->{document}->manakai_compat_mode ('quirks');
2590              !!!cp ('t11');
2591            } else {
2592              !!!cp ('t12');
2593          }          }
2594          } else {
2595            !!!cp ('t13');
2596        }        }
2597                
2598        ## Go to the root element phase.        ## Go to the "before html" insertion mode.
2599        !!!next-token;        !!!next-token;
2600        return;        return;
2601      } elsif ({      } elsif ({
# Line 2529  sub _tree_construction_initial ($) { Line 2603  sub _tree_construction_initial ($) {
2603                END_TAG_TOKEN, 1,                END_TAG_TOKEN, 1,
2604                END_OF_FILE_TOKEN, 1,                END_OF_FILE_TOKEN, 1,
2605               }->{$token->{type}}) {               }->{$token->{type}}) {
2606          !!!cp ('t14');
2607        !!!parse-error (type => 'no DOCTYPE');        !!!parse-error (type => 'no DOCTYPE');
2608        $self->{document}->manakai_compat_mode ('quirks');        $self->{document}->manakai_compat_mode ('quirks');
2609        ## Go to the root element phase        ## Go to the "before html" insertion mode.
2610        ## reprocess        ## reprocess
2611        return;        return;
2612      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
# Line 2539  sub _tree_construction_initial ($) { Line 2614  sub _tree_construction_initial ($) {
2614          ## Ignore the token          ## Ignore the token
2615    
2616          unless (length $token->{data}) {          unless (length $token->{data}) {
2617            ## Stay in the phase            !!!cp ('t15');
2618              ## Stay in the insertion mode.
2619            !!!next-token;            !!!next-token;
2620            redo INITIAL;            redo INITIAL;
2621            } else {
2622              !!!cp ('t16');
2623          }          }
2624          } else {
2625            !!!cp ('t17');
2626        }        }
2627    
2628        !!!parse-error (type => 'no DOCTYPE');        !!!parse-error (type => 'no DOCTYPE');
2629        $self->{document}->manakai_compat_mode ('quirks');        $self->{document}->manakai_compat_mode ('quirks');
2630        ## Go to the root element phase        ## Go to the "before html" insertion mode.
2631        ## reprocess        ## reprocess
2632        return;        return;
2633      } elsif ($token->{type} == COMMENT_TOKEN) {      } elsif ($token->{type} == COMMENT_TOKEN) {
2634          !!!cp ('t18');
2635        my $comment = $self->{document}->create_comment ($token->{data});        my $comment = $self->{document}->create_comment ($token->{data});
2636        $self->{document}->append_child ($comment);        $self->{document}->append_child ($comment);
2637                
2638        ## Stay in the phase.        ## Stay in the insertion mode.
2639        !!!next-token;        !!!next-token;
2640        redo INITIAL;        redo INITIAL;
2641      } else {      } else {
2642        die "$0: $token->{type}: Unknown token type";        die "$0: $token->{type}: Unknown token type";
2643      }      }
2644    } # INITIAL    } # INITIAL
2645    
2646      die "$0: _tree_construction_initial: This should be never reached";
2647  } # _tree_construction_initial  } # _tree_construction_initial
2648    
2649  sub _tree_construction_root_element ($) {  sub _tree_construction_root_element ($) {
2650    my $self = shift;    my $self = shift;
2651    
2652      ## NOTE: "before html" insertion mode.
2653        
2654    B: {    B: {
2655        if ($token->{type} == DOCTYPE_TOKEN) {        if ($token->{type} == DOCTYPE_TOKEN) {
2656            !!!cp ('t19');
2657          !!!parse-error (type => 'in html:#DOCTYPE');          !!!parse-error (type => 'in html:#DOCTYPE');
2658          ## Ignore the token          ## Ignore the token
2659          ## Stay in the phase          ## Stay in the insertion mode.
2660          !!!next-token;          !!!next-token;
2661          redo B;          redo B;
2662        } elsif ($token->{type} == COMMENT_TOKEN) {        } elsif ($token->{type} == COMMENT_TOKEN) {
2663            !!!cp ('t20');
2664          my $comment = $self->{document}->create_comment ($token->{data});          my $comment = $self->{document}->create_comment ($token->{data});
2665          $self->{document}->append_child ($comment);          $self->{document}->append_child ($comment);
2666          ## Stay in the phase          ## Stay in the insertion mode.
2667          !!!next-token;          !!!next-token;
2668          redo B;          redo B;
2669        } elsif ($token->{type} == CHARACTER_TOKEN) {        } elsif ($token->{type} == CHARACTER_TOKEN) {
# Line 2584  sub _tree_construction_root_element ($) Line 2671  sub _tree_construction_root_element ($)
2671            ## Ignore the token.            ## Ignore the token.
2672    
2673            unless (length $token->{data}) {            unless (length $token->{data}) {
2674              ## Stay in the phase              !!!cp ('t21');
2675                ## Stay in the insertion mode.
2676              !!!next-token;              !!!next-token;
2677              redo B;              redo B;
2678              } else {
2679                !!!cp ('t22');
2680            }            }
2681            } else {
2682              !!!cp ('t23');
2683          }          }
2684    
2685          $self->{application_cache_selection}->(undef);          $self->{application_cache_selection}->(undef);
2686    
2687          #          #
2688        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
2689          if ($token->{tag_name} eq 'html' and          if ($token->{tag_name} eq 'html') {
2690              $token->{attributes}->{manifest}) {            my $root_element;
2691            $self->{application_cache_selection}            !!!create-element ($root_element, $token->{tag_name}, $token->{attributes});
2692                 ->($token->{attributes}->{manifest}->{value});            $self->{document}->append_child ($root_element);
2693            ## ISSUE: No relative reference resolution?            push @{$self->{open_elements}}, [$root_element, 'html'];
2694    
2695              if ($token->{attributes}->{manifest}) {
2696                !!!cp ('t24');
2697                $self->{application_cache_selection}
2698                    ->($token->{attributes}->{manifest}->{value});
2699                ## ISSUE: No relative reference resolution?
2700              } else {
2701                !!!cp ('t25');
2702                $self->{application_cache_selection}->(undef);
2703              }
2704    
2705              !!!next-token;
2706              return; ## Go to the "before head" insertion mode.
2707          } else {          } else {
2708            $self->{application_cache_selection}->(undef);            !!!cp ('t25.1');
2709              #
2710          }          }
   
         ## ISSUE: There is an issue in the spec  
         #  
2711        } elsif ({        } elsif ({
2712                  END_TAG_TOKEN, 1,                  END_TAG_TOKEN, 1,
2713                  END_OF_FILE_TOKEN, 1,                  END_OF_FILE_TOKEN, 1,
2714                 }->{$token->{type}}) {                 }->{$token->{type}}) {
2715          $self->{application_cache_selection}->(undef);          !!!cp ('t26');
   
         ## ISSUE: There is an issue in the spec  
2716          #          #
2717        } else {        } else {
2718          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
2719        }        }
2720    
2721        my $root_element; !!!create-element ($root_element, 'html');      my $root_element; !!!create-element ($root_element, 'html');
2722        $self->{document}->append_child ($root_element);      $self->{document}->append_child ($root_element);
2723        push @{$self->{open_elements}}, [$root_element, 'html'];      push @{$self->{open_elements}}, [$root_element, 'html'];
2724        ## reprocess  
2725        #redo B;      $self->{application_cache_selection}->(undef);
2726        return; ## Go to the main phase.  
2727        ## NOTE: Reprocess the token.
2728        return; ## Go to the "before head" insertion mode.
2729    
2730        ## ISSUE: There is an issue in the spec
2731    } # B    } # B
2732    
2733      die "$0: _tree_construction_root_element: This should never be reached";
2734  } # _tree_construction_root_element  } # _tree_construction_root_element
2735    
2736  sub _reset_insertion_mode ($) {  sub _reset_insertion_mode ($) {
# Line 2638  sub _reset_insertion_mode ($) { Line 2745  sub _reset_insertion_mode ($) {
2745            
2746      ## Step 3      ## Step 3
2747      S3: {      S3: {
       ## ISSUE: Oops! "If node is the first node in the stack of open  
       ## elements, then set last to true. If the context element of the  
       ## HTML fragment parsing algorithm is neither a td element nor a  
       ## th element, then set node to the context element. (fragment case)":  
       ## The second "if" is in the scope of the first "if"!?  
2748        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {
2749          $last = 1;          $last = 1;
2750          if (defined $self->{inner_html_node}) {          if (defined $self->{inner_html_node}) {
2751            if ($self->{inner_html_node}->[1] eq 'td' or            if ($self->{inner_html_node}->[1] eq 'td' or
2752                $self->{inner_html_node}->[1] eq 'th') {                $self->{inner_html_node}->[1] eq 'th') {
2753                !!!cp ('t27');
2754              #              #
2755            } else {            } else {
2756                !!!cp ('t28');
2757              $node = $self->{inner_html_node};              $node = $self->{inner_html_node};
2758            }            }
2759          }          }
# Line 2658  sub _reset_insertion_mode ($) { Line 2762  sub _reset_insertion_mode ($) {
2762        ## Step 4..13        ## Step 4..13
2763        my $new_mode = {        my $new_mode = {
2764                        select => IN_SELECT_IM,                        select => IN_SELECT_IM,
2765                          ## NOTE: |option| and |optgroup| do not set
2766                          ## insertion mode to "in select" by themselves.
2767                        td => IN_CELL_IM,                        td => IN_CELL_IM,
2768                        th => IN_CELL_IM,                        th => IN_CELL_IM,
2769                        tr => IN_ROW_IM,                        tr => IN_ROW_IM,
# Line 2676  sub _reset_insertion_mode ($) { Line 2782  sub _reset_insertion_mode ($) {
2782        ## Step 14        ## Step 14
2783        if ($node->[1] eq 'html') {        if ($node->[1] eq 'html') {
2784          unless (defined $self->{head_element}) {          unless (defined $self->{head_element}) {
2785              !!!cp ('t29');
2786            $self->{insertion_mode} = BEFORE_HEAD_IM;            $self->{insertion_mode} = BEFORE_HEAD_IM;
2787          } else {          } else {
2788              ## ISSUE: Can this state be reached?
2789              !!!cp ('t30');
2790            $self->{insertion_mode} = AFTER_HEAD_IM;            $self->{insertion_mode} = AFTER_HEAD_IM;
2791          }          }
2792          return;          return;
2793          } else {
2794            !!!cp ('t31');
2795        }        }
2796                
2797        ## Step 15        ## Step 15
# Line 2693  sub _reset_insertion_mode ($) { Line 2804  sub _reset_insertion_mode ($) {
2804        ## Step 17        ## Step 17
2805        redo S3;        redo S3;
2806      } # S3      } # S3
2807    
2808      die "$0: _reset_insertion_mode: This line should never be reached";
2809  } # _reset_insertion_mode  } # _reset_insertion_mode
2810    
2811  sub _tree_construction_main ($) {  sub _tree_construction_main ($) {
# Line 2714  sub _tree_construction_main ($) { Line 2827  sub _tree_construction_main ($) {
2827      return if $entry->[0] eq '#marker';      return if $entry->[0] eq '#marker';
2828      for (@{$self->{open_elements}}) {      for (@{$self->{open_elements}}) {
2829        if ($entry->[0] eq $_->[0]) {        if ($entry->[0] eq $_->[0]) {
2830            !!!cp ('t32');
2831          return;          return;
2832        }        }
2833      }      }
# Line 2728  sub _tree_construction_main ($) { Line 2842  sub _tree_construction_main ($) {
2842    
2843        ## Step 6        ## Step 6
2844        if ($entry->[0] eq '#marker') {        if ($entry->[0] eq '#marker') {
2845            !!!cp ('t33_1');
2846          #          #
2847        } else {        } else {
2848          my $in_open_elements;          my $in_open_elements;
2849          OE: for (@{$self->{open_elements}}) {          OE: for (@{$self->{open_elements}}) {
2850            if ($entry->[0] eq $_->[0]) {            if ($entry->[0] eq $_->[0]) {
2851                !!!cp ('t33');
2852              $in_open_elements = 1;              $in_open_elements = 1;
2853              last OE;              last OE;
2854            }            }
2855          }          }
2856          if ($in_open_elements) {          if ($in_open_elements) {
2857              !!!cp ('t34');
2858            #            #
2859          } else {          } else {
2860              ## NOTE: <!DOCTYPE HTML><p><b><i><u></p> <p>X
2861              !!!cp ('t35');
2862            redo S4;            redo S4;
2863          }          }
2864        }        }
# Line 2762  sub _tree_construction_main ($) { Line 2881  sub _tree_construction_main ($) {
2881    
2882        ## Step 11        ## Step 11
2883        unless ($clone->[0] eq $active_formatting_elements->[-1]->[0]) {        unless ($clone->[0] eq $active_formatting_elements->[-1]->[0]) {
2884            !!!cp ('t36');
2885          ## Step 7'          ## Step 7'
2886          $i++;          $i++;
2887          $entry = $active_formatting_elements->[$i];          $entry = $active_formatting_elements->[$i];
2888                    
2889          redo S7;          redo S7;
2890        }        }
2891    
2892          !!!cp ('t37');
2893      } # S7      } # S7
2894    }; # $reconstruct_active_formatting_elements    }; # $reconstruct_active_formatting_elements
2895    
2896    my $clear_up_to_marker = sub {    my $clear_up_to_marker = sub {
2897      for (reverse 0..$#$active_formatting_elements) {      for (reverse 0..$#$active_formatting_elements) {
2898        if ($active_formatting_elements->[$_]->[0] eq '#marker') {        if ($active_formatting_elements->[$_]->[0] eq '#marker') {
2899            !!!cp ('t38');
2900          splice @$active_formatting_elements, $_;          splice @$active_formatting_elements, $_;
2901          return;          return;
2902        }        }
2903      }      }
2904    
2905        !!!cp ('t39');
2906    }; # $clear_up_to_marker    }; # $clear_up_to_marker
2907    
2908    my $parse_rcdata = sub ($$) {    my $insert;
2909      my ($content_model_flag, $insert) = @_;  
2910      my $parse_rcdata = sub ($) {
2911        my ($content_model_flag) = @_;
2912    
2913      ## Step 1      ## Step 1
2914      my $start_tag_name = $token->{tag_name};      my $start_tag_name = $token->{tag_name};
# Line 2789  sub _tree_construction_main ($) { Line 2916  sub _tree_construction_main ($) {
2916      !!!create-element ($el, $start_tag_name, $token->{attributes});      !!!create-element ($el, $start_tag_name, $token->{attributes});
2917    
2918      ## Step 2      ## Step 2
2919      $insert->($el); # /context node/->append_child ($el)      $insert->($el);
2920    
2921      ## Step 3      ## Step 3
2922      $self->{content_model} = $content_model_flag; # CDATA or RCDATA      $self->{content_model} = $content_model_flag; # CDATA or RCDATA
# Line 2799  sub _tree_construction_main ($) { Line 2926  sub _tree_construction_main ($) {
2926      my $text = '';      my $text = '';
2927      !!!next-token;      !!!next-token;
2928      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing
2929          !!!cp ('t40');
2930        $text .= $token->{data};        $text .= $token->{data};
2931        !!!next-token;        !!!next-token;
2932      }      }
2933    
2934      ## Step 5      ## Step 5
2935      if (length $text) {      if (length $text) {
2936          !!!cp ('t41');
2937        my $text = $self->{document}->create_text_node ($text);        my $text = $self->{document}->create_text_node ($text);
2938        $el->append_child ($text);        $el->append_child ($text);
2939      }      }
# Line 2813  sub _tree_construction_main ($) { Line 2942  sub _tree_construction_main ($) {
2942      $self->{content_model} = PCDATA_CONTENT_MODEL;      $self->{content_model} = PCDATA_CONTENT_MODEL;
2943    
2944      ## Step 7      ## Step 7
2945      if ($token->{type} == END_TAG_TOKEN and $token->{tag_name} eq $start_tag_name) {      if ($token->{type} == END_TAG_TOKEN and
2946            $token->{tag_name} eq $start_tag_name) {
2947          !!!cp ('t42');
2948        ## Ignore the token        ## Ignore the token
     } elsif ($content_model_flag == CDATA_CONTENT_MODEL) {  
       !!!parse-error (type => 'in CDATA:#'.$token->{type});  
     } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {  
       !!!parse-error (type => 'in RCDATA:#'.$token->{type});  
2949      } else {      } else {
2950        die "$0: $content_model_flag in parse_rcdata";        ## NOTE: An end-of-file token.
2951          if ($content_model_flag == CDATA_CONTENT_MODEL) {
2952            !!!cp ('t43');
2953            !!!parse-error (type => 'in CDATA:#'.$token->{type});
2954          } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {
2955            !!!cp ('t44');
2956            !!!parse-error (type => 'in RCDATA:#'.$token->{type});
2957          } else {
2958            die "$0: $content_model_flag in parse_rcdata";
2959          }
2960      }      }
2961      !!!next-token;      !!!next-token;
2962    }; # $parse_rcdata    }; # $parse_rcdata
2963    
2964    my $script_start_tag = sub ($) {    my $script_start_tag = sub () {
     my $insert = $_[0];  
2965      my $script_el;      my $script_el;
2966      !!!create-element ($script_el, 'script', $token->{attributes});      !!!create-element ($script_el, 'script', $token->{attributes});
2967      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
# Line 2837  sub _tree_construction_main ($) { Line 2972  sub _tree_construction_main ($) {
2972      my $text = '';      my $text = '';
2973      !!!next-token;      !!!next-token;
2974      while ($token->{type} == CHARACTER_TOKEN) {      while ($token->{type} == CHARACTER_TOKEN) {
2975          !!!cp ('t45');
2976        $text .= $token->{data};        $text .= $token->{data};
2977        !!!next-token;        !!!next-token;
2978      } # stop if non-character token or tokenizer stops tokenising      } # stop if non-character token or tokenizer stops tokenising
2979      if (length $text) {      if (length $text) {
2980          !!!cp ('t46');
2981        $script_el->manakai_append_text ($text);        $script_el->manakai_append_text ($text);
2982      }      }
2983                                
# Line 2848  sub _tree_construction_main ($) { Line 2985  sub _tree_construction_main ($) {
2985    
2986      if ($token->{type} == END_TAG_TOKEN and      if ($token->{type} == END_TAG_TOKEN and
2987          $token->{tag_name} eq 'script') {          $token->{tag_name} eq 'script') {
2988          !!!cp ('t47');
2989        ## Ignore the token        ## Ignore the token
2990      } else {      } else {
2991          !!!cp ('t48');
2992        !!!parse-error (type => 'in CDATA:#'.$token->{type});        !!!parse-error (type => 'in CDATA:#'.$token->{type});
2993        ## ISSUE: And ignore?        ## ISSUE: And ignore?
2994        ## TODO: mark as "already executed"        ## TODO: mark as "already executed"
2995      }      }
2996            
2997      if (defined $self->{inner_html_node}) {      if (defined $self->{inner_html_node}) {
2998          !!!cp ('t49');
2999        ## TODO: mark as "already executed"        ## TODO: mark as "already executed"
3000      } else {      } else {
3001          !!!cp ('t50');
3002        ## TODO: $old_insertion_point = current insertion point        ## TODO: $old_insertion_point = current insertion point
3003        ## TODO: insertion point = just before the next input character        ## TODO: insertion point = just before the next input character
3004    
# Line 2880  sub _tree_construction_main ($) { Line 3021  sub _tree_construction_main ($) {
3021        my $formatting_element_i_in_active;        my $formatting_element_i_in_active;
3022        AFE: for (reverse 0..$#$active_formatting_elements) {        AFE: for (reverse 0..$#$active_formatting_elements) {
3023          if ($active_formatting_elements->[$_]->[1] eq $tag_name) {          if ($active_formatting_elements->[$_]->[1] eq $tag_name) {
3024              !!!cp ('t51');
3025            $formatting_element = $active_formatting_elements->[$_];            $formatting_element = $active_formatting_elements->[$_];
3026            $formatting_element_i_in_active = $_;            $formatting_element_i_in_active = $_;
3027            last AFE;            last AFE;
3028          } elsif ($active_formatting_elements->[$_]->[0] eq '#marker') {          } elsif ($active_formatting_elements->[$_]->[0] eq '#marker') {
3029              !!!cp ('t52');
3030            last AFE;            last AFE;
3031          }          }
3032        } # AFE        } # AFE
3033        unless (defined $formatting_element) {        unless (defined $formatting_element) {
3034            !!!cp ('t53');
3035          !!!parse-error (type => 'unmatched end tag:'.$tag_name);          !!!parse-error (type => 'unmatched end tag:'.$tag_name);
3036          ## Ignore the token          ## Ignore the token
3037          !!!next-token;          !!!next-token;
# Line 2900  sub _tree_construction_main ($) { Line 3044  sub _tree_construction_main ($) {
3044          my $node = $self->{open_elements}->[$_];          my $node = $self->{open_elements}->[$_];
3045          if ($node->[0] eq $formatting_element->[0]) {          if ($node->[0] eq $formatting_element->[0]) {
3046            if ($in_scope) {            if ($in_scope) {
3047                !!!cp ('t54');
3048              $formatting_element_i_in_open = $_;              $formatting_element_i_in_open = $_;
3049              last INSCOPE;              last INSCOPE;
3050            } else { # in open elements but not in scope            } else { # in open elements but not in scope
3051                !!!cp ('t55');
3052              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3053              ## Ignore the token              ## Ignore the token
3054              !!!next-token;              !!!next-token;
# Line 2912  sub _tree_construction_main ($) { Line 3058  sub _tree_construction_main ($) {
3058                    table => 1, caption => 1, td => 1, th => 1,                    table => 1, caption => 1, td => 1, th => 1,
3059                    button => 1, marquee => 1, object => 1, html => 1,                    button => 1, marquee => 1, object => 1, html => 1,
3060                   }->{$node->[1]}) {                   }->{$node->[1]}) {
3061              !!!cp ('t56');
3062            $in_scope = 0;            $in_scope = 0;
3063          }          }
3064        } # INSCOPE        } # INSCOPE
3065        unless (defined $formatting_element_i_in_open) {        unless (defined $formatting_element_i_in_open) {
3066            !!!cp ('t57');
3067          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3068          pop @$active_formatting_elements; # $formatting_element          pop @$active_formatting_elements; # $formatting_element
3069          !!!next-token; ## TODO: ok?          !!!next-token; ## TODO: ok?
3070          return;          return;
3071        }        }
3072        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {
3073            !!!cp ('t58');
3074          !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);          !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3075        }        }
3076                
# Line 2934  sub _tree_construction_main ($) { Line 3083  sub _tree_construction_main ($) {
3083              #not $phrasing_category->{$node->[1]} and              #not $phrasing_category->{$node->[1]} and
3084              ($special_category->{$node->[1]} or              ($special_category->{$node->[1]} or
3085               $scoping_category->{$node->[1]})) {               $scoping_category->{$node->[1]})) {
3086              !!!cp ('t59');
3087            $furthest_block = $node;            $furthest_block = $node;
3088            $furthest_block_i_in_open = $_;            $furthest_block_i_in_open = $_;
3089          } elsif ($node->[0] eq $formatting_element->[0]) {          } elsif ($node->[0] eq $formatting_element->[0]) {
3090              !!!cp ('t60');
3091            last OE;            last OE;
3092          }          }
3093        } # OE        } # OE
3094                
3095        ## Step 3        ## Step 3
3096        unless (defined $furthest_block) { # MUST        unless (defined $furthest_block) { # MUST
3097            !!!cp ('t61');
3098          splice @{$self->{open_elements}}, $formatting_element_i_in_open;          splice @{$self->{open_elements}}, $formatting_element_i_in_open;
3099          splice @$active_formatting_elements, $formatting_element_i_in_active, 1;          splice @$active_formatting_elements, $formatting_element_i_in_active, 1;
3100          !!!next-token;          !!!next-token;
# Line 2955  sub _tree_construction_main ($) { Line 3107  sub _tree_construction_main ($) {
3107        ## Step 5        ## Step 5
3108        my $furthest_block_parent = $furthest_block->[0]->parent_node;        my $furthest_block_parent = $furthest_block->[0]->parent_node;
3109        if (defined $furthest_block_parent) {        if (defined $furthest_block_parent) {
3110            !!!cp ('t62');
3111          $furthest_block_parent->remove_child ($furthest_block->[0]);          $furthest_block_parent->remove_child ($furthest_block->[0]);
3112        }        }
3113                
# Line 2977  sub _tree_construction_main ($) { Line 3130  sub _tree_construction_main ($) {
3130          S7S2: {          S7S2: {
3131            for (reverse 0..$#$active_formatting_elements) {            for (reverse 0..$#$active_formatting_elements) {
3132              if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {              if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {
3133                  !!!cp ('t63');
3134                $node_i_in_active = $_;                $node_i_in_active = $_;
3135                last S7S2;                last S7S2;
3136              }              }
# Line 2990  sub _tree_construction_main ($) { Line 3144  sub _tree_construction_main ($) {
3144                    
3145          ## Step 4          ## Step 4
3146          if ($last_node->[0] eq $furthest_block->[0]) {          if ($last_node->[0] eq $furthest_block->[0]) {
3147              !!!cp ('t64');
3148            $bookmark_prev_el = $node->[0];            $bookmark_prev_el = $node->[0];
3149          }          }
3150                    
3151          ## Step 5          ## Step 5
3152          if ($node->[0]->has_child_nodes ()) {          if ($node->[0]->has_child_nodes ()) {
3153              !!!cp ('t65');
3154            my $clone = [$node->[0]->clone_node (0), $node->[1]];            my $clone = [$node->[0]->clone_node (0), $node->[1]];
3155            $active_formatting_elements->[$node_i_in_active] = $clone;            $active_formatting_elements->[$node_i_in_active] = $clone;
3156            $self->{open_elements}->[$node_i_in_open] = $clone;            $self->{open_elements}->[$node_i_in_open] = $clone;
# Line 3029  sub _tree_construction_main ($) { Line 3185  sub _tree_construction_main ($) {
3185        my $i;        my $i;
3186        AFE: for (reverse 0..$#$active_formatting_elements) {        AFE: for (reverse 0..$#$active_formatting_elements) {
3187          if ($active_formatting_elements->[$_]->[0] eq $formatting_element->[0]) {          if ($active_formatting_elements->[$_]->[0] eq $formatting_element->[0]) {
3188              !!!cp ('t66');
3189            splice @$active_formatting_elements, $_, 1;            splice @$active_formatting_elements, $_, 1;
3190            $i-- and last AFE if defined $i;            $i-- and last AFE if defined $i;
3191          } elsif ($active_formatting_elements->[$_]->[0] eq $bookmark_prev_el) {          } elsif ($active_formatting_elements->[$_]->[0] eq $bookmark_prev_el) {
3192              !!!cp ('t67');
3193            $i = $_;            $i = $_;
3194          }          }
3195        } # AFE        } # AFE
# Line 3041  sub _tree_construction_main ($) { Line 3199  sub _tree_construction_main ($) {
3199        undef $i;        undef $i;
3200        OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
3201          if ($self->{open_elements}->[$_]->[0] eq $formatting_element->[0]) {          if ($self->{open_elements}->[$_]->[0] eq $formatting_element->[0]) {
3202              !!!cp ('t68');
3203            splice @{$self->{open_elements}}, $_, 1;            splice @{$self->{open_elements}}, $_, 1;
3204            $i-- and last OE if defined $i;            $i-- and last OE if defined $i;
3205          } elsif ($self->{open_elements}->[$_]->[0] eq $furthest_block->[0]) {          } elsif ($self->{open_elements}->[$_]->[0] eq $furthest_block->[0]) {
3206              !!!cp ('t69');
3207            $i = $_;            $i = $_;
3208          }          }
3209        } # OE        } # OE
# Line 3054  sub _tree_construction_main ($) { Line 3214  sub _tree_construction_main ($) {
3214      } # FET      } # FET
3215    }; # $formatting_end_tag    }; # $formatting_end_tag
3216    
3217    my $insert_to_current = sub {    ## NOTE: $open_tables->[-1]->[0] is the "current table".
3218      ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.
3219      my $open_tables = [[$self->{open_elements}->[0]->[0]]];
3220    
3221      $insert = my $insert_to_current = sub {
3222      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);
3223    }; # $insert_to_current    }; # $insert_to_current
3224    
3225    my $insert_to_foster = sub {    my $insert_to_foster = sub {
3226                         my $child = shift;      my $child = shift;
3227                         if ({      if ({
3228                              table => 1, tbody => 1, tfoot => 1,           table => 1, tbody => 1, tfoot => 1, thead => 1, tr => 1,
3229                              thead => 1, tr => 1,          }->{$self->{open_elements}->[-1]->[1]}) {
3230                             }->{$self->{open_elements}->[-1]->[1]}) {        # MUST
3231                           # MUST        my $foster_parent_element;
3232                           my $foster_parent_element;        my $next_sibling;
                          my $next_sibling;  
3233                           OE: for (reverse 0..$#{$self->{open_elements}}) {                           OE: for (reverse 0..$#{$self->{open_elements}}) {
3234                             if ($self->{open_elements}->[$_]->[1] eq 'table') {                             if ($self->{open_elements}->[$_]->[1] eq 'table') {
3235                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
3236                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
3237                                   !!!cp ('t70');
3238                                 $foster_parent_element = $parent;                                 $foster_parent_element = $parent;
3239                                 $next_sibling = $self->{open_elements}->[$_]->[0];                                 $next_sibling = $self->{open_elements}->[$_]->[0];
3240                               } else {                               } else {
3241                                   !!!cp ('t71');
3242                                 $foster_parent_element                                 $foster_parent_element
3243                                   = $self->{open_elements}->[$_ - 1]->[0];                                   = $self->{open_elements}->[$_ - 1]->[0];
3244                               }                               }
# Line 3084  sub _tree_construction_main ($) { Line 3249  sub _tree_construction_main ($) {
3249                             unless defined $foster_parent_element;                             unless defined $foster_parent_element;
3250                           $foster_parent_element->insert_before                           $foster_parent_element->insert_before
3251                             ($child, $next_sibling);                             ($child, $next_sibling);
3252                         } else {        $open_tables->[-1]->[1] = 1; # tainted
3253                           $self->{open_elements}->[-1]->[0]->append_child ($child);      } else {
3254                         }        !!!cp ('t72');
3255          $self->{open_elements}->[-1]->[0]->append_child ($child);
3256        }
3257    }; # $insert_to_foster    }; # $insert_to_foster
3258    
   my $insert;  
   
3259    B: {    B: {
3260      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
3261          !!!cp ('t73');
3262        !!!parse-error (type => 'DOCTYPE in the middle');        !!!parse-error (type => 'DOCTYPE in the middle');
3263        ## Ignore the token        ## Ignore the token
3264        ## Stay in the phase        ## Stay in the phase
# Line 3100  sub _tree_construction_main ($) { Line 3266  sub _tree_construction_main ($) {
3266        redo B;        redo B;
3267      } elsif ($token->{type} == END_OF_FILE_TOKEN) {      } elsif ($token->{type} == END_OF_FILE_TOKEN) {
3268        if ($self->{insertion_mode} & AFTER_HTML_IMS) {        if ($self->{insertion_mode} & AFTER_HTML_IMS) {
3269            !!!cp ('t74');
3270          #          #
3271        } else {        } else {
3272          ## Generate implied end tags          ## Generate implied end tags
3273          if ({          while ({
3274               dd => 1, dt => 1, li => 1, p => 1, td => 1, th => 1, tr => 1,                  dd => 1, dt => 1, li => 1, p => 1,
3275               tbody => 1, tfoot=> 1, thead => 1,                 }->{$self->{open_elements}->[-1]->[1]}) {
3276              }->{$self->{open_elements}->[-1]->[1]}) {            !!!cp ('t75');
3277            !!!back-token;            pop @{$self->{open_elements}};
           $token = {type => END_TAG_TOKEN, tag_name => $self->{open_elements}->[-1]->[1]};  
           redo B;  
3278          }          }
3279                    
3280          if (@{$self->{open_elements}} > 2 or          if (@{$self->{open_elements}} > 2 or
3281              (@{$self->{open_elements}} == 2 and $self->{open_elements}->[1]->[1] ne 'body')) {              (@{$self->{open_elements}} == 2 and $self->{open_elements}->[1]->[1] ne 'body')) {
3282              !!!cp ('t76');
3283            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3284          } elsif (defined $self->{inner_html_node} and          } elsif (defined $self->{inner_html_node} and
3285                   @{$self->{open_elements}} > 1 and                   @{$self->{open_elements}} > 1 and
3286                   $self->{open_elements}->[1]->[1] ne 'body') {                   $self->{open_elements}->[1]->[1] ne 'body') {
3287    ## ISSUE: This case is never reached.
3288              !!!cp ('t77');
3289            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3290            } else {
3291              !!!cp ('t78');
3292          }          }
3293    
3294          ## ISSUE: There is an issue in the spec.          ## ISSUE: There is an issue in the spec.
# Line 3129  sub _tree_construction_main ($) { Line 3299  sub _tree_construction_main ($) {
3299      } elsif ($token->{type} == START_TAG_TOKEN and      } elsif ($token->{type} == START_TAG_TOKEN and
3300               $token->{tag_name} eq 'html') {               $token->{tag_name} eq 'html') {
3301        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
3302          ## Turn into the main phase          !!!cp ('t79');
3303          !!!parse-error (type => 'after html:html');          !!!parse-error (type => 'after html:html');
3304          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
3305        } elsif ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {        } elsif ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
3306          ## Turn into the main phase          !!!cp ('t80');
3307          !!!parse-error (type => 'after html:html');          !!!parse-error (type => 'after html:html');
3308          $self->{insertion_mode} = AFTER_FRAMESET_IM;          $self->{insertion_mode} = AFTER_FRAMESET_IM;
3309          } else {
3310            !!!cp ('t81');
3311        }        }
3312    
3313  ## ISSUE: "aa<html>" is not a parse error.        !!!cp ('t82');
3314  ## ISSUE: "<html>" in fragment is not a parse error.        !!!parse-error (type => 'not first start tag');
       unless ($token->{first_start_tag}) {  
         !!!parse-error (type => 'not first start tag');  
       }  
3315        my $top_el = $self->{open_elements}->[0]->[0];        my $top_el = $self->{open_elements}->[0]->[0];
3316        for my $attr_name (keys %{$token->{attributes}}) {        for my $attr_name (keys %{$token->{attributes}}) {
3317          unless ($top_el->has_attribute_ns (undef, $attr_name)) {          unless ($top_el->has_attribute_ns (undef, $attr_name)) {
3318              !!!cp ('t84');
3319            $top_el->set_attribute_ns            $top_el->set_attribute_ns
3320              (undef, [undef, $attr_name],              (undef, [undef, $attr_name],
3321               $token->{attributes}->{$attr_name}->{value});               $token->{attributes}->{$attr_name}->{value});
# Line 3156  sub _tree_construction_main ($) { Line 3326  sub _tree_construction_main ($) {
3326      } elsif ($token->{type} == COMMENT_TOKEN) {      } elsif ($token->{type} == COMMENT_TOKEN) {
3327        my $comment = $self->{document}->create_comment ($token->{data});        my $comment = $self->{document}->create_comment ($token->{data});
3328        if ($self->{insertion_mode} & AFTER_HTML_IMS) {        if ($self->{insertion_mode} & AFTER_HTML_IMS) {
3329            !!!cp ('t85');
3330          $self->{document}->append_child ($comment);          $self->{document}->append_child ($comment);
3331        } elsif ($self->{insertion_mode} == AFTER_BODY_IM) {        } elsif ($self->{insertion_mode} == AFTER_BODY_IM) {
3332            !!!cp ('t86');
3333          $self->{open_elements}->[0]->[0]->append_child ($comment);          $self->{open_elements}->[0]->[0]->append_child ($comment);
3334        } else {        } else {
3335            !!!cp ('t87');
3336          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
3337        }        }
3338        !!!next-token;        !!!next-token;
# Line 3167  sub _tree_construction_main ($) { Line 3340  sub _tree_construction_main ($) {
3340      } elsif ($self->{insertion_mode} & HEAD_IMS) {      } elsif ($self->{insertion_mode} & HEAD_IMS) {
3341        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
3342          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
3343            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3344                !!!cp ('t88.2');
3345                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
3346              } else {
3347                !!!cp ('t88.1');
3348                ## Ignore the token.
3349                !!!next-token;
3350                redo B;
3351              }
3352            unless (length $token->{data}) {            unless (length $token->{data}) {
3353                !!!cp ('t88');
3354              !!!next-token;              !!!next-token;
3355              redo B;              redo B;
3356            }            }
3357          }          }
3358    
3359          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3360              !!!cp ('t89');
3361            ## As if <head>            ## As if <head>
3362            !!!create-element ($self->{head_element}, 'head');            !!!create-element ($self->{head_element}, 'head');
3363            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});            $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
# Line 3185  sub _tree_construction_main ($) { Line 3368  sub _tree_construction_main ($) {
3368    
3369            ## Reprocess in the "after head" insertion mode...            ## Reprocess in the "after head" insertion mode...
3370          } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {          } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3371              !!!cp ('t90');
3372            ## As if </noscript>            ## As if </noscript>
3373            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
3374            !!!parse-error (type => 'in noscript:#character');            !!!parse-error (type => 'in noscript:#character');
# Line 3195  sub _tree_construction_main ($) { Line 3379  sub _tree_construction_main ($) {
3379    
3380            ## Reprocess in the "after head" insertion mode...            ## Reprocess in the "after head" insertion mode...
3381          } elsif ($self->{insertion_mode} == IN_HEAD_IM) {          } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3382              !!!cp ('t91');
3383            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
3384    
3385            ## Reprocess in the "after head" insertion mode...            ## Reprocess in the "after head" insertion mode...
3386            } else {
3387              !!!cp ('t92');
3388          }          }
3389    
3390              ## "after head" insertion mode              ## "after head" insertion mode
# Line 3209  sub _tree_construction_main ($) { Line 3396  sub _tree_construction_main ($) {
3396            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
3397              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
3398                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3399                    !!!cp ('t93');
3400                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes});                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes});
3401                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3402                  push @{$self->{open_elements}}, [$self->{head_element}, $token->{tag_name}];                  push @{$self->{open_elements}}, [$self->{head_element}, $token->{tag_name}];
# Line 3216  sub _tree_construction_main ($) { Line 3404  sub _tree_construction_main ($) {
3404                  !!!next-token;                  !!!next-token;
3405                  redo B;                  redo B;
3406                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3407                    !!!cp ('t94');
3408                  #                  #
3409                } else {                } else {
3410                    !!!cp ('t95');
3411                  !!!parse-error (type => 'in head:head'); # or in head noscript                  !!!parse-error (type => 'in head:head'); # or in head noscript
3412                  ## Ignore the token                  ## Ignore the token
3413                  !!!next-token;                  !!!next-token;
3414                  redo B;                  redo B;
3415                }                }
3416              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3417                  !!!cp ('t96');
3418                ## As if <head>                ## As if <head>
3419                !!!create-element ($self->{head_element}, 'head');                !!!create-element ($self->{head_element}, 'head');
3420                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
# Line 3231  sub _tree_construction_main ($) { Line 3422  sub _tree_construction_main ($) {
3422    
3423                $self->{insertion_mode} = IN_HEAD_IM;                $self->{insertion_mode} = IN_HEAD_IM;
3424                ## Reprocess in the "in head" insertion mode...                ## Reprocess in the "in head" insertion mode...
3425                } else {
3426                  !!!cp ('t97');
3427              }              }
3428    
3429              if ($token->{tag_name} eq 'base') {              if ($token->{tag_name} eq 'base') {
3430                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3431                    !!!cp ('t98');
3432                  ## As if </noscript>                  ## As if </noscript>
3433                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3434                  !!!parse-error (type => 'in noscript:base');                  !!!parse-error (type => 'in noscript:base');
3435                                
3436                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3437                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3438                  } else {
3439                    !!!cp ('t99');
3440                }                }
3441    
3442                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3443                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3444                    !!!cp ('t100');
3445                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3446                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3447                  } else {
3448                    !!!cp ('t101');
3449                }                }
3450                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3451                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3452                pop @{$self->{open_elements}}                pop @{$self->{open_elements}} # <head>
3453                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3454                !!!next-token;                !!!next-token;
3455                redo B;                redo B;
3456              } elsif ($token->{tag_name} eq 'link') {              } elsif ($token->{tag_name} eq 'link') {
3457                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3458                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3459                    !!!cp ('t102');
3460                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3461                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3462                  } else {
3463                    !!!cp ('t103');
3464                }                }
3465                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3466                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3467                pop @{$self->{open_elements}}                pop @{$self->{open_elements}} # <head>
3468                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3469                !!!next-token;                !!!next-token;
3470                redo B;                redo B;
3471              } elsif ($token->{tag_name} eq 'meta') {              } elsif ($token->{tag_name} eq 'meta') {
3472                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3473                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3474                    !!!cp ('t104');
3475                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3476                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3477                  } else {
3478                    !!!cp ('t105');
3479                }                }
3480                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3481                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
3482    
3483                unless ($self->{confident}) {                unless ($self->{confident}) {
3484                  if ($token->{attributes}->{charset}) { ## TODO: And if supported                  if ($token->{attributes}->{charset}) { ## TODO: And if supported
3485                      !!!cp ('t106');
3486                    $self->{change_encoding}                    $self->{change_encoding}
3487                        ->($self, $token->{attributes}->{charset}->{value});                        ->($self, $token->{attributes}->{charset}->{value});
3488                                        
# Line 3291  sub _tree_construction_main ($) { Line 3497  sub _tree_construction_main ($) {
3497                            [\x09-\x0D\x20]*=                            [\x09-\x0D\x20]*=
3498                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
3499                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
3500                        !!!cp ('t107');
3501                      $self->{change_encoding}                      $self->{change_encoding}
3502                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);
3503                      $meta_el->[0]->get_attribute_node_ns (undef, 'content')                      $meta_el->[0]->get_attribute_node_ns (undef, 'content')
3504                          ->set_user_data (manakai_has_reference =>                          ->set_user_data (manakai_has_reference =>
3505                                               $token->{attributes}->{content}                                               $token->{attributes}->{content}
3506                                                     ->{has_reference});                                                     ->{has_reference});
3507                      } else {
3508                        !!!cp ('t108');
3509                    }                    }
3510                  }                  }
3511                } else {                } else {
3512                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
3513                      !!!cp ('t109');
3514                    $meta_el->[0]->get_attribute_node_ns (undef, 'charset')                    $meta_el->[0]->get_attribute_node_ns (undef, 'charset')
3515                        ->set_user_data (manakai_has_reference =>                        ->set_user_data (manakai_has_reference =>
3516                                             $token->{attributes}->{charset}                                             $token->{attributes}->{charset}
3517                                                 ->{has_reference});                                                 ->{has_reference});
3518                  }                  }
3519                  if ($token->{attributes}->{content}) {                  if ($token->{attributes}->{content}) {
3520                      !!!cp ('t110');
3521                    $meta_el->[0]->get_attribute_node_ns (undef, 'content')                    $meta_el->[0]->get_attribute_node_ns (undef, 'content')
3522                        ->set_user_data (manakai_has_reference =>                        ->set_user_data (manakai_has_reference =>
3523                                             $token->{attributes}->{content}                                             $token->{attributes}->{content}
# Line 3314  sub _tree_construction_main ($) { Line 3525  sub _tree_construction_main ($) {
3525                  }                  }
3526                }                }
3527    
3528                pop @{$self->{open_elements}}                pop @{$self->{open_elements}} # <head>
3529                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3530                !!!next-token;                !!!next-token;
3531                redo B;                redo B;
3532              } elsif ($token->{tag_name} eq 'title') {              } elsif ($token->{tag_name} eq 'title') {
3533                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3534                    !!!cp ('t111');
3535                  ## As if </noscript>                  ## As if </noscript>
3536                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3537                  !!!parse-error (type => 'in noscript:title');                  !!!parse-error (type => 'in noscript:title');
# Line 3327  sub _tree_construction_main ($) { Line 3539  sub _tree_construction_main ($) {
3539                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3540                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3541                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3542                    !!!cp ('t112');
3543                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3544                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3545                  } else {
3546                    !!!cp ('t113');
3547                }                }
3548    
3549                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3550                my $parent = defined $self->{head_element} ? $self->{head_element}                my $parent = defined $self->{head_element} ? $self->{head_element}
3551                    : $self->{open_elements}->[-1]->[0];                    : $self->{open_elements}->[-1]->[0];
3552                $parse_rcdata->(RCDATA_CONTENT_MODEL,                $parse_rcdata->(RCDATA_CONTENT_MODEL);
3553                                sub { $parent->append_child ($_[0]) });                pop @{$self->{open_elements}} # <head>
               pop @{$self->{open_elements}}  
3554                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3555                redo B;                redo B;
3556              } elsif ($token->{tag_name} eq 'style') {              } elsif ($token->{tag_name} eq 'style') {
# Line 3344  sub _tree_construction_main ($) { Line 3558  sub _tree_construction_main ($) {
3558                ## insertion mode IN_HEAD_IM)                ## insertion mode IN_HEAD_IM)
3559                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3560                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3561                    !!!cp ('t114');
3562                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3563                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3564                  } else {
3565                    !!!cp ('t115');
3566                }                }
3567                $parse_rcdata->(CDATA_CONTENT_MODEL, $insert_to_current);                $parse_rcdata->(CDATA_CONTENT_MODEL);
3568                pop @{$self->{open_elements}}                pop @{$self->{open_elements}} # <head>
3569                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3570                redo B;                redo B;
3571              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
3572                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
3573                    !!!cp ('t116');
3574                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
3575                  !!!insert-element ($token->{tag_name}, $token->{attributes});                  !!!insert-element ($token->{tag_name}, $token->{attributes});
3576                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;
3577                  !!!next-token;                  !!!next-token;
3578                  redo B;                  redo B;
3579                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3580                    !!!cp ('t117');
3581                  !!!parse-error (type => 'in noscript:noscript');                  !!!parse-error (type => 'in noscript:noscript');
3582                  ## Ignore the token                  ## Ignore the token
3583                  !!!next-token;                  !!!next-token;
3584                  redo B;                  redo B;
3585                } else {                } else {
3586                    !!!cp ('t118');
3587                  #                  #
3588                }                }
3589              } elsif ($token->{tag_name} eq 'script') {              } elsif ($token->{tag_name} eq 'script') {
3590                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3591                    !!!cp ('t119');
3592                  ## As if </noscript>                  ## As if </noscript>
3593                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3594                  !!!parse-error (type => 'in noscript:script');                  !!!parse-error (type => 'in noscript:script');
# Line 3375  sub _tree_construction_main ($) { Line 3596  sub _tree_construction_main ($) {
3596                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3597                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3598                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3599                    !!!cp ('t120');
3600                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3601                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3602                  } else {
3603                    !!!cp ('t121');
3604                }                }
3605    
3606                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3607                $script_start_tag->($insert_to_current);                $script_start_tag->();
3608                pop @{$self->{open_elements}}                pop @{$self->{open_elements}} # <head>
3609                    if $self->{insertion_mode} == AFTER_HEAD_IM;                    if $self->{insertion_mode} == AFTER_HEAD_IM;
3610                redo B;                redo B;
3611              } elsif ($token->{tag_name} eq 'body' or              } elsif ($token->{tag_name} eq 'body' or
3612                       $token->{tag_name} eq 'frameset') {                       $token->{tag_name} eq 'frameset') {
3613                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3614                    !!!cp ('t122');
3615                  ## As if </noscript>                  ## As if </noscript>
3616                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3617                  !!!parse-error (type => 'in noscript:'.$token->{tag_name});                  !!!parse-error (type => 'in noscript:'.$token->{tag_name});
# Line 3397  sub _tree_construction_main ($) { Line 3622  sub _tree_construction_main ($) {
3622                                    
3623                  ## Reprocess in the "after head" insertion mode...                  ## Reprocess in the "after head" insertion mode...
3624                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3625                    !!!cp ('t124');
3626                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3627                                    
3628                  ## Reprocess in the "after head" insertion mode...                  ## Reprocess in the "after head" insertion mode...
3629                  } else {
3630                    !!!cp ('t125');
3631                }                }
3632    
3633                ## "after head" insertion mode                ## "after head" insertion mode
3634                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3635                if ($token->{tag_name} eq 'body') {                if ($token->{tag_name} eq 'body') {
3636                    !!!cp ('t126');
3637                  $self->{insertion_mode} = IN_BODY_IM;                  $self->{insertion_mode} = IN_BODY_IM;
3638                } elsif ($token->{tag_name} eq 'frameset') {                } elsif ($token->{tag_name} eq 'frameset') {
3639                    !!!cp ('t127');
3640                  $self->{insertion_mode} = IN_FRAMESET_IM;                  $self->{insertion_mode} = IN_FRAMESET_IM;
3641                } else {                } else {
3642                  die "$0: tag name: $self->{tag_name}";                  die "$0: tag name: $self->{tag_name}";
# Line 3414  sub _tree_construction_main ($) { Line 3644  sub _tree_construction_main ($) {
3644                !!!next-token;                !!!next-token;
3645                redo B;                redo B;
3646              } else {              } else {
3647                  !!!cp ('t128');
3648                #                #
3649              }              }
3650    
3651              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3652                  !!!cp ('t129');
3653                ## As if </noscript>                ## As if </noscript>
3654                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3655                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});
# Line 3428  sub _tree_construction_main ($) { Line 3660  sub _tree_construction_main ($) {
3660    
3661                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3662              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3663                  !!!cp ('t130');
3664                ## As if </head>                ## As if </head>
3665                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3666    
3667                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3668                } else {
3669                  !!!cp ('t131');
3670              }              }
3671    
3672              ## "after head" insertion mode              ## "after head" insertion mode
# Line 3443  sub _tree_construction_main ($) { Line 3678  sub _tree_construction_main ($) {
3678            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
3679              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
3680                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3681                    !!!cp ('t132');
3682                  ## As if <head>                  ## As if <head>
3683                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head');
3684                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
# Line 3454  sub _tree_construction_main ($) { Line 3690  sub _tree_construction_main ($) {
3690                  !!!next-token;                  !!!next-token;
3691                  redo B;                  redo B;
3692                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3693                    !!!cp ('t133');
3694                  ## As if </noscript>                  ## As if </noscript>
3695                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3696                  !!!parse-error (type => 'in noscript:script');                  !!!parse-error (type => 'in noscript:/head');
3697                                    
3698                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3699                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
# Line 3464  sub _tree_construction_main ($) { Line 3701  sub _tree_construction_main ($) {
3701                  !!!next-token;                  !!!next-token;
3702                  redo B;                  redo B;
3703                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3704                    !!!cp ('t134');
3705                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3706                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
3707                  !!!next-token;                  !!!next-token;
3708                  redo B;                  redo B;
3709                } else {                } else {
3710                    !!!cp ('t135');
3711                  #                  #
3712                }                }
3713              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
3714                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3715                    !!!cp ('t136');
3716                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3717                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3718                  !!!next-token;                  !!!next-token;
3719                  redo B;                  redo B;
3720                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3721                    !!!cp ('t137');
3722                  !!!parse-error (type => 'unmatched end tag:noscript');                  !!!parse-error (type => 'unmatched end tag:noscript');
3723                  ## Ignore the token ## ISSUE: An issue in the spec.                  ## Ignore the token ## ISSUE: An issue in the spec.
3724                  !!!next-token;                  !!!next-token;
3725                  redo B;                  redo B;
3726                } else {                } else {
3727                    !!!cp ('t138');
3728                  #                  #
3729                }                }
3730              } elsif ({              } elsif ({
3731                        body => 1, html => 1,                        body => 1, html => 1,
3732                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
3733                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3734                    !!!cp ('t139');
3735                  ## As if <head>                  ## As if <head>
3736                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head');
3737                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
# Line 3497  sub _tree_construction_main ($) { Line 3740  sub _tree_construction_main ($) {
3740                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3741                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3742                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3743                    !!!cp ('t140');
3744                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3745                  ## Ignore the token                  ## Ignore the token
3746                  !!!next-token;                  !!!next-token;
3747                  redo B;                  redo B;
3748                  } else {
3749                    !!!cp ('t141');
3750                }                }
3751                                
3752                #                #
# Line 3508  sub _tree_construction_main ($) { Line 3754  sub _tree_construction_main ($) {
3754                        p => 1, br => 1,                        p => 1, br => 1,
3755                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
3756                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3757                    !!!cp ('t142');
3758                  ## As if <head>                  ## As if <head>
3759                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head');
3760                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
# Line 3515  sub _tree_construction_main ($) { Line 3762  sub _tree_construction_main ($) {
3762    
3763                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3764                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3765                  } else {
3766                    !!!cp ('t143');
3767                }                }
3768    
3769                #                #
3770              } else {              } else {
3771                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3772                    !!!cp ('t144');
3773                  #                  #
3774                } else {                } else {
3775                    !!!cp ('t145');
3776                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3777                  ## Ignore the token                  ## Ignore the token
3778                  !!!next-token;                  !!!next-token;
# Line 3530  sub _tree_construction_main ($) { Line 3781  sub _tree_construction_main ($) {
3781              }              }
3782    
3783              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3784                  !!!cp ('t146');
3785                ## As if </noscript>                ## As if </noscript>
3786                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3787                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});
# Line 3540  sub _tree_construction_main ($) { Line 3792  sub _tree_construction_main ($) {
3792    
3793                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3794              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3795                  !!!cp ('t147');
3796                ## As if </head>                ## As if </head>
3797                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3798    
3799                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3800              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3801    ## ISSUE: This case cannot be reached?
3802                  !!!cp ('t148');
3803                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3804                ## Ignore the token ## ISSUE: An issue in the spec.                ## Ignore the token ## ISSUE: An issue in the spec.
3805                !!!next-token;                !!!next-token;
3806                redo B;                redo B;
3807                } else {
3808                  !!!cp ('t149');
3809              }              }
3810    
3811              ## "after head" insertion mode              ## "after head" insertion mode
# Line 3564  sub _tree_construction_main ($) { Line 3821  sub _tree_construction_main ($) {
3821            ## ISSUE: An issue in the spec.            ## ISSUE: An issue in the spec.
3822      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
3823            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
3824                !!!cp ('t150');
3825              ## NOTE: There is a code clone of "character in body".              ## NOTE: There is a code clone of "character in body".
3826              $reconstruct_active_formatting_elements->($insert_to_current);              $reconstruct_active_formatting_elements->($insert_to_current);
3827                            
# Line 3582  sub _tree_construction_main ($) { Line 3840  sub _tree_construction_main ($) {
3840                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3841                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3842                    if ($node->[1] eq 'td' or $node->[1] eq 'th') {                    if ($node->[1] eq 'td' or $node->[1] eq 'th') {
3843                        !!!cp ('t151');
3844                      $tn = $node->[1];                      $tn = $node->[1];
3845                      last INSCOPE;                      last INSCOPE;
3846                    } elsif ({                    } elsif ({
3847                              table => 1, html => 1,                              table => 1, html => 1,
3848                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3849                        !!!cp ('t152');
3850                      last INSCOPE;                      last INSCOPE;
3851                    }                    }
3852                  } # INSCOPE                  } # INSCOPE
3853                    unless (defined $tn) {                    unless (defined $tn) {
3854                        !!!cp ('t153');
3855    ## TODO: This error type is wrong.
3856                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3857                      ## Ignore the token                      ## Ignore the token
3858                      !!!next-token;                      !!!next-token;
3859                      redo B;                      redo B;
3860                    }                    }
3861                                    
3862                    !!!cp ('t154');
3863                  ## Close the cell                  ## Close the cell
3864                  !!!back-token; # <?>                  !!!back-token; # <?>
3865                  $token = {type => END_TAG_TOKEN, tag_name => $tn};                  $token = {type => END_TAG_TOKEN, tag_name => $tn};
# Line 3610  sub _tree_construction_main ($) { Line 3873  sub _tree_construction_main ($) {
3873                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3874                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3875                    if ($node->[1] eq 'caption') {                    if ($node->[1] eq 'caption') {
3876                        !!!cp ('t155');
3877                      $i = $_;                      $i = $_;
3878                      last INSCOPE;                      last INSCOPE;
3879                    } elsif ({                    } elsif ({
3880                              table => 1, html => 1,                              table => 1, html => 1,
3881                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3882                        !!!cp ('t156');
3883                      last INSCOPE;                      last INSCOPE;
3884                    }                    }
3885                  } # INSCOPE                  } # INSCOPE
3886                    unless (defined $i) {                    unless (defined $i) {
3887                        !!!cp ('t157');
3888    ## TODO: this type is wrong.
3889                      !!!parse-error (type => 'unmatched end tag:caption');                      !!!parse-error (type => 'unmatched end tag:caption');
3890                      ## Ignore the token                      ## Ignore the token
3891                      !!!next-token;                      !!!next-token;
# Line 3626  sub _tree_construction_main ($) { Line 3893  sub _tree_construction_main ($) {
3893                    }                    }
3894                                    
3895                  ## generate implied end tags                  ## generate implied end tags
3896                  if ({                  while ({
3897                       dd => 1, dt => 1, li => 1, p => 1,                          dd => 1, dt => 1, li => 1, p => 1,
3898                       td => 1, th => 1, tr => 1,                         }->{$self->{open_elements}->[-1]->[1]}) {
3899                       tbody => 1, tfoot=> 1, thead => 1,                    !!!cp ('t158');
3900                      }->{$self->{open_elements}->[-1]->[1]}) {                    pop @{$self->{open_elements}};
                   !!!back-token; # <?>  
                   $token = {type => END_TAG_TOKEN, tag_name => 'caption'};  
                   !!!back-token;  
                   $token = {type => END_TAG_TOKEN,  
                             tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                   redo B;  
3901                  }                  }
3902    
3903                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {
3904                      !!!cp ('t159');
3905                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3906                    } else {
3907                      !!!cp ('t160');
3908                  }                  }
3909                                    
3910                  splice @{$self->{open_elements}}, $i;                  splice @{$self->{open_elements}}, $i;
# Line 3652  sub _tree_construction_main ($) { Line 3916  sub _tree_construction_main ($) {
3916                  ## reprocess                  ## reprocess
3917                  redo B;                  redo B;
3918                } else {                } else {
3919                    !!!cp ('t161');
3920                  #                  #
3921                }                }
3922              } else {              } else {
3923                  !!!cp ('t162');
3924                #                #
3925              }              }
3926            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
# Line 3665  sub _tree_construction_main ($) { Line 3931  sub _tree_construction_main ($) {
3931                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3932                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3933                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[1] eq $token->{tag_name}) {
3934                        !!!cp ('t163');
3935                      $i = $_;                      $i = $_;
3936                      last INSCOPE;                      last INSCOPE;
3937                    } elsif ({                    } elsif ({
3938                              table => 1, html => 1,                              table => 1, html => 1,
3939                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3940                        !!!cp ('t164');
3941                      last INSCOPE;                      last INSCOPE;
3942                    }                    }
3943                  } # INSCOPE                  } # INSCOPE
3944                    unless (defined $i) {                    unless (defined $i) {
3945                        !!!cp ('t165');
3946                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3947                      ## Ignore the token                      ## Ignore the token
3948                      !!!next-token;                      !!!next-token;
# Line 3681  sub _tree_construction_main ($) { Line 3950  sub _tree_construction_main ($) {
3950                    }                    }
3951                                    
3952                  ## generate implied end tags                  ## generate implied end tags
3953                  if ({                  while ({
3954                       dd => 1, dt => 1, li => 1, p => 1,                          dd => 1, dt => 1, li => 1, p => 1,
3955                       td => ($token->{tag_name} eq 'th'),                         }->{$self->{open_elements}->[-1]->[1]}) {
3956                       th => ($token->{tag_name} eq 'td'),                    !!!cp ('t166');
3957                       tr => 1,                    pop @{$self->{open_elements}};
                      tbody => 1, tfoot=> 1, thead => 1,  
                     }->{$self->{open_elements}->[-1]->[1]}) {  
                   !!!back-token;  
                   $token = {type => END_TAG_TOKEN,  
                             tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                   redo B;  
3958                  }                  }
3959                    
3960                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
3961                      !!!cp ('t167');
3962                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3963                    } else {
3964                      !!!cp ('t168');
3965                  }                  }
3966                                    
3967                  splice @{$self->{open_elements}}, $i;                  splice @{$self->{open_elements}}, $i;
# Line 3707  sub _tree_construction_main ($) { Line 3973  sub _tree_construction_main ($) {
3973                  !!!next-token;                  !!!next-token;
3974                  redo B;                  redo B;
3975                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
3976                    !!!cp ('t169');
3977                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3978                  ## Ignore the token                  ## Ignore the token
3979                  !!!next-token;                  !!!next-token;
3980                  redo B;                  redo B;
3981                } else {                } else {
3982                    !!!cp ('t170');
3983                  #                  #
3984                }                }
3985              } elsif ($token->{tag_name} eq 'caption') {              } elsif ($token->{tag_name} eq 'caption') {
# Line 3721  sub _tree_construction_main ($) { Line 3989  sub _tree_construction_main ($) {
3989                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3990                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3991                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[1] eq $token->{tag_name}) {
3992                        !!!cp ('t171');
3993                      $i = $_;                      $i = $_;
3994                      last INSCOPE;                      last INSCOPE;
3995                    } elsif ({                    } elsif ({
3996                              table => 1, html => 1,                              table => 1, html => 1,
3997                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3998                        !!!cp ('t172');
3999                      last INSCOPE;                      last INSCOPE;
4000                    }                    }
4001                  } # INSCOPE                  } # INSCOPE
4002                    unless (defined $i) {                    unless (defined $i) {
4003                        !!!cp ('t173');
4004                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4005                      ## Ignore the token                      ## Ignore the token
4006                      !!!next-token;                      !!!next-token;
# Line 3737  sub _tree_construction_main ($) { Line 4008  sub _tree_construction_main ($) {
4008                    }                    }
4009                                    
4010                  ## generate implied end tags                  ## generate implied end tags
4011                  if ({                  while ({
4012                       dd => 1, dt => 1, li => 1, p => 1,                          dd => 1, dt => 1, li => 1, p => 1,
4013                       td => 1, th => 1, tr => 1,                         }->{$self->{open_elements}->[-1]->[1]}) {
4014                       tbody => 1, tfoot=> 1, thead => 1,                    !!!cp ('t174');
4015                      }->{$self->{open_elements}->[-1]->[1]}) {                    pop @{$self->{open_elements}};
                   !!!back-token;  
                   $token = {type => END_TAG_TOKEN,  
                             tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                   redo B;  
4016                  }                  }
4017                                    
4018                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4019                      !!!cp ('t175');
4020                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4021                    } else {
4022                      !!!cp ('t176');
4023                  }                  }
4024                                    
4025                  splice @{$self->{open_elements}}, $i;                  splice @{$self->{open_elements}}, $i;
# Line 3761  sub _tree_construction_main ($) { Line 4031  sub _tree_construction_main ($) {
4031                  !!!next-token;                  !!!next-token;
4032                  redo B;                  redo B;
4033                } elsif ($self->{insertion_mode} == IN_CELL_IM) {                } elsif ($self->{insertion_mode} == IN_CELL_IM) {
4034                    !!!cp ('t177');
4035                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4036                  ## Ignore the token                  ## Ignore the token
4037                  !!!next-token;                  !!!next-token;
4038                  redo B;                  redo B;
4039                } else {                } else {
4040                    !!!cp ('t178');
4041                  #                  #
4042                }                }
4043              } elsif ({              } elsif ({
# Line 3779  sub _tree_construction_main ($) { Line 4051  sub _tree_construction_main ($) {
4051                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4052                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4053                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4054                      !!!cp ('t179');
4055                    $i = $_;                    $i = $_;
4056                    last INSCOPE;                    last INSCOPE;
4057                  } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {                  } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {
4058                      !!!cp ('t180');
4059                    $tn = $node->[1];                    $tn = $node->[1];
4060                    ## NOTE: There is exactly one |td| or |th| element                    ## NOTE: There is exactly one |td| or |th| element
4061                    ## in scope in the stack of open elements by definition.                    ## in scope in the stack of open elements by definition.
4062                  } elsif ({                  } elsif ({
4063                            table => 1, html => 1,                            table => 1, html => 1,
4064                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4065                      !!!cp ('t181');
4066                    last INSCOPE;                    last INSCOPE;
4067                  }                  }
4068                } # INSCOPE                } # INSCOPE
4069                unless (defined $i) {                unless (defined $i) {
4070                    !!!cp ('t182');
4071                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4072                  ## Ignore the token                  ## Ignore the token
4073                  !!!next-token;                  !!!next-token;
4074                  redo B;                  redo B;
4075                  } else {
4076                    !!!cp ('t183');
4077                }                }
4078    
4079                ## Close the cell                ## Close the cell
# Line 3812  sub _tree_construction_main ($) { Line 4090  sub _tree_construction_main ($) {
4090                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4091                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4092                  if ($node->[1] eq 'caption') {                  if ($node->[1] eq 'caption') {
4093                      !!!cp ('t184');
4094                    $i = $_;                    $i = $_;
4095                    last INSCOPE;                    last INSCOPE;
4096                  } elsif ({                  } elsif ({
4097                            table => 1, html => 1,                            table => 1, html => 1,
4098                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4099                      !!!cp ('t185');
4100                    last INSCOPE;                    last INSCOPE;
4101                  }                  }
4102                } # INSCOPE                } # INSCOPE
4103                unless (defined $i) {                unless (defined $i) {
4104                    !!!cp ('t186');
4105                  !!!parse-error (type => 'unmatched end tag:caption');                  !!!parse-error (type => 'unmatched end tag:caption');
4106                  ## Ignore the token                  ## Ignore the token
4107                  !!!next-token;                  !!!next-token;
# Line 3828  sub _tree_construction_main ($) { Line 4109  sub _tree_construction_main ($) {
4109                }                }
4110                                
4111                ## generate implied end tags                ## generate implied end tags
4112                if ({                while ({
4113                     dd => 1, dt => 1, li => 1, p => 1,                        dd => 1, dt => 1, li => 1, p => 1,
4114                     td => 1, th => 1, tr => 1,                       }->{$self->{open_elements}->[-1]->[1]}) {
4115                     tbody => 1, tfoot=> 1, thead => 1,                  !!!cp ('t187');
4116                    }->{$self->{open_elements}->[-1]->[1]}) {                  pop @{$self->{open_elements}};
                 !!!back-token; # </table>  
                 $token = {type => END_TAG_TOKEN, tag_name => 'caption'};  
                 !!!back-token;  
                 $token = {type => END_TAG_TOKEN,  
                           tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                 redo B;  
4117                }                }
4118    
4119                if ($self->{open_elements}->[-1]->[1] ne 'caption') {                if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4120                    !!!cp ('t188');
4121                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4122                  } else {
4123                    !!!cp ('t189');
4124                }                }
4125    
4126                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
# Line 3857  sub _tree_construction_main ($) { Line 4135  sub _tree_construction_main ($) {
4135                        body => 1, col => 1, colgroup => 1, html => 1,                        body => 1, col => 1, colgroup => 1, html => 1,
4136                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4137                if ($self->{insertion_mode} & BODY_TABLE_IMS) {                if ($self->{insertion_mode} & BODY_TABLE_IMS) {
4138                    !!!cp ('t190');
4139                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4140                  ## Ignore the token                  ## Ignore the token
4141                  !!!next-token;                  !!!next-token;
4142                  redo B;                  redo B;
4143                } else {                } else {
4144                    !!!cp ('t191');
4145                  #                  #
4146                }                }
4147              } elsif ({              } elsif ({
# Line 3869  sub _tree_construction_main ($) { Line 4149  sub _tree_construction_main ($) {
4149                        thead => 1, tr => 1,                        thead => 1, tr => 1,
4150                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
4151                       $self->{insertion_mode} == IN_CAPTION_IM) {                       $self->{insertion_mode} == IN_CAPTION_IM) {
4152                  !!!cp ('t192');
4153                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4154                ## Ignore the token                ## Ignore the token
4155                !!!next-token;                !!!next-token;
4156                redo B;                redo B;
4157              } else {              } else {
4158                  !!!cp ('t193');
4159                #                #
4160              }              }
4161        } else {        } else {
# Line 3884  sub _tree_construction_main ($) { Line 4166  sub _tree_construction_main ($) {
4166        #        #
4167      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
4168        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4169              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if (not $open_tables->[-1]->[1] and # tainted
4170                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);              $token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
4171              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4172                                
4173                unless (length $token->{data}) {            unless (length $token->{data}) {
4174                  !!!next-token;              !!!cp ('t194');
4175                  redo B;              !!!next-token;
4176                }              redo B;
4177              }            } else {
4178                !!!cp ('t195');
4179              }
4180            }
4181    
4182              !!!parse-error (type => 'in table:#character');              !!!parse-error (type => 'in table:#character');
4183    
# Line 3913  sub _tree_construction_main ($) { Line 4199  sub _tree_construction_main ($) {
4199                  if ($self->{open_elements}->[$_]->[1] eq 'table') {                  if ($self->{open_elements}->[$_]->[1] eq 'table') {
4200                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4201                    if (defined $parent and $parent->node_type == 1) {                    if (defined $parent and $parent->node_type == 1) {
4202                        !!!cp ('t196');
4203                      $foster_parent_element = $parent;                      $foster_parent_element = $parent;
4204                      $next_sibling = $self->{open_elements}->[$_]->[0];                      $next_sibling = $self->{open_elements}->[$_]->[0];
4205                      $prev_sibling = $next_sibling->previous_sibling;                      $prev_sibling = $next_sibling->previous_sibling;
4206                    } else {                    } else {
4207                        !!!cp ('t197');
4208                      $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];                      $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
4209                      $prev_sibling = $foster_parent_element->last_child;                      $prev_sibling = $foster_parent_element->last_child;
4210                    }                    }
# Line 3928  sub _tree_construction_main ($) { Line 4216  sub _tree_construction_main ($) {
4216                  unless defined $foster_parent_element;                  unless defined $foster_parent_element;
4217                if (defined $prev_sibling and                if (defined $prev_sibling and
4218                    $prev_sibling->node_type == 3) {                    $prev_sibling->node_type == 3) {
4219                    !!!cp ('t198');
4220                  $prev_sibling->manakai_append_text ($token->{data});                  $prev_sibling->manakai_append_text ($token->{data});
4221                } else {                } else {
4222                    !!!cp ('t199');
4223                  $foster_parent_element->insert_before                  $foster_parent_element->insert_before
4224                    ($self->{document}->create_text_node ($token->{data}),                    ($self->{document}->create_text_node ($token->{data}),
4225                     $next_sibling);                     $next_sibling);
4226                }                }
4227              } else {            $open_tables->[-1]->[1] = 1; # tainted
4228                $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          } else {
4229              }            !!!cp ('t200');
4230              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4231            }
4232                            
4233              !!!next-token;          !!!next-token;
4234              redo B;          redo B;
4235        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
4236              if ({              if ({
4237                   tr => ($self->{insertion_mode} != IN_ROW_IM),                   tr => ($self->{insertion_mode} != IN_ROW_IM),
# Line 3949  sub _tree_construction_main ($) { Line 4241  sub _tree_construction_main ($) {
4241                  ## Clear back to table context                  ## Clear back to table context
4242                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4243                         $self->{open_elements}->[-1]->[1] ne 'html') {                         $self->{open_elements}->[-1]->[1] ne 'html') {
4244                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t201');
4245                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4246                  }                  }
4247                                    
# Line 3960  sub _tree_construction_main ($) { Line 4252  sub _tree_construction_main ($) {
4252    
4253                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {
4254                  unless ($token->{tag_name} eq 'tr') {                  unless ($token->{tag_name} eq 'tr') {
4255                      !!!cp ('t202');
4256                    !!!parse-error (type => 'missing start tag:tr');                    !!!parse-error (type => 'missing start tag:tr');
4257                  }                  }
4258                                    
# Line 3967  sub _tree_construction_main ($) { Line 4260  sub _tree_construction_main ($) {
4260                  while (not {                  while (not {
4261                    tbody => 1, tfoot => 1, thead => 1, html => 1,                    tbody => 1, tfoot => 1, thead => 1, html => 1,
4262                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4263                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t203');
4264                      ## ISSUE: Can this case be reached?
4265                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4266                  }                  }
4267                                    
4268                  $self->{insertion_mode} = IN_ROW_IM;                  $self->{insertion_mode} = IN_ROW_IM;
4269                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4270                      !!!cp ('t204');
4271                    !!!insert-element ($token->{tag_name}, $token->{attributes});                    !!!insert-element ($token->{tag_name}, $token->{attributes});
4272                    !!!next-token;                    !!!next-token;
4273                    redo B;                    redo B;
4274                  } else {                  } else {
4275                      !!!cp ('t205');
4276                    !!!insert-element ('tr');                    !!!insert-element ('tr');
4277                    ## reprocess in the "in row" insertion mode                    ## reprocess in the "in row" insertion mode
4278                  }                  }
4279                  } else {
4280                    !!!cp ('t206');
4281                }                }
4282    
4283                ## Clear back to table row context                ## Clear back to table row context
4284                while (not {                while (not {
4285                  tr => 1, html => 1,                  tr => 1, html => 1,
4286                }->{$self->{open_elements}->[-1]->[1]}) {                }->{$self->{open_elements}->[-1]->[1]}) {
4287                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!cp ('t207');
4288                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4289                }                }
4290                                
# Line 4009  sub _tree_construction_main ($) { Line 4307  sub _tree_construction_main ($) {
4307                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4308                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4309                    if ($node->[1] eq 'tr') {                    if ($node->[1] eq 'tr') {
4310                        !!!cp ('t208');
4311                      $i = $_;                      $i = $_;
4312                      last INSCOPE;                      last INSCOPE;
4313                    } elsif ({                    } elsif ({
4314                              table => 1, html => 1,                              html => 1,
4315    
4316                                ## NOTE: This element does not appear here, maybe.
4317                                table => 1,
4318                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4319                        !!!cp ('t209');
4320                      last INSCOPE;                      last INSCOPE;
4321                    }                    }
4322                  } # INSCOPE                  } # INSCOPE
4323                  unless (defined $i) {                  unless (defined $i) {
4324                    !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name});                   !!!cp ('t210');
4325    ## TODO: This type is wrong.
4326                     !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name});
4327                    ## Ignore the token                    ## Ignore the token
4328                    !!!next-token;                    !!!next-token;
4329                    redo B;                    redo B;
# Line 4028  sub _tree_construction_main ($) { Line 4333  sub _tree_construction_main ($) {
4333                  while (not {                  while (not {
4334                    tr => 1, html => 1,                    tr => 1, html => 1,
4335                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4336                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t211');
4337                      ## ISSUE: Can this case be reached?
4338                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4339                  }                  }
4340                                    
4341                  pop @{$self->{open_elements}}; # tr                  pop @{$self->{open_elements}}; # tr
4342                  $self->{insertion_mode} = IN_TABLE_BODY_IM;                  $self->{insertion_mode} = IN_TABLE_BODY_IM;
4343                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4344                      !!!cp ('t212');
4345                    ## reprocess                    ## reprocess
4346                    redo B;                    redo B;
4347                  } else {                  } else {
4348                      !!!cp ('t213');
4349                    ## reprocess in the "in table body" insertion mode...                    ## reprocess in the "in table body" insertion mode...
4350                  }                  }
4351                }                }
# Line 4050  sub _tree_construction_main ($) { Line 4358  sub _tree_construction_main ($) {
4358                    if ({                    if ({
4359                         tbody => 1, thead => 1, tfoot => 1,                         tbody => 1, thead => 1, tfoot => 1,
4360                        }->{$node->[1]}) {                        }->{$node->[1]}) {
4361                        !!!cp ('t214');
4362                      $i = $_;                      $i = $_;
4363                      last INSCOPE;                      last INSCOPE;
4364                    } elsif ({                    } elsif ({
4365                              table => 1, html => 1,                              table => 1, html => 1,
4366                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4367                        !!!cp ('t215');
4368                      last INSCOPE;                      last INSCOPE;
4369                    }                    }
4370                  } # INSCOPE                  } # INSCOPE
4371                  unless (defined $i) {                  unless (defined $i) {
4372                      !!!cp ('t216');
4373    ## TODO: This erorr type ios wrong.
4374                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4375                    ## Ignore the token                    ## Ignore the token
4376                    !!!next-token;                    !!!next-token;
# Line 4069  sub _tree_construction_main ($) { Line 4381  sub _tree_construction_main ($) {
4381                  while (not {                  while (not {
4382                    tbody => 1, tfoot => 1, thead => 1, html => 1,                    tbody => 1, tfoot => 1, thead => 1, html => 1,
4383                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4384                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t217');
4385                      ## ISSUE: Can this state be reached?
4386                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4387                  }                  }
4388                                    
# Line 4083  sub _tree_construction_main ($) { Line 4396  sub _tree_construction_main ($) {
4396                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4397                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4398                  ## reprocess in "in table" insertion mode...                  ## reprocess in "in table" insertion mode...
4399                  } else {
4400                    !!!cp ('t218');
4401                }                }
4402    
4403                if ($token->{tag_name} eq 'col') {                if ($token->{tag_name} eq 'col') {
4404                  ## Clear back to table context                  ## Clear back to table context
4405                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4406                         $self->{open_elements}->[-1]->[1] ne 'html') {                         $self->{open_elements}->[-1]->[1] ne 'html') {
4407                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t219');
4408                      ## ISSUE: Can this state be reached?
4409                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4410                  }                  }
4411                                    
# Line 4105  sub _tree_construction_main ($) { Line 4421  sub _tree_construction_main ($) {
4421                  ## Clear back to table context                  ## Clear back to table context
4422                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4423                         $self->{open_elements}->[-1]->[1] ne 'html') {                         $self->{open_elements}->[-1]->[1] ne 'html') {
4424                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t220');
4425                      ## ISSUE: Can this state be reached?
4426                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4427                  }                  }
4428                                    
# Line 4134  sub _tree_construction_main ($) { Line 4451  sub _tree_construction_main ($) {
4451                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4452                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4453                  if ($node->[1] eq 'table') {                  if ($node->[1] eq 'table') {
4454                      !!!cp ('t221');
4455                    $i = $_;                    $i = $_;
4456                    last INSCOPE;                    last INSCOPE;
4457                  } elsif ({                  } elsif ({
4458                            table => 1, html => 1,                            #table => 1,
4459                              html => 1,
4460                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4461                      !!!cp ('t222');
4462                    last INSCOPE;                    last INSCOPE;
4463                  }                  }
4464                } # INSCOPE                } # INSCOPE
4465                unless (defined $i) {                unless (defined $i) {
4466                    !!!cp ('t223');
4467    ## TODO: The following is wrong, maybe.
4468                  !!!parse-error (type => 'unmatched end tag:table');                  !!!parse-error (type => 'unmatched end tag:table');
4469                  ## Ignore tokens </table><table>                  ## Ignore tokens </table><table>
4470                  !!!next-token;                  !!!next-token;
# Line 4150  sub _tree_construction_main ($) { Line 4472  sub _tree_construction_main ($) {
4472                }                }
4473                                
4474                ## generate implied end tags                ## generate implied end tags
4475                if ({                while ({
4476                     dd => 1, dt => 1, li => 1, p => 1,                        dd => 1, dt => 1, li => 1, p => 1,
4477                     td => 1, th => 1, tr => 1,                       }->{$self->{open_elements}->[-1]->[1]}) {
4478                     tbody => 1, tfoot=> 1, thead => 1,                  !!!cp ('t224');
4479                    }->{$self->{open_elements}->[-1]->[1]}) {                  pop @{$self->{open_elements}};
                 !!!back-token; # <table>  
                 $token = {type => END_TAG_TOKEN, tag_name => 'table'};  
                 !!!back-token;  
                 $token = {type => END_TAG_TOKEN,  
                           tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                 redo B;  
4480                }                }
4481    
4482                if ($self->{open_elements}->[-1]->[1] ne 'table') {                if ($self->{open_elements}->[-1]->[1] ne 'table') {
4483                    !!!cp ('t225');
4484    ## ISSUE: Can this case be reached?
4485                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4486                  } else {
4487                    !!!cp ('t226');
4488                }                }
4489    
4490                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4491                  pop @{$open_tables};
4492    
4493                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4494    
4495                ## reprocess                ## reprocess
4496                redo B;                redo B;
4497          } else {          } elsif ($token->{tag_name} eq 'style') {
4498            !!!parse-error (type => 'in table:'.$token->{tag_name});            if (not $open_tables->[-1]->[1]) { # tainted
4499                !!!cp ('t227.8');
4500                ## NOTE: This is a "as if in head" code clone.
4501                $parse_rcdata->(CDATA_CONTENT_MODEL);
4502                redo B;
4503              } else {
4504                !!!cp ('t227.7');
4505                #
4506              }
4507            } elsif ($token->{tag_name} eq 'script') {
4508              if (not $open_tables->[-1]->[1]) { # tainted
4509                !!!cp ('t227.6');
4510                ## NOTE: This is a "as if in head" code clone.
4511                $script_start_tag->();
4512                redo B;
4513              } else {
4514                !!!cp ('t227.5');
4515                #
4516              }
4517            } elsif ($token->{tag_name} eq 'input') {
4518              if (not $open_tables->[-1]->[1]) { # tainted
4519                if ($token->{attributes}->{type}) { ## TODO: case
4520                  my $type = lc $token->{attributes}->{type}->{value};
4521                  if ($type eq 'hidden') {
4522                    !!!cp ('t227.3');
4523                    !!!parse-error (type => 'in table:'.$token->{tag_name});
4524    
4525            $insert = $insert_to_foster;                  !!!insert-element ($token->{tag_name}, $token->{attributes});
4526    
4527                    ## TODO: form element pointer
4528    
4529                    pop @{$self->{open_elements}};
4530    
4531                    !!!next-token;
4532                    redo B;
4533                  } else {
4534                    !!!cp ('t227.2');
4535                    #
4536                  }
4537                } else {
4538                  !!!cp ('t227.1');
4539                  #
4540                }
4541              } else {
4542                !!!cp ('t227.4');
4543                #
4544              }
4545            } else {
4546              !!!cp ('t227');
4547            #            #
4548          }          }
4549    
4550            !!!parse-error (type => 'in table:'.$token->{tag_name});
4551    
4552            $insert = $insert_to_foster;
4553            #
4554        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
4555              if ($token->{tag_name} eq 'tr' and              if ($token->{tag_name} eq 'tr' and
4556                  $self->{insertion_mode} == IN_ROW_IM) {                  $self->{insertion_mode} == IN_ROW_IM) {
# Line 4187  sub _tree_construction_main ($) { Line 4559  sub _tree_construction_main ($) {
4559                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4560                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4561                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4562                      !!!cp ('t228');
4563                    $i = $_;                    $i = $_;
4564                    last INSCOPE;                    last INSCOPE;
4565                  } elsif ({                  } elsif ({
4566                            table => 1, html => 1,                            table => 1, html => 1,
4567                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4568                      !!!cp ('t229');
4569                    last INSCOPE;                    last INSCOPE;
4570                  }                  }
4571                } # INSCOPE                } # INSCOPE
4572                unless (defined $i) {                unless (defined $i) {
4573                    !!!cp ('t230');
4574                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4575                  ## Ignore the token                  ## Ignore the token
4576                  !!!next-token;                  !!!next-token;
4577                  redo B;                  redo B;
4578                  } else {
4579                    !!!cp ('t232');
4580                }                }
4581    
4582                ## Clear back to table row context                ## Clear back to table row context
4583                while (not {                while (not {
4584                  tr => 1, html => 1,                  tr => 1, html => 1,
4585                }->{$self->{open_elements}->[-1]->[1]}) {                }->{$self->{open_elements}->[-1]->[1]}) {
4586                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!cp ('t231');
4587    ## ISSUE: Can this state be reached?
4588                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4589                }                }
4590    
# Line 4222  sub _tree_construction_main ($) { Line 4600  sub _tree_construction_main ($) {
4600                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4601                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4602                    if ($node->[1] eq 'tr') {                    if ($node->[1] eq 'tr') {
4603                        !!!cp ('t233');
4604                      $i = $_;                      $i = $_;
4605                      last INSCOPE;                      last INSCOPE;
4606                    } elsif ({                    } elsif ({
4607                              table => 1, html => 1,                              table => 1, html => 1,
4608                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4609                        !!!cp ('t234');
4610                      last INSCOPE;                      last INSCOPE;
4611                    }                    }
4612                  } # INSCOPE                  } # INSCOPE
4613                  unless (defined $i) {                  unless (defined $i) {
4614                      !!!cp ('t235');
4615    ## TODO: The following is wrong.
4616                    !!!parse-error (type => 'unmatched end tag:'.$token->{type});                    !!!parse-error (type => 'unmatched end tag:'.$token->{type});
4617                    ## Ignore the token                    ## Ignore the token
4618                    !!!next-token;                    !!!next-token;
# Line 4241  sub _tree_construction_main ($) { Line 4623  sub _tree_construction_main ($) {
4623                  while (not {                  while (not {
4624                    tr => 1, html => 1,                    tr => 1, html => 1,
4625                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4626                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t236');
4627    ## ISSUE: Can this state be reached?
4628                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4629                  }                  }
4630                                    
# Line 4258  sub _tree_construction_main ($) { Line 4641  sub _tree_construction_main ($) {
4641                    if ({                    if ({
4642                         tbody => 1, thead => 1, tfoot => 1,                         tbody => 1, thead => 1, tfoot => 1,
4643                        }->{$node->[1]}) {                        }->{$node->[1]}) {
4644                        !!!cp ('t237');
4645                      $i = $_;                      $i = $_;
4646                      last INSCOPE;                      last INSCOPE;
4647                    } elsif ({                    } elsif ({
4648                              table => 1, html => 1,                              table => 1, html => 1,
4649                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4650                        !!!cp ('t238');
4651                      last INSCOPE;                      last INSCOPE;
4652                    }                    }
4653                  } # INSCOPE                  } # INSCOPE
4654                  unless (defined $i) {                  unless (defined $i) {
4655                      !!!cp ('t239');
4656                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4657                    ## Ignore the token                    ## Ignore the token
4658                    !!!next-token;                    !!!next-token;
# Line 4277  sub _tree_construction_main ($) { Line 4663  sub _tree_construction_main ($) {
4663                  while (not {                  while (not {
4664                    tbody => 1, tfoot => 1, thead => 1, html => 1,                    tbody => 1, tfoot => 1, thead => 1, html => 1,
4665                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4666                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t240');
4667                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4668                  }                  }
4669                                    
# Line 4293  sub _tree_construction_main ($) { Line 4679  sub _tree_construction_main ($) {
4679                  ## reprocess in the "in table" insertion mode...                  ## reprocess in the "in table" insertion mode...
4680                }                }
4681    
4682                  ## NOTE: </table> in the "in table" insertion mode.
4683                  ## When you edit the code fragment below, please ensure that
4684                  ## the code for <table> in the "in table" insertion mode
4685                  ## is synced with it.
4686    
4687                ## have a table element in table scope                ## have a table element in table scope
4688                my $i;                my $i;
4689                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4690                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4691                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4692                      !!!cp ('t241');
4693                    $i = $_;                    $i = $_;
4694                    last INSCOPE;                    last INSCOPE;
4695                  } elsif ({                  } elsif ({
4696                            table => 1, html => 1,                            table => 1, html => 1,
4697                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4698                      !!!cp ('t242');
4699                    last INSCOPE;                    last INSCOPE;
4700                  }                  }
4701                } # INSCOPE                } # INSCOPE
4702                unless (defined $i) {                unless (defined $i) {
4703                    !!!cp ('t243');
4704                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4705                  ## Ignore the token                  ## Ignore the token
4706                  !!!next-token;                  !!!next-token;
4707                  redo B;                  redo B;
4708                }                }
   
               ## generate implied end tags  
               if ({  
                    dd => 1, dt => 1, li => 1, p => 1,  
                    td => 1, th => 1, tr => 1,  
                    tbody => 1, tfoot=> 1, thead => 1,  
                   }->{$self->{open_elements}->[-1]->[1]}) {  
                 !!!back-token;  
                 $token = {type => END_TAG_TOKEN,  
                           tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
                 redo B;  
               }  
                 
               if ($self->{open_elements}->[-1]->[1] ne 'table') {  
                 !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);  
               }  
4709                                    
4710                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4711                  pop @{$open_tables};
4712                                
4713                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4714                                
# Line 4345  sub _tree_construction_main ($) { Line 4724  sub _tree_construction_main ($) {
4724                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4725                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4726                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[1] eq $token->{tag_name}) {
4727                        !!!cp ('t247');
4728                      $i = $_;                      $i = $_;
4729                      last INSCOPE;                      last INSCOPE;
4730                    } elsif ({                    } elsif ({
4731                              table => 1, html => 1,                              table => 1, html => 1,
4732                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4733                        !!!cp ('t248');
4734                      last INSCOPE;                      last INSCOPE;
4735                    }                    }
4736                  } # INSCOPE                  } # INSCOPE
4737                    unless (defined $i) {                    unless (defined $i) {
4738                        !!!cp ('t249');
4739                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4740                      ## Ignore the token                      ## Ignore the token
4741                      !!!next-token;                      !!!next-token;
# Line 4366  sub _tree_construction_main ($) { Line 4748  sub _tree_construction_main ($) {
4748                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4749                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4750                    if ($node->[1] eq 'tr') {                    if ($node->[1] eq 'tr') {
4751                        !!!cp ('t250');
4752                      $i = $_;                      $i = $_;
4753                      last INSCOPE;                      last INSCOPE;
4754                    } elsif ({                    } elsif ({
4755                              table => 1, html => 1,                              table => 1, html => 1,
4756                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4757                        !!!cp ('t251');
4758                      last INSCOPE;                      last INSCOPE;
4759                    }                    }
4760                  } # INSCOPE                  } # INSCOPE
4761                    unless (defined $i) {                    unless (defined $i) {
4762                        !!!cp ('t252');
4763                      !!!parse-error (type => 'unmatched end tag:tr');                      !!!parse-error (type => 'unmatched end tag:tr');
4764                      ## Ignore the token                      ## Ignore the token
4765                      !!!next-token;                      !!!next-token;
# Line 4385  sub _tree_construction_main ($) { Line 4770  sub _tree_construction_main ($) {
4770                  while (not {                  while (not {
4771                    tr => 1, html => 1,                    tr => 1, html => 1,
4772                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4773                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t253');
4774    ## ISSUE: Can this case be reached?
4775                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4776                  }                  }
4777                                    
# Line 4399  sub _tree_construction_main ($) { Line 4785  sub _tree_construction_main ($) {
4785                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4786                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4787                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4788                      !!!cp ('t254');
4789                    $i = $_;                    $i = $_;
4790                    last INSCOPE;                    last INSCOPE;
4791                  } elsif ({                  } elsif ({
4792                            table => 1, html => 1,                            table => 1, html => 1,
4793                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4794                      !!!cp ('t255');
4795                    last INSCOPE;                    last INSCOPE;
4796                  }                  }
4797                } # INSCOPE                } # INSCOPE
4798                unless (defined $i) {                unless (defined $i) {
4799                    !!!cp ('t256');
4800                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4801                  ## Ignore the token                  ## Ignore the token
4802                  !!!next-token;                  !!!next-token;
# Line 4418  sub _tree_construction_main ($) { Line 4807  sub _tree_construction_main ($) {
4807                while (not {                while (not {
4808                  tbody => 1, tfoot => 1, thead => 1, html => 1,                  tbody => 1, tfoot => 1, thead => 1, html => 1,
4809                }->{$self->{open_elements}->[-1]->[1]}) {                }->{$self->{open_elements}->[-1]->[1]}) {
4810                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!cp ('t257');
4811    ## ISSUE: Can this case be reached?
4812                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4813                }                }
4814    
# Line 4432  sub _tree_construction_main ($) { Line 4822  sub _tree_construction_main ($) {
4822                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM
4823                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM
4824                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4825                  !!!cp ('t258');
4826                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4827                ## Ignore the token                ## Ignore the token
4828                !!!next-token;                !!!next-token;
4829                redo B;                redo B;
4830          } else {          } else {
4831              !!!cp ('t259');
4832            !!!parse-error (type => 'in table:/'.$token->{tag_name});            !!!parse-error (type => 'in table:/'.$token->{tag_name});
4833    
4834            $insert = $insert_to_foster;            $insert = $insert_to_foster;
# Line 4450  sub _tree_construction_main ($) { Line 4842  sub _tree_construction_main ($) {
4842              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
4843                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4844                unless (length $token->{data}) {                unless (length $token->{data}) {
4845                    !!!cp ('t260');
4846                  !!!next-token;                  !!!next-token;
4847                  redo B;                  redo B;
4848                }                }
4849              }              }
4850                            
4851                !!!cp ('t261');
4852              #              #
4853            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
4854              if ($token->{tag_name} eq 'col') {              if ($token->{tag_name} eq 'col') {
4855                  !!!cp ('t262');
4856                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
4857                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
4858                !!!next-token;                !!!next-token;
4859                redo B;                redo B;
4860              } else {              } else {
4861                  !!!cp ('t263');
4862                #                #
4863              }              }
4864            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
4865              if ($token->{tag_name} eq 'colgroup') {              if ($token->{tag_name} eq 'colgroup') {
4866                if ($self->{open_elements}->[-1]->[1] eq 'html') {                if ($self->{open_elements}->[-1]->[1] eq 'html') {
4867                    !!!cp ('t264');
4868                  !!!parse-error (type => 'unmatched end tag:colgroup');                  !!!parse-error (type => 'unmatched end tag:colgroup');
4869                  ## Ignore the token                  ## Ignore the token
4870                  !!!next-token;                  !!!next-token;
4871                  redo B;                  redo B;
4872                } else {                } else {
4873                    !!!cp ('t265');
4874                  pop @{$self->{open_elements}}; # colgroup                  pop @{$self->{open_elements}}; # colgroup
4875                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4876                  !!!next-token;                  !!!next-token;
4877                  redo B;                              redo B;            
4878                }                }
4879              } elsif ($token->{tag_name} eq 'col') {              } elsif ($token->{tag_name} eq 'col') {
4880                  !!!cp ('t266');
4881                !!!parse-error (type => 'unmatched end tag:col');                !!!parse-error (type => 'unmatched end tag:col');
4882                ## Ignore the token                ## Ignore the token
4883                !!!next-token;                !!!next-token;
4884                redo B;                redo B;
4885              } else {              } else {
4886                  !!!cp ('t267');
4887                #                #
4888              }              }
4889            } else {            } else {
4890              #              die "$0: $token->{type}: Unknown token type";
4891            }            }
4892    
4893            ## As if </colgroup>            ## As if </colgroup>
4894            if ($self->{open_elements}->[-1]->[1] eq 'html') {            if ($self->{open_elements}->[-1]->[1] eq 'html') {
4895                !!!cp ('t269');
4896              !!!parse-error (type => 'unmatched end tag:colgroup');              !!!parse-error (type => 'unmatched end tag:colgroup');
4897              ## Ignore the token              ## Ignore the token
4898              !!!next-token;              !!!next-token;
4899              redo B;              redo B;
4900            } else {            } else {
4901                !!!cp ('t270');
4902              pop @{$self->{open_elements}}; # colgroup              pop @{$self->{open_elements}}; # colgroup
4903              $self->{insertion_mode} = IN_TABLE_IM;              $self->{insertion_mode} = IN_TABLE_IM;
4904              ## reprocess              ## reprocess
4905              redo B;              redo B;
4906            }            }
4907      } elsif ($self->{insertion_mode} == IN_SELECT_IM) {      } elsif ($self->{insertion_mode} & SELECT_IMS) {
4908        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4909            !!!cp ('t271');
4910          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4911          !!!next-token;          !!!next-token;
4912          redo B;          redo B;
4913        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
4914              if ($token->{tag_name} eq 'option') {              if ($token->{tag_name} eq 'option') {
4915                if ($self->{open_elements}->[-1]->[1] eq 'option') {                if ($self->{open_elements}->[-1]->[1] eq 'option') {
4916                    !!!cp ('t272');
4917                  ## As if </option>                  ## As if </option>
4918                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4919                  } else {
4920                    !!!cp ('t273');
4921                }                }
4922    
4923                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
# Line 4519  sub _tree_construction_main ($) { Line 4925  sub _tree_construction_main ($) {
4925                redo B;                redo B;
4926              } elsif ($token->{tag_name} eq 'optgroup') {              } elsif ($token->{tag_name} eq 'optgroup') {
4927                if ($self->{open_elements}->[-1]->[1] eq 'option') {                if ($self->{open_elements}->[-1]->[1] eq 'option') {
4928                    !!!cp ('t274');
4929                  ## As if </option>                  ## As if </option>
4930                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4931                  } else {
4932                    !!!cp ('t275');
4933                }                }
4934    
4935                if ($self->{open_elements}->[-1]->[1] eq 'optgroup') {                if ($self->{open_elements}->[-1]->[1] eq 'optgroup') {
4936                    !!!cp ('t276');
4937                  ## As if </optgroup>                  ## As if </optgroup>
4938                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4939                  } else {
4940                    !!!cp ('t277');
4941                }                }
4942    
4943                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
4944                !!!next-token;                !!!next-token;
4945                redo B;                redo B;
4946              } elsif ($token->{tag_name} eq 'select') {          } elsif ($token->{tag_name} eq 'select' or
4947                !!!parse-error (type => 'not closed:select');                   $token->{tag_name} eq 'input' or
4948                ## As if </select> instead                   ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
4949                      {
4950                       caption => 1, table => 1,
4951                       tbody => 1, tfoot => 1, thead => 1,
4952                       tr => 1, td => 1, th => 1,
4953                      }->{$token->{tag_name}})) {
4954              ## TODO: The type below is not good - <select> is replaced by </select>
4955              !!!parse-error (type => 'not closed:select');
4956              ## NOTE: As if the token were </select> (<select> case) or
4957              ## as if there were </select> (otherwise).
4958                ## have an element in table scope                ## have an element in table scope
4959                my $i;                my $i;
4960                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4961                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4962                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq 'select') {
4963                      !!!cp ('t278');
4964                    $i = $_;                    $i = $_;
4965                    last INSCOPE;                    last INSCOPE;
4966                  } elsif ({                  } elsif ({
4967                            table => 1, html => 1,                            table => 1, html => 1,
4968                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4969                      !!!cp ('t279');
4970                    last INSCOPE;                    last INSCOPE;
4971                  }                  }
4972                } # INSCOPE                } # INSCOPE
4973                unless (defined $i) {                unless (defined $i) {
4974                    !!!cp ('t280');
4975                  !!!parse-error (type => 'unmatched end tag:select');                  !!!parse-error (type => 'unmatched end tag:select');
4976                  ## Ignore the token                  ## Ignore the token
4977                  !!!next-token;                  !!!next-token;
4978                  redo B;                  redo B;
4979                }                }
4980                                
4981                  !!!cp ('t281');
4982                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4983    
4984                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4985    
4986                !!!next-token;            if ($token->{tag_name} eq 'select') {
4987                redo B;              !!!cp ('t281.2');
4988                !!!next-token;
4989                redo B;
4990              } else {
4991                !!!cp ('t281.1');
4992                ## Reprocess the token.
4993                redo B;
4994              }
4995          } else {          } else {
4996              !!!cp ('t282');
4997            !!!parse-error (type => 'in select:'.$token->{tag_name});            !!!parse-error (type => 'in select:'.$token->{tag_name});
4998            ## Ignore the token            ## Ignore the token
4999            !!!next-token;            !!!next-token;
# Line 4570  sub _tree_construction_main ($) { Line 5003  sub _tree_construction_main ($) {
5003              if ($token->{tag_name} eq 'optgroup') {              if ($token->{tag_name} eq 'optgroup') {
5004                if ($self->{open_elements}->[-1]->[1] eq 'option' and                if ($self->{open_elements}->[-1]->[1] eq 'option' and
5005                    $self->{open_elements}->[-2]->[1] eq 'optgroup') {                    $self->{open_elements}->[-2]->[1] eq 'optgroup') {
5006                    !!!cp ('t283');
5007                  ## As if </option>                  ## As if </option>
5008                  splice @{$self->{open_elements}}, -2;                  splice @{$self->{open_elements}}, -2;
5009                } elsif ($self->{open_elements}->[-1]->[1] eq 'optgroup') {                } elsif ($self->{open_elements}->[-1]->[1] eq 'optgroup') {
5010                    !!!cp ('t284');
5011                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5012                } else {                } else {
5013                    !!!cp ('t285');
5014                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5015                  ## Ignore the token                  ## Ignore the token
5016                }                }
# Line 4582  sub _tree_construction_main ($) { Line 5018  sub _tree_construction_main ($) {
5018                redo B;                redo B;
5019              } elsif ($token->{tag_name} eq 'option') {              } elsif ($token->{tag_name} eq 'option') {
5020                if ($self->{open_elements}->[-1]->[1] eq 'option') {                if ($self->{open_elements}->[-1]->[1] eq 'option') {
5021                    !!!cp ('t286');
5022                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5023                } else {                } else {
5024                    !!!cp ('t287');
5025                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5026                  ## Ignore the token                  ## Ignore the token
5027                }                }
# Line 4595  sub _tree_construction_main ($) { Line 5033  sub _tree_construction_main ($) {
5033                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5034                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5035                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
5036                      !!!cp ('t288');
5037                    $i = $_;                    $i = $_;
5038                    last INSCOPE;                    last INSCOPE;
5039                  } elsif ({                  } elsif ({
5040                            table => 1, html => 1,                            table => 1, html => 1,
5041                           }->{$node->[1]}) {                           }->{$node->[1]}) {
5042                      !!!cp ('t289');
5043                    last INSCOPE;                    last INSCOPE;
5044                  }                  }
5045                } # INSCOPE                } # INSCOPE
5046                unless (defined $i) {                unless (defined $i) {
5047                    !!!cp ('t290');
5048                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5049                  ## Ignore the token                  ## Ignore the token
5050                  !!!next-token;                  !!!next-token;
5051                  redo B;                  redo B;
5052                }                }
5053                                
5054                  !!!cp ('t291');
5055                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
5056    
5057                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
5058    
5059                !!!next-token;                !!!next-token;
5060                redo B;                redo B;
5061              } elsif ({          } elsif ($self->{insertion_mode} == IN_SELECT_IN_TABLE_IM and
5062                        caption => 1, table => 1, tbody => 1,                   {
5063                        tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,                    caption => 1, table => 1, tbody => 1,
5064                       }->{$token->{tag_name}}) {                    tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,
5065                     }->{$token->{tag_name}}) {
5066    ## TODO: The following is wrong?
5067                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5068                                
5069                ## have an element in table scope                ## have an element in table scope
# Line 4627  sub _tree_construction_main ($) { Line 5071  sub _tree_construction_main ($) {
5071                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5072                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5073                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
5074                      !!!cp ('t292');
5075                    $i = $_;                    $i = $_;
5076                    last INSCOPE;                    last INSCOPE;
5077                  } elsif ({                  } elsif ({
5078                            table => 1, html => 1,                            table => 1, html => 1,
5079                           }->{$node->[1]}) {                           }->{$node->[1]}) {
5080                      !!!cp ('t293');
5081                    last INSCOPE;                    last INSCOPE;
5082                  }                  }
5083                } # INSCOPE                } # INSCOPE
5084                unless (defined $i) {                unless (defined $i) {
5085                    !!!cp ('t294');
5086                  ## Ignore the token                  ## Ignore the token
5087                  !!!next-token;                  !!!next-token;
5088                  redo B;                  redo B;
# Line 4647  sub _tree_construction_main ($) { Line 5094  sub _tree_construction_main ($) {
5094                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5095                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5096                  if ($node->[1] eq 'select') {                  if ($node->[1] eq 'select') {
5097                      !!!cp ('t295');
5098                    $i = $_;                    $i = $_;
5099                    last INSCOPE;                    last INSCOPE;
5100                  } elsif ({                  } elsif ({
5101                            table => 1, html => 1,                            table => 1, html => 1,
5102                           }->{$node->[1]}) {                           }->{$node->[1]}) {
5103    ## ISSUE: Can this state be reached?
5104                      !!!cp ('t296');
5105                    last INSCOPE;                    last INSCOPE;
5106                  }                  }
5107                } # INSCOPE                } # INSCOPE
5108                unless (defined $i) {                unless (defined $i) {
5109                    !!!cp ('t297');
5110    ## TODO: The following error type is correct?
5111                  !!!parse-error (type => 'unmatched end tag:select');                  !!!parse-error (type => 'unmatched end tag:select');
5112                  ## Ignore the </select> token                  ## Ignore the </select> token
5113                  !!!next-token; ## TODO: ok?                  !!!next-token; ## TODO: ok?
5114                  redo B;                  redo B;
5115                }                }
5116                                
5117                  !!!cp ('t298');
5118                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
5119    
5120                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
# Line 4669  sub _tree_construction_main ($) { Line 5122  sub _tree_construction_main ($) {
5122                ## reprocess                ## reprocess
5123                redo B;                redo B;
5124          } else {          } else {
5125              !!!cp ('t299');
5126            !!!parse-error (type => 'in select:/'.$token->{tag_name});            !!!parse-error (type => 'in select:/'.$token->{tag_name});
5127            ## Ignore the token            ## Ignore the token
5128            !!!next-token;            !!!next-token;
# Line 4687  sub _tree_construction_main ($) { Line 5141  sub _tree_construction_main ($) {
5141            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5142                        
5143            unless (length $token->{data}) {            unless (length $token->{data}) {
5144                !!!cp ('t300');
5145              !!!next-token;              !!!next-token;
5146              redo B;              redo B;
5147            }            }
5148          }          }
5149                    
5150          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5151              !!!cp ('t301');
5152            !!!parse-error (type => 'after html:#character');            !!!parse-error (type => 'after html:#character');
5153    
5154            ## Reprocess in the "main" phase, "after body" insertion mode...            ## Reprocess in the "after body" insertion mode.
5155            } else {
5156              !!!cp ('t302');
5157          }          }
5158                    
5159          ## "after body" insertion mode          ## "after body" insertion mode
# Line 4706  sub _tree_construction_main ($) { Line 5164  sub _tree_construction_main ($) {
5164          redo B;          redo B;
5165        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5166          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5167              !!!cp ('t303');
5168            !!!parse-error (type => 'after html:'.$token->{tag_name});            !!!parse-error (type => 'after html:'.$token->{tag_name});
5169                        
5170            ## Reprocess in the "main" phase, "after body" insertion mode...            ## Reprocess in the "after body" insertion mode.
5171            } else {
5172              !!!cp ('t304');
5173          }          }
5174    
5175          ## "after body" insertion mode          ## "after body" insertion mode
# Line 4719  sub _tree_construction_main ($) { Line 5180  sub _tree_construction_main ($) {
5180          redo B;          redo B;
5181        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5182          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5183              !!!cp ('t305');
5184            !!!parse-error (type => 'after html:/'.$token->{tag_name});            !!!parse-error (type => 'after html:/'.$token->{tag_name});
5185                        
5186            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
5187            ## Reprocess in the "main" phase, "after body" insertion mode...            ## Reprocess in the "after body" insertion mode.
5188            } else {
5189              !!!cp ('t306');
5190          }          }
5191    
5192          ## "after body" insertion mode          ## "after body" insertion mode
5193          if ($token->{tag_name} eq 'html') {          if ($token->{tag_name} eq 'html') {
5194            if (defined $self->{inner_html_node}) {            if (defined $self->{inner_html_node}) {
5195                !!!cp ('t307');
5196              !!!parse-error (type => 'unmatched end tag:html');              !!!parse-error (type => 'unmatched end tag:html');
5197              ## Ignore the token              ## Ignore the token
5198              !!!next-token;              !!!next-token;
5199              redo B;              redo B;
5200            } else {            } else {
5201                !!!cp ('t308');
5202              $self->{insertion_mode} = AFTER_HTML_BODY_IM;              $self->{insertion_mode} = AFTER_HTML_BODY_IM;
5203              !!!next-token;              !!!next-token;
5204              redo B;              redo B;
5205            }            }
5206          } else {          } else {
5207              !!!cp ('t309');
5208            !!!parse-error (type => 'after body:/'.$token->{tag_name});            !!!parse-error (type => 'after body:/'.$token->{tag_name});
5209    
5210            $self->{insertion_mode} = IN_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
# Line 4753  sub _tree_construction_main ($) { Line 5220  sub _tree_construction_main ($) {
5220            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5221                        
5222            unless (length $token->{data}) {            unless (length $token->{data}) {
5223                !!!cp ('t310');
5224              !!!next-token;              !!!next-token;
5225              redo B;              redo B;
5226            }            }
# Line 4760  sub _tree_construction_main ($) { Line 5228  sub _tree_construction_main ($) {
5228                    
5229          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {
5230            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5231                !!!cp ('t311');
5232              !!!parse-error (type => 'in frameset:#character');              !!!parse-error (type => 'in frameset:#character');
5233            } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {            } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {
5234                !!!cp ('t312');
5235              !!!parse-error (type => 'after frameset:#character');              !!!parse-error (type => 'after frameset:#character');
5236            } else { # "after html frameset"            } else { # "after html frameset"
5237                !!!cp ('t313');
5238              !!!parse-error (type => 'after html:#character');              !!!parse-error (type => 'after html:#character');
5239    
5240              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
5241              ## Reprocess in the "main" phase, "after frameset"...              ## Reprocess in the "after frameset" insertion mode.
5242              !!!parse-error (type => 'after frameset:#character');              !!!parse-error (type => 'after frameset:#character');
5243            }            }
5244                        
5245            ## Ignore the token.            ## Ignore the token.
5246            if (length $token->{data}) {            if (length $token->{data}) {
5247                !!!cp ('t314');
5248              ## reprocess the rest of characters              ## reprocess the rest of characters
5249            } else {            } else {
5250                !!!cp ('t315');
5251              !!!next-token;              !!!next-token;
5252            }            }
5253            redo B;            redo B;
# Line 4783  sub _tree_construction_main ($) { Line 5256  sub _tree_construction_main ($) {
5256          die qq[$0: Character "$token->{data}"];          die qq[$0: Character "$token->{data}"];
5257        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5258          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
5259              !!!cp ('t316');
5260            !!!parse-error (type => 'after html:'.$token->{tag_name});            !!!parse-error (type => 'after html:'.$token->{tag_name});
5261    
5262            $self->{insertion_mode} = AFTER_FRAMESET_IM;            $self->{insertion_mode} = AFTER_FRAMESET_IM;
5263            ## Process in the "main" phase, "after frameset" insertion mode...            ## Process in the "after frameset" insertion mode.
5264          }          } else {
5265              !!!cp ('t317');
5266            }
5267    
5268          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
5269              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5270              !!!cp ('t318');
5271            !!!insert-element ($token->{tag_name}, $token->{attributes});            !!!insert-element ($token->{tag_name}, $token->{attributes});
5272            !!!next-token;            !!!next-token;
5273            redo B;            redo B;
5274          } elsif ($token->{tag_name} eq 'frame' and          } elsif ($token->{tag_name} eq 'frame' and
5275                   $self->{insertion_mode} == IN_FRAMESET_IM) {                   $self->{insertion_mode} == IN_FRAMESET_IM) {
5276              !!!cp ('t319');
5277            !!!insert-element ($token->{tag_name}, $token->{attributes});            !!!insert-element ($token->{tag_name}, $token->{attributes});
5278            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
5279            !!!next-token;            !!!next-token;
5280            redo B;            redo B;
5281          } elsif ($token->{tag_name} eq 'noframes') {          } elsif ($token->{tag_name} eq 'noframes') {
5282              !!!cp ('t320');
5283            ## NOTE: As if in body.            ## NOTE: As if in body.
5284            $parse_rcdata->(CDATA_CONTENT_MODEL, $insert_to_current);            $parse_rcdata->(CDATA_CONTENT_MODEL);
5285            redo B;            redo B;
5286          } else {          } else {
5287            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5288                !!!cp ('t321');
5289              !!!parse-error (type => 'in frameset:'.$token->{tag_name});              !!!parse-error (type => 'in frameset:'.$token->{tag_name});
5290            } else {            } else {
5291                !!!cp ('t322');
5292              !!!parse-error (type => 'after frameset:'.$token->{tag_name});              !!!parse-error (type => 'after frameset:'.$token->{tag_name});
5293            }            }
5294            ## Ignore the token            ## Ignore the token
# Line 4816  sub _tree_construction_main ($) { Line 5297  sub _tree_construction_main ($) {
5297          }          }
5298        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5299          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
5300              !!!cp ('t323');
5301            !!!parse-error (type => 'after html:/'.$token->{tag_name});            !!!parse-error (type => 'after html:/'.$token->{tag_name});
5302    
5303            $self->{insertion_mode} = AFTER_FRAMESET_IM;            $self->{insertion_mode} = AFTER_FRAMESET_IM;
5304            ## Process in the "main" phase, "after frameset" insertion mode...            ## Process in the "after frameset" insertion mode.
5305            } else {
5306              !!!cp ('t324');
5307          }          }
5308    
5309          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
5310              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5311            if ($self->{open_elements}->[-1]->[1] eq 'html' and            if ($self->{open_elements}->[-1]->[1] eq 'html' and
5312                @{$self->{open_elements}} == 1) {                @{$self->{open_elements}} == 1) {
5313                !!!cp ('t325');
5314              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5315              ## Ignore the token              ## Ignore the token
5316              !!!next-token;              !!!next-token;
5317            } else {            } else {
5318                !!!cp ('t326');
5319              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
5320              !!!next-token;              !!!next-token;
5321            }            }
5322    
5323            if (not defined $self->{inner_html_node} and            if (not defined $self->{inner_html_node} and
5324                $self->{open_elements}->[-1]->[1] ne 'frameset') {                $self->{open_elements}->[-1]->[1] ne 'frameset') {
5325                !!!cp ('t327');
5326              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
5327              } else {
5328                !!!cp ('t328');
5329            }            }
5330            redo B;            redo B;
5331          } elsif ($token->{tag_name} eq 'html' and          } elsif ($token->{tag_name} eq 'html' and
5332                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {
5333              !!!cp ('t329');
5334            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;
5335            !!!next-token;            !!!next-token;
5336            redo B;            redo B;
5337          } else {          } else {
5338            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5339                !!!cp ('t330');
5340              !!!parse-error (type => 'in frameset:/'.$token->{tag_name});              !!!parse-error (type => 'in frameset:/'.$token->{tag_name});
5341            } else {            } else {
5342                !!!cp ('t331');
5343              !!!parse-error (type => 'after frameset:/'.$token->{tag_name});              !!!parse-error (type => 'after frameset:/'.$token->{tag_name});
5344            }            }
5345            ## Ignore the token            ## Ignore the token
# Line 4866  sub _tree_construction_main ($) { Line 5358  sub _tree_construction_main ($) {
5358      ## "in body" insertion mode      ## "in body" insertion mode
5359      if ($token->{type} == START_TAG_TOKEN) {      if ($token->{type} == START_TAG_TOKEN) {
5360        if ($token->{tag_name} eq 'script') {        if ($token->{tag_name} eq 'script') {
5361            !!!cp ('t332');
5362          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5363          $script_start_tag->($insert);          $script_start_tag->();
5364          redo B;          redo B;
5365        } elsif ($token->{tag_name} eq 'style') {        } elsif ($token->{tag_name} eq 'style') {
5366            !!!cp ('t333');
5367          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5368          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);          $parse_rcdata->(CDATA_CONTENT_MODEL);
5369          redo B;          redo B;
5370        } elsif ({        } elsif ({
5371                  base => 1, link => 1,                  base => 1, link => 1,
5372                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5373            !!!cp ('t334');
5374          ## NOTE: This is an "as if in head" code clone, only "-t" differs          ## NOTE: This is an "as if in head" code clone, only "-t" differs
5375          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5376          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.
# Line 4888  sub _tree_construction_main ($) { Line 5383  sub _tree_construction_main ($) {
5383    
5384          unless ($self->{confident}) {          unless ($self->{confident}) {
5385            if ($token->{attributes}->{charset}) { ## TODO: And if supported            if ($token->{attributes}->{charset}) { ## TODO: And if supported
5386                !!!cp ('t335');
5387              $self->{change_encoding}              $self->{change_encoding}
5388                  ->($self, $token->{attributes}->{charset}->{value});                  ->($self, $token->{attributes}->{charset}->{value});
5389                            
# Line 4902  sub _tree_construction_main ($) { Line 5398  sub _tree_construction_main ($) {
5398                      [\x09-\x0D\x20]*=                      [\x09-\x0D\x20]*=
5399                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
5400                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
5401                  !!!cp ('t336');
5402                $self->{change_encoding}                $self->{change_encoding}
5403                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);
5404                $meta_el->[0]->get_attribute_node_ns (undef, 'content')                $meta_el->[0]->get_attribute_node_ns (undef, 'content')
# Line 4912  sub _tree_construction_main ($) { Line 5409  sub _tree_construction_main ($) {
5409            }            }
5410          } else {          } else {
5411            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
5412                !!!cp ('t337');
5413              $meta_el->[0]->get_attribute_node_ns (undef, 'charset')              $meta_el->[0]->get_attribute_node_ns (undef, 'charset')
5414                  ->set_user_data (manakai_has_reference =>                  ->set_user_data (manakai_has_reference =>
5415                                       $token->{attributes}->{charset}                                       $token->{attributes}->{charset}
5416                                           ->{has_reference});                                           ->{has_reference});
5417            }            }
5418            if ($token->{attributes}->{content}) {            if ($token->{attributes}->{content}) {
5419                !!!cp ('t338');
5420              $meta_el->[0]->get_attribute_node_ns (undef, 'content')              $meta_el->[0]->get_attribute_node_ns (undef, 'content')
5421                  ->set_user_data (manakai_has_reference =>                  ->set_user_data (manakai_has_reference =>
5422                                       $token->{attributes}->{content}                                       $token->{attributes}->{content}
# Line 4928  sub _tree_construction_main ($) { Line 5427  sub _tree_construction_main ($) {
5427          !!!next-token;          !!!next-token;
5428          redo B;          redo B;
5429        } elsif ($token->{tag_name} eq 'title') {        } elsif ($token->{tag_name} eq 'title') {
5430          !!!parse-error (type => 'in body:title');          !!!cp ('t341');
5431          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5432          $parse_rcdata->(RCDATA_CONTENT_MODEL, sub {          $parse_rcdata->(RCDATA_CONTENT_MODEL);
           if (defined $self->{head_element}) {  
             $self->{head_element}->append_child ($_[0]);  
           } else {  
             $insert->($_[0]);  
           }  
         });  
5433          redo B;          redo B;
5434        } elsif ($token->{tag_name} eq 'body') {        } elsif ($token->{tag_name} eq 'body') {
5435          !!!parse-error (type => 'in body:body');          !!!parse-error (type => 'in body:body');
5436                                
5437          if (@{$self->{open_elements}} == 1 or          if (@{$self->{open_elements}} == 1 or
5438              $self->{open_elements}->[1]->[1] ne 'body') {              $self->{open_elements}->[1]->[1] ne 'body') {
5439              !!!cp ('t342');
5440            ## Ignore the token            ## Ignore the token
5441          } else {          } else {
5442            my $body_el = $self->{open_elements}->[1]->[0];            my $body_el = $self->{open_elements}->[1]->[0];
5443            for my $attr_name (keys %{$token->{attributes}}) {            for my $attr_name (keys %{$token->{attributes}}) {
5444              unless ($body_el->has_attribute_ns (undef, $attr_name)) {              unless ($body_el->has_attribute_ns (undef, $attr_name)) {
5445                  !!!cp ('t343');
5446                $body_el->set_attribute_ns                $body_el->set_attribute_ns
5447                  (undef, [undef, $attr_name],                  (undef, [undef, $attr_name],
5448                   $token->{attributes}->{$attr_name}->{value});                   $token->{attributes}->{$attr_name}->{value});
# Line 4958  sub _tree_construction_main ($) { Line 5453  sub _tree_construction_main ($) {
5453          redo B;          redo B;
5454        } elsif ({        } elsif ({
5455                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
5456                  div => 1, dl => 1, fieldset => 1, listing => 1,                  div => 1, dl => 1, fieldset => 1,
5457                    h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
5458                  menu => 1, ol => 1, p => 1, ul => 1,                  menu => 1, ol => 1, p => 1, ul => 1,
5459                  pre => 1,                  pre => 1, listing => 1,
5460                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5461          ## has a p element in scope          ## has a p element in scope
5462          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5463            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5464                !!!cp ('t344');
5465              !!!back-token;              !!!back-token;
5466              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5467              redo B;              redo B;
# Line 4972  sub _tree_construction_main ($) { Line 5469  sub _tree_construction_main ($) {
5469                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5470                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5471                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5472                !!!cp ('t345');
5473              last INSCOPE;              last INSCOPE;
5474            }            }
5475          } # INSCOPE          } # INSCOPE
5476                        
5477          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5478          if ($token->{tag_name} eq 'pre') {          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {
5479            !!!next-token;            !!!next-token;
5480            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5481              $token->{data} =~ s/^\x0A//;              $token->{data} =~ s/^\x0A//;
5482              unless (length $token->{data}) {              unless (length $token->{data}) {
5483                  !!!cp ('t346');
5484                !!!next-token;                !!!next-token;
5485                } else {
5486                  !!!cp ('t349');
5487              }              }
5488              } else {
5489                !!!cp ('t348');
5490            }            }
5491          } else {          } else {
5492              !!!cp ('t347');
5493            !!!next-token;            !!!next-token;
5494          }          }
5495          redo B;          redo B;
5496        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
5497          if (defined $self->{form_element}) {          if (defined $self->{form_element}) {
5498              !!!cp ('t350');
5499            !!!parse-error (type => 'in form:form');            !!!parse-error (type => 'in form:form');
5500            ## Ignore the token            ## Ignore the token
5501            !!!next-token;            !!!next-token;
# Line 4999  sub _tree_construction_main ($) { Line 5504  sub _tree_construction_main ($) {
5504            ## has a p element in scope            ## has a p element in scope
5505            INSCOPE: for (reverse @{$self->{open_elements}}) {            INSCOPE: for (reverse @{$self->{open_elements}}) {
5506              if ($_->[1] eq 'p') {              if ($_->[1] eq 'p') {
5507                  !!!cp ('t351');
5508                !!!back-token;                !!!back-token;
5509                $token = {type => END_TAG_TOKEN, tag_name => 'p'};                $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5510                redo B;                redo B;
# Line 5006  sub _tree_construction_main ($) { Line 5512  sub _tree_construction_main ($) {
5512                        table => 1, caption => 1, td => 1, th => 1,                        table => 1, caption => 1, td => 1, th => 1,
5513                        button => 1, marquee => 1, object => 1, html => 1,                        button => 1, marquee => 1, object => 1, html => 1,
5514                       }->{$_->[1]}) {                       }->{$_->[1]}) {
5515                  !!!cp ('t352');
5516                last INSCOPE;                last INSCOPE;
5517              }              }
5518            } # INSCOPE            } # INSCOPE
# Line 5019  sub _tree_construction_main ($) { Line 5526  sub _tree_construction_main ($) {
5526          ## has a p element in scope          ## has a p element in scope
5527          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5528            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5529                !!!cp ('t353');
5530              !!!back-token;              !!!back-token;
5531              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5532              redo B;              redo B;
# Line 5026  sub _tree_construction_main ($) { Line 5534  sub _tree_construction_main ($) {
5534                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5535                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5536                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5537                !!!cp ('t354');
5538              last INSCOPE;              last INSCOPE;
5539            }            }
5540          } # INSCOPE          } # INSCOPE
# Line 5037  sub _tree_construction_main ($) { Line 5546  sub _tree_construction_main ($) {
5546            ## Step 2            ## Step 2
5547            if ($node->[1] eq 'li') {            if ($node->[1] eq 'li') {
5548              if ($i != -1) {              if ($i != -1) {
5549                  !!!cp ('t355');
5550                !!!parse-error (type => 'end tag missing:'.                !!!parse-error (type => 'end tag missing:'.
5551                                $self->{open_elements}->[-1]->[1]);                                $self->{open_elements}->[-1]->[1]);
5552                } else {
5553                  !!!cp ('t356');
5554              }              }
5555              splice @{$self->{open_elements}}, $i;              splice @{$self->{open_elements}}, $i;
5556              last LI;              last LI;
5557              } else {
5558                !!!cp ('t357');
5559            }            }
5560                        
5561            ## Step 3            ## Step 3
# Line 5050  sub _tree_construction_main ($) { Line 5564  sub _tree_construction_main ($) {
5564                ($special_category->{$node->[1]} or                ($special_category->{$node->[1]} or
5565                 $scoping_category->{$node->[1]}) and                 $scoping_category->{$node->[1]}) and
5566                $node->[1] ne 'address' and $node->[1] ne 'div') {                $node->[1] ne 'address' and $node->[1] ne 'div') {
5567                !!!cp ('t358');
5568              last LI;              last LI;
5569            }            }
5570                        
5571              !!!cp ('t359');
5572            ## Step 4            ## Step 4
5573            $i--;            $i--;
5574            $node = $self->{open_elements}->[$i];            $node = $self->{open_elements}->[$i];
# Line 5066  sub _tree_construction_main ($) { Line 5582  sub _tree_construction_main ($) {
5582          ## has a p element in scope          ## has a p element in scope
5583          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5584            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5585                !!!cp ('t360');
5586              !!!back-token;              !!!back-token;
5587              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5588              redo B;              redo B;
# Line 5073  sub _tree_construction_main ($) { Line 5590  sub _tree_construction_main ($) {
5590                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5591                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5592                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5593                !!!cp ('t361');
5594              last INSCOPE;              last INSCOPE;
5595            }            }
5596          } # INSCOPE          } # INSCOPE
# Line 5084  sub _tree_construction_main ($) { Line 5602  sub _tree_construction_main ($) {
5602            ## Step 2            ## Step 2
5603            if ($node->[1] eq 'dt' or $node->[1] eq 'dd') {            if ($node->[1] eq 'dt' or $node->[1] eq 'dd') {
5604              if ($i != -1) {              if ($i != -1) {
5605                  !!!cp ('t362');
5606                !!!parse-error (type => 'end tag missing:'.                !!!parse-error (type => 'end tag missing:'.
5607                                $self->{open_elements}->[-1]->[1]);                                $self->{open_elements}->[-1]->[1]);
5608                } else {
5609                  !!!cp ('t363');
5610              }              }
5611              splice @{$self->{open_elements}}, $i;              splice @{$self->{open_elements}}, $i;
5612              last LI;              last LI;
5613              } else {
5614                !!!cp ('t364');
5615            }            }
5616                        
5617            ## Step 3            ## Step 3
# Line 5097  sub _tree_construction_main ($) { Line 5620  sub _tree_construction_main ($) {
5620                ($special_category->{$node->[1]} or                ($special_category->{$node->[1]} or
5621                 $scoping_category->{$node->[1]}) and                 $scoping_category->{$node->[1]}) and
5622                $node->[1] ne 'address' and $node->[1] ne 'div') {                $node->[1] ne 'address' and $node->[1] ne 'div') {
5623                !!!cp ('t365');
5624              last LI;              last LI;
5625            }            }
5626                        
5627              !!!cp ('t366');
5628            ## Step 4            ## Step 4
5629            $i--;            $i--;
5630            $node = $self->{open_elements}->[$i];            $node = $self->{open_elements}->[$i];
# Line 5113  sub _tree_construction_main ($) { Line 5638  sub _tree_construction_main ($) {
5638          ## has a p element in scope          ## has a p element in scope
5639          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5640            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5641                !!!cp ('t367');
5642              !!!back-token;              !!!back-token;
5643              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5644              redo B;              redo B;
# Line 5120  sub _tree_construction_main ($) { Line 5646  sub _tree_construction_main ($) {
5646                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5647                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5648                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5649                !!!cp ('t368');
5650              last INSCOPE;              last INSCOPE;
5651            }            }
5652          } # INSCOPE          } # INSCOPE
# Line 5130  sub _tree_construction_main ($) { Line 5657  sub _tree_construction_main ($) {
5657                        
5658          !!!next-token;          !!!next-token;
5659          redo B;          redo B;
       } elsif ({  
                 h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,  
                }->{$token->{tag_name}}) {  
         ## has a p element in scope  
         INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
           my $node = $self->{open_elements}->[$_];  
           if ($node->[1] eq 'p') {  
             !!!back-token;  
             $token = {type => END_TAG_TOKEN, tag_name => 'p'};  
             redo B;  
           } elsif ({  
                     table => 1, caption => 1, td => 1, th => 1,  
                     button => 1, marquee => 1, object => 1, html => 1,  
                    }->{$node->[1]}) {  
             last INSCOPE;  
           }  
         } # INSCOPE  
             
         ## NOTE: See <http://html5.org/tools/web-apps-tracker?from=925&to=926>  
         ## has an element in scope  
         #my $i;  
         #INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
         #  my $node = $self->{open_elements}->[$_];  
         #  if ({  
         #       h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,  
         #      }->{$node->[1]}) {  
         #    $i = $_;  
         #    last INSCOPE;  
         #  } elsif ({  
         #            table => 1, caption => 1, td => 1, th => 1,  
         #            button => 1, marquee => 1, object => 1, html => 1,  
         #           }->{$node->[1]}) {  
         #    last INSCOPE;  
         #  }  
         #} # INSCOPE  
         #    
         #if (defined $i) {  
         #  !!! parse-error (type => 'in hn:hn');  
         #  splice @{$self->{open_elements}}, $i;  
         #}  
             
         !!!insert-element-t ($token->{tag_name}, $token->{attributes});  
             
         !!!next-token;  
         redo B;  
5660        } elsif ($token->{tag_name} eq 'a') {        } elsif ($token->{tag_name} eq 'a') {
5661          AFE: for my $i (reverse 0..$#$active_formatting_elements) {          AFE: for my $i (reverse 0..$#$active_formatting_elements) {
5662            my $node = $active_formatting_elements->[$i];            my $node = $active_formatting_elements->[$i];
5663            if ($node->[1] eq 'a') {            if ($node->[1] eq 'a') {
5664                !!!cp ('t371');
5665              !!!parse-error (type => 'in a:a');              !!!parse-error (type => 'in a:a');
5666                            
5667              !!!back-token;              !!!back-token;
# Line 5187  sub _tree_construction_main ($) { Line 5670  sub _tree_construction_main ($) {
5670                            
5671              AFE2: for (reverse 0..$#$active_formatting_elements) {              AFE2: for (reverse 0..$#$active_formatting_elements) {
5672                if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {                if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {
5673                    !!!cp ('t372');
5674                  splice @$active_formatting_elements, $_, 1;                  splice @$active_formatting_elements, $_, 1;
5675                  last AFE2;                  last AFE2;
5676                }                }
5677              } # AFE2              } # AFE2
5678              OE: for (reverse 0..$#{$self->{open_elements}}) {              OE: for (reverse 0..$#{$self->{open_elements}}) {
5679                if ($self->{open_elements}->[$_]->[0] eq $node->[0]) {                if ($self->{open_elements}->[$_]->[0] eq $node->[0]) {
5680                    !!!cp ('t373');
5681                  splice @{$self->{open_elements}}, $_, 1;                  splice @{$self->{open_elements}}, $_, 1;
5682                  last OE;                  last OE;
5683                }                }
5684              } # OE              } # OE
5685              last AFE;              last AFE;
5686            } elsif ($node->[0] eq '#marker') {            } elsif ($node->[0] eq '#marker') {
5687                !!!cp ('t374');
5688              last AFE;              last AFE;
5689            }            }
5690          } # AFE          } # AFE
# Line 5215  sub _tree_construction_main ($) { Line 5701  sub _tree_construction_main ($) {
5701                  s => 1, small => 1, strile => 1,                  s => 1, small => 1, strile => 1,
5702                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
5703                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5704            !!!cp ('t375');
5705          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5706                    
5707          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5229  sub _tree_construction_main ($) { Line 5716  sub _tree_construction_main ($) {
5716          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5717            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
5718            if ($node->[1] eq 'nobr') {            if ($node->[1] eq 'nobr') {
5719                !!!cp ('t376');
5720              !!!parse-error (type => 'in nobr:nobr');              !!!parse-error (type => 'in nobr:nobr');
5721              !!!back-token;              !!!back-token;
5722              $token = {type => END_TAG_TOKEN, tag_name => 'nobr'};              $token = {type => END_TAG_TOKEN, tag_name => 'nobr'};
# Line 5237  sub _tree_construction_main ($) { Line 5725  sub _tree_construction_main ($) {
5725                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5726                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5727                     }->{$node->[1]}) {                     }->{$node->[1]}) {
5728                !!!cp ('t377');
5729              last INSCOPE;              last INSCOPE;
5730            }            }
5731          } # INSCOPE          } # INSCOPE
# Line 5251  sub _tree_construction_main ($) { Line 5740  sub _tree_construction_main ($) {
5740          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5741            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
5742            if ($node->[1] eq 'button') {            if ($node->[1] eq 'button') {
5743                !!!cp ('t378');
5744              !!!parse-error (type => 'in button:button');              !!!parse-error (type => 'in button:button');
5745              !!!back-token;              !!!back-token;
5746              $token = {type => END_TAG_TOKEN, tag_name => 'button'};              $token = {type => END_TAG_TOKEN, tag_name => 'button'};
# Line 5259  sub _tree_construction_main ($) { Line 5749  sub _tree_construction_main ($) {
5749                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5750                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5751                     }->{$node->[1]}) {                     }->{$node->[1]}) {
5752                !!!cp ('t379');
5753              last INSCOPE;              last INSCOPE;
5754            }            }
5755          } # INSCOPE          } # INSCOPE
# Line 5266  sub _tree_construction_main ($) { Line 5757  sub _tree_construction_main ($) {
5757          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5758                        
5759          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5760    
5761            ## TODO: associate with $self->{form_element} if defined
5762    
5763          push @$active_formatting_elements, ['#marker', ''];          push @$active_formatting_elements, ['#marker', ''];
5764    
5765          !!!next-token;          !!!next-token;
5766          redo B;          redo B;
5767        } elsif ($token->{tag_name} eq 'marquee' or        } elsif ($token->{tag_name} eq 'marquee' or
5768                 $token->{tag_name} eq 'object') {                 $token->{tag_name} eq 'object') {
5769            !!!cp ('t380');
5770          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5771                    
5772          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5280  sub _tree_construction_main ($) { Line 5775  sub _tree_construction_main ($) {
5775          !!!next-token;          !!!next-token;
5776          redo B;          redo B;
5777        } elsif ($token->{tag_name} eq 'xmp') {        } elsif ($token->{tag_name} eq 'xmp') {
5778            !!!cp ('t381');
5779          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5780          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);          $parse_rcdata->(CDATA_CONTENT_MODEL);
5781          redo B;          redo B;
5782        } elsif ($token->{tag_name} eq 'table') {        } elsif ($token->{tag_name} eq 'table') {
5783          ## has a p element in scope          ## has a p element in scope
5784          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5785            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5786                !!!cp ('t382');
5787              !!!back-token;              !!!back-token;
5788              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5789              redo B;              redo B;
# Line 5294  sub _tree_construction_main ($) { Line 5791  sub _tree_construction_main ($) {
5791                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5792                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5793                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5794                !!!cp ('t383');
5795              last INSCOPE;              last INSCOPE;
5796            }            }
5797          } # INSCOPE          } # INSCOPE
5798                        
5799          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5800                      push @{$open_tables}, [$self->{open_elements}->[-1]->[0]];
5801    
5802          $self->{insertion_mode} = IN_TABLE_IM;          $self->{insertion_mode} = IN_TABLE_IM;
5803                        
5804          !!!next-token;          !!!next-token;
# Line 5310  sub _tree_construction_main ($) { Line 5809  sub _tree_construction_main ($) {
5809                  image => 1,                  image => 1,
5810                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5811          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
5812              !!!cp ('t384');
5813            !!!parse-error (type => 'image');            !!!parse-error (type => 'image');
5814            $token->{tag_name} = 'img';            $token->{tag_name} = 'img';
5815            } else {
5816              !!!cp ('t385');
5817          }          }
5818    
5819          ## NOTE: There is an "as if <br>" code clone.          ## NOTE: There is an "as if <br>" code clone.
# Line 5326  sub _tree_construction_main ($) { Line 5828  sub _tree_construction_main ($) {
5828          ## has a p element in scope          ## has a p element in scope
5829          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5830            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5831                !!!cp ('t386');
5832              !!!back-token;              !!!back-token;
5833              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5834              redo B;              redo B;
# Line 5333  sub _tree_construction_main ($) { Line 5836  sub _tree_construction_main ($) {
5836                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5837                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5838                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5839                !!!cp ('t387');
5840              last INSCOPE;              last INSCOPE;
5841            }            }
5842          } # INSCOPE          } # INSCOPE
# Line 5343  sub _tree_construction_main ($) { Line 5847  sub _tree_construction_main ($) {
5847          !!!next-token;          !!!next-token;
5848          redo B;          redo B;
5849        } elsif ($token->{tag_name} eq 'input') {        } elsif ($token->{tag_name} eq 'input') {
5850            !!!cp ('t388');
5851          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5852                    
5853          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5355  sub _tree_construction_main ($) { Line 5860  sub _tree_construction_main ($) {
5860          !!!parse-error (type => 'isindex');          !!!parse-error (type => 'isindex');
5861                    
5862          if (defined $self->{form_element}) {          if (defined $self->{form_element}) {
5863              !!!cp ('t389');
5864            ## Ignore the token            ## Ignore the token
5865            !!!next-token;            !!!next-token;
5866            redo B;            redo B;
# Line 5374  sub _tree_construction_main ($) { Line 5880  sub _tree_construction_main ($) {
5880                          {type => START_TAG_TOKEN, tag_name => 'label'},                          {type => START_TAG_TOKEN, tag_name => 'label'},
5881                         );                         );
5882            if ($prompt_attr) {            if ($prompt_attr) {
5883                !!!cp ('t390');
5884              push @tokens, {type => CHARACTER_TOKEN, data => $prompt_attr->{value}};              push @tokens, {type => CHARACTER_TOKEN, data => $prompt_attr->{value}};
5885            } else {            } else {
5886                !!!cp ('t391');
5887              push @tokens, {type => CHARACTER_TOKEN,              push @tokens, {type => CHARACTER_TOKEN,
5888                             data => 'This is a searchable index. Insert your search keywords here: '}; # SHOULD                             data => 'This is a searchable index. Insert your search keywords here: '}; # SHOULD
5889              ## TODO: make this configurable              ## TODO: make this configurable
# Line 5407  sub _tree_construction_main ($) { Line 5915  sub _tree_construction_main ($) {
5915          if ($token->{type} == CHARACTER_TOKEN) {          if ($token->{type} == CHARACTER_TOKEN) {
5916            $token->{data} =~ s/^\x0A//;            $token->{data} =~ s/^\x0A//;
5917            unless (length $token->{data}) {            unless (length $token->{data}) {
5918                !!!cp ('t392');
5919              !!!next-token;              !!!next-token;
5920              } else {
5921                !!!cp ('t393');
5922            }            }
5923            } else {
5924              !!!cp ('t394');
5925          }          }
5926          while ($token->{type} == CHARACTER_TOKEN) {          while ($token->{type} == CHARACTER_TOKEN) {
5927              !!!cp ('t395');
5928            $text .= $token->{data};            $text .= $token->{data};
5929            !!!next-token;            !!!next-token;
5930          }          }
5931          if (length $text) {          if (length $text) {
5932              !!!cp ('t396');
5933            $el->manakai_append_text ($text);            $el->manakai_append_text ($text);
5934          }          }
5935                    
# Line 5422  sub _tree_construction_main ($) { Line 5937  sub _tree_construction_main ($) {
5937                    
5938          if ($token->{type} == END_TAG_TOKEN and          if ($token->{type} == END_TAG_TOKEN and
5939              $token->{tag_name} eq $tag_name) {              $token->{tag_name} eq $tag_name) {
5940              !!!cp ('t397');
5941            ## Ignore the token            ## Ignore the token
5942          } else {          } else {
5943              !!!cp ('t398');
5944            !!!parse-error (type => 'in RCDATA:#'.$token->{type});            !!!parse-error (type => 'in RCDATA:#'.$token->{type});
5945          }          }
5946          !!!next-token;          !!!next-token;
# Line 5434  sub _tree_construction_main ($) { Line 5951  sub _tree_construction_main ($) {
5951                  noframes => 1,                  noframes => 1,
5952                  noscript => 0, ## TODO: 1 if scripting is enabled                  noscript => 0, ## TODO: 1 if scripting is enabled
5953                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5954            !!!cp ('t399');
5955          ## NOTE: There is an "as if in body" code clone.          ## NOTE: There is an "as if in body" code clone.
5956          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);          $parse_rcdata->(CDATA_CONTENT_MODEL);
5957          redo B;          redo B;
5958        } elsif ($token->{tag_name} eq 'select') {        } elsif ($token->{tag_name} eq 'select') {
5959            !!!cp ('t400');
5960          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5961                    
5962          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5963    
5964            ## TODO: associate with $self->{form_element} if defined
5965                    
5966          $self->{insertion_mode} = IN_SELECT_IM;          if ($self->{insertion_mode} & TABLE_IMS or
5967                $self->{insertion_mode} & BODY_TABLE_IMS or
5968                $self->{insertion_mode} == IN_COLUMN_GROUP_IM) {
5969              !!!cp ('t400.1');
5970              $self->{insertion_mode} = IN_SELECT_IN_TABLE_IM;
5971            } else {
5972              !!!cp ('t400.2');
5973              $self->{insertion_mode} = IN_SELECT_IM;
5974            }
5975          !!!next-token;          !!!next-token;
5976          redo B;          redo B;
5977        } elsif ({        } elsif ({
# Line 5451  sub _tree_construction_main ($) { Line 5980  sub _tree_construction_main ($) {
5980                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
5981                  thead => 1, tr => 1,                  thead => 1, tr => 1,
5982                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5983            !!!cp ('t401');
5984          !!!parse-error (type => 'in body:'.$token->{tag_name});          !!!parse-error (type => 'in body:'.$token->{tag_name});
5985          ## Ignore the token          ## Ignore the token
5986          !!!next-token;          !!!next-token;
# Line 5458  sub _tree_construction_main ($) { Line 5988  sub _tree_construction_main ($) {
5988                    
5989          ## ISSUE: An issue on HTML5 new elements in the spec.          ## ISSUE: An issue on HTML5 new elements in the spec.
5990        } else {        } else {
5991            !!!cp ('t402');
5992          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5993                    
5994          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5475  sub _tree_construction_main ($) { Line 6006  sub _tree_construction_main ($) {
6006                         th => 1, tr => 1, body => 1, html => 1,                         th => 1, tr => 1, body => 1, html => 1,
6007                       tbody => 1, tfoot => 1, thead => 1,                       tbody => 1, tfoot => 1, thead => 1,
6008                      }->{$_->[1]}) {                      }->{$_->[1]}) {
6009                  !!!cp ('t403');
6010                !!!parse-error (type => 'not closed:'.$_->[1]);                !!!parse-error (type => 'not closed:'.$_->[1]);
6011                } else {
6012                  !!!cp ('t404');
6013              }              }
6014            }            }
6015    
# Line 5483  sub _tree_construction_main ($) { Line 6017  sub _tree_construction_main ($) {
6017            !!!next-token;            !!!next-token;
6018            redo B;            redo B;
6019          } else {          } else {
6020              !!!cp ('t405');
6021            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6022            ## Ignore the token            ## Ignore the token
6023            !!!next-token;            !!!next-token;
# Line 5492  sub _tree_construction_main ($) { Line 6027  sub _tree_construction_main ($) {
6027          if (@{$self->{open_elements}} > 1 and $self->{open_elements}->[1]->[1] eq 'body') {          if (@{$self->{open_elements}} > 1 and $self->{open_elements}->[1]->[1] eq 'body') {
6028            ## ISSUE: There is an issue in the spec.            ## ISSUE: There is an issue in the spec.
6029            if ($self->{open_elements}->[-1]->[1] ne 'body') {            if ($self->{open_elements}->[-1]->[1] ne 'body') {
6030                !!!cp ('t406');
6031              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[1]->[1]);              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[1]->[1]);
6032              } else {
6033                !!!cp ('t407');
6034            }            }
6035            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
6036            ## reprocess            ## reprocess
6037            redo B;            redo B;
6038          } else {          } else {
6039              !!!cp ('t408');
6040            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6041            ## Ignore the token            ## Ignore the token
6042            !!!next-token;            !!!next-token;
# Line 5507  sub _tree_construction_main ($) { Line 6046  sub _tree_construction_main ($) {
6046                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
6047                  div => 1, dl => 1, fieldset => 1, listing => 1,                  div => 1, dl => 1, fieldset => 1, listing => 1,
6048                  menu => 1, ol => 1, pre => 1, ul => 1,                  menu => 1, ol => 1, pre => 1, ul => 1,
                 p => 1,  
6049                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
6050                  button => 1, marquee => 1, object => 1,                  button => 1, marquee => 1, object => 1,
6051                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 5516  sub _tree_construction_main ($) { Line 6054  sub _tree_construction_main ($) {
6054          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6055            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6056            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] eq $token->{tag_name}) {
6057              ## generate implied end tags              !!!cp ('t410');
             if ({  
                  dd => ($token->{tag_name} ne 'dd'),  
                  dt => ($token->{tag_name} ne 'dt'),  
                  li => ($token->{tag_name} ne 'li'),  
                  p => ($token->{tag_name} ne 'p'),  
                  td => 1, th => 1, tr => 1,  
                  tbody => 1, tfoot=> 1, thead => 1,  
                 }->{$self->{open_elements}->[-1]->[1]}) {  
               !!!back-token;  
               $token = {type => END_TAG_TOKEN,  
                         tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
               redo B;  
             }  
6058              $i = $_;              $i = $_;
6059              last INSCOPE unless $token->{tag_name} eq 'p';              last INSCOPE;
6060            } elsif ({            } elsif ({
6061                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
6062                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
6063                     }->{$node->[1]}) {                     }->{$node->[1]}) {
6064                !!!cp ('t411');
6065              last INSCOPE;              last INSCOPE;
6066            }            }
6067          } # INSCOPE          } # INSCOPE
6068            
6069          if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {          unless (defined $i) { # has an element in scope
6070            if (defined $i) {            !!!cp ('t413');
6071              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6072            } else {
6073              ## Step 1. generate implied end tags
6074              while ({
6075                      dd => ($token->{tag_name} ne 'dd'),
6076                      dt => ($token->{tag_name} ne 'dt'),
6077                      li => ($token->{tag_name} ne 'li'),
6078                      p => 1,
6079                     }->{$self->{open_elements}->[-1]->[1]}) {
6080                !!!cp ('t409');
6081                pop @{$self->{open_elements}};
6082              }
6083    
6084              ## Step 2.
6085              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6086                !!!cp ('t412');
6087              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6088            } else {            } else {
6089              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});              !!!cp ('t414');
6090            }            }
6091          }  
6092                      ## Step 3.
         if (defined $i) {  
6093            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
6094          } elsif ($token->{tag_name} eq 'p') {  
6095            ## As if <p>, then reprocess the current token            ## Step 4.
6096            my $el;            $clear_up_to_marker->()
6097            !!!create-element ($el, 'p');                if {
6098            $insert->($el);                  button => 1, marquee => 1, object => 1,
6099                  }->{$token->{tag_name}};
6100          }          }
         $clear_up_to_marker->()  
           if {  
             button => 1, marquee => 1, object => 1,  
           }->{$token->{tag_name}};  
6101          !!!next-token;          !!!next-token;
6102          redo B;          redo B;
6103        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
6104            undef $self->{form_element};
6105    
6106          ## has an element in scope          ## has an element in scope
6107            my $i;
6108          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6109            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6110            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] eq $token->{tag_name}) {
6111              ## generate implied end tags              !!!cp ('t418');
6112              if ({              $i = $_;
                  dd => 1, dt => 1, li => 1, p => 1,  
                  td => 1, th => 1, tr => 1,  
                  tbody => 1, tfoot=> 1, thead => 1,  
                 }->{$self->{open_elements}->[-1]->[1]}) {  
               !!!back-token;  
               $token = {type => END_TAG_TOKEN,  
                         tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
               redo B;  
             }  
6113              last INSCOPE;              last INSCOPE;
6114            } elsif ({            } elsif ({
6115                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
6116                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
6117                     }->{$node->[1]}) {                     }->{$node->[1]}) {
6118                !!!cp ('t419');
6119              last INSCOPE;              last INSCOPE;
6120            }            }
6121          } # INSCOPE          } # INSCOPE
6122            
6123          if ($self->{open_elements}->[-1]->[1] eq $token->{tag_name}) {          unless (defined $i) { # has an element in scope
6124            pop @{$self->{open_elements}};            !!!cp ('t421');
         } else {  
6125            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6126            } else {
6127              ## Step 1. generate implied end tags
6128              while ({
6129                      dd => 1, dt => 1, li => 1, p => 1,
6130                     }->{$self->{open_elements}->[-1]->[1]}) {
6131                !!!cp ('t417');
6132                pop @{$self->{open_elements}};
6133              }
6134              
6135              ## Step 2.
6136              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6137                !!!cp ('t417.1');
6138                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6139              } else {
6140                !!!cp ('t420');
6141              }  
6142              
6143              ## Step 3.
6144              splice @{$self->{open_elements}}, $i;
6145          }          }
6146    
         undef $self->{form_element};  
6147          !!!next-token;          !!!next-token;
6148          redo B;          redo B;
6149        } elsif ({        } elsif ({
# Line 5606  sub _tree_construction_main ($) { Line 6156  sub _tree_construction_main ($) {
6156            if ({            if ({
6157                 h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                 h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
6158                }->{$node->[1]}) {                }->{$node->[1]}) {
6159              ## generate implied end tags              !!!cp ('t423');
             if ({  
                  dd => 1, dt => 1, li => 1, p => 1,  
                  td => 1, th => 1, tr => 1,  
                  tbody => 1, tfoot=> 1, thead => 1,  
                 }->{$self->{open_elements}->[-1]->[1]}) {  
               !!!back-token;  
               $token = {type => END_TAG_TOKEN,  
                         tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
               redo B;  
             }  
6160              $i = $_;              $i = $_;
6161              last INSCOPE;              last INSCOPE;
6162            } elsif ({            } elsif ({
6163                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
6164                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
6165                     }->{$node->[1]}) {                     }->{$node->[1]}) {
6166                !!!cp ('t424');
6167              last INSCOPE;              last INSCOPE;
6168            }            }
6169          } # INSCOPE          } # INSCOPE
6170            
6171          if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {          unless (defined $i) { # has an element in scope
6172              !!!cp ('t425.1');
6173            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6174            } else {
6175              ## Step 1. generate implied end tags
6176              while ({
6177                      dd => 1, dt => 1, li => 1, p => 1,
6178                     }->{$self->{open_elements}->[-1]->[1]}) {
6179                !!!cp ('t422');
6180                pop @{$self->{open_elements}};
6181              }
6182              
6183              ## Step 2.
6184              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6185                !!!cp ('t425');
6186                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6187              } else {
6188                !!!cp ('t426');
6189              }
6190    
6191              ## Step 3.
6192              splice @{$self->{open_elements}}, $i;
6193          }          }
6194                    
6195          splice @{$self->{open_elements}}, $i if defined $i;          !!!next-token;
6196            redo B;
6197          } elsif ($token->{tag_name} eq 'p') {
6198            ## has an element in scope
6199            my $i;
6200            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6201              my $node = $self->{open_elements}->[$_];
6202              if ($node->[1] eq $token->{tag_name}) {
6203                !!!cp ('t410.1');
6204                $i = $_;
6205                last INSCOPE;
6206              } elsif ({
6207                        table => 1, caption => 1, td => 1, th => 1,
6208                        button => 1, marquee => 1, object => 1, html => 1,
6209                       }->{$node->[1]}) {
6210                !!!cp ('t411.1');
6211                last INSCOPE;
6212              }
6213            } # INSCOPE
6214    
6215            if (defined $i) {
6216              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6217                !!!cp ('t412.1');
6218                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6219              } else {
6220                !!!cp ('t414.1');
6221              }
6222    
6223              splice @{$self->{open_elements}}, $i;
6224            } else {
6225              !!!cp ('t413.1');
6226              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6227    
6228              !!!cp ('t415.1');
6229              ## As if <p>, then reprocess the current token
6230              my $el;
6231              !!!create-element ($el, 'p');
6232              $insert->($el);
6233              ## NOTE: Not inserted into |$self->{open_elements}|.
6234            }
6235    
6236          !!!next-token;          !!!next-token;
6237          redo B;          redo B;
6238        } elsif ({        } elsif ({
# Line 5640  sub _tree_construction_main ($) { Line 6241  sub _tree_construction_main ($) {
6241                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strile => 1,
6242                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
6243                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6244            !!!cp ('t427');
6245          $formatting_end_tag->($token->{tag_name});          $formatting_end_tag->($token->{tag_name});
6246          redo B;          redo B;
6247        } elsif ($token->{tag_name} eq 'br') {        } elsif ($token->{tag_name} eq 'br') {
6248            !!!cp ('t428');
6249          !!!parse-error (type => 'unmatched end tag:br');          !!!parse-error (type => 'unmatched end tag:br');
6250    
6251          ## As if <br>          ## As if <br>
# Line 5667  sub _tree_construction_main ($) { Line 6270  sub _tree_construction_main ($) {
6270                  table => 1, textarea => 1, wbr => 1,                  table => 1, textarea => 1, wbr => 1,
6271                  noscript => 0, ## TODO: if scripting is enabled                  noscript => 0, ## TODO: if scripting is enabled
6272                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6273            !!!cp ('t429');
6274          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6275          ## Ignore the token          ## Ignore the token
6276          !!!next-token;          !!!next-token;
# Line 5684  sub _tree_construction_main ($) { Line 6288  sub _tree_construction_main ($) {
6288            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] eq $token->{tag_name}) {
6289              ## Step 1              ## Step 1
6290              ## generate implied end tags              ## generate implied end tags
6291              if ({              while ({
6292                   dd => 1, dt => 1, li => 1, p => 1,                      dd => 1, dt => 1, li => 1, p => 1,
6293                   td => 1, th => 1, tr => 1,                     }->{$self->{open_elements}->[-1]->[1]}) {
6294                   tbody => 1, tfoot => 1, thead => 1,                !!!cp ('t430');
6295                  }->{$self->{open_elements}->[-1]->[1]}) {                ## ISSUE: Can this case be reached?
6296                !!!back-token;                pop @{$self->{open_elements}};
               $token = {type => END_TAG_TOKEN,  
                         tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
               redo B;  
6297              }              }
6298                    
6299              ## Step 2              ## Step 2
6300              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {
6301                  !!!cp ('t431');
6302                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
6303                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6304                } else {
6305                  !!!cp ('t432');
6306              }              }
6307                            
6308              ## Step 3              ## Step 3
# Line 5712  sub _tree_construction_main ($) { Line 6316  sub _tree_construction_main ($) {
6316                  #not $phrasing_category->{$node->[1]} and                  #not $phrasing_category->{$node->[1]} and
6317                  ($special_category->{$node->[1]} or                  ($special_category->{$node->[1]} or
6318                   $scoping_category->{$node->[1]})) {                   $scoping_category->{$node->[1]})) {
6319                  !!!cp ('t433');
6320                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6321                ## Ignore the token                ## Ignore the token
6322                !!!next-token;                !!!next-token;
6323                last S2;                last S2;
6324              }              }
6325    
6326                !!!cp ('t434');
6327            }            }
6328                        
6329            ## Step 4            ## Step 4
# Line 5732  sub _tree_construction_main ($) { Line 6339  sub _tree_construction_main ($) {
6339      redo B;      redo B;
6340    } # B    } # B
6341    
   ## NOTE: The "trailing end" phase in HTML5 is split into  
   ## two insertion modes: "after html body" and "after html frameset".  
   ## NOTE: States in the main stage is preserved while  
   ## the parser stays in the trailing end phase. # MUST  
   
6342    ## Stop parsing # MUST    ## Stop parsing # MUST
6343        
6344    ## TODO: script stuffs    ## TODO: script stuffs
# Line 5778  sub set_inner_html ($$$) { Line 6380  sub set_inner_html ($$$) {
6380      my $p = $class->new;      my $p = $class->new;
6381      $p->{document} = $doc;      $p->{document} = $doc;
6382    
6383      ## Step 9 # MUST      ## Step 8 # MUST
6384      my $i = 0;      my $i = 0;
6385      my $line = 1;      my $line = 1;
6386      my $column = 0;      my $column = 0;
# Line 5795  sub set_inner_html ($$$) { Line 6397  sub set_inner_html ($$$) {
6397        if ($self->{next_char} == 0x000A) { # LF        if ($self->{next_char} == 0x000A) { # LF
6398          $line++;          $line++;
6399          $column = 0;          $column = 0;
6400            !!!cp ('i1');
6401        } elsif ($self->{next_char} == 0x000D) { # CR        } elsif ($self->{next_char} == 0x000D) { # CR
6402          $i++ if substr ($$s, $i, 1) eq "\x0A";          $i++ if substr ($$s, $i, 1) eq "\x0A";
6403          $self->{next_char} = 0x000A; # LF # MUST          $self->{next_char} = 0x000A; # LF # MUST
6404          $line++;          $line++;
6405          $column = 0;          $column = 0;
6406            !!!cp ('i2');
6407        } elsif ($self->{next_char} > 0x10FFFF) {        } elsif ($self->{next_char} > 0x10FFFF) {
6408          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
6409            !!!cp ('i3');
6410        } elsif ($self->{next_char} == 0x0000) { # NULL        } elsif ($self->{next_char} == 0x0000) { # NULL
6411            !!!cp ('i4');
6412          !!!parse-error (type => 'NULL');          !!!parse-error (type => 'NULL');
6413          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
6414        }        }
# Line 5841  sub set_inner_html ($$$) { Line 6447  sub set_inner_html ($$$) {
6447    
6448      $p->{inner_html_node} = [$node, $node_ln];      $p->{inner_html_node} = [$node, $node_ln];
6449    
6450      ## Step 4      ## Step 3
6451      my $root = $doc->create_element_ns      my $root = $doc->create_element_ns
6452        ('http://www.w3.org/1999/xhtml', [undef, 'html']);        ('http://www.w3.org/1999/xhtml', [undef, 'html']);
6453    
6454      ## Step 5 # MUST      ## Step 4 # MUST
6455      $doc->append_child ($root);      $doc->append_child ($root);
6456    
6457      ## Step 6 # MUST      ## Step 5 # MUST
6458      push @{$p->{open_elements}}, [$root, 'html'];      push @{$p->{open_elements}}, [$root, 'html'];
6459    
6460      undef $p->{head_element};      undef $p->{head_element};
6461    
6462      ## Step 7 # MUST      ## Step 6 # MUST
6463      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;
6464    
6465      ## Step 8 # MUST      ## Step 7 # MUST
6466      my $anode = $node;      my $anode = $node;
6467      AN: while (defined $anode) {      AN: while (defined $anode) {
6468        if ($anode->node_type == 1) {        if ($anode->node_type == 1) {
6469          my $nsuri = $anode->namespace_uri;          my $nsuri = $anode->namespace_uri;
6470          if (defined $nsuri and $nsuri eq 'http://www.w3.org/1999/xhtml') {          if (defined $nsuri and $nsuri eq 'http://www.w3.org/1999/xhtml') {
6471            if ($anode->manakai_local_name eq 'form') {            if ($anode->manakai_local_name eq 'form') {
6472                !!!cp ('i5');
6473              $p->{form_element} = $anode;              $p->{form_element} = $anode;
6474              last AN;              last AN;
6475            }            }
# Line 5871  sub set_inner_html ($$$) { Line 6478  sub set_inner_html ($$$) {
6478        $anode = $anode->parent_node;        $anode = $anode->parent_node;
6479      } # AN      } # AN
6480            
6481      ## Step 3 # MUST      ## Step 9 # MUST
     ## Step 10 # MUST  
6482      {      {
6483        my $self = $p;        my $self = $p;
6484        !!!next-token;        !!!next-token;
6485      }      }
6486      $p->_tree_construction_main;      $p->_tree_construction_main;
6487    
6488      ## Step 11 # MUST      ## Step 10 # MUST
6489      my @cn = @{$node->child_nodes};      my @cn = @{$node->child_nodes};
6490      for (@cn) {      for (@cn) {
6491        $node->remove_child ($_);        $node->remove_child ($_);
6492      }      }
6493      ## ISSUE: mutation events? read-only?      ## ISSUE: mutation events? read-only?
6494    
6495      ## Step 12 # MUST      ## Step 11 # MUST
6496      @cn = @{$root->child_nodes};      @cn = @{$root->child_nodes};
6497      for (@cn) {      for (@cn) {
6498        $this_doc->adopt_node ($_);        $this_doc->adopt_node ($_);

Legend:
Removed from v.1.77  
changed lines
  Added in v.1.101

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24