/[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.95 by wakaba, Sat Mar 8 05:09:25 2008 UTC
# Line 304  sub ROW_IMS ()        { 0b10000000 } Line 304  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    
307    ## NOTE: "initial" and "before html" insertion modes have no constants.
308    
309    ## NOTE: "after after body" insertion mode.
310  sub AFTER_HTML_BODY_IM () { AFTER_HTML_IMS | BODY_AFTER_IMS }  sub AFTER_HTML_BODY_IM () { AFTER_HTML_IMS | BODY_AFTER_IMS }
311    
312    ## NOTE: "after after frameset" insertion mode.
313  sub AFTER_HTML_FRAMESET_IM () { AFTER_HTML_IMS | FRAME_IMS }  sub AFTER_HTML_FRAMESET_IM () { AFTER_HTML_IMS | FRAME_IMS }
314    
315  sub IN_HEAD_IM () { HEAD_IMS | 0b00 }  sub IN_HEAD_IM () { HEAD_IMS | 0b00 }
316  sub IN_HEAD_NOSCRIPT_IM () { HEAD_IMS | 0b01 }  sub IN_HEAD_NOSCRIPT_IM () { HEAD_IMS | 0b01 }
317  sub AFTER_HEAD_IM () { HEAD_IMS | 0b10 }  sub AFTER_HEAD_IM () { HEAD_IMS | 0b10 }
# Line 656  sub _get_next_token ($) { Line 662  sub _get_next_token ($) {
662            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
663          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
664            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
665            if ($self->{current_token}->{attributes}) {            #if ($self->{current_token}->{attributes}) {
666              !!!cp (36);            #  ## NOTE: This should never be reached.
667              !!!parse-error (type => 'end tag attribute');            #  !!! cp (36);
668            } else {            #  !!! parse-error (type => 'end tag attribute');
669              #} else {
670              !!!cp (37);              !!!cp (37);
671            }            #}
672          } else {          } else {
673            die "$0: $self->{current_token}->{type}: Unknown token type";            die "$0: $self->{current_token}->{type}: Unknown token type";
674          }          }
# Line 688  sub _get_next_token ($) { Line 695  sub _get_next_token ($) {
695            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};            $self->{last_emitted_start_tag_name} = $self->{current_token}->{tag_name};
696          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {          } elsif ($self->{current_token}->{type} == END_TAG_TOKEN) {
697            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST            $self->{content_model} = PCDATA_CONTENT_MODEL; # MUST
698            if ($self->{current_token}->{attributes}) {            #if ($self->{current_token}->{attributes}) {
699              !!!cp (40);            #  ## NOTE: This state should never be reached.
700              !!!parse-error (type => 'end tag attribute');            #  !!! cp (40);
701            } else {            #  !!! parse-error (type => 'end tag attribute');
702              #} else {
703              !!!cp (41);              !!!cp (41);
704            }            #}
705          } else {          } else {
706            die "$0: $self->{current_token}->{type}: Unknown token type";            die "$0: $self->{current_token}->{type}: Unknown token type";
707          }          }
# Line 912  sub _get_next_token ($) { Line 920  sub _get_next_token ($) {
920              !!!cp (67);              !!!cp (67);
921              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
922            } else {            } else {
923                ## NOTE: This state should never be reached.
924              !!!cp (68);              !!!cp (68);
925            }            }
926          } else {          } else {
# Line 963  sub _get_next_token ($) { Line 972  sub _get_next_token ($) {
972              !!!cp (74);              !!!cp (74);
973              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
974            } else {            } else {
975                ## NOTE: This state should never be reached.
976              !!!cp (75);              !!!cp (75);
977            }            }
978          } else {          } else {
# Line 1011  sub _get_next_token ($) { Line 1021  sub _get_next_token ($) {
1021              !!!cp (80);              !!!cp (80);
1022              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1023            } else {            } else {
1024                ## NOTE: This state should never be reached.
1025              !!!cp (81);              !!!cp (81);
1026            }            }
1027          } else {          } else {
# Line 1067  sub _get_next_token ($) { Line 1078  sub _get_next_token ($) {
1078              !!!cp (88);              !!!cp (88);
1079              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1080            } else {            } else {
1081                ## NOTE: This state should never be reached.
1082              !!!cp (89);              !!!cp (89);
1083            }            }
1084          } else {          } else {
# Line 1091  sub _get_next_token ($) { Line 1103  sub _get_next_token ($) {
1103              !!!cp (91);              !!!cp (91);
1104              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1105            } else {            } else {
1106                ## NOTE: This state should never be reached.
1107              !!!cp (92);              !!!cp (92);
1108            }            }
1109          } else {          } else {
# Line 1139  sub _get_next_token ($) { Line 1152  sub _get_next_token ($) {
1152              !!!cp (98);              !!!cp (98);
1153              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1154            } else {            } else {
1155                ## NOTE: This state should never be reached.
1156              !!!cp (99);              !!!cp (99);
1157            }            }
1158          } else {          } else {
# Line 1182  sub _get_next_token ($) { Line 1196  sub _get_next_token ($) {
1196              !!!cp (104);              !!!cp (104);
1197              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1198            } else {            } else {
1199                ## NOTE: This state should never be reached.
1200              !!!cp (105);              !!!cp (105);
1201            }            }
1202          } else {          } else {
# Line 1228  sub _get_next_token ($) { Line 1243  sub _get_next_token ($) {
1243              !!!cp (110);              !!!cp (110);
1244              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1245            } else {            } else {
1246                ## NOTE: This state should never be reached.
1247              !!!cp (111);              !!!cp (111);
1248            }            }
1249          } else {          } else {
# Line 1252  sub _get_next_token ($) { Line 1268  sub _get_next_token ($) {
1268              !!!cp (113);              !!!cp (113);
1269              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1270            } else {            } else {
1271                ## NOTE: This state should never be reached.
1272              !!!cp (114);              !!!cp (114);
1273            }            }
1274          } else {          } else {
# Line 1323  sub _get_next_token ($) { Line 1340  sub _get_next_token ($) {
1340              !!!cp (120);              !!!cp (120);
1341              !!!parse-error (type => 'end tag attribute');              !!!parse-error (type => 'end tag attribute');
1342            } else {            } else {
1343                ## NOTE: This state should never be reached.
1344              !!!cp (121);              !!!cp (121);
1345            }            }
1346          } else {          } else {
# Line 2190  sub _tokenize_attempt_to_consume_an_enti Line 2208  sub _tokenize_attempt_to_consume_an_enti
2208         0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, & # 0x000D # CR         0x0020 => 1, 0x003C => 1, 0x0026 => 1, -1 => 1, # SP, <, & # 0x000D # CR
2209         $additional => 1,         $additional => 1,
2210        }->{$self->{next_char}}) {        }->{$self->{next_char}}) {
2211        !!!cp (1001);
2212      ## Don't consume      ## Don't consume
2213      ## No error      ## No error
2214      return undef;      return undef;
# Line 2203  sub _tokenize_attempt_to_consume_an_enti Line 2222  sub _tokenize_attempt_to_consume_an_enti
2222          !!!next-input-character;          !!!next-input-character;
2223          if (0x0030 <= $self->{next_char} and          if (0x0030 <= $self->{next_char} and
2224              $self->{next_char} <= 0x0039) { # 0..9              $self->{next_char} <= 0x0039) { # 0..9
2225              !!!cp (1002);
2226            $code ||= 0;            $code ||= 0;
2227            $code *= 0x10;            $code *= 0x10;
2228            $code += $self->{next_char} - 0x0030;            $code += $self->{next_char} - 0x0030;
2229            redo X;            redo X;
2230          } elsif (0x0061 <= $self->{next_char} and          } elsif (0x0061 <= $self->{next_char} and
2231                   $self->{next_char} <= 0x0066) { # a..f                   $self->{next_char} <= 0x0066) { # a..f
2232              !!!cp (1003);
2233            $code ||= 0;            $code ||= 0;
2234            $code *= 0x10;            $code *= 0x10;
2235            $code += $self->{next_char} - 0x0060 + 9;            $code += $self->{next_char} - 0x0060 + 9;
2236            redo X;            redo X;
2237          } elsif (0x0041 <= $self->{next_char} and          } elsif (0x0041 <= $self->{next_char} and
2238                   $self->{next_char} <= 0x0046) { # A..F                   $self->{next_char} <= 0x0046) { # A..F
2239              !!!cp (1004);
2240            $code ||= 0;            $code ||= 0;
2241            $code *= 0x10;            $code *= 0x10;
2242            $code += $self->{next_char} - 0x0040 + 9;            $code += $self->{next_char} - 0x0040 + 9;
2243            redo X;            redo X;
2244          } elsif (not defined $code) { # no hexadecimal digit          } elsif (not defined $code) { # no hexadecimal digit
2245              !!!cp (1005);
2246            !!!parse-error (type => 'bare hcro');            !!!parse-error (type => 'bare hcro');
2247            !!!back-next-input-character ($x_char, $self->{next_char});            !!!back-next-input-character ($x_char, $self->{next_char});
2248            $self->{next_char} = 0x0023; # #            $self->{next_char} = 0x0023; # #
2249            return undef;            return undef;
2250          } elsif ($self->{next_char} == 0x003B) { # ;          } elsif ($self->{next_char} == 0x003B) { # ;
2251              !!!cp (1006);
2252            !!!next-input-character;            !!!next-input-character;
2253          } else {          } else {
2254              !!!cp (1007);
2255            !!!parse-error (type => 'no refc');            !!!parse-error (type => 'no refc');
2256          }          }
2257    
2258          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {          if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
2259              !!!cp (1008);
2260            !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);            !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);
2261            $code = 0xFFFD;            $code = 0xFFFD;
2262          } elsif ($code > 0x10FFFF) {          } elsif ($code > 0x10FFFF) {
2263              !!!cp (1009);
2264            !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);            !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);
2265            $code = 0xFFFD;            $code = 0xFFFD;
2266          } elsif ($code == 0x000D) {          } elsif ($code == 0x000D) {
2267              !!!cp (1010);
2268            !!!parse-error (type => 'CR character reference');            !!!parse-error (type => 'CR character reference');
2269            $code = 0x000A;            $code = 0x000A;
2270          } elsif (0x80 <= $code and $code <= 0x9F) {          } elsif (0x80 <= $code and $code <= 0x9F) {
2271              !!!cp (1011);
2272            !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);            !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);
2273            $code = $c1_entity_char->{$code};            $code = $c1_entity_char->{$code};
2274          }          }
# Line 2254  sub _tokenize_attempt_to_consume_an_enti Line 2283  sub _tokenize_attempt_to_consume_an_enti
2283                
2284        while (0x0030 <= $self->{next_char} and        while (0x0030 <= $self->{next_char} and
2285                  $self->{next_char} <= 0x0039) { # 0..9                  $self->{next_char} <= 0x0039) { # 0..9
2286            !!!cp (1012);
2287          $code *= 10;          $code *= 10;
2288          $code += $self->{next_char} - 0x0030;          $code += $self->{next_char} - 0x0030;
2289                    
# Line 2261  sub _tokenize_attempt_to_consume_an_enti Line 2291  sub _tokenize_attempt_to_consume_an_enti
2291        }        }
2292    
2293        if ($self->{next_char} == 0x003B) { # ;        if ($self->{next_char} == 0x003B) { # ;
2294            !!!cp (1013);
2295          !!!next-input-character;          !!!next-input-character;
2296        } else {        } else {
2297            !!!cp (1014);
2298          !!!parse-error (type => 'no refc');          !!!parse-error (type => 'no refc');
2299        }        }
2300    
2301        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {        if ($code == 0 or (0xD800 <= $code and $code <= 0xDFFF)) {
2302            !!!cp (1015);
2303          !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);          !!!parse-error (type => sprintf 'invalid character reference:U+%04X', $code);
2304          $code = 0xFFFD;          $code = 0xFFFD;
2305        } elsif ($code > 0x10FFFF) {        } elsif ($code > 0x10FFFF) {
2306            !!!cp (1016);
2307          !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);          !!!parse-error (type => sprintf 'invalid character reference:U-%08X', $code);
2308          $code = 0xFFFD;          $code = 0xFFFD;
2309        } elsif ($code == 0x000D) {        } elsif ($code == 0x000D) {
2310            !!!cp (1017);
2311          !!!parse-error (type => 'CR character reference');          !!!parse-error (type => 'CR character reference');
2312          $code = 0x000A;          $code = 0x000A;
2313        } elsif (0x80 <= $code and $code <= 0x9F) {        } elsif (0x80 <= $code and $code <= 0x9F) {
2314            !!!cp (1018);
2315          !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);          !!!parse-error (type => sprintf 'C1 character reference:U+%04X', $code);
2316          $code = $c1_entity_char->{$code};          $code = $c1_entity_char->{$code};
2317        }        }
2318                
2319        return {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1};        return {type => CHARACTER_TOKEN, data => chr $code, has_reference => 1};
2320      } else {      } else {
2321          !!!cp (1019);
2322        !!!parse-error (type => 'bare nero');        !!!parse-error (type => 'bare nero');
2323        !!!back-next-input-character ($self->{next_char});        !!!back-next-input-character ($self->{next_char});
2324        $self->{next_char} = 0x0023; # #        $self->{next_char} = 0x0023; # #
# Line 2311  sub _tokenize_attempt_to_consume_an_enti Line 2348  sub _tokenize_attempt_to_consume_an_enti
2348        $entity_name .= chr $self->{next_char};        $entity_name .= chr $self->{next_char};
2349        if (defined $EntityChar->{$entity_name}) {        if (defined $EntityChar->{$entity_name}) {
2350          if ($self->{next_char} == 0x003B) { # ;          if ($self->{next_char} == 0x003B) { # ;
2351              !!!cp (1020);
2352            $value = $EntityChar->{$entity_name};            $value = $EntityChar->{$entity_name};
2353            $match = 1;            $match = 1;
2354            !!!next-input-character;            !!!next-input-character;
2355            last;            last;
2356          } else {          } else {
2357              !!!cp (1021);
2358            $value = $EntityChar->{$entity_name};            $value = $EntityChar->{$entity_name};
2359            $match = -1;            $match = -1;
2360            !!!next-input-character;            !!!next-input-character;
2361          }          }
2362        } else {        } else {
2363            !!!cp (1022);
2364          $value .= chr $self->{next_char};          $value .= chr $self->{next_char};
2365          $match *= 2;          $match *= 2;
2366          !!!next-input-character;          !!!next-input-character;
# Line 2328  sub _tokenize_attempt_to_consume_an_enti Line 2368  sub _tokenize_attempt_to_consume_an_enti
2368      }      }
2369            
2370      if ($match > 0) {      if ($match > 0) {
2371          !!!cp (1023);
2372        return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};        return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};
2373      } elsif ($match < 0) {      } elsif ($match < 0) {
2374        !!!parse-error (type => 'no refc');        !!!parse-error (type => 'no refc');
2375        if ($in_attr and $match < -1) {        if ($in_attr and $match < -1) {
2376            !!!cp (1024);
2377          return {type => CHARACTER_TOKEN, data => '&'.$entity_name};          return {type => CHARACTER_TOKEN, data => '&'.$entity_name};
2378        } else {        } else {
2379            !!!cp (1025);
2380          return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};          return {type => CHARACTER_TOKEN, data => $value, has_reference => 1};
2381        }        }
2382      } else {      } else {
2383          !!!cp (1026);
2384        !!!parse-error (type => 'bare ero');        !!!parse-error (type => 'bare ero');
2385        ## NOTE: "No characters are consumed" in the spec.        ## NOTE: "No characters are consumed" in the spec.
2386        return {type => CHARACTER_TOKEN, data => '&'.$value};        return {type => CHARACTER_TOKEN, data => '&'.$value};
2387      }      }
2388    } else {    } else {
2389        !!!cp (1027);
2390      ## no characters are consumed      ## no characters are consumed
2391      !!!parse-error (type => 'bare ero');      !!!parse-error (type => 'bare ero');
2392      return undef;      return undef;
# Line 2381  sub _construct_tree ($) { Line 2426  sub _construct_tree ($) {
2426        
2427    !!!next-token;    !!!next-token;
2428    
   $self->{insertion_mode} = BEFORE_HEAD_IM;  
2429    undef $self->{form_element};    undef $self->{form_element};
2430    undef $self->{head_element};    undef $self->{head_element};
2431    $self->{open_elements} = [];    $self->{open_elements} = [];
2432    undef $self->{inner_html_node};    undef $self->{inner_html_node};
2433    
2434      ## NOTE: The "initial" insertion mode.
2435    $self->_tree_construction_initial; # MUST    $self->_tree_construction_initial; # MUST
2436    
2437      ## NOTE: The "before html" insertion mode.
2438    $self->_tree_construction_root_element;    $self->_tree_construction_root_element;
2439      $self->{insertion_mode} = BEFORE_HEAD_IM;
2440    
2441      ## NOTE: The "before head" insertion mode and so on.
2442    $self->_tree_construction_main;    $self->_tree_construction_main;
2443  } # _construct_tree  } # _construct_tree
2444    
2445  sub _tree_construction_initial ($) {  sub _tree_construction_initial ($) {
2446    my $self = shift;    my $self = shift;
2447    
2448      ## NOTE: "initial" insertion mode
2449    
2450    INITIAL: {    INITIAL: {
2451      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
2452        ## 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 2458  sub _tree_construction_initial ($) {
2458        if (not defined $token->{name} or # <!DOCTYPE>        if (not defined $token->{name} or # <!DOCTYPE>
2459            defined $token->{public_identifier} or            defined $token->{public_identifier} or
2460            defined $token->{system_identifier}) {            defined $token->{system_identifier}) {
2461            !!!cp ('t1');
2462          !!!parse-error (type => 'not HTML5');          !!!parse-error (type => 'not HTML5');
2463        } elsif ($doctype_name ne 'HTML') {        } elsif ($doctype_name ne 'HTML') {
2464            !!!cp ('t2');
2465          ## ISSUE: ASCII case-insensitive? (in fact it does not matter)          ## ISSUE: ASCII case-insensitive? (in fact it does not matter)
2466          !!!parse-error (type => 'not HTML5');          !!!parse-error (type => 'not HTML5');
2467          } else {
2468            !!!cp ('t3');
2469        }        }
2470                
2471        my $doctype = $self->{document}->create_document_type_definition        my $doctype = $self->{document}->create_document_type_definition
# Line 2422  sub _tree_construction_initial ($) { Line 2479  sub _tree_construction_initial ($) {
2479        $self->{document}->append_child ($doctype);        $self->{document}->append_child ($doctype);
2480                
2481        if ($token->{quirks} or $doctype_name ne 'HTML') {        if ($token->{quirks} or $doctype_name ne 'HTML') {
2482            !!!cp ('t4');
2483          $self->{document}->manakai_compat_mode ('quirks');          $self->{document}->manakai_compat_mode ('quirks');
2484        } elsif (defined $token->{public_identifier}) {        } elsif (defined $token->{public_identifier}) {
2485          my $pubid = $token->{public_identifier};          my $pubid = $token->{public_identifier};
# Line 2500  sub _tree_construction_initial ($) { Line 2558  sub _tree_construction_initial ($) {
2558            "-/W3C/DTD HTML 4.0 TRANSITIONAL/EN" => 1,            "-/W3C/DTD HTML 4.0 TRANSITIONAL/EN" => 1,
2559            "HTML" => 1,            "HTML" => 1,
2560          }->{$pubid}) {          }->{$pubid}) {
2561              !!!cp ('t5');
2562            $self->{document}->manakai_compat_mode ('quirks');            $self->{document}->manakai_compat_mode ('quirks');
2563          } elsif ($pubid eq "-//W3C//DTD HTML 4.01 FRAMESET//EN" or          } elsif ($pubid eq "-//W3C//DTD HTML 4.01 FRAMESET//EN" or
2564                   $pubid eq "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN") {                   $pubid eq "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN") {
2565            if (defined $token->{system_identifier}) {            if (defined $token->{system_identifier}) {
2566                !!!cp ('t6');
2567              $self->{document}->manakai_compat_mode ('quirks');              $self->{document}->manakai_compat_mode ('quirks');
2568            } else {            } else {
2569                !!!cp ('t7');
2570              $self->{document}->manakai_compat_mode ('limited quirks');              $self->{document}->manakai_compat_mode ('limited quirks');
2571            }            }
2572          } elsif ($pubid eq "-//W3C//DTD XHTML 1.0 Frameset//EN" or          } elsif ($pubid eq "-//W3C//DTD XHTML 1.0 FRAMESET//EN" or
2573                   $pubid eq "-//W3C//DTD XHTML 1.0 Transitional//EN") {                   $pubid eq "-//W3C//DTD XHTML 1.0 TRANSITIONAL//EN") {
2574              !!!cp ('t8');
2575            $self->{document}->manakai_compat_mode ('limited quirks');            $self->{document}->manakai_compat_mode ('limited quirks');
2576            } else {
2577              !!!cp ('t9');
2578          }          }
2579          } else {
2580            !!!cp ('t10');
2581        }        }
2582        if (defined $token->{system_identifier}) {        if (defined $token->{system_identifier}) {
2583          my $sysid = $token->{system_identifier};          my $sysid = $token->{system_identifier};
2584          $sysid =~ tr/A-Z/a-z/;          $sysid =~ tr/A-Z/a-z/;
2585          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") {
2586              ## TODO: Check the spec: PUBLIC "(limited quirks)" "(quirks)"
2587            $self->{document}->manakai_compat_mode ('quirks');            $self->{document}->manakai_compat_mode ('quirks');
2588              !!!cp ('t11');
2589            } else {
2590              !!!cp ('t12');
2591          }          }
2592          } else {
2593            !!!cp ('t13');
2594        }        }
2595                
2596        ## Go to the root element phase.        ## Go to the "before html" insertion mode.
2597        !!!next-token;        !!!next-token;
2598        return;        return;
2599      } elsif ({      } elsif ({
# Line 2529  sub _tree_construction_initial ($) { Line 2601  sub _tree_construction_initial ($) {
2601                END_TAG_TOKEN, 1,                END_TAG_TOKEN, 1,
2602                END_OF_FILE_TOKEN, 1,                END_OF_FILE_TOKEN, 1,
2603               }->{$token->{type}}) {               }->{$token->{type}}) {
2604          !!!cp ('t14');
2605        !!!parse-error (type => 'no DOCTYPE');        !!!parse-error (type => 'no DOCTYPE');
2606        $self->{document}->manakai_compat_mode ('quirks');        $self->{document}->manakai_compat_mode ('quirks');
2607        ## Go to the root element phase        ## Go to the "before html" insertion mode.
2608        ## reprocess        ## reprocess
2609        return;        return;
2610      } elsif ($token->{type} == CHARACTER_TOKEN) {      } elsif ($token->{type} == CHARACTER_TOKEN) {
# Line 2539  sub _tree_construction_initial ($) { Line 2612  sub _tree_construction_initial ($) {
2612          ## Ignore the token          ## Ignore the token
2613    
2614          unless (length $token->{data}) {          unless (length $token->{data}) {
2615            ## Stay in the phase            !!!cp ('t15');
2616              ## Stay in the insertion mode.
2617            !!!next-token;            !!!next-token;
2618            redo INITIAL;            redo INITIAL;
2619            } else {
2620              !!!cp ('t16');
2621          }          }
2622          } else {
2623            !!!cp ('t17');
2624        }        }
2625    
2626        !!!parse-error (type => 'no DOCTYPE');        !!!parse-error (type => 'no DOCTYPE');
2627        $self->{document}->manakai_compat_mode ('quirks');        $self->{document}->manakai_compat_mode ('quirks');
2628        ## Go to the root element phase        ## Go to the "before html" insertion mode.
2629        ## reprocess        ## reprocess
2630        return;        return;
2631      } elsif ($token->{type} == COMMENT_TOKEN) {      } elsif ($token->{type} == COMMENT_TOKEN) {
2632          !!!cp ('t18');
2633        my $comment = $self->{document}->create_comment ($token->{data});        my $comment = $self->{document}->create_comment ($token->{data});
2634        $self->{document}->append_child ($comment);        $self->{document}->append_child ($comment);
2635                
2636        ## Stay in the phase.        ## Stay in the insertion mode.
2637        !!!next-token;        !!!next-token;
2638        redo INITIAL;        redo INITIAL;
2639      } else {      } else {
2640        die "$0: $token->{type}: Unknown token type";        die "$0: $token->{type}: Unknown token type";
2641      }      }
2642    } # INITIAL    } # INITIAL
2643    
2644      die "$0: _tree_construction_initial: This should be never reached";
2645  } # _tree_construction_initial  } # _tree_construction_initial
2646    
2647  sub _tree_construction_root_element ($) {  sub _tree_construction_root_element ($) {
2648    my $self = shift;    my $self = shift;
2649    
2650      ## NOTE: "before html" insertion mode.
2651        
2652    B: {    B: {
2653        if ($token->{type} == DOCTYPE_TOKEN) {        if ($token->{type} == DOCTYPE_TOKEN) {
2654            !!!cp ('t19');
2655          !!!parse-error (type => 'in html:#DOCTYPE');          !!!parse-error (type => 'in html:#DOCTYPE');
2656          ## Ignore the token          ## Ignore the token
2657          ## Stay in the phase          ## Stay in the insertion mode.
2658          !!!next-token;          !!!next-token;
2659          redo B;          redo B;
2660        } elsif ($token->{type} == COMMENT_TOKEN) {        } elsif ($token->{type} == COMMENT_TOKEN) {
2661            !!!cp ('t20');
2662          my $comment = $self->{document}->create_comment ($token->{data});          my $comment = $self->{document}->create_comment ($token->{data});
2663          $self->{document}->append_child ($comment);          $self->{document}->append_child ($comment);
2664          ## Stay in the phase          ## Stay in the insertion mode.
2665          !!!next-token;          !!!next-token;
2666          redo B;          redo B;
2667        } elsif ($token->{type} == CHARACTER_TOKEN) {        } elsif ($token->{type} == CHARACTER_TOKEN) {
# Line 2584  sub _tree_construction_root_element ($) Line 2669  sub _tree_construction_root_element ($)
2669            ## Ignore the token.            ## Ignore the token.
2670    
2671            unless (length $token->{data}) {            unless (length $token->{data}) {
2672              ## Stay in the phase              !!!cp ('t21');
2673                ## Stay in the insertion mode.
2674              !!!next-token;              !!!next-token;
2675              redo B;              redo B;
2676              } else {
2677                !!!cp ('t22');
2678            }            }
2679            } else {
2680              !!!cp ('t23');
2681          }          }
2682    
2683          $self->{application_cache_selection}->(undef);          $self->{application_cache_selection}->(undef);
2684    
2685          #          #
2686        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
2687          if ($token->{tag_name} eq 'html' and          if ($token->{tag_name} eq 'html') {
2688              $token->{attributes}->{manifest}) {            my $root_element;
2689            $self->{application_cache_selection}            !!!create-element ($root_element, $token->{tag_name}, $token->{attributes});
2690                 ->($token->{attributes}->{manifest}->{value});            $self->{document}->append_child ($root_element);
2691            ## ISSUE: No relative reference resolution?            push @{$self->{open_elements}}, [$root_element, 'html'];
2692    
2693              if ($token->{attributes}->{manifest}) {
2694                !!!cp ('t24');
2695                $self->{application_cache_selection}
2696                    ->($token->{attributes}->{manifest}->{value});
2697                ## ISSUE: No relative reference resolution?
2698              } else {
2699                !!!cp ('t25');
2700                $self->{application_cache_selection}->(undef);
2701              }
2702    
2703              !!!next-token;
2704              return; ## Go to the "before head" insertion mode.
2705          } else {          } else {
2706            $self->{application_cache_selection}->(undef);            !!!cp ('t25.1');
2707              #
2708          }          }
   
         ## ISSUE: There is an issue in the spec  
         #  
2709        } elsif ({        } elsif ({
2710                  END_TAG_TOKEN, 1,                  END_TAG_TOKEN, 1,
2711                  END_OF_FILE_TOKEN, 1,                  END_OF_FILE_TOKEN, 1,
2712                 }->{$token->{type}}) {                 }->{$token->{type}}) {
2713          $self->{application_cache_selection}->(undef);          !!!cp ('t26');
   
         ## ISSUE: There is an issue in the spec  
2714          #          #
2715        } else {        } else {
2716          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
2717        }        }
2718    
2719        my $root_element; !!!create-element ($root_element, 'html');      my $root_element; !!!create-element ($root_element, 'html');
2720        $self->{document}->append_child ($root_element);      $self->{document}->append_child ($root_element);
2721        push @{$self->{open_elements}}, [$root_element, 'html'];      push @{$self->{open_elements}}, [$root_element, 'html'];
2722        ## reprocess  
2723        #redo B;      $self->{application_cache_selection}->(undef);
2724        return; ## Go to the main phase.  
2725        ## NOTE: Reprocess the token.
2726        return; ## Go to the "before head" insertion mode.
2727    
2728        ## ISSUE: There is an issue in the spec
2729    } # B    } # B
2730    
2731      die "$0: _tree_construction_root_element: This should never be reached";
2732  } # _tree_construction_root_element  } # _tree_construction_root_element
2733    
2734  sub _reset_insertion_mode ($) {  sub _reset_insertion_mode ($) {
# Line 2638  sub _reset_insertion_mode ($) { Line 2743  sub _reset_insertion_mode ($) {
2743            
2744      ## Step 3      ## Step 3
2745      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"!?  
2746        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {        if ($self->{open_elements}->[0]->[0] eq $node->[0]) {
2747          $last = 1;          $last = 1;
2748          if (defined $self->{inner_html_node}) {          if (defined $self->{inner_html_node}) {
2749            if ($self->{inner_html_node}->[1] eq 'td' or            if ($self->{inner_html_node}->[1] eq 'td' or
2750                $self->{inner_html_node}->[1] eq 'th') {                $self->{inner_html_node}->[1] eq 'th') {
2751                !!!cp ('t27');
2752              #              #
2753            } else {            } else {
2754                !!!cp ('t28');
2755              $node = $self->{inner_html_node};              $node = $self->{inner_html_node};
2756            }            }
2757          }          }
# Line 2658  sub _reset_insertion_mode ($) { Line 2760  sub _reset_insertion_mode ($) {
2760        ## Step 4..13        ## Step 4..13
2761        my $new_mode = {        my $new_mode = {
2762                        select => IN_SELECT_IM,                        select => IN_SELECT_IM,
2763                          ## NOTE: |option| and |optgroup| do not set
2764                          ## insertion mode to "in select" by themselves.
2765                        td => IN_CELL_IM,                        td => IN_CELL_IM,
2766                        th => IN_CELL_IM,                        th => IN_CELL_IM,
2767                        tr => IN_ROW_IM,                        tr => IN_ROW_IM,
# Line 2676  sub _reset_insertion_mode ($) { Line 2780  sub _reset_insertion_mode ($) {
2780        ## Step 14        ## Step 14
2781        if ($node->[1] eq 'html') {        if ($node->[1] eq 'html') {
2782          unless (defined $self->{head_element}) {          unless (defined $self->{head_element}) {
2783              !!!cp ('t29');
2784            $self->{insertion_mode} = BEFORE_HEAD_IM;            $self->{insertion_mode} = BEFORE_HEAD_IM;
2785          } else {          } else {
2786              ## ISSUE: Can this state be reached?
2787              !!!cp ('t30');
2788            $self->{insertion_mode} = AFTER_HEAD_IM;            $self->{insertion_mode} = AFTER_HEAD_IM;
2789          }          }
2790          return;          return;
2791          } else {
2792            !!!cp ('t31');
2793        }        }
2794                
2795        ## Step 15        ## Step 15
# Line 2693  sub _reset_insertion_mode ($) { Line 2802  sub _reset_insertion_mode ($) {
2802        ## Step 17        ## Step 17
2803        redo S3;        redo S3;
2804      } # S3      } # S3
2805    
2806      die "$0: _reset_insertion_mode: This line should never be reached";
2807  } # _reset_insertion_mode  } # _reset_insertion_mode
2808    
2809  sub _tree_construction_main ($) {  sub _tree_construction_main ($) {
# Line 2714  sub _tree_construction_main ($) { Line 2825  sub _tree_construction_main ($) {
2825      return if $entry->[0] eq '#marker';      return if $entry->[0] eq '#marker';
2826      for (@{$self->{open_elements}}) {      for (@{$self->{open_elements}}) {
2827        if ($entry->[0] eq $_->[0]) {        if ($entry->[0] eq $_->[0]) {
2828            !!!cp ('t32');
2829          return;          return;
2830        }        }
2831      }      }
# Line 2728  sub _tree_construction_main ($) { Line 2840  sub _tree_construction_main ($) {
2840    
2841        ## Step 6        ## Step 6
2842        if ($entry->[0] eq '#marker') {        if ($entry->[0] eq '#marker') {
2843            !!!cp ('t33_1');
2844          #          #
2845        } else {        } else {
2846          my $in_open_elements;          my $in_open_elements;
2847          OE: for (@{$self->{open_elements}}) {          OE: for (@{$self->{open_elements}}) {
2848            if ($entry->[0] eq $_->[0]) {            if ($entry->[0] eq $_->[0]) {
2849                !!!cp ('t33');
2850              $in_open_elements = 1;              $in_open_elements = 1;
2851              last OE;              last OE;
2852            }            }
2853          }          }
2854          if ($in_open_elements) {          if ($in_open_elements) {
2855              !!!cp ('t34');
2856            #            #
2857          } else {          } else {
2858              ## NOTE: <!DOCTYPE HTML><p><b><i><u></p> <p>X
2859              !!!cp ('t35');
2860            redo S4;            redo S4;
2861          }          }
2862        }        }
# Line 2762  sub _tree_construction_main ($) { Line 2879  sub _tree_construction_main ($) {
2879    
2880        ## Step 11        ## Step 11
2881        unless ($clone->[0] eq $active_formatting_elements->[-1]->[0]) {        unless ($clone->[0] eq $active_formatting_elements->[-1]->[0]) {
2882            !!!cp ('t36');
2883          ## Step 7'          ## Step 7'
2884          $i++;          $i++;
2885          $entry = $active_formatting_elements->[$i];          $entry = $active_formatting_elements->[$i];
2886                    
2887          redo S7;          redo S7;
2888        }        }
2889    
2890          !!!cp ('t37');
2891      } # S7      } # S7
2892    }; # $reconstruct_active_formatting_elements    }; # $reconstruct_active_formatting_elements
2893    
2894    my $clear_up_to_marker = sub {    my $clear_up_to_marker = sub {
2895      for (reverse 0..$#$active_formatting_elements) {      for (reverse 0..$#$active_formatting_elements) {
2896        if ($active_formatting_elements->[$_]->[0] eq '#marker') {        if ($active_formatting_elements->[$_]->[0] eq '#marker') {
2897            !!!cp ('t38');
2898          splice @$active_formatting_elements, $_;          splice @$active_formatting_elements, $_;
2899          return;          return;
2900        }        }
2901      }      }
2902    
2903        !!!cp ('t39');
2904    }; # $clear_up_to_marker    }; # $clear_up_to_marker
2905    
2906    my $parse_rcdata = sub ($$) {    my $parse_rcdata = sub ($$) {
# Line 2799  sub _tree_construction_main ($) { Line 2922  sub _tree_construction_main ($) {
2922      my $text = '';      my $text = '';
2923      !!!next-token;      !!!next-token;
2924      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing      while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing
2925          !!!cp ('t40');
2926        $text .= $token->{data};        $text .= $token->{data};
2927        !!!next-token;        !!!next-token;
2928      }      }
2929    
2930      ## Step 5      ## Step 5
2931      if (length $text) {      if (length $text) {
2932          !!!cp ('t41');
2933        my $text = $self->{document}->create_text_node ($text);        my $text = $self->{document}->create_text_node ($text);
2934        $el->append_child ($text);        $el->append_child ($text);
2935      }      }
# Line 2813  sub _tree_construction_main ($) { Line 2938  sub _tree_construction_main ($) {
2938      $self->{content_model} = PCDATA_CONTENT_MODEL;      $self->{content_model} = PCDATA_CONTENT_MODEL;
2939    
2940      ## Step 7      ## Step 7
2941      if ($token->{type} == END_TAG_TOKEN and $token->{tag_name} eq $start_tag_name) {      if ($token->{type} == END_TAG_TOKEN and
2942            $token->{tag_name} eq $start_tag_name) {
2943          !!!cp ('t42');
2944        ## Ignore the token        ## Ignore the token
2945      } elsif ($content_model_flag == CDATA_CONTENT_MODEL) {      } elsif ($content_model_flag == CDATA_CONTENT_MODEL) {
2946          !!!cp ('t43');
2947        !!!parse-error (type => 'in CDATA:#'.$token->{type});        !!!parse-error (type => 'in CDATA:#'.$token->{type});
2948      } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {      } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {
2949          !!!cp ('t44');
2950        !!!parse-error (type => 'in RCDATA:#'.$token->{type});        !!!parse-error (type => 'in RCDATA:#'.$token->{type});
2951      } else {      } else {
2952        die "$0: $content_model_flag in parse_rcdata";        die "$0: $content_model_flag in parse_rcdata";
# Line 2837  sub _tree_construction_main ($) { Line 2966  sub _tree_construction_main ($) {
2966      my $text = '';      my $text = '';
2967      !!!next-token;      !!!next-token;
2968      while ($token->{type} == CHARACTER_TOKEN) {      while ($token->{type} == CHARACTER_TOKEN) {
2969          !!!cp ('t45');
2970        $text .= $token->{data};        $text .= $token->{data};
2971        !!!next-token;        !!!next-token;
2972      } # stop if non-character token or tokenizer stops tokenising      } # stop if non-character token or tokenizer stops tokenising
2973      if (length $text) {      if (length $text) {
2974          !!!cp ('t46');
2975        $script_el->manakai_append_text ($text);        $script_el->manakai_append_text ($text);
2976      }      }
2977                                
# Line 2848  sub _tree_construction_main ($) { Line 2979  sub _tree_construction_main ($) {
2979    
2980      if ($token->{type} == END_TAG_TOKEN and      if ($token->{type} == END_TAG_TOKEN and
2981          $token->{tag_name} eq 'script') {          $token->{tag_name} eq 'script') {
2982          !!!cp ('t47');
2983        ## Ignore the token        ## Ignore the token
2984      } else {      } else {
2985          !!!cp ('t48');
2986        !!!parse-error (type => 'in CDATA:#'.$token->{type});        !!!parse-error (type => 'in CDATA:#'.$token->{type});
2987        ## ISSUE: And ignore?        ## ISSUE: And ignore?
2988        ## TODO: mark as "already executed"        ## TODO: mark as "already executed"
2989      }      }
2990            
2991      if (defined $self->{inner_html_node}) {      if (defined $self->{inner_html_node}) {
2992          !!!cp ('t49');
2993        ## TODO: mark as "already executed"        ## TODO: mark as "already executed"
2994      } else {      } else {
2995          !!!cp ('t50');
2996        ## TODO: $old_insertion_point = current insertion point        ## TODO: $old_insertion_point = current insertion point
2997        ## TODO: insertion point = just before the next input character        ## TODO: insertion point = just before the next input character
2998    
# Line 2880  sub _tree_construction_main ($) { Line 3015  sub _tree_construction_main ($) {
3015        my $formatting_element_i_in_active;        my $formatting_element_i_in_active;
3016        AFE: for (reverse 0..$#$active_formatting_elements) {        AFE: for (reverse 0..$#$active_formatting_elements) {
3017          if ($active_formatting_elements->[$_]->[1] eq $tag_name) {          if ($active_formatting_elements->[$_]->[1] eq $tag_name) {
3018              !!!cp ('t51');
3019            $formatting_element = $active_formatting_elements->[$_];            $formatting_element = $active_formatting_elements->[$_];
3020            $formatting_element_i_in_active = $_;            $formatting_element_i_in_active = $_;
3021            last AFE;            last AFE;
3022          } elsif ($active_formatting_elements->[$_]->[0] eq '#marker') {          } elsif ($active_formatting_elements->[$_]->[0] eq '#marker') {
3023              !!!cp ('t52');
3024            last AFE;            last AFE;
3025          }          }
3026        } # AFE        } # AFE
3027        unless (defined $formatting_element) {        unless (defined $formatting_element) {
3028            !!!cp ('t53');
3029          !!!parse-error (type => 'unmatched end tag:'.$tag_name);          !!!parse-error (type => 'unmatched end tag:'.$tag_name);
3030          ## Ignore the token          ## Ignore the token
3031          !!!next-token;          !!!next-token;
# Line 2900  sub _tree_construction_main ($) { Line 3038  sub _tree_construction_main ($) {
3038          my $node = $self->{open_elements}->[$_];          my $node = $self->{open_elements}->[$_];
3039          if ($node->[0] eq $formatting_element->[0]) {          if ($node->[0] eq $formatting_element->[0]) {
3040            if ($in_scope) {            if ($in_scope) {
3041                !!!cp ('t54');
3042              $formatting_element_i_in_open = $_;              $formatting_element_i_in_open = $_;
3043              last INSCOPE;              last INSCOPE;
3044            } else { # in open elements but not in scope            } else { # in open elements but not in scope
3045                !!!cp ('t55');
3046              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3047              ## Ignore the token              ## Ignore the token
3048              !!!next-token;              !!!next-token;
# Line 2912  sub _tree_construction_main ($) { Line 3052  sub _tree_construction_main ($) {
3052                    table => 1, caption => 1, td => 1, th => 1,                    table => 1, caption => 1, td => 1, th => 1,
3053                    button => 1, marquee => 1, object => 1, html => 1,                    button => 1, marquee => 1, object => 1, html => 1,
3054                   }->{$node->[1]}) {                   }->{$node->[1]}) {
3055              !!!cp ('t56');
3056            $in_scope = 0;            $in_scope = 0;
3057          }          }
3058        } # INSCOPE        } # INSCOPE
3059        unless (defined $formatting_element_i_in_open) {        unless (defined $formatting_element_i_in_open) {
3060            !!!cp ('t57');
3061          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3062          pop @$active_formatting_elements; # $formatting_element          pop @$active_formatting_elements; # $formatting_element
3063          !!!next-token; ## TODO: ok?          !!!next-token; ## TODO: ok?
3064          return;          return;
3065        }        }
3066        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {        if (not $self->{open_elements}->[-1]->[0] eq $formatting_element->[0]) {
3067            !!!cp ('t58');
3068          !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);          !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3069        }        }
3070                
# Line 2934  sub _tree_construction_main ($) { Line 3077  sub _tree_construction_main ($) {
3077              #not $phrasing_category->{$node->[1]} and              #not $phrasing_category->{$node->[1]} and
3078              ($special_category->{$node->[1]} or              ($special_category->{$node->[1]} or
3079               $scoping_category->{$node->[1]})) {               $scoping_category->{$node->[1]})) {
3080              !!!cp ('t59');
3081            $furthest_block = $node;            $furthest_block = $node;
3082            $furthest_block_i_in_open = $_;            $furthest_block_i_in_open = $_;
3083          } elsif ($node->[0] eq $formatting_element->[0]) {          } elsif ($node->[0] eq $formatting_element->[0]) {
3084              !!!cp ('t60');
3085            last OE;            last OE;
3086          }          }
3087        } # OE        } # OE
3088                
3089        ## Step 3        ## Step 3
3090        unless (defined $furthest_block) { # MUST        unless (defined $furthest_block) { # MUST
3091            !!!cp ('t61');
3092          splice @{$self->{open_elements}}, $formatting_element_i_in_open;          splice @{$self->{open_elements}}, $formatting_element_i_in_open;
3093          splice @$active_formatting_elements, $formatting_element_i_in_active, 1;          splice @$active_formatting_elements, $formatting_element_i_in_active, 1;
3094          !!!next-token;          !!!next-token;
# Line 2955  sub _tree_construction_main ($) { Line 3101  sub _tree_construction_main ($) {
3101        ## Step 5        ## Step 5
3102        my $furthest_block_parent = $furthest_block->[0]->parent_node;        my $furthest_block_parent = $furthest_block->[0]->parent_node;
3103        if (defined $furthest_block_parent) {        if (defined $furthest_block_parent) {
3104            !!!cp ('t62');
3105          $furthest_block_parent->remove_child ($furthest_block->[0]);          $furthest_block_parent->remove_child ($furthest_block->[0]);
3106        }        }
3107                
# Line 2977  sub _tree_construction_main ($) { Line 3124  sub _tree_construction_main ($) {
3124          S7S2: {          S7S2: {
3125            for (reverse 0..$#$active_formatting_elements) {            for (reverse 0..$#$active_formatting_elements) {
3126              if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {              if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {
3127                  !!!cp ('t63');
3128                $node_i_in_active = $_;                $node_i_in_active = $_;
3129                last S7S2;                last S7S2;
3130              }              }
# Line 2990  sub _tree_construction_main ($) { Line 3138  sub _tree_construction_main ($) {
3138                    
3139          ## Step 4          ## Step 4
3140          if ($last_node->[0] eq $furthest_block->[0]) {          if ($last_node->[0] eq $furthest_block->[0]) {
3141              !!!cp ('t64');
3142            $bookmark_prev_el = $node->[0];            $bookmark_prev_el = $node->[0];
3143          }          }
3144                    
3145          ## Step 5          ## Step 5
3146          if ($node->[0]->has_child_nodes ()) {          if ($node->[0]->has_child_nodes ()) {
3147              !!!cp ('t65');
3148            my $clone = [$node->[0]->clone_node (0), $node->[1]];            my $clone = [$node->[0]->clone_node (0), $node->[1]];
3149            $active_formatting_elements->[$node_i_in_active] = $clone;            $active_formatting_elements->[$node_i_in_active] = $clone;
3150            $self->{open_elements}->[$node_i_in_open] = $clone;            $self->{open_elements}->[$node_i_in_open] = $clone;
# Line 3029  sub _tree_construction_main ($) { Line 3179  sub _tree_construction_main ($) {
3179        my $i;        my $i;
3180        AFE: for (reverse 0..$#$active_formatting_elements) {        AFE: for (reverse 0..$#$active_formatting_elements) {
3181          if ($active_formatting_elements->[$_]->[0] eq $formatting_element->[0]) {          if ($active_formatting_elements->[$_]->[0] eq $formatting_element->[0]) {
3182              !!!cp ('t66');
3183            splice @$active_formatting_elements, $_, 1;            splice @$active_formatting_elements, $_, 1;
3184            $i-- and last AFE if defined $i;            $i-- and last AFE if defined $i;
3185          } elsif ($active_formatting_elements->[$_]->[0] eq $bookmark_prev_el) {          } elsif ($active_formatting_elements->[$_]->[0] eq $bookmark_prev_el) {
3186              !!!cp ('t67');
3187            $i = $_;            $i = $_;
3188          }          }
3189        } # AFE        } # AFE
# Line 3041  sub _tree_construction_main ($) { Line 3193  sub _tree_construction_main ($) {
3193        undef $i;        undef $i;
3194        OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
3195          if ($self->{open_elements}->[$_]->[0] eq $formatting_element->[0]) {          if ($self->{open_elements}->[$_]->[0] eq $formatting_element->[0]) {
3196              !!!cp ('t68');
3197            splice @{$self->{open_elements}}, $_, 1;            splice @{$self->{open_elements}}, $_, 1;
3198            $i-- and last OE if defined $i;            $i-- and last OE if defined $i;
3199          } elsif ($self->{open_elements}->[$_]->[0] eq $furthest_block->[0]) {          } elsif ($self->{open_elements}->[$_]->[0] eq $furthest_block->[0]) {
3200              !!!cp ('t69');
3201            $i = $_;            $i = $_;
3202          }          }
3203        } # OE        } # OE
# Line 3054  sub _tree_construction_main ($) { Line 3208  sub _tree_construction_main ($) {
3208      } # FET      } # FET
3209    }; # $formatting_end_tag    }; # $formatting_end_tag
3210    
3211      ## NOTE: $open_tables->[-1]->[0] is the "current table".
3212      ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.
3213      my $open_tables = [[$self->{open_elements}->[0]->[0]]];
3214    
3215    my $insert_to_current = sub {    my $insert_to_current = sub {
3216      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);
3217    }; # $insert_to_current    }; # $insert_to_current
3218    
3219    my $insert_to_foster = sub {    my $insert_to_foster = sub {
3220                         my $child = shift;      my $child = shift;
3221                         if ({      if ({
3222                              table => 1, tbody => 1, tfoot => 1,           table => 1, tbody => 1, tfoot => 1, thead => 1, tr => 1,
3223                              thead => 1, tr => 1,          }->{$self->{open_elements}->[-1]->[1]}) {
3224                             }->{$self->{open_elements}->[-1]->[1]}) {        # MUST
3225                           # MUST        my $foster_parent_element;
3226                           my $foster_parent_element;        my $next_sibling;
                          my $next_sibling;  
3227                           OE: for (reverse 0..$#{$self->{open_elements}}) {                           OE: for (reverse 0..$#{$self->{open_elements}}) {
3228                             if ($self->{open_elements}->[$_]->[1] eq 'table') {                             if ($self->{open_elements}->[$_]->[1] eq 'table') {
3229                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
3230                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
3231                                   !!!cp ('t70');
3232                                 $foster_parent_element = $parent;                                 $foster_parent_element = $parent;
3233                                 $next_sibling = $self->{open_elements}->[$_]->[0];                                 $next_sibling = $self->{open_elements}->[$_]->[0];
3234                               } else {                               } else {
3235                                   !!!cp ('t71');
3236                                 $foster_parent_element                                 $foster_parent_element
3237                                   = $self->{open_elements}->[$_ - 1]->[0];                                   = $self->{open_elements}->[$_ - 1]->[0];
3238                               }                               }
# Line 3084  sub _tree_construction_main ($) { Line 3243  sub _tree_construction_main ($) {
3243                             unless defined $foster_parent_element;                             unless defined $foster_parent_element;
3244                           $foster_parent_element->insert_before                           $foster_parent_element->insert_before
3245                             ($child, $next_sibling);                             ($child, $next_sibling);
3246                         } else {        $open_tables->[-1]->[1] = 1; # tainted
3247                           $self->{open_elements}->[-1]->[0]->append_child ($child);      } else {
3248                         }        !!!cp ('t72');
3249          $self->{open_elements}->[-1]->[0]->append_child ($child);
3250        }
3251    }; # $insert_to_foster    }; # $insert_to_foster
3252    
3253    my $insert;    my $insert;
3254    
3255    B: {    B: {
3256      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
3257          !!!cp ('t73');
3258        !!!parse-error (type => 'DOCTYPE in the middle');        !!!parse-error (type => 'DOCTYPE in the middle');
3259        ## Ignore the token        ## Ignore the token
3260        ## Stay in the phase        ## Stay in the phase
# Line 3100  sub _tree_construction_main ($) { Line 3262  sub _tree_construction_main ($) {
3262        redo B;        redo B;
3263      } elsif ($token->{type} == END_OF_FILE_TOKEN) {      } elsif ($token->{type} == END_OF_FILE_TOKEN) {
3264        if ($self->{insertion_mode} & AFTER_HTML_IMS) {        if ($self->{insertion_mode} & AFTER_HTML_IMS) {
3265            !!!cp ('t74');
3266          #          #
3267        } else {        } else {
3268          ## Generate implied end tags          ## Generate implied end tags
3269          if ({          while ({
3270               dd => 1, dt => 1, li => 1, p => 1, td => 1, th => 1, tr => 1,                  dd => 1, dt => 1, li => 1, p => 1,
3271               tbody => 1, tfoot=> 1, thead => 1,                 }->{$self->{open_elements}->[-1]->[1]}) {
3272              }->{$self->{open_elements}->[-1]->[1]}) {            !!!cp ('t75');
3273            !!!back-token;            pop @{$self->{open_elements}};
           $token = {type => END_TAG_TOKEN, tag_name => $self->{open_elements}->[-1]->[1]};  
           redo B;  
3274          }          }
3275                    
3276          if (@{$self->{open_elements}} > 2 or          if (@{$self->{open_elements}} > 2 or
3277              (@{$self->{open_elements}} == 2 and $self->{open_elements}->[1]->[1] ne 'body')) {              (@{$self->{open_elements}} == 2 and $self->{open_elements}->[1]->[1] ne 'body')) {
3278              !!!cp ('t76');
3279            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3280          } elsif (defined $self->{inner_html_node} and          } elsif (defined $self->{inner_html_node} and
3281                   @{$self->{open_elements}} > 1 and                   @{$self->{open_elements}} > 1 and
3282                   $self->{open_elements}->[1]->[1] ne 'body') {                   $self->{open_elements}->[1]->[1] ne 'body') {
3283    ## ISSUE: This case is never reached.
3284              !!!cp ('t77');
3285            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);            !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3286            } else {
3287              !!!cp ('t78');
3288          }          }
3289    
3290          ## ISSUE: There is an issue in the spec.          ## ISSUE: There is an issue in the spec.
# Line 3129  sub _tree_construction_main ($) { Line 3295  sub _tree_construction_main ($) {
3295      } elsif ($token->{type} == START_TAG_TOKEN and      } elsif ($token->{type} == START_TAG_TOKEN and
3296               $token->{tag_name} eq 'html') {               $token->{tag_name} eq 'html') {
3297        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {        if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
3298          ## Turn into the main phase          !!!cp ('t79');
3299          !!!parse-error (type => 'after html:html');          !!!parse-error (type => 'after html:html');
3300          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
3301        } elsif ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {        } elsif ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
3302          ## Turn into the main phase          !!!cp ('t80');
3303          !!!parse-error (type => 'after html:html');          !!!parse-error (type => 'after html:html');
3304          $self->{insertion_mode} = AFTER_FRAMESET_IM;          $self->{insertion_mode} = AFTER_FRAMESET_IM;
3305          } else {
3306            !!!cp ('t81');
3307        }        }
3308    
3309  ## ISSUE: "aa<html>" is not a parse error.        !!!cp ('t82');
3310  ## 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');  
       }  
3311        my $top_el = $self->{open_elements}->[0]->[0];        my $top_el = $self->{open_elements}->[0]->[0];
3312        for my $attr_name (keys %{$token->{attributes}}) {        for my $attr_name (keys %{$token->{attributes}}) {
3313          unless ($top_el->has_attribute_ns (undef, $attr_name)) {          unless ($top_el->has_attribute_ns (undef, $attr_name)) {
3314              !!!cp ('t84');
3315            $top_el->set_attribute_ns            $top_el->set_attribute_ns
3316              (undef, [undef, $attr_name],              (undef, [undef, $attr_name],
3317               $token->{attributes}->{$attr_name}->{value});               $token->{attributes}->{$attr_name}->{value});
# Line 3156  sub _tree_construction_main ($) { Line 3322  sub _tree_construction_main ($) {
3322      } elsif ($token->{type} == COMMENT_TOKEN) {      } elsif ($token->{type} == COMMENT_TOKEN) {
3323        my $comment = $self->{document}->create_comment ($token->{data});        my $comment = $self->{document}->create_comment ($token->{data});
3324        if ($self->{insertion_mode} & AFTER_HTML_IMS) {        if ($self->{insertion_mode} & AFTER_HTML_IMS) {
3325            !!!cp ('t85');
3326          $self->{document}->append_child ($comment);          $self->{document}->append_child ($comment);
3327        } elsif ($self->{insertion_mode} == AFTER_BODY_IM) {        } elsif ($self->{insertion_mode} == AFTER_BODY_IM) {
3328            !!!cp ('t86');
3329          $self->{open_elements}->[0]->[0]->append_child ($comment);          $self->{open_elements}->[0]->[0]->append_child ($comment);
3330        } else {        } else {
3331            !!!cp ('t87');
3332          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
3333        }        }
3334        !!!next-token;        !!!next-token;
# Line 3169  sub _tree_construction_main ($) { Line 3338  sub _tree_construction_main ($) {
3338          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
3339            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
3340            unless (length $token->{data}) {            unless (length $token->{data}) {
3341                !!!cp ('t88');
3342              !!!next-token;              !!!next-token;
3343              redo B;              redo B;
3344            }            }
3345          }          }
3346    
3347          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3348              !!!cp ('t89');
3349            ## As if <head>            ## As if <head>
3350            !!!create-element ($self->{head_element}, 'head');            !!!create-element ($self->{head_element}, 'head');
3351            $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 3356  sub _tree_construction_main ($) {
3356    
3357            ## Reprocess in the "after head" insertion mode...            ## Reprocess in the "after head" insertion mode...
3358          } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {          } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3359              !!!cp ('t90');
3360            ## As if </noscript>            ## As if </noscript>
3361            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
3362            !!!parse-error (type => 'in noscript:#character');            !!!parse-error (type => 'in noscript:#character');
# Line 3195  sub _tree_construction_main ($) { Line 3367  sub _tree_construction_main ($) {
3367    
3368            ## Reprocess in the "after head" insertion mode...            ## Reprocess in the "after head" insertion mode...
3369          } elsif ($self->{insertion_mode} == IN_HEAD_IM) {          } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3370              !!!cp ('t91');
3371            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
3372    
3373            ## Reprocess in the "after head" insertion mode...            ## Reprocess in the "after head" insertion mode...
3374            } else {
3375              !!!cp ('t92');
3376          }          }
3377    
3378              ## "after head" insertion mode              ## "after head" insertion mode
# Line 3209  sub _tree_construction_main ($) { Line 3384  sub _tree_construction_main ($) {
3384            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
3385              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
3386                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3387                    !!!cp ('t93');
3388                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes});                  !!!create-element ($self->{head_element}, $token->{tag_name}, $token->{attributes});
3389                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
3390                  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 3392  sub _tree_construction_main ($) {
3392                  !!!next-token;                  !!!next-token;
3393                  redo B;                  redo B;
3394                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3395                    !!!cp ('t94');
3396                  #                  #
3397                } else {                } else {
3398                    !!!cp ('t95');
3399                  !!!parse-error (type => 'in head:head'); # or in head noscript                  !!!parse-error (type => 'in head:head'); # or in head noscript
3400                  ## Ignore the token                  ## Ignore the token
3401                  !!!next-token;                  !!!next-token;
3402                  redo B;                  redo B;
3403                }                }
3404              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3405                  !!!cp ('t96');
3406                ## As if <head>                ## As if <head>
3407                !!!create-element ($self->{head_element}, 'head');                !!!create-element ($self->{head_element}, 'head');
3408                $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 3410  sub _tree_construction_main ($) {
3410    
3411                $self->{insertion_mode} = IN_HEAD_IM;                $self->{insertion_mode} = IN_HEAD_IM;
3412                ## Reprocess in the "in head" insertion mode...                ## Reprocess in the "in head" insertion mode...
3413                } else {
3414                  !!!cp ('t97');
3415              }              }
3416    
3417              if ($token->{tag_name} eq 'base') {              if ($token->{tag_name} eq 'base') {
3418                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3419                    !!!cp ('t98');
3420                  ## As if </noscript>                  ## As if </noscript>
3421                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3422                  !!!parse-error (type => 'in noscript:base');                  !!!parse-error (type => 'in noscript:base');
3423                                
3424                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3425                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3426                  } else {
3427                    !!!cp ('t99');
3428                }                }
3429    
3430                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3431                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3432                    !!!cp ('t100');
3433                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3434                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3435                  } else {
3436                    !!!cp ('t101');
3437                }                }
3438                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3439                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 3257  sub _tree_construction_main ($) { Line 3444  sub _tree_construction_main ($) {
3444              } elsif ($token->{tag_name} eq 'link') {              } elsif ($token->{tag_name} eq 'link') {
3445                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3446                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3447                    !!!cp ('t102');
3448                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3449                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3450                  } else {
3451                    !!!cp ('t103');
3452                }                }
3453                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3454                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 3269  sub _tree_construction_main ($) { Line 3459  sub _tree_construction_main ($) {
3459              } elsif ($token->{tag_name} eq 'meta') {              } elsif ($token->{tag_name} eq 'meta') {
3460                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3461                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3462                    !!!cp ('t104');
3463                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3464                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3465                  } else {
3466                    !!!cp ('t105');
3467                }                }
3468                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3469                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.
3470    
3471                unless ($self->{confident}) {                unless ($self->{confident}) {
3472                  if ($token->{attributes}->{charset}) { ## TODO: And if supported                  if ($token->{attributes}->{charset}) { ## TODO: And if supported
3473                      !!!cp ('t106');
3474                    $self->{change_encoding}                    $self->{change_encoding}
3475                        ->($self, $token->{attributes}->{charset}->{value});                        ->($self, $token->{attributes}->{charset}->{value});
3476                                        
# Line 3291  sub _tree_construction_main ($) { Line 3485  sub _tree_construction_main ($) {
3485                            [\x09-\x0D\x20]*=                            [\x09-\x0D\x20]*=
3486                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                            [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
3487                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                            ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
3488                        !!!cp ('t107');
3489                      $self->{change_encoding}                      $self->{change_encoding}
3490                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);                          ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);
3491                      $meta_el->[0]->get_attribute_node_ns (undef, 'content')                      $meta_el->[0]->get_attribute_node_ns (undef, 'content')
3492                          ->set_user_data (manakai_has_reference =>                          ->set_user_data (manakai_has_reference =>
3493                                               $token->{attributes}->{content}                                               $token->{attributes}->{content}
3494                                                     ->{has_reference});                                                     ->{has_reference});
3495                      } else {
3496                        !!!cp ('t108');
3497                    }                    }
3498                  }                  }
3499                } else {                } else {
3500                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
3501                      !!!cp ('t109');
3502                    $meta_el->[0]->get_attribute_node_ns (undef, 'charset')                    $meta_el->[0]->get_attribute_node_ns (undef, 'charset')
3503                        ->set_user_data (manakai_has_reference =>                        ->set_user_data (manakai_has_reference =>
3504                                             $token->{attributes}->{charset}                                             $token->{attributes}->{charset}
3505                                                 ->{has_reference});                                                 ->{has_reference});
3506                  }                  }
3507                  if ($token->{attributes}->{content}) {                  if ($token->{attributes}->{content}) {
3508                      !!!cp ('t110');
3509                    $meta_el->[0]->get_attribute_node_ns (undef, 'content')                    $meta_el->[0]->get_attribute_node_ns (undef, 'content')
3510                        ->set_user_data (manakai_has_reference =>                        ->set_user_data (manakai_has_reference =>
3511                                             $token->{attributes}->{content}                                             $token->{attributes}->{content}
# Line 3320  sub _tree_construction_main ($) { Line 3519  sub _tree_construction_main ($) {
3519                redo B;                redo B;
3520              } elsif ($token->{tag_name} eq 'title') {              } elsif ($token->{tag_name} eq 'title') {
3521                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3522                    !!!cp ('t111');
3523                  ## As if </noscript>                  ## As if </noscript>
3524                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3525                  !!!parse-error (type => 'in noscript:title');                  !!!parse-error (type => 'in noscript:title');
# Line 3327  sub _tree_construction_main ($) { Line 3527  sub _tree_construction_main ($) {
3527                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3528                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3529                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3530                    !!!cp ('t112');
3531                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3532                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3533                  } else {
3534                    !!!cp ('t113');
3535                }                }
3536    
3537                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
# Line 3344  sub _tree_construction_main ($) { Line 3547  sub _tree_construction_main ($) {
3547                ## insertion mode IN_HEAD_IM)                ## insertion mode IN_HEAD_IM)
3548                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
3549                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3550                    !!!cp ('t114');
3551                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3552                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3553                  } else {
3554                    !!!cp ('t115');
3555                }                }
3556                $parse_rcdata->(CDATA_CONTENT_MODEL, $insert_to_current);                $parse_rcdata->(CDATA_CONTENT_MODEL, $insert_to_current);
3557                pop @{$self->{open_elements}}                pop @{$self->{open_elements}}
# Line 3353  sub _tree_construction_main ($) { Line 3559  sub _tree_construction_main ($) {
3559                redo B;                redo B;
3560              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
3561                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
3562                    !!!cp ('t116');
3563                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
3564                  !!!insert-element ($token->{tag_name}, $token->{attributes});                  !!!insert-element ($token->{tag_name}, $token->{attributes});
3565                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;                  $self->{insertion_mode} = IN_HEAD_NOSCRIPT_IM;
3566                  !!!next-token;                  !!!next-token;
3567                  redo B;                  redo B;
3568                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3569                    !!!cp ('t117');
3570                  !!!parse-error (type => 'in noscript:noscript');                  !!!parse-error (type => 'in noscript:noscript');
3571                  ## Ignore the token                  ## Ignore the token
3572                  !!!next-token;                  !!!next-token;
3573                  redo B;                  redo B;
3574                } else {                } else {
3575                    !!!cp ('t118');
3576                  #                  #
3577                }                }
3578              } elsif ($token->{tag_name} eq 'script') {              } elsif ($token->{tag_name} eq 'script') {
3579                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3580                    !!!cp ('t119');
3581                  ## As if </noscript>                  ## As if </noscript>
3582                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3583                  !!!parse-error (type => 'in noscript:script');                  !!!parse-error (type => 'in noscript:script');
# Line 3375  sub _tree_construction_main ($) { Line 3585  sub _tree_construction_main ($) {
3585                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3586                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3587                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
3588                    !!!cp ('t120');
3589                  !!!parse-error (type => 'after head:'.$token->{tag_name});                  !!!parse-error (type => 'after head:'.$token->{tag_name});
3590                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];                  push @{$self->{open_elements}}, [$self->{head_element}, 'head'];
3591                  } else {
3592                    !!!cp ('t121');
3593                }                }
3594    
3595                ## NOTE: There is a "as if in head" code clone.                ## NOTE: There is a "as if in head" code clone.
# Line 3387  sub _tree_construction_main ($) { Line 3600  sub _tree_construction_main ($) {
3600              } elsif ($token->{tag_name} eq 'body' or              } elsif ($token->{tag_name} eq 'body' or
3601                       $token->{tag_name} eq 'frameset') {                       $token->{tag_name} eq 'frameset') {
3602                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3603                    !!!cp ('t122');
3604                  ## As if </noscript>                  ## As if </noscript>
3605                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3606                  !!!parse-error (type => 'in noscript:'.$token->{tag_name});                  !!!parse-error (type => 'in noscript:'.$token->{tag_name});
# Line 3397  sub _tree_construction_main ($) { Line 3611  sub _tree_construction_main ($) {
3611                                    
3612                  ## Reprocess in the "after head" insertion mode...                  ## Reprocess in the "after head" insertion mode...
3613                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3614                    !!!cp ('t124');
3615                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3616                                    
3617                  ## Reprocess in the "after head" insertion mode...                  ## Reprocess in the "after head" insertion mode...
3618                  } else {
3619                    !!!cp ('t125');
3620                }                }
3621    
3622                ## "after head" insertion mode                ## "after head" insertion mode
3623                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
3624                if ($token->{tag_name} eq 'body') {                if ($token->{tag_name} eq 'body') {
3625                    !!!cp ('t126');
3626                  $self->{insertion_mode} = IN_BODY_IM;                  $self->{insertion_mode} = IN_BODY_IM;
3627                } elsif ($token->{tag_name} eq 'frameset') {                } elsif ($token->{tag_name} eq 'frameset') {
3628                    !!!cp ('t127');
3629                  $self->{insertion_mode} = IN_FRAMESET_IM;                  $self->{insertion_mode} = IN_FRAMESET_IM;
3630                } else {                } else {
3631                  die "$0: tag name: $self->{tag_name}";                  die "$0: tag name: $self->{tag_name}";
# Line 3414  sub _tree_construction_main ($) { Line 3633  sub _tree_construction_main ($) {
3633                !!!next-token;                !!!next-token;
3634                redo B;                redo B;
3635              } else {              } else {
3636                  !!!cp ('t128');
3637                #                #
3638              }              }
3639    
3640              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3641                  !!!cp ('t129');
3642                ## As if </noscript>                ## As if </noscript>
3643                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3644                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});
# Line 3428  sub _tree_construction_main ($) { Line 3649  sub _tree_construction_main ($) {
3649    
3650                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3651              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3652                  !!!cp ('t130');
3653                ## As if </head>                ## As if </head>
3654                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3655    
3656                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3657                } else {
3658                  !!!cp ('t131');
3659              }              }
3660    
3661              ## "after head" insertion mode              ## "after head" insertion mode
# Line 3443  sub _tree_construction_main ($) { Line 3667  sub _tree_construction_main ($) {
3667            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
3668              if ($token->{tag_name} eq 'head') {              if ($token->{tag_name} eq 'head') {
3669                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3670                    !!!cp ('t132');
3671                  ## As if <head>                  ## As if <head>
3672                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head');
3673                  $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 3679  sub _tree_construction_main ($) {
3679                  !!!next-token;                  !!!next-token;
3680                  redo B;                  redo B;
3681                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3682                    !!!cp ('t133');
3683                  ## As if </noscript>                  ## As if </noscript>
3684                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3685                  !!!parse-error (type => 'in noscript:script');                  !!!parse-error (type => 'in noscript:/head');
3686                                    
3687                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3688                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
# Line 3464  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_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3693                    !!!cp ('t134');
3694                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3695                  $self->{insertion_mode} = AFTER_HEAD_IM;                  $self->{insertion_mode} = AFTER_HEAD_IM;
3696                  !!!next-token;                  !!!next-token;
3697                  redo B;                  redo B;
3698                } else {                } else {
3699                    !!!cp ('t135');
3700                  #                  #
3701                }                }
3702              } elsif ($token->{tag_name} eq 'noscript') {              } elsif ($token->{tag_name} eq 'noscript') {
3703                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3704                    !!!cp ('t136');
3705                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
3706                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3707                  !!!next-token;                  !!!next-token;
3708                  redo B;                  redo B;
3709                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3710                    !!!cp ('t137');
3711                  !!!parse-error (type => 'unmatched end tag:noscript');                  !!!parse-error (type => 'unmatched end tag:noscript');
3712                  ## Ignore the token ## ISSUE: An issue in the spec.                  ## Ignore the token ## ISSUE: An issue in the spec.
3713                  !!!next-token;                  !!!next-token;
3714                  redo B;                  redo B;
3715                } else {                } else {
3716                    !!!cp ('t138');
3717                  #                  #
3718                }                }
3719              } elsif ({              } elsif ({
3720                        body => 1, html => 1,                        body => 1, html => 1,
3721                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
3722                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3723                    !!!cp ('t139');
3724                  ## As if <head>                  ## As if <head>
3725                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head');
3726                  $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 3729  sub _tree_construction_main ($) {
3729                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3730                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3731                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3732                    !!!cp ('t140');
3733                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3734                  ## Ignore the token                  ## Ignore the token
3735                  !!!next-token;                  !!!next-token;
3736                  redo B;                  redo B;
3737                  } else {
3738                    !!!cp ('t141');
3739                }                }
3740                                
3741                #                #
# Line 3508  sub _tree_construction_main ($) { Line 3743  sub _tree_construction_main ($) {
3743                        p => 1, br => 1,                        p => 1, br => 1,
3744                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
3745                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3746                    !!!cp ('t142');
3747                  ## As if <head>                  ## As if <head>
3748                  !!!create-element ($self->{head_element}, 'head');                  !!!create-element ($self->{head_element}, 'head');
3749                  $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 3751  sub _tree_construction_main ($) {
3751    
3752                  $self->{insertion_mode} = IN_HEAD_IM;                  $self->{insertion_mode} = IN_HEAD_IM;
3753                  ## Reprocess in the "in head" insertion mode...                  ## Reprocess in the "in head" insertion mode...
3754                  } else {
3755                    !!!cp ('t143');
3756                }                }
3757    
3758                #                #
3759              } else {              } else {
3760                if ($self->{insertion_mode} == AFTER_HEAD_IM) {                if ($self->{insertion_mode} == AFTER_HEAD_IM) {
3761                    !!!cp ('t144');
3762                  #                  #
3763                } else {                } else {
3764                    !!!cp ('t145');
3765                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3766                  ## Ignore the token                  ## Ignore the token
3767                  !!!next-token;                  !!!next-token;
# Line 3530  sub _tree_construction_main ($) { Line 3770  sub _tree_construction_main ($) {
3770              }              }
3771    
3772              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
3773                  !!!cp ('t146');
3774                ## As if </noscript>                ## As if </noscript>
3775                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3776                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});                !!!parse-error (type => 'in noscript:/'.$token->{tag_name});
# Line 3540  sub _tree_construction_main ($) { Line 3781  sub _tree_construction_main ($) {
3781    
3782                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3783              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
3784                  !!!cp ('t147');
3785                ## As if </head>                ## As if </head>
3786                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3787    
3788                ## Reprocess in the "after head" insertion mode...                ## Reprocess in the "after head" insertion mode...
3789              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {
3790    ## ISSUE: This case cannot be reached?
3791                  !!!cp ('t148');
3792                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3793                ## Ignore the token ## ISSUE: An issue in the spec.                ## Ignore the token ## ISSUE: An issue in the spec.
3794                !!!next-token;                !!!next-token;
3795                redo B;                redo B;
3796                } else {
3797                  !!!cp ('t149');
3798              }              }
3799    
3800              ## "after head" insertion mode              ## "after head" insertion mode
# Line 3564  sub _tree_construction_main ($) { Line 3810  sub _tree_construction_main ($) {
3810            ## ISSUE: An issue in the spec.            ## ISSUE: An issue in the spec.
3811      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
3812            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
3813                !!!cp ('t150');
3814              ## NOTE: There is a code clone of "character in body".              ## NOTE: There is a code clone of "character in body".
3815              $reconstruct_active_formatting_elements->($insert_to_current);              $reconstruct_active_formatting_elements->($insert_to_current);
3816                            
# Line 3582  sub _tree_construction_main ($) { Line 3829  sub _tree_construction_main ($) {
3829                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3830                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3831                    if ($node->[1] eq 'td' or $node->[1] eq 'th') {                    if ($node->[1] eq 'td' or $node->[1] eq 'th') {
3832                        !!!cp ('t151');
3833                      $tn = $node->[1];                      $tn = $node->[1];
3834                      last INSCOPE;                      last INSCOPE;
3835                    } elsif ({                    } elsif ({
3836                              table => 1, html => 1,                              table => 1, html => 1,
3837                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3838                        !!!cp ('t152');
3839                      last INSCOPE;                      last INSCOPE;
3840                    }                    }
3841                  } # INSCOPE                  } # INSCOPE
3842                    unless (defined $tn) {                    unless (defined $tn) {
3843                        !!!cp ('t153');
3844    ## TODO: This error type is wrong.
3845                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3846                      ## Ignore the token                      ## Ignore the token
3847                      !!!next-token;                      !!!next-token;
3848                      redo B;                      redo B;
3849                    }                    }
3850                                    
3851                    !!!cp ('t154');
3852                  ## Close the cell                  ## Close the cell
3853                  !!!back-token; # <?>                  !!!back-token; # <?>
3854                  $token = {type => END_TAG_TOKEN, tag_name => $tn};                  $token = {type => END_TAG_TOKEN, tag_name => $tn};
# Line 3610  sub _tree_construction_main ($) { Line 3862  sub _tree_construction_main ($) {
3862                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3863                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3864                    if ($node->[1] eq 'caption') {                    if ($node->[1] eq 'caption') {
3865                        !!!cp ('t155');
3866                      $i = $_;                      $i = $_;
3867                      last INSCOPE;                      last INSCOPE;
3868                    } elsif ({                    } elsif ({
3869                              table => 1, html => 1,                              table => 1, html => 1,
3870                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3871                        !!!cp ('t156');
3872                      last INSCOPE;                      last INSCOPE;
3873                    }                    }
3874                  } # INSCOPE                  } # INSCOPE
3875                    unless (defined $i) {                    unless (defined $i) {
3876                        !!!cp ('t157');
3877    ## TODO: this type is wrong.
3878                      !!!parse-error (type => 'unmatched end tag:caption');                      !!!parse-error (type => 'unmatched end tag:caption');
3879                      ## Ignore the token                      ## Ignore the token
3880                      !!!next-token;                      !!!next-token;
# Line 3626  sub _tree_construction_main ($) { Line 3882  sub _tree_construction_main ($) {
3882                    }                    }
3883                                    
3884                  ## generate implied end tags                  ## generate implied end tags
3885                  if ({                  while ({
3886                       dd => 1, dt => 1, li => 1, p => 1,                          dd => 1, dt => 1, li => 1, p => 1,
3887                       td => 1, th => 1, tr => 1,                         }->{$self->{open_elements}->[-1]->[1]}) {
3888                       tbody => 1, tfoot=> 1, thead => 1,                    !!!cp ('t158');
3889                      }->{$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;  
3890                  }                  }
3891    
3892                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {
3893                      !!!cp ('t159');
3894                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3895                    } else {
3896                      !!!cp ('t160');
3897                  }                  }
3898                                    
3899                  splice @{$self->{open_elements}}, $i;                  splice @{$self->{open_elements}}, $i;
# Line 3652  sub _tree_construction_main ($) { Line 3905  sub _tree_construction_main ($) {
3905                  ## reprocess                  ## reprocess
3906                  redo B;                  redo B;
3907                } else {                } else {
3908                    !!!cp ('t161');
3909                  #                  #
3910                }                }
3911              } else {              } else {
3912                  !!!cp ('t162');
3913                #                #
3914              }              }
3915            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
# Line 3665  sub _tree_construction_main ($) { Line 3920  sub _tree_construction_main ($) {
3920                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3921                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3922                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[1] eq $token->{tag_name}) {
3923                        !!!cp ('t163');
3924                      $i = $_;                      $i = $_;
3925                      last INSCOPE;                      last INSCOPE;
3926                    } elsif ({                    } elsif ({
3927                              table => 1, html => 1,                              table => 1, html => 1,
3928                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3929                        !!!cp ('t164');
3930                      last INSCOPE;                      last INSCOPE;
3931                    }                    }
3932                  } # INSCOPE                  } # INSCOPE
3933                    unless (defined $i) {                    unless (defined $i) {
3934                        !!!cp ('t165');
3935                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3936                      ## Ignore the token                      ## Ignore the token
3937                      !!!next-token;                      !!!next-token;
# Line 3681  sub _tree_construction_main ($) { Line 3939  sub _tree_construction_main ($) {
3939                    }                    }
3940                                    
3941                  ## generate implied end tags                  ## generate implied end tags
3942                  if ({                  while ({
3943                       dd => 1, dt => 1, li => 1, p => 1,                          dd => 1, dt => 1, li => 1, p => 1,
3944                       td => ($token->{tag_name} eq 'th'),                         }->{$self->{open_elements}->[-1]->[1]}) {
3945                       th => ($token->{tag_name} eq 'td'),                    !!!cp ('t166');
3946                       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;  
3947                  }                  }
3948                    
3949                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {                  if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
3950                      !!!cp ('t167');
3951                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
3952                    } else {
3953                      !!!cp ('t168');
3954                  }                  }
3955                                    
3956                  splice @{$self->{open_elements}}, $i;                  splice @{$self->{open_elements}}, $i;
# Line 3707  sub _tree_construction_main ($) { Line 3962  sub _tree_construction_main ($) {
3962                  !!!next-token;                  !!!next-token;
3963                  redo B;                  redo B;
3964                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {                } elsif ($self->{insertion_mode} == IN_CAPTION_IM) {
3965                    !!!cp ('t169');
3966                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3967                  ## Ignore the token                  ## Ignore the token
3968                  !!!next-token;                  !!!next-token;
3969                  redo B;                  redo B;
3970                } else {                } else {
3971                    !!!cp ('t170');
3972                  #                  #
3973                }                }
3974              } elsif ($token->{tag_name} eq 'caption') {              } elsif ($token->{tag_name} eq 'caption') {
# Line 3721  sub _tree_construction_main ($) { Line 3978  sub _tree_construction_main ($) {
3978                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3979                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
3980                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[1] eq $token->{tag_name}) {
3981                        !!!cp ('t171');
3982                      $i = $_;                      $i = $_;
3983                      last INSCOPE;                      last INSCOPE;
3984                    } elsif ({                    } elsif ({
3985                              table => 1, html => 1,                              table => 1, html => 1,
3986                             }->{$node->[1]}) {                             }->{$node->[1]}) {
3987                        !!!cp ('t172');
3988                      last INSCOPE;                      last INSCOPE;
3989                    }                    }
3990                  } # INSCOPE                  } # INSCOPE
3991                    unless (defined $i) {                    unless (defined $i) {
3992                        !!!cp ('t173');
3993                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
3994                      ## Ignore the token                      ## Ignore the token
3995                      !!!next-token;                      !!!next-token;
# Line 3737  sub _tree_construction_main ($) { Line 3997  sub _tree_construction_main ($) {
3997                    }                    }
3998                                    
3999                  ## generate implied end tags                  ## generate implied end tags
4000                  if ({                  while ({
4001                       dd => 1, dt => 1, li => 1, p => 1,                          dd => 1, dt => 1, li => 1, p => 1,
4002                       td => 1, th => 1, tr => 1,                         }->{$self->{open_elements}->[-1]->[1]}) {
4003                       tbody => 1, tfoot=> 1, thead => 1,                    !!!cp ('t174');
4004                      }->{$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;  
4005                  }                  }
4006                                    
4007                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {                  if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4008                      !!!cp ('t175');
4009                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4010                    } else {
4011                      !!!cp ('t176');
4012                  }                  }
4013                                    
4014                  splice @{$self->{open_elements}}, $i;                  splice @{$self->{open_elements}}, $i;
# Line 3761  sub _tree_construction_main ($) { Line 4020  sub _tree_construction_main ($) {
4020                  !!!next-token;                  !!!next-token;
4021                  redo B;                  redo B;
4022                } elsif ($self->{insertion_mode} == IN_CELL_IM) {                } elsif ($self->{insertion_mode} == IN_CELL_IM) {
4023                    !!!cp ('t177');
4024                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4025                  ## Ignore the token                  ## Ignore the token
4026                  !!!next-token;                  !!!next-token;
4027                  redo B;                  redo B;
4028                } else {                } else {
4029                    !!!cp ('t178');
4030                  #                  #
4031                }                }
4032              } elsif ({              } elsif ({
# Line 3779  sub _tree_construction_main ($) { Line 4040  sub _tree_construction_main ($) {
4040                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4041                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4042                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4043                      !!!cp ('t179');
4044                    $i = $_;                    $i = $_;
4045                    last INSCOPE;                    last INSCOPE;
4046                  } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {                  } elsif ($node->[1] eq 'td' or $node->[1] eq 'th') {
4047                      !!!cp ('t180');
4048                    $tn = $node->[1];                    $tn = $node->[1];
4049                    ## NOTE: There is exactly one |td| or |th| element                    ## NOTE: There is exactly one |td| or |th| element
4050                    ## in scope in the stack of open elements by definition.                    ## in scope in the stack of open elements by definition.
4051                  } elsif ({                  } elsif ({
4052                            table => 1, html => 1,                            table => 1, html => 1,
4053                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4054                      !!!cp ('t181');
4055                    last INSCOPE;                    last INSCOPE;
4056                  }                  }
4057                } # INSCOPE                } # INSCOPE
4058                unless (defined $i) {                unless (defined $i) {
4059                    !!!cp ('t182');
4060                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4061                  ## Ignore the token                  ## Ignore the token
4062                  !!!next-token;                  !!!next-token;
4063                  redo B;                  redo B;
4064                  } else {
4065                    !!!cp ('t183');
4066                }                }
4067    
4068                ## Close the cell                ## Close the cell
# Line 3812  sub _tree_construction_main ($) { Line 4079  sub _tree_construction_main ($) {
4079                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4080                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4081                  if ($node->[1] eq 'caption') {                  if ($node->[1] eq 'caption') {
4082                      !!!cp ('t184');
4083                    $i = $_;                    $i = $_;
4084                    last INSCOPE;                    last INSCOPE;
4085                  } elsif ({                  } elsif ({
4086                            table => 1, html => 1,                            table => 1, html => 1,
4087                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4088                      !!!cp ('t185');
4089                    last INSCOPE;                    last INSCOPE;
4090                  }                  }
4091                } # INSCOPE                } # INSCOPE
4092                unless (defined $i) {                unless (defined $i) {
4093                    !!!cp ('t186');
4094                  !!!parse-error (type => 'unmatched end tag:caption');                  !!!parse-error (type => 'unmatched end tag:caption');
4095                  ## Ignore the token                  ## Ignore the token
4096                  !!!next-token;                  !!!next-token;
# Line 3828  sub _tree_construction_main ($) { Line 4098  sub _tree_construction_main ($) {
4098                }                }
4099                                
4100                ## generate implied end tags                ## generate implied end tags
4101                if ({                while ({
4102                     dd => 1, dt => 1, li => 1, p => 1,                        dd => 1, dt => 1, li => 1, p => 1,
4103                     td => 1, th => 1, tr => 1,                       }->{$self->{open_elements}->[-1]->[1]}) {
4104                     tbody => 1, tfoot=> 1, thead => 1,                  !!!cp ('t187');
4105                    }->{$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;  
4106                }                }
4107    
4108                if ($self->{open_elements}->[-1]->[1] ne 'caption') {                if ($self->{open_elements}->[-1]->[1] ne 'caption') {
4109                    !!!cp ('t188');
4110                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4111                  } else {
4112                    !!!cp ('t189');
4113                }                }
4114    
4115                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
# Line 3857  sub _tree_construction_main ($) { Line 4124  sub _tree_construction_main ($) {
4124                        body => 1, col => 1, colgroup => 1, html => 1,                        body => 1, col => 1, colgroup => 1, html => 1,
4125                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4126                if ($self->{insertion_mode} & BODY_TABLE_IMS) {                if ($self->{insertion_mode} & BODY_TABLE_IMS) {
4127                    !!!cp ('t190');
4128                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4129                  ## Ignore the token                  ## Ignore the token
4130                  !!!next-token;                  !!!next-token;
4131                  redo B;                  redo B;
4132                } else {                } else {
4133                    !!!cp ('t191');
4134                  #                  #
4135                }                }
4136              } elsif ({              } elsif ({
# Line 3869  sub _tree_construction_main ($) { Line 4138  sub _tree_construction_main ($) {
4138                        thead => 1, tr => 1,                        thead => 1, tr => 1,
4139                       }->{$token->{tag_name}} and                       }->{$token->{tag_name}} and
4140                       $self->{insertion_mode} == IN_CAPTION_IM) {                       $self->{insertion_mode} == IN_CAPTION_IM) {
4141                  !!!cp ('t192');
4142                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4143                ## Ignore the token                ## Ignore the token
4144                !!!next-token;                !!!next-token;
4145                redo B;                redo B;
4146              } else {              } else {
4147                  !!!cp ('t193');
4148                #                #
4149              }              }
4150        } else {        } else {
# Line 3884  sub _tree_construction_main ($) { Line 4155  sub _tree_construction_main ($) {
4155        #        #
4156      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
4157        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4158              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {          if (not $open_tables->[-1]->[1] and # tainted
4159                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);              $token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
4160              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4161                                
4162                unless (length $token->{data}) {            unless (length $token->{data}) {
4163                  !!!next-token;              !!!cp ('t194');
4164                  redo B;              !!!next-token;
4165                }              redo B;
4166              }            } else {
4167                !!!cp ('t195');
4168              }
4169            }
4170    
4171              !!!parse-error (type => 'in table:#character');              !!!parse-error (type => 'in table:#character');
4172    
# Line 3913  sub _tree_construction_main ($) { Line 4188  sub _tree_construction_main ($) {
4188                  if ($self->{open_elements}->[$_]->[1] eq 'table') {                  if ($self->{open_elements}->[$_]->[1] eq 'table') {
4189                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4190                    if (defined $parent and $parent->node_type == 1) {                    if (defined $parent and $parent->node_type == 1) {
4191                        !!!cp ('t196');
4192                      $foster_parent_element = $parent;                      $foster_parent_element = $parent;
4193                      $next_sibling = $self->{open_elements}->[$_]->[0];                      $next_sibling = $self->{open_elements}->[$_]->[0];
4194                      $prev_sibling = $next_sibling->previous_sibling;                      $prev_sibling = $next_sibling->previous_sibling;
4195                    } else {                    } else {
4196                        !!!cp ('t197');
4197                      $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];                      $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
4198                      $prev_sibling = $foster_parent_element->last_child;                      $prev_sibling = $foster_parent_element->last_child;
4199                    }                    }
# Line 3928  sub _tree_construction_main ($) { Line 4205  sub _tree_construction_main ($) {
4205                  unless defined $foster_parent_element;                  unless defined $foster_parent_element;
4206                if (defined $prev_sibling and                if (defined $prev_sibling and
4207                    $prev_sibling->node_type == 3) {                    $prev_sibling->node_type == 3) {
4208                    !!!cp ('t198');
4209                  $prev_sibling->manakai_append_text ($token->{data});                  $prev_sibling->manakai_append_text ($token->{data});
4210                } else {                } else {
4211                    !!!cp ('t199');
4212                  $foster_parent_element->insert_before                  $foster_parent_element->insert_before
4213                    ($self->{document}->create_text_node ($token->{data}),                    ($self->{document}->create_text_node ($token->{data}),
4214                     $next_sibling);                     $next_sibling);
4215                }                }
4216              } else {            $open_tables->[-1]->[1] = 1; # tainted
4217                $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          } else {
4218              }            !!!cp ('t200');
4219              $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4220            }
4221                            
4222              !!!next-token;          !!!next-token;
4223              redo B;          redo B;
4224        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
4225              if ({              if ({
4226                   tr => ($self->{insertion_mode} != IN_ROW_IM),                   tr => ($self->{insertion_mode} != IN_ROW_IM),
# Line 3949  sub _tree_construction_main ($) { Line 4230  sub _tree_construction_main ($) {
4230                  ## Clear back to table context                  ## Clear back to table context
4231                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4232                         $self->{open_elements}->[-1]->[1] ne 'html') {                         $self->{open_elements}->[-1]->[1] ne 'html') {
4233                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t201');
4234                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4235                  }                  }
4236                                    
# Line 3960  sub _tree_construction_main ($) { Line 4241  sub _tree_construction_main ($) {
4241    
4242                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {                if ($self->{insertion_mode} == IN_TABLE_BODY_IM) {
4243                  unless ($token->{tag_name} eq 'tr') {                  unless ($token->{tag_name} eq 'tr') {
4244                      !!!cp ('t202');
4245                    !!!parse-error (type => 'missing start tag:tr');                    !!!parse-error (type => 'missing start tag:tr');
4246                  }                  }
4247                                    
# Line 3967  sub _tree_construction_main ($) { Line 4249  sub _tree_construction_main ($) {
4249                  while (not {                  while (not {
4250                    tbody => 1, tfoot => 1, thead => 1, html => 1,                    tbody => 1, tfoot => 1, thead => 1, html => 1,
4251                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4252                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t203');
4253                      ## ISSUE: Can this case be reached?
4254                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4255                  }                  }
4256                                    
4257                  $self->{insertion_mode} = IN_ROW_IM;                  $self->{insertion_mode} = IN_ROW_IM;
4258                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4259                      !!!cp ('t204');
4260                    !!!insert-element ($token->{tag_name}, $token->{attributes});                    !!!insert-element ($token->{tag_name}, $token->{attributes});
4261                    !!!next-token;                    !!!next-token;
4262                    redo B;                    redo B;
4263                  } else {                  } else {
4264                      !!!cp ('t205');
4265                    !!!insert-element ('tr');                    !!!insert-element ('tr');
4266                    ## reprocess in the "in row" insertion mode                    ## reprocess in the "in row" insertion mode
4267                  }                  }
4268                  } else {
4269                    !!!cp ('t206');
4270                }                }
4271    
4272                ## Clear back to table row context                ## Clear back to table row context
4273                while (not {                while (not {
4274                  tr => 1, html => 1,                  tr => 1, html => 1,
4275                }->{$self->{open_elements}->[-1]->[1]}) {                }->{$self->{open_elements}->[-1]->[1]}) {
4276                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!cp ('t207');
4277                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4278                }                }
4279                                
# Line 4009  sub _tree_construction_main ($) { Line 4296  sub _tree_construction_main ($) {
4296                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4297                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4298                    if ($node->[1] eq 'tr') {                    if ($node->[1] eq 'tr') {
4299                        !!!cp ('t208');
4300                      $i = $_;                      $i = $_;
4301                      last INSCOPE;                      last INSCOPE;
4302                    } elsif ({                    } elsif ({
4303                              table => 1, html => 1,                              html => 1,
4304    
4305                                ## NOTE: This element does not appear here, maybe.
4306                                table => 1,
4307                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4308                        !!!cp ('t209');
4309                      last INSCOPE;                      last INSCOPE;
4310                    }                    }
4311                  } # INSCOPE                  } # INSCOPE
4312                  unless (defined $i) {                  unless (defined $i) {
4313                    !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name});                   !!!cp ('t210');
4314    ## TODO: This type is wrong.
4315                     !!!parse-error (type => 'unmacthed end tag:'.$token->{tag_name});
4316                    ## Ignore the token                    ## Ignore the token
4317                    !!!next-token;                    !!!next-token;
4318                    redo B;                    redo B;
# Line 4028  sub _tree_construction_main ($) { Line 4322  sub _tree_construction_main ($) {
4322                  while (not {                  while (not {
4323                    tr => 1, html => 1,                    tr => 1, html => 1,
4324                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4325                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t211');
4326                      ## ISSUE: Can this case be reached?
4327                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4328                  }                  }
4329                                    
4330                  pop @{$self->{open_elements}}; # tr                  pop @{$self->{open_elements}}; # tr
4331                  $self->{insertion_mode} = IN_TABLE_BODY_IM;                  $self->{insertion_mode} = IN_TABLE_BODY_IM;
4332                  if ($token->{tag_name} eq 'tr') {                  if ($token->{tag_name} eq 'tr') {
4333                      !!!cp ('t212');
4334                    ## reprocess                    ## reprocess
4335                    redo B;                    redo B;
4336                  } else {                  } else {
4337                      !!!cp ('t213');
4338                    ## reprocess in the "in table body" insertion mode...                    ## reprocess in the "in table body" insertion mode...
4339                  }                  }
4340                }                }
# Line 4050  sub _tree_construction_main ($) { Line 4347  sub _tree_construction_main ($) {
4347                    if ({                    if ({
4348                         tbody => 1, thead => 1, tfoot => 1,                         tbody => 1, thead => 1, tfoot => 1,
4349                        }->{$node->[1]}) {                        }->{$node->[1]}) {
4350                        !!!cp ('t214');
4351                      $i = $_;                      $i = $_;
4352                      last INSCOPE;                      last INSCOPE;
4353                    } elsif ({                    } elsif ({
4354                              table => 1, html => 1,                              table => 1, html => 1,
4355                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4356                        !!!cp ('t215');
4357                      last INSCOPE;                      last INSCOPE;
4358                    }                    }
4359                  } # INSCOPE                  } # INSCOPE
4360                  unless (defined $i) {                  unless (defined $i) {
4361                      !!!cp ('t216');
4362    ## TODO: This erorr type ios wrong.
4363                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4364                    ## Ignore the token                    ## Ignore the token
4365                    !!!next-token;                    !!!next-token;
# Line 4069  sub _tree_construction_main ($) { Line 4370  sub _tree_construction_main ($) {
4370                  while (not {                  while (not {
4371                    tbody => 1, tfoot => 1, thead => 1, html => 1,                    tbody => 1, tfoot => 1, thead => 1, html => 1,
4372                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4373                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t217');
4374                      ## ISSUE: Can this state be reached?
4375                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4376                  }                  }
4377                                    
# Line 4083  sub _tree_construction_main ($) { Line 4385  sub _tree_construction_main ($) {
4385                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4386                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4387                  ## reprocess in "in table" insertion mode...                  ## reprocess in "in table" insertion mode...
4388                  } else {
4389                    !!!cp ('t218');
4390                }                }
4391    
4392                if ($token->{tag_name} eq 'col') {                if ($token->{tag_name} eq 'col') {
4393                  ## Clear back to table context                  ## Clear back to table context
4394                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4395                         $self->{open_elements}->[-1]->[1] ne 'html') {                         $self->{open_elements}->[-1]->[1] ne 'html') {
4396                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t219');
4397                      ## ISSUE: Can this state be reached?
4398                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4399                  }                  }
4400                                    
# Line 4105  sub _tree_construction_main ($) { Line 4410  sub _tree_construction_main ($) {
4410                  ## Clear back to table context                  ## Clear back to table context
4411                  while ($self->{open_elements}->[-1]->[1] ne 'table' and                  while ($self->{open_elements}->[-1]->[1] ne 'table' and
4412                         $self->{open_elements}->[-1]->[1] ne 'html') {                         $self->{open_elements}->[-1]->[1] ne 'html') {
4413                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t220');
4414                      ## ISSUE: Can this state be reached?
4415                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4416                  }                  }
4417                                    
# Line 4134  sub _tree_construction_main ($) { Line 4440  sub _tree_construction_main ($) {
4440                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4441                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4442                  if ($node->[1] eq 'table') {                  if ($node->[1] eq 'table') {
4443                      !!!cp ('t221');
4444                    $i = $_;                    $i = $_;
4445                    last INSCOPE;                    last INSCOPE;
4446                  } elsif ({                  } elsif ({
4447                            table => 1, html => 1,                            #table => 1,
4448                              html => 1,
4449                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4450                      !!!cp ('t222');
4451                    last INSCOPE;                    last INSCOPE;
4452                  }                  }
4453                } # INSCOPE                } # INSCOPE
4454                unless (defined $i) {                unless (defined $i) {
4455                    !!!cp ('t223');
4456    ## TODO: The following is wrong, maybe.
4457                  !!!parse-error (type => 'unmatched end tag:table');                  !!!parse-error (type => 'unmatched end tag:table');
4458                  ## Ignore tokens </table><table>                  ## Ignore tokens </table><table>
4459                  !!!next-token;                  !!!next-token;
# Line 4150  sub _tree_construction_main ($) { Line 4461  sub _tree_construction_main ($) {
4461                }                }
4462                                
4463                ## generate implied end tags                ## generate implied end tags
4464                if ({                while ({
4465                     dd => 1, dt => 1, li => 1, p => 1,                        dd => 1, dt => 1, li => 1, p => 1,
4466                     td => 1, th => 1, tr => 1,                       }->{$self->{open_elements}->[-1]->[1]}) {
4467                     tbody => 1, tfoot=> 1, thead => 1,                  !!!cp ('t224');
4468                    }->{$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;  
4469                }                }
4470    
4471                if ($self->{open_elements}->[-1]->[1] ne 'table') {                if ($self->{open_elements}->[-1]->[1] ne 'table') {
4472                    !!!cp ('t225');
4473    ## ISSUE: Can this case be reached?
4474                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
4475                  } else {
4476                    !!!cp ('t226');
4477                }                }
4478    
4479                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4480                  pop @{$open_tables};
4481    
4482                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4483    
4484                ## reprocess                ## reprocess
4485                redo B;                redo B;
4486          } else {          } else {
4487              !!!cp ('t227');
4488            !!!parse-error (type => 'in table:'.$token->{tag_name});            !!!parse-error (type => 'in table:'.$token->{tag_name});
4489    
4490            $insert = $insert_to_foster;            $insert = $insert_to_foster;
# Line 4187  sub _tree_construction_main ($) { Line 4498  sub _tree_construction_main ($) {
4498                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4499                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4500                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4501                      !!!cp ('t228');
4502                    $i = $_;                    $i = $_;
4503                    last INSCOPE;                    last INSCOPE;
4504                  } elsif ({                  } elsif ({
4505                            table => 1, html => 1,                            table => 1, html => 1,
4506                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4507                      !!!cp ('t229');
4508                    last INSCOPE;                    last INSCOPE;
4509                  }                  }
4510                } # INSCOPE                } # INSCOPE
4511                unless (defined $i) {                unless (defined $i) {
4512                    !!!cp ('t230');
4513                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4514                  ## Ignore the token                  ## Ignore the token
4515                  !!!next-token;                  !!!next-token;
4516                  redo B;                  redo B;
4517                  } else {
4518                    !!!cp ('t232');
4519                }                }
4520    
4521                ## Clear back to table row context                ## Clear back to table row context
4522                while (not {                while (not {
4523                  tr => 1, html => 1,                  tr => 1, html => 1,
4524                }->{$self->{open_elements}->[-1]->[1]}) {                }->{$self->{open_elements}->[-1]->[1]}) {
4525                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!cp ('t231');
4526    ## ISSUE: Can this state be reached?
4527                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4528                }                }
4529    
# Line 4222  sub _tree_construction_main ($) { Line 4539  sub _tree_construction_main ($) {
4539                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4540                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4541                    if ($node->[1] eq 'tr') {                    if ($node->[1] eq 'tr') {
4542                        !!!cp ('t233');
4543                      $i = $_;                      $i = $_;
4544                      last INSCOPE;                      last INSCOPE;
4545                    } elsif ({                    } elsif ({
4546                              table => 1, html => 1,                              table => 1, html => 1,
4547                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4548                        !!!cp ('t234');
4549                      last INSCOPE;                      last INSCOPE;
4550                    }                    }
4551                  } # INSCOPE                  } # INSCOPE
4552                  unless (defined $i) {                  unless (defined $i) {
4553                      !!!cp ('t235');
4554    ## TODO: The following is wrong.
4555                    !!!parse-error (type => 'unmatched end tag:'.$token->{type});                    !!!parse-error (type => 'unmatched end tag:'.$token->{type});
4556                    ## Ignore the token                    ## Ignore the token
4557                    !!!next-token;                    !!!next-token;
# Line 4241  sub _tree_construction_main ($) { Line 4562  sub _tree_construction_main ($) {
4562                  while (not {                  while (not {
4563                    tr => 1, html => 1,                    tr => 1, html => 1,
4564                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4565                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t236');
4566    ## ISSUE: Can this state be reached?
4567                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4568                  }                  }
4569                                    
# Line 4258  sub _tree_construction_main ($) { Line 4580  sub _tree_construction_main ($) {
4580                    if ({                    if ({
4581                         tbody => 1, thead => 1, tfoot => 1,                         tbody => 1, thead => 1, tfoot => 1,
4582                        }->{$node->[1]}) {                        }->{$node->[1]}) {
4583                        !!!cp ('t237');
4584                      $i = $_;                      $i = $_;
4585                      last INSCOPE;                      last INSCOPE;
4586                    } elsif ({                    } elsif ({
4587                              table => 1, html => 1,                              table => 1, html => 1,
4588                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4589                        !!!cp ('t238');
4590                      last INSCOPE;                      last INSCOPE;
4591                    }                    }
4592                  } # INSCOPE                  } # INSCOPE
4593                  unless (defined $i) {                  unless (defined $i) {
4594                      !!!cp ('t239');
4595                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                    !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4596                    ## Ignore the token                    ## Ignore the token
4597                    !!!next-token;                    !!!next-token;
# Line 4277  sub _tree_construction_main ($) { Line 4602  sub _tree_construction_main ($) {
4602                  while (not {                  while (not {
4603                    tbody => 1, tfoot => 1, thead => 1, html => 1,                    tbody => 1, tfoot => 1, thead => 1, html => 1,
4604                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4605                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t240');
4606                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4607                  }                  }
4608                                    
# Line 4293  sub _tree_construction_main ($) { Line 4618  sub _tree_construction_main ($) {
4618                  ## reprocess in the "in table" insertion mode...                  ## reprocess in the "in table" insertion mode...
4619                }                }
4620    
4621                  ## NOTE: </table> in the "in table" insertion mode.
4622                  ## When you edit the code fragment below, please ensure that
4623                  ## the code for <table> in the "in table" insertion mode
4624                  ## is synced with it.
4625    
4626                ## have a table element in table scope                ## have a table element in table scope
4627                my $i;                my $i;
4628                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4629                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4630                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4631                      !!!cp ('t241');
4632                    $i = $_;                    $i = $_;
4633                    last INSCOPE;                    last INSCOPE;
4634                  } elsif ({                  } elsif ({
4635                            table => 1, html => 1,                            table => 1, html => 1,
4636                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4637                      !!!cp ('t242');
4638                    last INSCOPE;                    last INSCOPE;
4639                  }                  }
4640                } # INSCOPE                } # INSCOPE
4641                unless (defined $i) {                unless (defined $i) {
4642                    !!!cp ('t243');
4643                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4644                  ## Ignore the token                  ## Ignore the token
4645                  !!!next-token;                  !!!next-token;
4646                  redo B;                  redo B;
4647                }                }
   
               ## 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]);  
               }  
4648                                    
4649                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4650                  pop @{$open_tables};
4651                                
4652                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
4653                                
# Line 4345  sub _tree_construction_main ($) { Line 4663  sub _tree_construction_main ($) {
4663                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4664                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4665                    if ($node->[1] eq $token->{tag_name}) {                    if ($node->[1] eq $token->{tag_name}) {
4666                        !!!cp ('t247');
4667                      $i = $_;                      $i = $_;
4668                      last INSCOPE;                      last INSCOPE;
4669                    } elsif ({                    } elsif ({
4670                              table => 1, html => 1,                              table => 1, html => 1,
4671                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4672                        !!!cp ('t248');
4673                      last INSCOPE;                      last INSCOPE;
4674                    }                    }
4675                  } # INSCOPE                  } # INSCOPE
4676                    unless (defined $i) {                    unless (defined $i) {
4677                        !!!cp ('t249');
4678                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                      !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4679                      ## Ignore the token                      ## Ignore the token
4680                      !!!next-token;                      !!!next-token;
# Line 4366  sub _tree_construction_main ($) { Line 4687  sub _tree_construction_main ($) {
4687                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4688                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
4689                    if ($node->[1] eq 'tr') {                    if ($node->[1] eq 'tr') {
4690                        !!!cp ('t250');
4691                      $i = $_;                      $i = $_;
4692                      last INSCOPE;                      last INSCOPE;
4693                    } elsif ({                    } elsif ({
4694                              table => 1, html => 1,                              table => 1, html => 1,
4695                             }->{$node->[1]}) {                             }->{$node->[1]}) {
4696                        !!!cp ('t251');
4697                      last INSCOPE;                      last INSCOPE;
4698                    }                    }
4699                  } # INSCOPE                  } # INSCOPE
4700                    unless (defined $i) {                    unless (defined $i) {
4701                        !!!cp ('t252');
4702                      !!!parse-error (type => 'unmatched end tag:tr');                      !!!parse-error (type => 'unmatched end tag:tr');
4703                      ## Ignore the token                      ## Ignore the token
4704                      !!!next-token;                      !!!next-token;
# Line 4385  sub _tree_construction_main ($) { Line 4709  sub _tree_construction_main ($) {
4709                  while (not {                  while (not {
4710                    tr => 1, html => 1,                    tr => 1, html => 1,
4711                  }->{$self->{open_elements}->[-1]->[1]}) {                  }->{$self->{open_elements}->[-1]->[1]}) {
4712                    !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                    !!!cp ('t253');
4713    ## ISSUE: Can this case be reached?
4714                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
4715                  }                  }
4716                                    
# Line 4399  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 ('t254');
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 ('t255');
4734                    last INSCOPE;                    last INSCOPE;
4735                  }                  }
4736                } # INSCOPE                } # INSCOPE
4737                unless (defined $i) {                unless (defined $i) {
4738                    !!!cp ('t256');
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 4418  sub _tree_construction_main ($) { Line 4746  sub _tree_construction_main ($) {
4746                while (not {                while (not {
4747                  tbody => 1, tfoot => 1, thead => 1, html => 1,                  tbody => 1, tfoot => 1, thead => 1, html => 1,
4748                }->{$self->{open_elements}->[-1]->[1]}) {                }->{$self->{open_elements}->[-1]->[1]}) {
4749                  !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                  !!!cp ('t257');
4750    ## ISSUE: Can this case be reached?
4751                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4752                }                }
4753    
# Line 4432  sub _tree_construction_main ($) { Line 4761  sub _tree_construction_main ($) {
4761                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM                        tr => 1, # $self->{insertion_mode} == IN_ROW_IM
4762                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM                        tbody => 1, tfoot => 1, thead => 1, # $self->{insertion_mode} == IN_TABLE_IM
4763                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4764                  !!!cp ('t258');
4765                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4766                ## Ignore the token                ## Ignore the token
4767                !!!next-token;                !!!next-token;
4768                redo B;                redo B;
4769          } else {          } else {
4770              !!!cp ('t259');
4771            !!!parse-error (type => 'in table:/'.$token->{tag_name});            !!!parse-error (type => 'in table:/'.$token->{tag_name});
4772    
4773            $insert = $insert_to_foster;            $insert = $insert_to_foster;
# Line 4450  sub _tree_construction_main ($) { Line 4781  sub _tree_construction_main ($) {
4781              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {              if ($token->{data} =~ s/^([\x09\x0A\x0B\x0C\x20]+)//) {
4782                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4783                unless (length $token->{data}) {                unless (length $token->{data}) {
4784                    !!!cp ('t260');
4785                  !!!next-token;                  !!!next-token;
4786                  redo B;                  redo B;
4787                }                }
4788              }              }
4789                            
4790                !!!cp ('t261');
4791              #              #
4792            } elsif ($token->{type} == START_TAG_TOKEN) {            } elsif ($token->{type} == START_TAG_TOKEN) {
4793              if ($token->{tag_name} eq 'col') {              if ($token->{tag_name} eq 'col') {
4794                  !!!cp ('t262');
4795                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
4796                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
4797                !!!next-token;                !!!next-token;
4798                redo B;                redo B;
4799              } else {              } else {
4800                  !!!cp ('t263');
4801                #                #
4802              }              }
4803            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
4804              if ($token->{tag_name} eq 'colgroup') {              if ($token->{tag_name} eq 'colgroup') {
4805                if ($self->{open_elements}->[-1]->[1] eq 'html') {                if ($self->{open_elements}->[-1]->[1] eq 'html') {
4806                    !!!cp ('t264');
4807                  !!!parse-error (type => 'unmatched end tag:colgroup');                  !!!parse-error (type => 'unmatched end tag:colgroup');
4808                  ## Ignore the token                  ## Ignore the token
4809                  !!!next-token;                  !!!next-token;
4810                  redo B;                  redo B;
4811                } else {                } else {
4812                    !!!cp ('t265');
4813                  pop @{$self->{open_elements}}; # colgroup                  pop @{$self->{open_elements}}; # colgroup
4814                  $self->{insertion_mode} = IN_TABLE_IM;                  $self->{insertion_mode} = IN_TABLE_IM;
4815                  !!!next-token;                  !!!next-token;
4816                  redo B;                              redo B;            
4817                }                }
4818              } elsif ($token->{tag_name} eq 'col') {              } elsif ($token->{tag_name} eq 'col') {
4819                  !!!cp ('t266');
4820                !!!parse-error (type => 'unmatched end tag:col');                !!!parse-error (type => 'unmatched end tag:col');
4821                ## Ignore the token                ## Ignore the token
4822                !!!next-token;                !!!next-token;
4823                redo B;                redo B;
4824              } else {              } else {
4825                  !!!cp ('t267');
4826                #                #
4827              }              }
4828            } else {            } else {
4829              #              die "$0: $token->{type}: Unknown token type";
4830            }            }
4831    
4832            ## As if </colgroup>            ## As if </colgroup>
4833            if ($self->{open_elements}->[-1]->[1] eq 'html') {            if ($self->{open_elements}->[-1]->[1] eq 'html') {
4834                !!!cp ('t269');
4835              !!!parse-error (type => 'unmatched end tag:colgroup');              !!!parse-error (type => 'unmatched end tag:colgroup');
4836              ## Ignore the token              ## Ignore the token
4837              !!!next-token;              !!!next-token;
4838              redo B;              redo B;
4839            } else {            } else {
4840                !!!cp ('t270');
4841              pop @{$self->{open_elements}}; # colgroup              pop @{$self->{open_elements}}; # colgroup
4842              $self->{insertion_mode} = IN_TABLE_IM;              $self->{insertion_mode} = IN_TABLE_IM;
4843              ## reprocess              ## reprocess
# Line 4504  sub _tree_construction_main ($) { Line 4845  sub _tree_construction_main ($) {
4845            }            }
4846      } elsif ($self->{insertion_mode} == IN_SELECT_IM) {      } elsif ($self->{insertion_mode} == IN_SELECT_IM) {
4847        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4848            !!!cp ('t271');
4849          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
4850          !!!next-token;          !!!next-token;
4851          redo B;          redo B;
4852        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
4853              if ($token->{tag_name} eq 'option') {              if ($token->{tag_name} eq 'option') {
4854                if ($self->{open_elements}->[-1]->[1] eq 'option') {                if ($self->{open_elements}->[-1]->[1] eq 'option') {
4855                    !!!cp ('t272');
4856                  ## As if </option>                  ## As if </option>
4857                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4858                  } else {
4859                    !!!cp ('t273');
4860                }                }
4861    
4862                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
# Line 4519  sub _tree_construction_main ($) { Line 4864  sub _tree_construction_main ($) {
4864                redo B;                redo B;
4865              } elsif ($token->{tag_name} eq 'optgroup') {              } elsif ($token->{tag_name} eq 'optgroup') {
4866                if ($self->{open_elements}->[-1]->[1] eq 'option') {                if ($self->{open_elements}->[-1]->[1] eq 'option') {
4867                    !!!cp ('t274');
4868                  ## As if </option>                  ## As if </option>
4869                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4870                  } else {
4871                    !!!cp ('t275');
4872                }                }
4873    
4874                if ($self->{open_elements}->[-1]->[1] eq 'optgroup') {                if ($self->{open_elements}->[-1]->[1] eq 'optgroup') {
4875                    !!!cp ('t276');
4876                  ## As if </optgroup>                  ## As if </optgroup>
4877                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4878                  } else {
4879                    !!!cp ('t277');
4880                }                }
4881    
4882                !!!insert-element ($token->{tag_name}, $token->{attributes});                !!!insert-element ($token->{tag_name}, $token->{attributes});
4883                !!!next-token;                !!!next-token;
4884                redo B;                redo B;
4885              } elsif ($token->{tag_name} eq 'select') {              } elsif ($token->{tag_name} eq 'select') {
4886    ## TODO: The type below is not good - <select> is replaced by </select>
4887                !!!parse-error (type => 'not closed:select');                !!!parse-error (type => 'not closed:select');
4888                ## As if </select> instead                ## As if </select> instead
4889                ## have an element in table scope                ## have an element in table scope
# Line 4539  sub _tree_construction_main ($) { Line 4891  sub _tree_construction_main ($) {
4891                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4892                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4893                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4894                      !!!cp ('t278');
4895                    $i = $_;                    $i = $_;
4896                    last INSCOPE;                    last INSCOPE;
4897                  } elsif ({                  } elsif ({
4898                            table => 1, html => 1,                            table => 1, html => 1,
4899                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4900                      !!!cp ('t279');
4901                    last INSCOPE;                    last INSCOPE;
4902                  }                  }
4903                } # INSCOPE                } # INSCOPE
4904                unless (defined $i) {                unless (defined $i) {
4905                    !!!cp ('t280');
4906                  !!!parse-error (type => 'unmatched end tag:select');                  !!!parse-error (type => 'unmatched end tag:select');
4907                  ## Ignore the token                  ## Ignore the token
4908                  !!!next-token;                  !!!next-token;
4909                  redo B;                  redo B;
4910                }                }
4911                                
4912                  !!!cp ('t281');
4913                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4914    
4915                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
# Line 4561  sub _tree_construction_main ($) { Line 4917  sub _tree_construction_main ($) {
4917                !!!next-token;                !!!next-token;
4918                redo B;                redo B;
4919          } else {          } else {
4920              !!!cp ('t282');
4921            !!!parse-error (type => 'in select:'.$token->{tag_name});            !!!parse-error (type => 'in select:'.$token->{tag_name});
4922            ## Ignore the token            ## Ignore the token
4923            !!!next-token;            !!!next-token;
# Line 4570  sub _tree_construction_main ($) { Line 4927  sub _tree_construction_main ($) {
4927              if ($token->{tag_name} eq 'optgroup') {              if ($token->{tag_name} eq 'optgroup') {
4928                if ($self->{open_elements}->[-1]->[1] eq 'option' and                if ($self->{open_elements}->[-1]->[1] eq 'option' and
4929                    $self->{open_elements}->[-2]->[1] eq 'optgroup') {                    $self->{open_elements}->[-2]->[1] eq 'optgroup') {
4930                    !!!cp ('t283');
4931                  ## As if </option>                  ## As if </option>
4932                  splice @{$self->{open_elements}}, -2;                  splice @{$self->{open_elements}}, -2;
4933                } elsif ($self->{open_elements}->[-1]->[1] eq 'optgroup') {                } elsif ($self->{open_elements}->[-1]->[1] eq 'optgroup') {
4934                    !!!cp ('t284');
4935                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4936                } else {                } else {
4937                    !!!cp ('t285');
4938                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4939                  ## Ignore the token                  ## Ignore the token
4940                }                }
# Line 4582  sub _tree_construction_main ($) { Line 4942  sub _tree_construction_main ($) {
4942                redo B;                redo B;
4943              } elsif ($token->{tag_name} eq 'option') {              } elsif ($token->{tag_name} eq 'option') {
4944                if ($self->{open_elements}->[-1]->[1] eq 'option') {                if ($self->{open_elements}->[-1]->[1] eq 'option') {
4945                    !!!cp ('t286');
4946                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
4947                } else {                } else {
4948                    !!!cp ('t287');
4949                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4950                  ## Ignore the token                  ## Ignore the token
4951                }                }
# Line 4595  sub _tree_construction_main ($) { Line 4957  sub _tree_construction_main ($) {
4957                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4958                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4959                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4960                      !!!cp ('t288');
4961                    $i = $_;                    $i = $_;
4962                    last INSCOPE;                    last INSCOPE;
4963                  } elsif ({                  } elsif ({
4964                            table => 1, html => 1,                            table => 1, html => 1,
4965                           }->{$node->[1]}) {                           }->{$node->[1]}) {
4966                      !!!cp ('t289');
4967                    last INSCOPE;                    last INSCOPE;
4968                  }                  }
4969                } # INSCOPE                } # INSCOPE
4970                unless (defined $i) {                unless (defined $i) {
4971                    !!!cp ('t290');
4972                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                  !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4973                  ## Ignore the token                  ## Ignore the token
4974                  !!!next-token;                  !!!next-token;
4975                  redo B;                  redo B;
4976                }                }
4977                                
4978                  !!!cp ('t291');
4979                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4980    
4981                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
# Line 4620  sub _tree_construction_main ($) { Line 4986  sub _tree_construction_main ($) {
4986                        caption => 1, table => 1, tbody => 1,                        caption => 1, table => 1, tbody => 1,
4987                        tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,                        tfoot => 1, thead => 1, tr => 1, td => 1, th => 1,
4988                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
4989    ## TODO: The following is wrong?
4990                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
4991                                
4992                ## have an element in table scope                ## have an element in table scope
# Line 4627  sub _tree_construction_main ($) { Line 4994  sub _tree_construction_main ($) {
4994                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
4995                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
4996                  if ($node->[1] eq $token->{tag_name}) {                  if ($node->[1] eq $token->{tag_name}) {
4997                      !!!cp ('t292');
4998                    $i = $_;                    $i = $_;
4999                    last INSCOPE;                    last INSCOPE;
5000                  } elsif ({                  } elsif ({
5001                            table => 1, html => 1,                            table => 1, html => 1,
5002                           }->{$node->[1]}) {                           }->{$node->[1]}) {
5003                      !!!cp ('t293');
5004                    last INSCOPE;                    last INSCOPE;
5005                  }                  }
5006                } # INSCOPE                } # INSCOPE
5007                unless (defined $i) {                unless (defined $i) {
5008                    !!!cp ('t294');
5009                  ## Ignore the token                  ## Ignore the token
5010                  !!!next-token;                  !!!next-token;
5011                  redo B;                  redo B;
# Line 4647  sub _tree_construction_main ($) { Line 5017  sub _tree_construction_main ($) {
5017                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5018                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5019                  if ($node->[1] eq 'select') {                  if ($node->[1] eq 'select') {
5020                      !!!cp ('t295');
5021                    $i = $_;                    $i = $_;
5022                    last INSCOPE;                    last INSCOPE;
5023                  } elsif ({                  } elsif ({
5024                            table => 1, html => 1,                            table => 1, html => 1,
5025                           }->{$node->[1]}) {                           }->{$node->[1]}) {
5026    ## ISSUE: Can this state be reached?
5027                      !!!cp ('t296');
5028                    last INSCOPE;                    last INSCOPE;
5029                  }                  }
5030                } # INSCOPE                } # INSCOPE
5031                unless (defined $i) {                unless (defined $i) {
5032                    !!!cp ('t297');
5033    ## TODO: The following error type is correct?
5034                  !!!parse-error (type => 'unmatched end tag:select');                  !!!parse-error (type => 'unmatched end tag:select');
5035                  ## Ignore the </select> token                  ## Ignore the </select> token
5036                  !!!next-token; ## TODO: ok?                  !!!next-token; ## TODO: ok?
5037                  redo B;                  redo B;
5038                }                }
5039                                
5040                  !!!cp ('t298');
5041                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
5042    
5043                $self->_reset_insertion_mode;                $self->_reset_insertion_mode;
# Line 4669  sub _tree_construction_main ($) { Line 5045  sub _tree_construction_main ($) {
5045                ## reprocess                ## reprocess
5046                redo B;                redo B;
5047          } else {          } else {
5048              !!!cp ('t299');
5049            !!!parse-error (type => 'in select:/'.$token->{tag_name});            !!!parse-error (type => 'in select:/'.$token->{tag_name});
5050            ## Ignore the token            ## Ignore the token
5051            !!!next-token;            !!!next-token;
# Line 4687  sub _tree_construction_main ($) { Line 5064  sub _tree_construction_main ($) {
5064            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5065                        
5066            unless (length $token->{data}) {            unless (length $token->{data}) {
5067                !!!cp ('t300');
5068              !!!next-token;              !!!next-token;
5069              redo B;              redo B;
5070            }            }
5071          }          }
5072                    
5073          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5074              !!!cp ('t301');
5075            !!!parse-error (type => 'after html:#character');            !!!parse-error (type => 'after html:#character');
5076    
5077            ## Reprocess in the "main" phase, "after body" insertion mode...            ## Reprocess in the "after body" insertion mode.
5078            } else {
5079              !!!cp ('t302');
5080          }          }
5081                    
5082          ## "after body" insertion mode          ## "after body" insertion mode
# Line 4706  sub _tree_construction_main ($) { Line 5087  sub _tree_construction_main ($) {
5087          redo B;          redo B;
5088        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5089          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5090              !!!cp ('t303');
5091            !!!parse-error (type => 'after html:'.$token->{tag_name});            !!!parse-error (type => 'after html:'.$token->{tag_name});
5092                        
5093            ## Reprocess in the "main" phase, "after body" insertion mode...            ## Reprocess in the "after body" insertion mode.
5094            } else {
5095              !!!cp ('t304');
5096          }          }
5097    
5098          ## "after body" insertion mode          ## "after body" insertion mode
# Line 4719  sub _tree_construction_main ($) { Line 5103  sub _tree_construction_main ($) {
5103          redo B;          redo B;
5104        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5105          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {          if ($self->{insertion_mode} == AFTER_HTML_BODY_IM) {
5106              !!!cp ('t305');
5107            !!!parse-error (type => 'after html:/'.$token->{tag_name});            !!!parse-error (type => 'after html:/'.$token->{tag_name});
5108                        
5109            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
5110            ## Reprocess in the "main" phase, "after body" insertion mode...            ## Reprocess in the "after body" insertion mode.
5111            } else {
5112              !!!cp ('t306');
5113          }          }
5114    
5115          ## "after body" insertion mode          ## "after body" insertion mode
5116          if ($token->{tag_name} eq 'html') {          if ($token->{tag_name} eq 'html') {
5117            if (defined $self->{inner_html_node}) {            if (defined $self->{inner_html_node}) {
5118                !!!cp ('t307');
5119              !!!parse-error (type => 'unmatched end tag:html');              !!!parse-error (type => 'unmatched end tag:html');
5120              ## Ignore the token              ## Ignore the token
5121              !!!next-token;              !!!next-token;
5122              redo B;              redo B;
5123            } else {            } else {
5124                !!!cp ('t308');
5125              $self->{insertion_mode} = AFTER_HTML_BODY_IM;              $self->{insertion_mode} = AFTER_HTML_BODY_IM;
5126              !!!next-token;              !!!next-token;
5127              redo B;              redo B;
5128            }            }
5129          } else {          } else {
5130              !!!cp ('t309');
5131            !!!parse-error (type => 'after body:/'.$token->{tag_name});            !!!parse-error (type => 'after body:/'.$token->{tag_name});
5132    
5133            $self->{insertion_mode} = IN_BODY_IM;            $self->{insertion_mode} = IN_BODY_IM;
# Line 4753  sub _tree_construction_main ($) { Line 5143  sub _tree_construction_main ($) {
5143            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);            $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
5144                        
5145            unless (length $token->{data}) {            unless (length $token->{data}) {
5146                !!!cp ('t310');
5147              !!!next-token;              !!!next-token;
5148              redo B;              redo B;
5149            }            }
# Line 4760  sub _tree_construction_main ($) { Line 5151  sub _tree_construction_main ($) {
5151                    
5152          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {          if ($token->{data} =~ s/^[^\x09\x0A\x0B\x0C\x20]+//) {
5153            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5154                !!!cp ('t311');
5155              !!!parse-error (type => 'in frameset:#character');              !!!parse-error (type => 'in frameset:#character');
5156            } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {            } elsif ($self->{insertion_mode} == AFTER_FRAMESET_IM) {
5157                !!!cp ('t312');
5158              !!!parse-error (type => 'after frameset:#character');              !!!parse-error (type => 'after frameset:#character');
5159            } else { # "after html frameset"            } else { # "after html frameset"
5160                !!!cp ('t313');
5161              !!!parse-error (type => 'after html:#character');              !!!parse-error (type => 'after html:#character');
5162    
5163              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
5164              ## Reprocess in the "main" phase, "after frameset"...              ## Reprocess in the "after frameset" insertion mode.
5165              !!!parse-error (type => 'after frameset:#character');              !!!parse-error (type => 'after frameset:#character');
5166            }            }
5167                        
5168            ## Ignore the token.            ## Ignore the token.
5169            if (length $token->{data}) {            if (length $token->{data}) {
5170                !!!cp ('t314');
5171              ## reprocess the rest of characters              ## reprocess the rest of characters
5172            } else {            } else {
5173                !!!cp ('t315');
5174              !!!next-token;              !!!next-token;
5175            }            }
5176            redo B;            redo B;
# Line 4783  sub _tree_construction_main ($) { Line 5179  sub _tree_construction_main ($) {
5179          die qq[$0: Character "$token->{data}"];          die qq[$0: Character "$token->{data}"];
5180        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
5181          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
5182              !!!cp ('t316');
5183            !!!parse-error (type => 'after html:'.$token->{tag_name});            !!!parse-error (type => 'after html:'.$token->{tag_name});
5184    
5185            $self->{insertion_mode} = AFTER_FRAMESET_IM;            $self->{insertion_mode} = AFTER_FRAMESET_IM;
5186            ## Process in the "main" phase, "after frameset" insertion mode...            ## Process in the "after frameset" insertion mode.
5187          }          } else {
5188              !!!cp ('t317');
5189            }
5190    
5191          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
5192              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5193              !!!cp ('t318');
5194            !!!insert-element ($token->{tag_name}, $token->{attributes});            !!!insert-element ($token->{tag_name}, $token->{attributes});
5195            !!!next-token;            !!!next-token;
5196            redo B;            redo B;
5197          } elsif ($token->{tag_name} eq 'frame' and          } elsif ($token->{tag_name} eq 'frame' and
5198                   $self->{insertion_mode} == IN_FRAMESET_IM) {                   $self->{insertion_mode} == IN_FRAMESET_IM) {
5199              !!!cp ('t319');
5200            !!!insert-element ($token->{tag_name}, $token->{attributes});            !!!insert-element ($token->{tag_name}, $token->{attributes});
5201            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
5202            !!!next-token;            !!!next-token;
5203            redo B;            redo B;
5204          } elsif ($token->{tag_name} eq 'noframes') {          } elsif ($token->{tag_name} eq 'noframes') {
5205              !!!cp ('t320');
5206            ## NOTE: As if in body.            ## NOTE: As if in body.
5207            $parse_rcdata->(CDATA_CONTENT_MODEL, $insert_to_current);            $parse_rcdata->(CDATA_CONTENT_MODEL, $insert_to_current);
5208            redo B;            redo B;
5209          } else {          } else {
5210            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5211                !!!cp ('t321');
5212              !!!parse-error (type => 'in frameset:'.$token->{tag_name});              !!!parse-error (type => 'in frameset:'.$token->{tag_name});
5213            } else {            } else {
5214                !!!cp ('t322');
5215              !!!parse-error (type => 'after frameset:'.$token->{tag_name});              !!!parse-error (type => 'after frameset:'.$token->{tag_name});
5216            }            }
5217            ## Ignore the token            ## Ignore the token
# Line 4816  sub _tree_construction_main ($) { Line 5220  sub _tree_construction_main ($) {
5220          }          }
5221        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
5222          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {          if ($self->{insertion_mode} == AFTER_HTML_FRAMESET_IM) {
5223              !!!cp ('t323');
5224            !!!parse-error (type => 'after html:/'.$token->{tag_name});            !!!parse-error (type => 'after html:/'.$token->{tag_name});
5225    
5226            $self->{insertion_mode} = AFTER_FRAMESET_IM;            $self->{insertion_mode} = AFTER_FRAMESET_IM;
5227            ## Process in the "main" phase, "after frameset" insertion mode...            ## Process in the "after frameset" insertion mode.
5228            } else {
5229              !!!cp ('t324');
5230          }          }
5231    
5232          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
5233              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
5234            if ($self->{open_elements}->[-1]->[1] eq 'html' and            if ($self->{open_elements}->[-1]->[1] eq 'html' and
5235                @{$self->{open_elements}} == 1) {                @{$self->{open_elements}} == 1) {
5236                !!!cp ('t325');
5237              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5238              ## Ignore the token              ## Ignore the token
5239              !!!next-token;              !!!next-token;
5240            } else {            } else {
5241                !!!cp ('t326');
5242              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
5243              !!!next-token;              !!!next-token;
5244            }            }
5245    
5246            if (not defined $self->{inner_html_node} and            if (not defined $self->{inner_html_node} and
5247                $self->{open_elements}->[-1]->[1] ne 'frameset') {                $self->{open_elements}->[-1]->[1] ne 'frameset') {
5248                !!!cp ('t327');
5249              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
5250              } else {
5251                !!!cp ('t328');
5252            }            }
5253            redo B;            redo B;
5254          } elsif ($token->{tag_name} eq 'html' and          } elsif ($token->{tag_name} eq 'html' and
5255                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {                   $self->{insertion_mode} == AFTER_FRAMESET_IM) {
5256              !!!cp ('t329');
5257            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;            $self->{insertion_mode} = AFTER_HTML_FRAMESET_IM;
5258            !!!next-token;            !!!next-token;
5259            redo B;            redo B;
5260          } else {          } else {
5261            if ($self->{insertion_mode} == IN_FRAMESET_IM) {            if ($self->{insertion_mode} == IN_FRAMESET_IM) {
5262                !!!cp ('t330');
5263              !!!parse-error (type => 'in frameset:/'.$token->{tag_name});              !!!parse-error (type => 'in frameset:/'.$token->{tag_name});
5264            } else {            } else {
5265                !!!cp ('t331');
5266              !!!parse-error (type => 'after frameset:/'.$token->{tag_name});              !!!parse-error (type => 'after frameset:/'.$token->{tag_name});
5267            }            }
5268            ## Ignore the token            ## Ignore the token
# Line 4866  sub _tree_construction_main ($) { Line 5281  sub _tree_construction_main ($) {
5281      ## "in body" insertion mode      ## "in body" insertion mode
5282      if ($token->{type} == START_TAG_TOKEN) {      if ($token->{type} == START_TAG_TOKEN) {
5283        if ($token->{tag_name} eq 'script') {        if ($token->{tag_name} eq 'script') {
5284            !!!cp ('t332');
5285          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5286          $script_start_tag->($insert);          $script_start_tag->($insert);
5287          redo B;          redo B;
5288        } elsif ($token->{tag_name} eq 'style') {        } elsif ($token->{tag_name} eq 'style') {
5289            !!!cp ('t333');
5290          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5291          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);
5292          redo B;          redo B;
5293        } elsif ({        } elsif ({
5294                  base => 1, link => 1,                  base => 1, link => 1,
5295                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5296            !!!cp ('t334');
5297          ## 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
5298          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5299          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 5306  sub _tree_construction_main ($) {
5306    
5307          unless ($self->{confident}) {          unless ($self->{confident}) {
5308            if ($token->{attributes}->{charset}) { ## TODO: And if supported            if ($token->{attributes}->{charset}) { ## TODO: And if supported
5309                !!!cp ('t335');
5310              $self->{change_encoding}              $self->{change_encoding}
5311                  ->($self, $token->{attributes}->{charset}->{value});                  ->($self, $token->{attributes}->{charset}->{value});
5312                            
# Line 4902  sub _tree_construction_main ($) { Line 5321  sub _tree_construction_main ($) {
5321                      [\x09-\x0D\x20]*=                      [\x09-\x0D\x20]*=
5322                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|                      [\x09-\x0D\x20]*(?>"([^"]*)"|'([^']*)'|
5323                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {                      ([^"'\x09-\x0D\x20][^\x09-\x0D\x20]*))/x) {
5324                  !!!cp ('t336');
5325                $self->{change_encoding}                $self->{change_encoding}
5326                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);                    ->($self, defined $1 ? $1 : defined $2 ? $2 : $3);
5327                $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 5332  sub _tree_construction_main ($) {
5332            }            }
5333          } else {          } else {
5334            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
5335                !!!cp ('t337');
5336              $meta_el->[0]->get_attribute_node_ns (undef, 'charset')              $meta_el->[0]->get_attribute_node_ns (undef, 'charset')
5337                  ->set_user_data (manakai_has_reference =>                  ->set_user_data (manakai_has_reference =>
5338                                       $token->{attributes}->{charset}                                       $token->{attributes}->{charset}
5339                                           ->{has_reference});                                           ->{has_reference});
5340            }            }
5341            if ($token->{attributes}->{content}) {            if ($token->{attributes}->{content}) {
5342                !!!cp ('t338');
5343              $meta_el->[0]->get_attribute_node_ns (undef, 'content')              $meta_el->[0]->get_attribute_node_ns (undef, 'content')
5344                  ->set_user_data (manakai_has_reference =>                  ->set_user_data (manakai_has_reference =>
5345                                       $token->{attributes}->{content}                                       $token->{attributes}->{content}
# Line 4928  sub _tree_construction_main ($) { Line 5350  sub _tree_construction_main ($) {
5350          !!!next-token;          !!!next-token;
5351          redo B;          redo B;
5352        } elsif ($token->{tag_name} eq 'title') {        } elsif ($token->{tag_name} eq 'title') {
5353            !!!cp ('t341');
5354          !!!parse-error (type => 'in body:title');          !!!parse-error (type => 'in body:title');
5355          ## NOTE: This is an "as if in head" code clone          ## NOTE: This is an "as if in head" code clone
5356          $parse_rcdata->(RCDATA_CONTENT_MODEL, sub {          $parse_rcdata->(RCDATA_CONTENT_MODEL, sub {
5357            if (defined $self->{head_element}) {            if (defined $self->{head_element}) {
5358                !!!cp ('t339');
5359              $self->{head_element}->append_child ($_[0]);              $self->{head_element}->append_child ($_[0]);
5360            } else {            } else {
5361                !!!cp ('t340');
5362              $insert->($_[0]);              $insert->($_[0]);
5363            }            }
5364          });          });
# Line 4943  sub _tree_construction_main ($) { Line 5368  sub _tree_construction_main ($) {
5368                                
5369          if (@{$self->{open_elements}} == 1 or          if (@{$self->{open_elements}} == 1 or
5370              $self->{open_elements}->[1]->[1] ne 'body') {              $self->{open_elements}->[1]->[1] ne 'body') {
5371              !!!cp ('t342');
5372            ## Ignore the token            ## Ignore the token
5373          } else {          } else {
5374            my $body_el = $self->{open_elements}->[1]->[0];            my $body_el = $self->{open_elements}->[1]->[0];
5375            for my $attr_name (keys %{$token->{attributes}}) {            for my $attr_name (keys %{$token->{attributes}}) {
5376              unless ($body_el->has_attribute_ns (undef, $attr_name)) {              unless ($body_el->has_attribute_ns (undef, $attr_name)) {
5377                  !!!cp ('t343');
5378                $body_el->set_attribute_ns                $body_el->set_attribute_ns
5379                  (undef, [undef, $attr_name],                  (undef, [undef, $attr_name],
5380                   $token->{attributes}->{$attr_name}->{value});                   $token->{attributes}->{$attr_name}->{value});
# Line 4958  sub _tree_construction_main ($) { Line 5385  sub _tree_construction_main ($) {
5385          redo B;          redo B;
5386        } elsif ({        } elsif ({
5387                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
5388                  div => 1, dl => 1, fieldset => 1, listing => 1,                  div => 1, dl => 1, fieldset => 1,
5389                  menu => 1, ol => 1, p => 1, ul => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
5390                    listing => 1, menu => 1, ol => 1, p => 1, ul => 1,
5391                  pre => 1,                  pre => 1,
5392                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5393          ## has a p element in scope          ## has a p element in scope
5394          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5395            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5396                !!!cp ('t344');
5397              !!!back-token;              !!!back-token;
5398              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5399              redo B;              redo B;
# Line 4972  sub _tree_construction_main ($) { Line 5401  sub _tree_construction_main ($) {
5401                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5402                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5403                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5404                !!!cp ('t345');
5405              last INSCOPE;              last INSCOPE;
5406            }            }
5407          } # INSCOPE          } # INSCOPE
# Line 4982  sub _tree_construction_main ($) { Line 5412  sub _tree_construction_main ($) {
5412            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5413              $token->{data} =~ s/^\x0A//;              $token->{data} =~ s/^\x0A//;
5414              unless (length $token->{data}) {              unless (length $token->{data}) {
5415                  !!!cp ('t346');
5416                !!!next-token;                !!!next-token;
5417                } else {
5418                  !!!cp ('t349');
5419              }              }
5420              } else {
5421                !!!cp ('t348');
5422            }            }
5423          } else {          } else {
5424              !!!cp ('t347');
5425            !!!next-token;            !!!next-token;
5426          }          }
5427          redo B;          redo B;
5428        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
5429          if (defined $self->{form_element}) {          if (defined $self->{form_element}) {
5430              !!!cp ('t350');
5431            !!!parse-error (type => 'in form:form');            !!!parse-error (type => 'in form:form');
5432            ## Ignore the token            ## Ignore the token
5433            !!!next-token;            !!!next-token;
# Line 4999  sub _tree_construction_main ($) { Line 5436  sub _tree_construction_main ($) {
5436            ## has a p element in scope            ## has a p element in scope
5437            INSCOPE: for (reverse @{$self->{open_elements}}) {            INSCOPE: for (reverse @{$self->{open_elements}}) {
5438              if ($_->[1] eq 'p') {              if ($_->[1] eq 'p') {
5439                  !!!cp ('t351');
5440                !!!back-token;                !!!back-token;
5441                $token = {type => END_TAG_TOKEN, tag_name => 'p'};                $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5442                redo B;                redo B;
# Line 5006  sub _tree_construction_main ($) { Line 5444  sub _tree_construction_main ($) {
5444                        table => 1, caption => 1, td => 1, th => 1,                        table => 1, caption => 1, td => 1, th => 1,
5445                        button => 1, marquee => 1, object => 1, html => 1,                        button => 1, marquee => 1, object => 1, html => 1,
5446                       }->{$_->[1]}) {                       }->{$_->[1]}) {
5447                  !!!cp ('t352');
5448                last INSCOPE;                last INSCOPE;
5449              }              }
5450            } # INSCOPE            } # INSCOPE
# Line 5019  sub _tree_construction_main ($) { Line 5458  sub _tree_construction_main ($) {
5458          ## has a p element in scope          ## has a p element in scope
5459          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5460            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5461                !!!cp ('t353');
5462              !!!back-token;              !!!back-token;
5463              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5464              redo B;              redo B;
# Line 5026  sub _tree_construction_main ($) { Line 5466  sub _tree_construction_main ($) {
5466                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5467                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5468                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5469                !!!cp ('t354');
5470              last INSCOPE;              last INSCOPE;
5471            }            }
5472          } # INSCOPE          } # INSCOPE
# Line 5037  sub _tree_construction_main ($) { Line 5478  sub _tree_construction_main ($) {
5478            ## Step 2            ## Step 2
5479            if ($node->[1] eq 'li') {            if ($node->[1] eq 'li') {
5480              if ($i != -1) {              if ($i != -1) {
5481                  !!!cp ('t355');
5482                !!!parse-error (type => 'end tag missing:'.                !!!parse-error (type => 'end tag missing:'.
5483                                $self->{open_elements}->[-1]->[1]);                                $self->{open_elements}->[-1]->[1]);
5484                } else {
5485                  !!!cp ('t356');
5486              }              }
5487              splice @{$self->{open_elements}}, $i;              splice @{$self->{open_elements}}, $i;
5488              last LI;              last LI;
5489              } else {
5490                !!!cp ('t357');
5491            }            }
5492                        
5493            ## Step 3            ## Step 3
# Line 5050  sub _tree_construction_main ($) { Line 5496  sub _tree_construction_main ($) {
5496                ($special_category->{$node->[1]} or                ($special_category->{$node->[1]} or
5497                 $scoping_category->{$node->[1]}) and                 $scoping_category->{$node->[1]}) and
5498                $node->[1] ne 'address' and $node->[1] ne 'div') {                $node->[1] ne 'address' and $node->[1] ne 'div') {
5499                !!!cp ('t358');
5500              last LI;              last LI;
5501            }            }
5502                        
5503              !!!cp ('t359');
5504            ## Step 4            ## Step 4
5505            $i--;            $i--;
5506            $node = $self->{open_elements}->[$i];            $node = $self->{open_elements}->[$i];
# Line 5066  sub _tree_construction_main ($) { Line 5514  sub _tree_construction_main ($) {
5514          ## has a p element in scope          ## has a p element in scope
5515          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5516            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5517                !!!cp ('t360');
5518              !!!back-token;              !!!back-token;
5519              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5520              redo B;              redo B;
# Line 5073  sub _tree_construction_main ($) { Line 5522  sub _tree_construction_main ($) {
5522                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5523                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5524                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5525                !!!cp ('t361');
5526              last INSCOPE;              last INSCOPE;
5527            }            }
5528          } # INSCOPE          } # INSCOPE
# Line 5084  sub _tree_construction_main ($) { Line 5534  sub _tree_construction_main ($) {
5534            ## Step 2            ## Step 2
5535            if ($node->[1] eq 'dt' or $node->[1] eq 'dd') {            if ($node->[1] eq 'dt' or $node->[1] eq 'dd') {
5536              if ($i != -1) {              if ($i != -1) {
5537                  !!!cp ('t362');
5538                !!!parse-error (type => 'end tag missing:'.                !!!parse-error (type => 'end tag missing:'.
5539                                $self->{open_elements}->[-1]->[1]);                                $self->{open_elements}->[-1]->[1]);
5540                } else {
5541                  !!!cp ('t363');
5542              }              }
5543              splice @{$self->{open_elements}}, $i;              splice @{$self->{open_elements}}, $i;
5544              last LI;              last LI;
5545              } else {
5546                !!!cp ('t364');
5547            }            }
5548                        
5549            ## Step 3            ## Step 3
# Line 5097  sub _tree_construction_main ($) { Line 5552  sub _tree_construction_main ($) {
5552                ($special_category->{$node->[1]} or                ($special_category->{$node->[1]} or
5553                 $scoping_category->{$node->[1]}) and                 $scoping_category->{$node->[1]}) and
5554                $node->[1] ne 'address' and $node->[1] ne 'div') {                $node->[1] ne 'address' and $node->[1] ne 'div') {
5555                !!!cp ('t365');
5556              last LI;              last LI;
5557            }            }
5558                        
5559              !!!cp ('t366');
5560            ## Step 4            ## Step 4
5561            $i--;            $i--;
5562            $node = $self->{open_elements}->[$i];            $node = $self->{open_elements}->[$i];
# Line 5113  sub _tree_construction_main ($) { Line 5570  sub _tree_construction_main ($) {
5570          ## has a p element in scope          ## has a p element in scope
5571          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5572            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5573                !!!cp ('t367');
5574              !!!back-token;              !!!back-token;
5575              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5576              redo B;              redo B;
# Line 5120  sub _tree_construction_main ($) { Line 5578  sub _tree_construction_main ($) {
5578                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5579                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5580                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5581                !!!cp ('t368');
5582              last INSCOPE;              last INSCOPE;
5583            }            }
5584          } # INSCOPE          } # INSCOPE
# Line 5130  sub _tree_construction_main ($) { Line 5589  sub _tree_construction_main ($) {
5589                        
5590          !!!next-token;          !!!next-token;
5591          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;  
5592        } elsif ($token->{tag_name} eq 'a') {        } elsif ($token->{tag_name} eq 'a') {
5593          AFE: for my $i (reverse 0..$#$active_formatting_elements) {          AFE: for my $i (reverse 0..$#$active_formatting_elements) {
5594            my $node = $active_formatting_elements->[$i];            my $node = $active_formatting_elements->[$i];
5595            if ($node->[1] eq 'a') {            if ($node->[1] eq 'a') {
5596                !!!cp ('t371');
5597              !!!parse-error (type => 'in a:a');              !!!parse-error (type => 'in a:a');
5598                            
5599              !!!back-token;              !!!back-token;
# Line 5187  sub _tree_construction_main ($) { Line 5602  sub _tree_construction_main ($) {
5602                            
5603              AFE2: for (reverse 0..$#$active_formatting_elements) {              AFE2: for (reverse 0..$#$active_formatting_elements) {
5604                if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {                if ($active_formatting_elements->[$_]->[0] eq $node->[0]) {
5605                    !!!cp ('t372');
5606                  splice @$active_formatting_elements, $_, 1;                  splice @$active_formatting_elements, $_, 1;
5607                  last AFE2;                  last AFE2;
5608                }                }
5609              } # AFE2              } # AFE2
5610              OE: for (reverse 0..$#{$self->{open_elements}}) {              OE: for (reverse 0..$#{$self->{open_elements}}) {
5611                if ($self->{open_elements}->[$_]->[0] eq $node->[0]) {                if ($self->{open_elements}->[$_]->[0] eq $node->[0]) {
5612                    !!!cp ('t373');
5613                  splice @{$self->{open_elements}}, $_, 1;                  splice @{$self->{open_elements}}, $_, 1;
5614                  last OE;                  last OE;
5615                }                }
5616              } # OE              } # OE
5617              last AFE;              last AFE;
5618            } elsif ($node->[0] eq '#marker') {            } elsif ($node->[0] eq '#marker') {
5619                !!!cp ('t374');
5620              last AFE;              last AFE;
5621            }            }
5622          } # AFE          } # AFE
# Line 5215  sub _tree_construction_main ($) { Line 5633  sub _tree_construction_main ($) {
5633                  s => 1, small => 1, strile => 1,                  s => 1, small => 1, strile => 1,
5634                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
5635                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5636            !!!cp ('t375');
5637          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5638                    
5639          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5229  sub _tree_construction_main ($) { Line 5648  sub _tree_construction_main ($) {
5648          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5649            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
5650            if ($node->[1] eq 'nobr') {            if ($node->[1] eq 'nobr') {
5651                !!!cp ('t376');
5652              !!!parse-error (type => 'in nobr:nobr');              !!!parse-error (type => 'in nobr:nobr');
5653              !!!back-token;              !!!back-token;
5654              $token = {type => END_TAG_TOKEN, tag_name => 'nobr'};              $token = {type => END_TAG_TOKEN, tag_name => 'nobr'};
# Line 5237  sub _tree_construction_main ($) { Line 5657  sub _tree_construction_main ($) {
5657                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5658                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5659                     }->{$node->[1]}) {                     }->{$node->[1]}) {
5660                !!!cp ('t377');
5661              last INSCOPE;              last INSCOPE;
5662            }            }
5663          } # INSCOPE          } # INSCOPE
# Line 5251  sub _tree_construction_main ($) { Line 5672  sub _tree_construction_main ($) {
5672          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5673            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
5674            if ($node->[1] eq 'button') {            if ($node->[1] eq 'button') {
5675                !!!cp ('t378');
5676              !!!parse-error (type => 'in button:button');              !!!parse-error (type => 'in button:button');
5677              !!!back-token;              !!!back-token;
5678              $token = {type => END_TAG_TOKEN, tag_name => 'button'};              $token = {type => END_TAG_TOKEN, tag_name => 'button'};
# Line 5259  sub _tree_construction_main ($) { Line 5681  sub _tree_construction_main ($) {
5681                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5682                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5683                     }->{$node->[1]}) {                     }->{$node->[1]}) {
5684                !!!cp ('t379');
5685              last INSCOPE;              last INSCOPE;
5686            }            }
5687          } # INSCOPE          } # INSCOPE
# Line 5266  sub _tree_construction_main ($) { Line 5689  sub _tree_construction_main ($) {
5689          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5690                        
5691          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5692    
5693            ## TODO: associate with $self->{form_element} if defined
5694    
5695          push @$active_formatting_elements, ['#marker', ''];          push @$active_formatting_elements, ['#marker', ''];
5696    
5697          !!!next-token;          !!!next-token;
5698          redo B;          redo B;
5699        } elsif ($token->{tag_name} eq 'marquee' or        } elsif ($token->{tag_name} eq 'marquee' or
5700                 $token->{tag_name} eq 'object') {                 $token->{tag_name} eq 'object') {
5701            !!!cp ('t380');
5702          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5703                    
5704          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5280  sub _tree_construction_main ($) { Line 5707  sub _tree_construction_main ($) {
5707          !!!next-token;          !!!next-token;
5708          redo B;          redo B;
5709        } elsif ($token->{tag_name} eq 'xmp') {        } elsif ($token->{tag_name} eq 'xmp') {
5710            !!!cp ('t381');
5711          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5712          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);
5713          redo B;          redo B;
# Line 5287  sub _tree_construction_main ($) { Line 5715  sub _tree_construction_main ($) {
5715          ## has a p element in scope          ## has a p element in scope
5716          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5717            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5718                !!!cp ('t382');
5719              !!!back-token;              !!!back-token;
5720              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5721              redo B;              redo B;
# Line 5294  sub _tree_construction_main ($) { Line 5723  sub _tree_construction_main ($) {
5723                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5724                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5725                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5726                !!!cp ('t383');
5727              last INSCOPE;              last INSCOPE;
5728            }            }
5729          } # INSCOPE          } # INSCOPE
5730                        
5731          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5732                      push @{$open_tables}, [$self->{open_elements}->[-1]->[0]];
5733    
5734          $self->{insertion_mode} = IN_TABLE_IM;          $self->{insertion_mode} = IN_TABLE_IM;
5735                        
5736          !!!next-token;          !!!next-token;
# Line 5310  sub _tree_construction_main ($) { Line 5741  sub _tree_construction_main ($) {
5741                  image => 1,                  image => 1,
5742                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5743          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
5744              !!!cp ('t384');
5745            !!!parse-error (type => 'image');            !!!parse-error (type => 'image');
5746            $token->{tag_name} = 'img';            $token->{tag_name} = 'img';
5747            } else {
5748              !!!cp ('t385');
5749          }          }
5750    
5751          ## 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 5760  sub _tree_construction_main ($) {
5760          ## has a p element in scope          ## has a p element in scope
5761          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
5762            if ($_->[1] eq 'p') {            if ($_->[1] eq 'p') {
5763                !!!cp ('t386');
5764              !!!back-token;              !!!back-token;
5765              $token = {type => END_TAG_TOKEN, tag_name => 'p'};              $token = {type => END_TAG_TOKEN, tag_name => 'p'};
5766              redo B;              redo B;
# Line 5333  sub _tree_construction_main ($) { Line 5768  sub _tree_construction_main ($) {
5768                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5769                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5770                     }->{$_->[1]}) {                     }->{$_->[1]}) {
5771                !!!cp ('t387');
5772              last INSCOPE;              last INSCOPE;
5773            }            }
5774          } # INSCOPE          } # INSCOPE
# Line 5343  sub _tree_construction_main ($) { Line 5779  sub _tree_construction_main ($) {
5779          !!!next-token;          !!!next-token;
5780          redo B;          redo B;
5781        } elsif ($token->{tag_name} eq 'input') {        } elsif ($token->{tag_name} eq 'input') {
5782            !!!cp ('t388');
5783          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5784                    
5785          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5355  sub _tree_construction_main ($) { Line 5792  sub _tree_construction_main ($) {
5792          !!!parse-error (type => 'isindex');          !!!parse-error (type => 'isindex');
5793                    
5794          if (defined $self->{form_element}) {          if (defined $self->{form_element}) {
5795              !!!cp ('t389');
5796            ## Ignore the token            ## Ignore the token
5797            !!!next-token;            !!!next-token;
5798            redo B;            redo B;
# Line 5374  sub _tree_construction_main ($) { Line 5812  sub _tree_construction_main ($) {
5812                          {type => START_TAG_TOKEN, tag_name => 'label'},                          {type => START_TAG_TOKEN, tag_name => 'label'},
5813                         );                         );
5814            if ($prompt_attr) {            if ($prompt_attr) {
5815                !!!cp ('t390');
5816              push @tokens, {type => CHARACTER_TOKEN, data => $prompt_attr->{value}};              push @tokens, {type => CHARACTER_TOKEN, data => $prompt_attr->{value}};
5817            } else {            } else {
5818                !!!cp ('t391');
5819              push @tokens, {type => CHARACTER_TOKEN,              push @tokens, {type => CHARACTER_TOKEN,
5820                             data => 'This is a searchable index. Insert your search keywords here: '}; # SHOULD                             data => 'This is a searchable index. Insert your search keywords here: '}; # SHOULD
5821              ## TODO: make this configurable              ## TODO: make this configurable
# Line 5407  sub _tree_construction_main ($) { Line 5847  sub _tree_construction_main ($) {
5847          if ($token->{type} == CHARACTER_TOKEN) {          if ($token->{type} == CHARACTER_TOKEN) {
5848            $token->{data} =~ s/^\x0A//;            $token->{data} =~ s/^\x0A//;
5849            unless (length $token->{data}) {            unless (length $token->{data}) {
5850                !!!cp ('t392');
5851              !!!next-token;              !!!next-token;
5852              } else {
5853                !!!cp ('t393');
5854            }            }
5855            } else {
5856              !!!cp ('t394');
5857          }          }
5858          while ($token->{type} == CHARACTER_TOKEN) {          while ($token->{type} == CHARACTER_TOKEN) {
5859              !!!cp ('t395');
5860            $text .= $token->{data};            $text .= $token->{data};
5861            !!!next-token;            !!!next-token;
5862          }          }
5863          if (length $text) {          if (length $text) {
5864              !!!cp ('t396');
5865            $el->manakai_append_text ($text);            $el->manakai_append_text ($text);
5866          }          }
5867                    
# Line 5422  sub _tree_construction_main ($) { Line 5869  sub _tree_construction_main ($) {
5869                    
5870          if ($token->{type} == END_TAG_TOKEN and          if ($token->{type} == END_TAG_TOKEN and
5871              $token->{tag_name} eq $tag_name) {              $token->{tag_name} eq $tag_name) {
5872              !!!cp ('t397');
5873            ## Ignore the token            ## Ignore the token
5874          } else {          } else {
5875              !!!cp ('t398');
5876            !!!parse-error (type => 'in RCDATA:#'.$token->{type});            !!!parse-error (type => 'in RCDATA:#'.$token->{type});
5877          }          }
5878          !!!next-token;          !!!next-token;
# Line 5434  sub _tree_construction_main ($) { Line 5883  sub _tree_construction_main ($) {
5883                  noframes => 1,                  noframes => 1,
5884                  noscript => 0, ## TODO: 1 if scripting is enabled                  noscript => 0, ## TODO: 1 if scripting is enabled
5885                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5886            !!!cp ('t399');
5887          ## NOTE: There is an "as if in body" code clone.          ## NOTE: There is an "as if in body" code clone.
5888          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);          $parse_rcdata->(CDATA_CONTENT_MODEL, $insert);
5889          redo B;          redo B;
5890        } elsif ($token->{tag_name} eq 'select') {        } elsif ($token->{tag_name} eq 'select') {
5891            !!!cp ('t400');
5892          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5893                    
5894          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
5895    
5896            ## TODO: associate with $self->{form_element} if defined
5897                    
5898          $self->{insertion_mode} = IN_SELECT_IM;          $self->{insertion_mode} = IN_SELECT_IM;
5899          !!!next-token;          !!!next-token;
# Line 5451  sub _tree_construction_main ($) { Line 5904  sub _tree_construction_main ($) {
5904                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
5905                  thead => 1, tr => 1,                  thead => 1, tr => 1,
5906                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
5907            !!!cp ('t401');
5908          !!!parse-error (type => 'in body:'.$token->{tag_name});          !!!parse-error (type => 'in body:'.$token->{tag_name});
5909          ## Ignore the token          ## Ignore the token
5910          !!!next-token;          !!!next-token;
# Line 5458  sub _tree_construction_main ($) { Line 5912  sub _tree_construction_main ($) {
5912                    
5913          ## ISSUE: An issue on HTML5 new elements in the spec.          ## ISSUE: An issue on HTML5 new elements in the spec.
5914        } else {        } else {
5915            !!!cp ('t402');
5916          $reconstruct_active_formatting_elements->($insert_to_current);          $reconstruct_active_formatting_elements->($insert_to_current);
5917                    
5918          !!!insert-element-t ($token->{tag_name}, $token->{attributes});          !!!insert-element-t ($token->{tag_name}, $token->{attributes});
# Line 5475  sub _tree_construction_main ($) { Line 5930  sub _tree_construction_main ($) {
5930                         th => 1, tr => 1, body => 1, html => 1,                         th => 1, tr => 1, body => 1, html => 1,
5931                       tbody => 1, tfoot => 1, thead => 1,                       tbody => 1, tfoot => 1, thead => 1,
5932                      }->{$_->[1]}) {                      }->{$_->[1]}) {
5933                  !!!cp ('t403');
5934                !!!parse-error (type => 'not closed:'.$_->[1]);                !!!parse-error (type => 'not closed:'.$_->[1]);
5935                } else {
5936                  !!!cp ('t404');
5937              }              }
5938            }            }
5939    
# Line 5483  sub _tree_construction_main ($) { Line 5941  sub _tree_construction_main ($) {
5941            !!!next-token;            !!!next-token;
5942            redo B;            redo B;
5943          } else {          } else {
5944              !!!cp ('t405');
5945            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5946            ## Ignore the token            ## Ignore the token
5947            !!!next-token;            !!!next-token;
# Line 5492  sub _tree_construction_main ($) { Line 5951  sub _tree_construction_main ($) {
5951          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') {
5952            ## ISSUE: There is an issue in the spec.            ## ISSUE: There is an issue in the spec.
5953            if ($self->{open_elements}->[-1]->[1] ne 'body') {            if ($self->{open_elements}->[-1]->[1] ne 'body') {
5954                !!!cp ('t406');
5955              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[1]->[1]);              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[1]->[1]);
5956              } else {
5957                !!!cp ('t407');
5958            }            }
5959            $self->{insertion_mode} = AFTER_BODY_IM;            $self->{insertion_mode} = AFTER_BODY_IM;
5960            ## reprocess            ## reprocess
5961            redo B;            redo B;
5962          } else {          } else {
5963              !!!cp ('t408');
5964            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5965            ## Ignore the token            ## Ignore the token
5966            !!!next-token;            !!!next-token;
# Line 5507  sub _tree_construction_main ($) { Line 5970  sub _tree_construction_main ($) {
5970                  address => 1, blockquote => 1, center => 1, dir => 1,                  address => 1, blockquote => 1, center => 1, dir => 1,
5971                  div => 1, dl => 1, fieldset => 1, listing => 1,                  div => 1, dl => 1, fieldset => 1, listing => 1,
5972                  menu => 1, ol => 1, pre => 1, ul => 1,                  menu => 1, ol => 1, pre => 1, ul => 1,
                 p => 1,  
5973                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
5974                  button => 1, marquee => 1, object => 1,                  button => 1, marquee => 1, object => 1,
5975                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 5516  sub _tree_construction_main ($) { Line 5978  sub _tree_construction_main ($) {
5978          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5979            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
5980            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] eq $token->{tag_name}) {
5981              ## 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;  
             }  
5982              $i = $_;              $i = $_;
5983              last INSCOPE unless $token->{tag_name} eq 'p';              last INSCOPE;
5984            } elsif ({            } elsif ({
5985                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
5986                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
5987                     }->{$node->[1]}) {                     }->{$node->[1]}) {
5988                !!!cp ('t411');
5989              last INSCOPE;              last INSCOPE;
5990            }            }
5991          } # INSCOPE          } # INSCOPE
5992            
5993          if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {          unless (defined $i) { # has an element in scope
5994            if (defined $i) {            !!!cp ('t413');
5995              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
5996            } else {
5997              ## Step 1. generate implied end tags
5998              while ({
5999                      dd => ($token->{tag_name} ne 'dd'),
6000                      dt => ($token->{tag_name} ne 'dt'),
6001                      li => ($token->{tag_name} ne 'li'),
6002                      p => 1,
6003                     }->{$self->{open_elements}->[-1]->[1]}) {
6004                !!!cp ('t409');
6005                pop @{$self->{open_elements}};
6006              }
6007    
6008              ## Step 2.
6009              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6010                !!!cp ('t412');
6011              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);              !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6012            } else {            } else {
6013              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});              !!!cp ('t414');
6014            }            }
6015          }  
6016                      ## Step 3.
         if (defined $i) {  
6017            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
6018          } elsif ($token->{tag_name} eq 'p') {  
6019            ## As if <p>, then reprocess the current token            ## Step 4.
6020            my $el;            $clear_up_to_marker->()
6021            !!!create-element ($el, 'p');                if {
6022            $insert->($el);                  button => 1, marquee => 1, object => 1,
6023                  }->{$token->{tag_name}};
6024          }          }
         $clear_up_to_marker->()  
           if {  
             button => 1, marquee => 1, object => 1,  
           }->{$token->{tag_name}};  
6025          !!!next-token;          !!!next-token;
6026          redo B;          redo B;
6027        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
6028            undef $self->{form_element};
6029    
6030          ## has an element in scope          ## has an element in scope
6031            my $i;
6032          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6033            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
6034            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] eq $token->{tag_name}) {
6035              ## generate implied end tags              !!!cp ('t418');
6036              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;  
             }  
6037              last INSCOPE;              last INSCOPE;
6038            } elsif ({            } elsif ({
6039                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
6040                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
6041                     }->{$node->[1]}) {                     }->{$node->[1]}) {
6042                !!!cp ('t419');
6043              last INSCOPE;              last INSCOPE;
6044            }            }
6045          } # INSCOPE          } # INSCOPE
6046            
6047          if ($self->{open_elements}->[-1]->[1] eq $token->{tag_name}) {          unless (defined $i) { # has an element in scope
6048            pop @{$self->{open_elements}};            !!!cp ('t421');
         } else {  
6049            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6050            } else {
6051              ## Step 1. generate implied end tags
6052              while ({
6053                      dd => 1, dt => 1, li => 1, p => 1,
6054                     }->{$self->{open_elements}->[-1]->[1]}) {
6055                !!!cp ('t417');
6056                pop @{$self->{open_elements}};
6057              }
6058              
6059              ## Step 2.
6060              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6061                !!!cp ('t417.1');
6062                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6063              } else {
6064                !!!cp ('t420');
6065              }  
6066              
6067              ## Step 3.
6068              splice @{$self->{open_elements}}, $i;
6069          }          }
6070    
         undef $self->{form_element};  
6071          !!!next-token;          !!!next-token;
6072          redo B;          redo B;
6073        } elsif ({        } elsif ({
# Line 5606  sub _tree_construction_main ($) { Line 6080  sub _tree_construction_main ($) {
6080            if ({            if ({
6081                 h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                 h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
6082                }->{$node->[1]}) {                }->{$node->[1]}) {
6083              ## 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;  
             }  
6084              $i = $_;              $i = $_;
6085              last INSCOPE;              last INSCOPE;
6086            } elsif ({            } elsif ({
6087                      table => 1, caption => 1, td => 1, th => 1,                      table => 1, caption => 1, td => 1, th => 1,
6088                      button => 1, marquee => 1, object => 1, html => 1,                      button => 1, marquee => 1, object => 1, html => 1,
6089                     }->{$node->[1]}) {                     }->{$node->[1]}) {
6090                !!!cp ('t424');
6091              last INSCOPE;              last INSCOPE;
6092            }            }
6093          } # INSCOPE          } # INSCOPE
6094            
6095          if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {          unless (defined $i) { # has an element in scope
6096              !!!cp ('t425.1');
6097            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});            !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6098            } else {
6099              ## Step 1. generate implied end tags
6100              while ({
6101                      dd => 1, dt => 1, li => 1, p => 1,
6102                     }->{$self->{open_elements}->[-1]->[1]}) {
6103                !!!cp ('t422');
6104                pop @{$self->{open_elements}};
6105              }
6106              
6107              ## Step 2.
6108              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6109                !!!cp ('t425');
6110                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6111              } else {
6112                !!!cp ('t426');
6113              }
6114    
6115              ## Step 3.
6116              splice @{$self->{open_elements}}, $i;
6117          }          }
6118                    
6119          splice @{$self->{open_elements}}, $i if defined $i;          !!!next-token;
6120            redo B;
6121          } elsif ($token->{tag_name} eq 'p') {
6122            ## has an element in scope
6123            my $i;
6124            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6125              my $node = $self->{open_elements}->[$_];
6126              if ($node->[1] eq $token->{tag_name}) {
6127                !!!cp ('t410.1');
6128                $i = $_;
6129                last INSCOPE;
6130              } elsif ({
6131                        table => 1, caption => 1, td => 1, th => 1,
6132                        button => 1, marquee => 1, object => 1, html => 1,
6133                       }->{$node->[1]}) {
6134                !!!cp ('t411.1');
6135                last INSCOPE;
6136              }
6137            } # INSCOPE
6138    
6139            if (defined $i) {
6140              if ($self->{open_elements}->[-1]->[1] ne $token->{tag_name}) {
6141                !!!cp ('t412.1');
6142                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6143              } else {
6144                !!!cp ('t414.1');
6145              }
6146    
6147              splice @{$self->{open_elements}}, $i;
6148            } else {
6149              !!!cp ('t413.1');
6150              !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6151    
6152              !!!cp ('t415.1');
6153              ## As if <p>, then reprocess the current token
6154              my $el;
6155              !!!create-element ($el, 'p');
6156              $insert->($el);
6157              ## NOTE: Not inserted into |$self->{open_elements}|.
6158            }
6159    
6160          !!!next-token;          !!!next-token;
6161          redo B;          redo B;
6162        } elsif ({        } elsif ({
# Line 5640  sub _tree_construction_main ($) { Line 6165  sub _tree_construction_main ($) {
6165                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strile => 1,
6166                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
6167                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6168            !!!cp ('t427');
6169          $formatting_end_tag->($token->{tag_name});          $formatting_end_tag->($token->{tag_name});
6170          redo B;          redo B;
6171        } elsif ($token->{tag_name} eq 'br') {        } elsif ($token->{tag_name} eq 'br') {
6172            !!!cp ('t428');
6173          !!!parse-error (type => 'unmatched end tag:br');          !!!parse-error (type => 'unmatched end tag:br');
6174    
6175          ## As if <br>          ## As if <br>
# Line 5667  sub _tree_construction_main ($) { Line 6194  sub _tree_construction_main ($) {
6194                  table => 1, textarea => 1, wbr => 1,                  table => 1, textarea => 1, wbr => 1,
6195                  noscript => 0, ## TODO: if scripting is enabled                  noscript => 0, ## TODO: if scripting is enabled
6196                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6197            !!!cp ('t429');
6198          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});          !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6199          ## Ignore the token          ## Ignore the token
6200          !!!next-token;          !!!next-token;
# Line 5684  sub _tree_construction_main ($) { Line 6212  sub _tree_construction_main ($) {
6212            if ($node->[1] eq $token->{tag_name}) {            if ($node->[1] eq $token->{tag_name}) {
6213              ## Step 1              ## Step 1
6214              ## generate implied end tags              ## generate implied end tags
6215              if ({              while ({
6216                   dd => 1, dt => 1, li => 1, p => 1,                      dd => 1, dt => 1, li => 1, p => 1,
6217                   td => 1, th => 1, tr => 1,                     }->{$self->{open_elements}->[-1]->[1]}) {
6218                   tbody => 1, tfoot => 1, thead => 1,                !!!cp ('t430');
6219                  }->{$self->{open_elements}->[-1]->[1]}) {                ## ISSUE: Can this case be reached?
6220                !!!back-token;                pop @{$self->{open_elements}};
               $token = {type => END_TAG_TOKEN,  
                         tag_name => $self->{open_elements}->[-1]->[1]}; # MUST  
               redo B;  
6221              }              }
6222                    
6223              ## Step 2              ## Step 2
6224              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {              if ($token->{tag_name} ne $self->{open_elements}->[-1]->[1]) {
6225                  !!!cp ('t431');
6226                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
6227                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);                !!!parse-error (type => 'not closed:'.$self->{open_elements}->[-1]->[1]);
6228                } else {
6229                  !!!cp ('t432');
6230              }              }
6231                            
6232              ## Step 3              ## Step 3
# Line 5712  sub _tree_construction_main ($) { Line 6240  sub _tree_construction_main ($) {
6240                  #not $phrasing_category->{$node->[1]} and                  #not $phrasing_category->{$node->[1]} and
6241                  ($special_category->{$node->[1]} or                  ($special_category->{$node->[1]} or
6242                   $scoping_category->{$node->[1]})) {                   $scoping_category->{$node->[1]})) {
6243                  !!!cp ('t433');
6244                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});                !!!parse-error (type => 'unmatched end tag:'.$token->{tag_name});
6245                ## Ignore the token                ## Ignore the token
6246                !!!next-token;                !!!next-token;
6247                last S2;                last S2;
6248              }              }
6249    
6250                !!!cp ('t434');
6251            }            }
6252                        
6253            ## Step 4            ## Step 4
# Line 5732  sub _tree_construction_main ($) { Line 6263  sub _tree_construction_main ($) {
6263      redo B;      redo B;
6264    } # B    } # B
6265    
   ## 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  
   
6266    ## Stop parsing # MUST    ## Stop parsing # MUST
6267        
6268    ## TODO: script stuffs    ## TODO: script stuffs
# Line 5778  sub set_inner_html ($$$) { Line 6304  sub set_inner_html ($$$) {
6304      my $p = $class->new;      my $p = $class->new;
6305      $p->{document} = $doc;      $p->{document} = $doc;
6306    
6307      ## Step 9 # MUST      ## Step 8 # MUST
6308      my $i = 0;      my $i = 0;
6309      my $line = 1;      my $line = 1;
6310      my $column = 0;      my $column = 0;
# Line 5795  sub set_inner_html ($$$) { Line 6321  sub set_inner_html ($$$) {
6321        if ($self->{next_char} == 0x000A) { # LF        if ($self->{next_char} == 0x000A) { # LF
6322          $line++;          $line++;
6323          $column = 0;          $column = 0;
6324            !!!cp ('i1');
6325        } elsif ($self->{next_char} == 0x000D) { # CR        } elsif ($self->{next_char} == 0x000D) { # CR
6326          $i++ if substr ($$s, $i, 1) eq "\x0A";          $i++ if substr ($$s, $i, 1) eq "\x0A";
6327          $self->{next_char} = 0x000A; # LF # MUST          $self->{next_char} = 0x000A; # LF # MUST
6328          $line++;          $line++;
6329          $column = 0;          $column = 0;
6330            !!!cp ('i2');
6331        } elsif ($self->{next_char} > 0x10FFFF) {        } elsif ($self->{next_char} > 0x10FFFF) {
6332          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
6333            !!!cp ('i3');
6334        } elsif ($self->{next_char} == 0x0000) { # NULL        } elsif ($self->{next_char} == 0x0000) { # NULL
6335            !!!cp ('i4');
6336          !!!parse-error (type => 'NULL');          !!!parse-error (type => 'NULL');
6337          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST          $self->{next_char} = 0xFFFD; # REPLACEMENT CHARACTER # MUST
6338        }        }
# Line 5841  sub set_inner_html ($$$) { Line 6371  sub set_inner_html ($$$) {
6371    
6372      $p->{inner_html_node} = [$node, $node_ln];      $p->{inner_html_node} = [$node, $node_ln];
6373    
6374      ## Step 4      ## Step 3
6375      my $root = $doc->create_element_ns      my $root = $doc->create_element_ns
6376        ('http://www.w3.org/1999/xhtml', [undef, 'html']);        ('http://www.w3.org/1999/xhtml', [undef, 'html']);
6377    
6378      ## Step 5 # MUST      ## Step 4 # MUST
6379      $doc->append_child ($root);      $doc->append_child ($root);
6380    
6381      ## Step 6 # MUST      ## Step 5 # MUST
6382      push @{$p->{open_elements}}, [$root, 'html'];      push @{$p->{open_elements}}, [$root, 'html'];
6383    
6384      undef $p->{head_element};      undef $p->{head_element};
6385    
6386      ## Step 7 # MUST      ## Step 6 # MUST
6387      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;
6388    
6389      ## Step 8 # MUST      ## Step 7 # MUST
6390      my $anode = $node;      my $anode = $node;
6391      AN: while (defined $anode) {      AN: while (defined $anode) {
6392        if ($anode->node_type == 1) {        if ($anode->node_type == 1) {
6393          my $nsuri = $anode->namespace_uri;          my $nsuri = $anode->namespace_uri;
6394          if (defined $nsuri and $nsuri eq 'http://www.w3.org/1999/xhtml') {          if (defined $nsuri and $nsuri eq 'http://www.w3.org/1999/xhtml') {
6395            if ($anode->manakai_local_name eq 'form') {            if ($anode->manakai_local_name eq 'form') {
6396                !!!cp ('i5');
6397              $p->{form_element} = $anode;              $p->{form_element} = $anode;
6398              last AN;              last AN;
6399            }            }
# Line 5871  sub set_inner_html ($$$) { Line 6402  sub set_inner_html ($$$) {
6402        $anode = $anode->parent_node;        $anode = $anode->parent_node;
6403      } # AN      } # AN
6404            
6405      ## Step 3 # MUST      ## Step 9 # MUST
     ## Step 10 # MUST  
6406      {      {
6407        my $self = $p;        my $self = $p;
6408        !!!next-token;        !!!next-token;
6409      }      }
6410      $p->_tree_construction_main;      $p->_tree_construction_main;
6411    
6412      ## Step 11 # MUST      ## Step 10 # MUST
6413      my @cn = @{$node->child_nodes};      my @cn = @{$node->child_nodes};
6414      for (@cn) {      for (@cn) {
6415        $node->remove_child ($_);        $node->remove_child ($_);
6416      }      }
6417      ## ISSUE: mutation events? read-only?      ## ISSUE: mutation events? read-only?
6418    
6419      ## Step 12 # MUST      ## Step 11 # MUST
6420      @cn = @{$root->child_nodes};      @cn = @{$root->child_nodes};
6421      for (@cn) {      for (@cn) {
6422        $this_doc->adopt_node ($_);        $this_doc->adopt_node ($_);

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24