/[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.217 by wakaba, Sun Jul 5 05:13:13 2009 UTC revision 1.243 by wakaba, Sun Sep 6 13:52:06 2009 UTC
# Line 179  my $el_category = { Line 179  my $el_category = {
179    dt => DTDD_EL,    dt => DTDD_EL,
180    em => FORMATTING_EL,    em => FORMATTING_EL,
181    embed => MISC_SPECIAL_EL,    embed => MISC_SPECIAL_EL,
   eventsource => MISC_SPECIAL_EL,  
182    fieldset => MISC_SPECIAL_EL,    fieldset => MISC_SPECIAL_EL,
183    figure => MISC_SPECIAL_EL,    figure => MISC_SPECIAL_EL,
184    font => FORMATTING_EL,    font => FORMATTING_EL,
# Line 195  my $el_category = { Line 194  my $el_category = {
194    h6 => HEADING_EL,    h6 => HEADING_EL,
195    head => MISC_SPECIAL_EL,    head => MISC_SPECIAL_EL,
196    header => MISC_SPECIAL_EL,    header => MISC_SPECIAL_EL,
197      hgroup => MISC_SPECIAL_EL,
198    hr => MISC_SPECIAL_EL,    hr => MISC_SPECIAL_EL,
199    html => HTML_EL,    html => HTML_EL,
200    i => FORMATTING_EL,    i => FORMATTING_EL,
# Line 203  my $el_category = { Line 203  my $el_category = {
203    #image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec.    #image => MISC_SPECIAL_EL, ## NOTE: Commented out in the spec.
204    input => MISC_SPECIAL_EL,    input => MISC_SPECIAL_EL,
205    isindex => MISC_SPECIAL_EL,    isindex => MISC_SPECIAL_EL,
206      ## XXX keygen? (Whether a void element is in Special or not does not
207      ## affect to the processing, however.)
208    li => LI_EL,    li => LI_EL,
209    link => MISC_SPECIAL_EL,    link => MISC_SPECIAL_EL,
210    listing => MISC_SPECIAL_EL,    listing => MISC_SPECIAL_EL,
# Line 247  my $el_category = { Line 249  my $el_category = {
249    u => FORMATTING_EL,    u => FORMATTING_EL,
250    ul => MISC_SPECIAL_EL,    ul => MISC_SPECIAL_EL,
251    wbr => MISC_SPECIAL_EL,    wbr => MISC_SPECIAL_EL,
252      xmp => MISC_SPECIAL_EL,
253  };  };
254    
255  my $el_category_f = {  my $el_category_f = {
# Line 647  sub parse_char_stream ($$$;$$) { Line 650  sub parse_char_stream ($$$;$$) {
650    
651    ## NOTE: |set_inner_html| copies most of this method's code    ## NOTE: |set_inner_html| copies most of this method's code
652    
653      ## Confidence: irrelevant.
654    $self->{confident} = 1 unless exists $self->{confident};    $self->{confident} = 1 unless exists $self->{confident};
655    
656    $self->{document}->input_encoding ($self->{input_encoding})    $self->{document}->input_encoding ($self->{input_encoding})
657        if defined $self->{input_encoding};        if defined $self->{input_encoding};
658  ## TODO: |{input_encoding}| is needless?  ## TODO: |{input_encoding}| is needless?
# Line 864  sub _initialize_tree_constructor ($) { Line 869  sub _initialize_tree_constructor ($) {
869    $self->{document}->manakai_is_html (1); # MUST    $self->{document}->manakai_is_html (1); # MUST
870    $self->{document}->set_user_data (manakai_source_line => 1);    $self->{document}->set_user_data (manakai_source_line => 1);
871    $self->{document}->set_user_data (manakai_source_column => 1);    $self->{document}->set_user_data (manakai_source_column => 1);
872    
873      $self->{frameset_ok} = 1;
874  } # _initialize_tree_constructor  } # _initialize_tree_constructor
875    
876  sub _terminate_tree_constructor ($) {  sub _terminate_tree_constructor ($) {
# Line 911  sub _tree_construction_initial ($) { Line 918  sub _tree_construction_initial ($) {
918    
919    INITIAL: {    INITIAL: {
920      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
921        ## NOTE: Conformance checkers MAY, instead of reporting "not HTML5"        ## NOTE: Conformance checkers MAY, instead of reporting "not
922        ## error, switch to a conformance checking mode for another        ## HTML5" error, switch to a conformance checking mode for
923        ## language.        ## another language.  (We don't support such mode switchings; it
924          ## is nonsense to do anything different from what browsers do.)
925        my $doctype_name = $token->{name};        my $doctype_name = $token->{name};
926        $doctype_name = '' unless defined $doctype_name;        $doctype_name = '' unless defined $doctype_name;
927        $doctype_name =~ tr/a-z/A-Z/; # ASCII case-insensitive        my $doctype = $self->{document}->create_document_type_definition
928        if (not defined $token->{name} or # <!DOCTYPE>            ($doctype_name);
929            defined $token->{sysid}) {  
930          $doctype_name =~ tr/A-Z/a-z/; # ASCII case-insensitive
931          if ($doctype_name ne 'html') {
932          !!!cp ('t1');          !!!cp ('t1');
933          !!!parse-error (type => 'not HTML5', token => $token);          !!!parse-error (type => 'not HTML5', token => $token);
934        } elsif ($doctype_name ne 'HTML') {        } elsif (defined $token->{pubid}) {
935          !!!cp ('t2');          !!!cp ('t2');
936            ## XXX Obsolete permitted DOCTYPEs
937          !!!parse-error (type => 'not HTML5', token => $token);          !!!parse-error (type => 'not HTML5', token => $token);
938        } elsif (defined $token->{pubid}) {        } elsif (defined $token->{sysid}) {
939          if ($token->{pubid} eq 'XSLT-compat') {          if ($token->{sysid} eq 'about:legacy-compat') {
940            !!!cp ('t1.2');            !!!cp ('t1.2'); ## <!DOCTYPE HTML SYSTEM "about:legacy-compat">
941            !!!parse-error (type => 'XSLT-compat', token => $token,            !!!parse-error (type => 'XSLT-compat', token => $token,
942                            level => $self->{level}->{should});                            level => $self->{level}->{should});
943          } else {          } else {
944            !!!parse-error (type => 'not HTML5', token => $token);            !!!parse-error (type => 'not HTML5', token => $token);
945          }          }
946        } else {        } else { ## <!DOCTYPE HTML>
947          !!!cp ('t3');          !!!cp ('t3');
948          #          #
949        }        }
950                
       my $doctype = $self->{document}->create_document_type_definition  
         ($token->{name}); ## ISSUE: If name is missing (e.g. <!DOCTYPE>)?  
951        ## NOTE: Default value for both |public_id| and |system_id| attributes        ## NOTE: Default value for both |public_id| and |system_id| attributes
952        ## are empty strings, so that we don't set any value in missing cases.        ## are empty strings, so that we don't set any value in missing cases.
953        $doctype->public_id ($token->{pubid}) if defined $token->{pubid};        $doctype->public_id ($token->{pubid}) if defined $token->{pubid};
954        $doctype->system_id ($token->{sysid}) if defined $token->{sysid};        $doctype->system_id ($token->{sysid}) if defined $token->{sysid};
955    
956        ## NOTE: Other DocumentType attributes are null or empty lists.        ## NOTE: Other DocumentType attributes are null or empty lists.
957        ## In Firefox3, |internalSubset| attribute is set to the empty        ## In Firefox3, |internalSubset| attribute is set to the empty
958        ## string, while |null| is an allowed value for the attribute        ## string, while |null| is an allowed value for the attribute
959        ## according to DOM3 Core.        ## according to DOM3 Core.
960        $self->{document}->append_child ($doctype);        $self->{document}->append_child ($doctype);
961                
962        if ($token->{quirks} or $doctype_name ne 'HTML') {        if ($token->{quirks} or $doctype_name ne 'html') {
963          !!!cp ('t4');          !!!cp ('t4');
964          $self->{document}->manakai_compat_mode ('quirks');          $self->{document}->manakai_compat_mode ('quirks');
965        } elsif (defined $token->{pubid}) {        } elsif (defined $token->{pubid}) {
# Line 1419  sub _tree_construction_main ($) { Line 1429  sub _tree_construction_main ($) {
1429      ## Step 3      ## Step 3
1430      ## TODO: Mark as "already executed", if ...      ## TODO: Mark as "already executed", if ...
1431    
1432      ## Step 4      ## Step 4 (HTML5 revision 2702)
1433      $insert->($script_el);      $insert->($script_el);
   
     ## ISSUE: $script_el is not put into the stack  
1434      push @{$self->{open_elements}}, [$script_el, $el_category->{script}];      push @{$self->{open_elements}}, [$script_el, $el_category->{script}];
1435    
1436      ## Step 5      ## Step 5
# Line 1437  sub _tree_construction_main ($) { Line 1445  sub _tree_construction_main ($) {
1445    }; # $script_start_tag    }; # $script_start_tag
1446    
1447    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.
1448    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag (OBSOLETE; unused).
1449    ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.    ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.
1450    my $open_tables = [[$self->{open_elements}->[0]->[0]]];    my $open_tables = [[$self->{open_elements}->[0]->[0]]];
1451    
# Line 1607  sub _tree_construction_main ($) { Line 1615  sub _tree_construction_main ($) {
1615                
1616        ## Step 8        ## Step 8
1617        if ($common_ancestor_node->[1] & TABLE_ROWS_EL) {        if ($common_ancestor_node->[1] & TABLE_ROWS_EL) {
1618            ## Foster parenting.
1619          my $foster_parent_element;          my $foster_parent_element;
1620          my $next_sibling;          my $next_sibling;
1621          OE: for (reverse 0..$#{$self->{open_elements}}) {          OE: for (reverse 0..$#{$self->{open_elements}}) {
1622            if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {            if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
1623                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;              !!!cp ('t65.2');
1624                               if (defined $parent and $parent->node_type == 1) {              $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
1625                                 !!!cp ('t65.1');              $next_sibling = $self->{open_elements}->[$_]->[0];
1626                                 $foster_parent_element = $parent;              undef $next_sibling
1627                                 $next_sibling = $self->{open_elements}->[$_]->[0];                  unless $next_sibling->parent_node eq $foster_parent_element;
1628                               } else {              last OE;
1629                                 !!!cp ('t65.2');            }
1630                                 $foster_parent_element          } # OE
1631                                   = $self->{open_elements}->[$_ - 1]->[0];          $foster_parent_element ||= $self->{open_elements}->[0]->[0];
1632                               }  
                              last OE;  
                            }  
                          } # OE  
                          $foster_parent_element = $self->{open_elements}->[0]->[0]  
                            unless defined $foster_parent_element;  
1633          $foster_parent_element->insert_before ($last_node->[0], $next_sibling);          $foster_parent_element->insert_before ($last_node->[0], $next_sibling);
1634          $open_tables->[-1]->[1] = 1; # tainted          $open_tables->[-1]->[1] = 1; # tainted
1635        } else {        } else {
# Line 1681  sub _tree_construction_main ($) { Line 1685  sub _tree_construction_main ($) {
1685      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);      $self->{open_elements}->[-1]->[0]->append_child ($_[0]);
1686    }; # $insert_to_current    }; # $insert_to_current
1687    
1688      ## Foster parenting.  Note that there are three "foster parenting"
1689      ## code in the parser: for elements (this one), for texts, and for
1690      ## elements in the AAA code.
1691    my $insert_to_foster = sub {    my $insert_to_foster = sub {
1692      my $child = shift;      my $child = shift;
1693      if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {      if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
# Line 1689  sub _tree_construction_main ($) { Line 1696  sub _tree_construction_main ($) {
1696        my $next_sibling;        my $next_sibling;
1697        OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
1698          if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {          if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
1699                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;            !!!cp ('t71');
1700                               if (defined $parent and $parent->node_type == 1) {            $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
1701                                 !!!cp ('t70');            $next_sibling = $self->{open_elements}->[$_]->[0];
1702                                 $foster_parent_element = $parent;            undef $next_sibling
1703                                 $next_sibling = $self->{open_elements}->[$_]->[0];                unless $next_sibling->parent_node eq $foster_parent_element;
1704                               } else {            last OE;
1705                                 !!!cp ('t71');          }
1706                                 $foster_parent_element        } # OE
1707                                   = $self->{open_elements}->[$_ - 1]->[0];        $foster_parent_element ||= $self->{open_elements}->[0]->[0];
1708                               }  
1709                               last OE;        $foster_parent_element->insert_before ($child, $next_sibling);
                            }  
                          } # OE  
                          $foster_parent_element = $self->{open_elements}->[0]->[0]  
                            unless defined $foster_parent_element;  
                          $foster_parent_element->insert_before  
                            ($child, $next_sibling);  
1710        $open_tables->[-1]->[1] = 1; # tainted        $open_tables->[-1]->[1] = 1; # tainted
1711      } else {      } else {
1712        !!!cp ('t72');        !!!cp ('t72');
# Line 1733  sub _tree_construction_main ($) { Line 1734  sub _tree_construction_main ($) {
1734    ## document.write ("b")</script>|    ## document.write ("b")</script>|
1735    
1736    B: while (1) {    B: while (1) {
1737    
1738        ## The "in table text" insertion mode.
1739        if ($self->{insertion_mode} & TABLE_IMS and
1740            not $self->{insertion_mode} & IN_FOREIGN_CONTENT_IM and
1741            not $self->{insertion_mode} & IN_CDATA_RCDATA_IM) {
1742          C: {
1743            my $s;
1744            if ($token->{type} == CHARACTER_TOKEN) {
1745              !!!cp ('t194');
1746              $self->{pending_chars} ||= [];
1747              push @{$self->{pending_chars}}, $token;
1748              !!!next-token;
1749              next B;
1750            } else {
1751              if ($self->{pending_chars}) {
1752                $s = join '', map { $_->{data} } @{$self->{pending_chars}};
1753                delete $self->{pending_chars};
1754                if ($s =~ /[^\x09\x0A\x0C\x0D\x20]/) {
1755                  !!!cp ('t195');
1756                  #
1757                } else {
1758                  !!!cp ('t195.1');
1759                  #$self->{open_elements}->[-1]->[0]->manakai_append_text ($s);
1760                  $self->{open_elements}->[-1]->[0]->append_child
1761                      ($self->{document}->create_text_node ($s));
1762                  last C;
1763                }
1764              } else {
1765                !!!cp ('t195.2');
1766                last C;
1767              }
1768            }
1769    
1770            ## Foster parenting.
1771            !!!parse-error (type => 'in table:#text', token => $token);
1772    
1773            ## NOTE: As if in body, but insert into the foster parent element.
1774            $reconstruct_active_formatting_elements->($insert_to_foster);
1775                
1776            if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
1777              # MUST
1778              my $foster_parent_element;
1779              my $next_sibling;
1780              OE: for (reverse 0..$#{$self->{open_elements}}) {
1781                if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
1782                  !!!cp ('t197');
1783                  $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
1784                  $next_sibling = $self->{open_elements}->[$_]->[0];
1785                  undef $next_sibling
1786                    unless $next_sibling->parent_node eq $foster_parent_element;
1787                  last OE;
1788                }
1789              } # OE
1790              $foster_parent_element ||= $self->{open_elements}->[0]->[0];
1791    
1792              !!!cp ('t199');
1793              $foster_parent_element->insert_before
1794                  ($self->{document}->create_text_node ($s), $next_sibling);
1795    
1796              $open_tables->[-1]->[1] = 1; # tainted
1797              $open_tables->[-1]->[2] = 1; # ~node inserted
1798            } else {
1799              ## NOTE: Fragment case or in a foster parent'ed element
1800              ## (e.g. |<table><span>a|).  In fragment case, whether the
1801              ## character is appended to existing node or a new node is
1802              ## created is irrelevant, since the foster parent'ed nodes
1803              ## are discarded and fragment parsing does not invoke any
1804              ## script.
1805              !!!cp ('t200');
1806              $self->{open_elements}->[-1]->[0]->manakai_append_text ($s);
1807            }
1808          } # C
1809        } # TABLE_IMS
1810    
1811      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
1812        !!!cp ('t73');        !!!cp ('t73');
1813        !!!parse-error (type => 'in html:#DOCTYPE', token => $token);        !!!parse-error (type => 'in html:#DOCTYPE', token => $token);
# Line 1859  sub _tree_construction_main ($) { Line 1934  sub _tree_construction_main ($) {
1934      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
1935        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
1936          !!!cp ('t87.1');          !!!cp ('t87.1');
1937    
1938          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});          $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
1939    
1940            if ($token->{data} =~ /[^\x09\x0A\x0C\x0D\x20]/) {
1941              delete $self->{frameset_ok};
1942            }
1943    
1944          !!!next-token;          !!!next-token;
1945          next B;          next B;
1946        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
# Line 1874  sub _tree_construction_main ($) { Line 1955  sub _tree_construction_main ($) {
1955          } elsif ({          } elsif ({
1956                    b => 1, big => 1, blockquote => 1, body => 1, br => 1,                    b => 1, big => 1, blockquote => 1, body => 1, br => 1,
1957                    center => 1, code => 1, dd => 1, div => 1, dl => 1, dt => 1,                    center => 1, code => 1, dd => 1, div => 1, dl => 1, dt => 1,
1958                    em => 1, embed => 1, font => 1, h1 => 1, h2 => 1, h3 => 1,                    em => 1, embed => 1, h1 => 1, h2 => 1, h3 => 1,
1959                    h4 => 1, h5 => 1, h6 => 1, head => 1, hr => 1, i => 1,                    h4 => 1, h5 => 1, h6 => 1, head => 1, hr => 1, i => 1,
1960                    img => 1, li => 1, listing => 1, menu => 1, meta => 1,                    img => 1, li => 1, listing => 1, menu => 1, meta => 1,
1961                    nobr => 1, ol => 1, p => 1, pre => 1, ruby => 1, s => 1,                    nobr => 1, ol => 1, p => 1, pre => 1, ruby => 1, s => 1,
1962                    small => 1, span => 1, strong => 1, strike => 1, sub => 1,                    small => 1, span => 1, strong => 1, strike => 1, sub => 1,
1963                    sup => 1, table => 1, tt => 1, u => 1, ul => 1, var => 1,                    sup => 1, table => 1, tt => 1, u => 1, ul => 1, var => 1,
1964                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}} or
1965                     ($token->{tag_name} eq 'font' and
1966                      ($token->{attributes}->{color} or
1967                       $token->{attributes}->{face} or
1968                       $token->{attributes}->{size}))) {
1969            !!!cp ('t87.2');            !!!cp ('t87.2');
1970            !!!parse-error (type => 'not closed',            !!!parse-error (type => 'not closed',
1971                            text => $self->{open_elements}->[-1]->[0]                            text => $self->{open_elements}->[-1]->[0]
# Line 1956  sub _tree_construction_main ($) { Line 2041  sub _tree_construction_main ($) {
2041          }          }
2042        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
2043          ## NOTE: "using the rules for secondary insertion mode" then "continue"          ## NOTE: "using the rules for secondary insertion mode" then "continue"
2044          !!!cp ('t87.5');          if ($token->{tag_name} eq 'script') {
2045          #            !!!cp ('t87.41');
2046              #
2047              ## XXXscript: Execute script here.
2048            } else {
2049              !!!cp ('t87.5');
2050              #
2051            }
2052        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
2053          !!!cp ('t87.6');          !!!cp ('t87.6');
2054          !!!parse-error (type => 'not closed',          !!!parse-error (type => 'not closed',
# Line 2044  sub _tree_construction_main ($) { Line 2135  sub _tree_construction_main ($) {
2135          ## As if <body>          ## As if <body>
2136          !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
2137          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
2138          ## reprocess          ## The "frameset-ok" flag is left unchanged in this case.
2139            ## Reporcess the token.
2140          next B;          next B;
2141        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
2142          if ($token->{tag_name} eq 'head') {          if ($token->{tag_name} eq 'head') {
# Line 2141  sub _tree_construction_main ($) { Line 2233  sub _tree_construction_main ($) {
2233            !!!ack ('t103.1');            !!!ack ('t103.1');
2234            !!!next-token;            !!!next-token;
2235            next B;            next B;
2236          } elsif ($token->{tag_name} eq 'command' or          } elsif ($token->{tag_name} eq 'command') {
                  $token->{tag_name} eq 'eventsource') {  
2237            if ($self->{insertion_mode} == IN_HEAD_IM) {            if ($self->{insertion_mode} == IN_HEAD_IM) {
2238              ## NOTE: If the insertion mode at the time of the emission              ## NOTE: If the insertion mode at the time of the emission
2239              ## of the token was "before head", $self->{insertion_mode}              ## of the token was "before head", $self->{insertion_mode}
# Line 2257  sub _tree_construction_main ($) { Line 2348  sub _tree_construction_main ($) {
2348    
2349            ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
2350            $parse_rcdata->(RCDATA_CONTENT_MODEL);            $parse_rcdata->(RCDATA_CONTENT_MODEL);
2351            ## ISSUE: A spec bug [Bug 6038]  
2352              ## NOTE: At this point the stack of open elements contain
2353              ## the |head| element (index == -2) and the |script| element
2354              ## (index == -1).  In the "after head" insertion mode the
2355              ## |head| element is inserted only for the purpose of
2356              ## providing the context for the |script| element, and
2357              ## therefore we can now and have to remove the element from
2358              ## the stack.
2359            splice @{$self->{open_elements}}, -2, 1, () # <head>            splice @{$self->{open_elements}}, -2, 1, () # <head>
2360                if ($self->{insertion_mode} & IM_MASK) == AFTER_HEAD_IM;                if ($self->{insertion_mode} & IM_MASK) == AFTER_HEAD_IM;
2361            next B;            next B;
# Line 2331  sub _tree_construction_main ($) { Line 2429  sub _tree_construction_main ($) {
2429            next B;            next B;
2430          } elsif ($token->{tag_name} eq 'body' or          } elsif ($token->{tag_name} eq 'body' or
2431                   $token->{tag_name} eq 'frameset') {                   $token->{tag_name} eq 'frameset') {
2432                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
2433                  !!!cp ('t122');              !!!cp ('t122');
2434                  ## As if </noscript>              ## As if </noscript>
2435                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2436                  !!!parse-error (type => 'in noscript',              !!!parse-error (type => 'in noscript',
2437                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
2438                                
2439                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
2440                  ## As if </head>              ## As if </head>
2441                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2442                                
2443                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2444                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {            } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
2445                  !!!cp ('t124');              !!!cp ('t124');
2446                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2447                                
2448                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2449                } else {            } else {
2450                  !!!cp ('t125');              !!!cp ('t125');
2451                }            }
2452    
2453                ## "after head" insertion mode            ## "after head" insertion mode
2454                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
2455                if ($token->{tag_name} eq 'body') {            if ($token->{tag_name} eq 'body') {
2456                  !!!cp ('t126');              !!!cp ('t126');
2457                  $self->{insertion_mode} = IN_BODY_IM;              delete $self->{frameset_ok};
2458                } elsif ($token->{tag_name} eq 'frameset') {              $self->{insertion_mode} = IN_BODY_IM;
2459                  !!!cp ('t127');            } elsif ($token->{tag_name} eq 'frameset') {
2460                  $self->{insertion_mode} = IN_FRAMESET_IM;              !!!cp ('t127');
2461                } else {              $self->{insertion_mode} = IN_FRAMESET_IM;
2462                  die "$0: tag name: $self->{tag_name}";            } else {
2463                }              die "$0: tag name: $self->{tag_name}";
2464                !!!nack ('t127.1');            }
2465                !!!next-token;            !!!nack ('t127.1');
2466                next B;            !!!next-token;
2467              } else {            next B;
2468                !!!cp ('t128');          } else {
2469                #            !!!cp ('t128');
2470              }            #
2471            }
2472    
2473              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
2474                !!!cp ('t129');                !!!cp ('t129');
# Line 2393  sub _tree_construction_main ($) { Line 2492  sub _tree_construction_main ($) {
2492                !!!cp ('t131');                !!!cp ('t131');
2493              }              }
2494    
2495              ## "after head" insertion mode          ## "after head" insertion mode
2496              ## As if <body>          ## As if <body>
2497              !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
2498              $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
2499              ## reprocess          ## The "frameset-ok" flag is not changed in this case.
2500              !!!ack-later;          ## Reprocess the token.
2501              next B;          !!!ack-later;
2502            } elsif ($token->{type} == END_TAG_TOKEN) {          next B;
2503              if ($token->{tag_name} eq 'head') {        } elsif ($token->{type} == END_TAG_TOKEN) {
2504                if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          ## "Before head", "in head", and "after head" insertion modes
2505                  !!!cp ('t132');          ## ignore most of end tags.  Exceptions are "body", "html",
2506                  ## As if <head>          ## and "br" end tags.  "Before head" and "in head" insertion
2507                  !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);          ## modes also recognize "head" end tag.  "In head noscript"
2508                  $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});          ## insertion modes ignore end tags except for "noscript" and
2509                  push @{$self->{open_elements}},          ## "br".
                     [$self->{head_element}, $el_category->{head}];  
2510    
2511                  ## Reprocess in the "in head" insertion mode...          if ($token->{tag_name} eq 'head') {
2512                  pop @{$self->{open_elements}};            if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
2513                  $self->{insertion_mode} = AFTER_HEAD_IM;              !!!cp ('t132');
2514                  !!!next-token;              ## As if <head>
2515                  next B;              !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
2516                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
2517                  !!!cp ('t133');              push @{$self->{open_elements}},
2518                  ## As if </noscript>                  [$self->{head_element}, $el_category->{head}];
2519                  pop @{$self->{open_elements}};  
2520                  !!!parse-error (type => 'in noscript:/',              ## Reprocess in the "in head" insertion mode...
2521                                  text => 'head', token => $token);              pop @{$self->{open_elements}};
2522                                $self->{insertion_mode} = AFTER_HEAD_IM;
2523                  ## Reprocess in the "in head" insertion mode...              !!!next-token;
2524                  pop @{$self->{open_elements}};              next B;
2525                  $self->{insertion_mode} = AFTER_HEAD_IM;            } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
2526                  !!!next-token;              !!!cp ('t133');
2527                  next B;              #
2528                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {            } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
2529                  !!!cp ('t134');              !!!cp ('t134');
2530                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2531                  $self->{insertion_mode} = AFTER_HEAD_IM;              $self->{insertion_mode} = AFTER_HEAD_IM;
2532                  !!!next-token;              !!!next-token;
2533                  next B;              next B;
2534                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
2535                  !!!cp ('t134.1');              !!!cp ('t134.1');
2536                  !!!parse-error (type => 'unmatched end tag', text => 'head',              #
2537                                  token => $token);            } else {
2538                  ## Ignore the token              die "$0: $self->{insertion_mode}: Unknown insertion mode";
2539                  !!!next-token;            }
2540                  next B;          } elsif ($token->{tag_name} eq 'noscript') {
2541                } else {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
2542                  die "$0: $self->{insertion_mode}: Unknown insertion mode";              !!!cp ('t136');
2543                }              pop @{$self->{open_elements}};
2544              } elsif ($token->{tag_name} eq 'noscript') {              $self->{insertion_mode} = IN_HEAD_IM;
2545                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              !!!next-token;
2546                  !!!cp ('t136');              next B;
2547                  pop @{$self->{open_elements}};            } else {
2548                  $self->{insertion_mode} = IN_HEAD_IM;              !!!cp ('t138');
2549                  !!!next-token;              #
2550                  next B;            }
2551                } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM or          } elsif ({
2552                         $self->{insertion_mode} == AFTER_HEAD_IM) {              body => ($self->{insertion_mode} != IN_HEAD_NOSCRIPT_IM),
2553                  !!!cp ('t137');              html => ($self->{insertion_mode} != IN_HEAD_NOSCRIPT_IM),
2554                  !!!parse-error (type => 'unmatched end tag',              br => 1,
2555                                  text => 'noscript', token => $token);          }->{$token->{tag_name}}) {
2556                  ## Ignore the token ## ISSUE: An issue in the spec.            if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
2557                  !!!next-token;              !!!cp ('t142.2');
2558                  next B;              ## (before head) as if <head>, (in head) as if </head>
2559                } else {              !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);
2560                  !!!cp ('t138');              $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});
2561                  #              $self->{insertion_mode} = AFTER_HEAD_IM;
               }  
             } elsif ({  
                       body => 1, html => 1,  
                      }->{$token->{tag_name}}) {  
               ## TODO: This branch is entirely redundant.  
               if ($self->{insertion_mode} == BEFORE_HEAD_IM or  
                   $self->{insertion_mode} == IN_HEAD_IM or  
                   $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {  
                 !!!cp ('t140');  
                 !!!parse-error (type => 'unmatched end tag',  
                                 text => $token->{tag_name}, token => $token);  
                 ## Ignore the token  
                 !!!next-token;  
                 next B;  
               } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {  
                 !!!cp ('t140.1');  
                 !!!parse-error (type => 'unmatched end tag',  
                                 text => $token->{tag_name}, token => $token);  
                 ## Ignore the token  
                 !!!next-token;  
                 next B;  
               } else {  
                 die "$0: $self->{insertion_mode}: Unknown insertion mode";  
               }  
             } elsif ($token->{tag_name} eq 'p') {  
               !!!cp ('t142');  
               !!!parse-error (type => 'unmatched end tag',  
                               text => $token->{tag_name}, token => $token);  
               ## Ignore the token  
               !!!next-token;  
               next B;  
             } elsif ($token->{tag_name} eq 'br') {  
               if ($self->{insertion_mode} == BEFORE_HEAD_IM) {  
                 !!!cp ('t142.2');  
                 ## (before head) as if <head>, (in head) as if </head>  
                 !!!create-element ($self->{head_element}, $HTML_NS, 'head',, $token);  
                 $self->{open_elements}->[-1]->[0]->append_child ($self->{head_element});  
                 $self->{insertion_mode} = AFTER_HEAD_IM;  
2562        
2563                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2564                } elsif ($self->{insertion_mode} == IN_HEAD_IM) {            } elsif ($self->{insertion_mode} == IN_HEAD_IM) {
2565                  !!!cp ('t143.2');              !!!cp ('t143.2');
2566                  ## As if </head>              ## As if </head>
2567                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2568                  $self->{insertion_mode} = AFTER_HEAD_IM;              $self->{insertion_mode} = AFTER_HEAD_IM;
2569        
2570                  ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2571                } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            } elsif ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
2572                  !!!cp ('t143.3');              !!!cp ('t143.3');
2573                  ## NOTE: Two parse errors for <head><noscript></br>              ## NOTE: Two parse errors for <head><noscript></br>
2574                  !!!parse-error (type => 'unmatched end tag',              !!!parse-error (type => 'unmatched end tag',
2575                                  text => 'br', token => $token);                              text => $token->{tag_name}, token => $token);
2576                  ## As if </noscript>              ## As if </noscript>
2577                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
2578                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
   
                 ## Reprocess in the "in head" insertion mode...  
                 ## As if </head>  
                 pop @{$self->{open_elements}};  
                 $self->{insertion_mode} = AFTER_HEAD_IM;  
   
                 ## Reprocess in the "after head" insertion mode...  
               } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {  
                 !!!cp ('t143.4');  
                 #  
               } else {  
                 die "$0: $self->{insertion_mode}: Unknown insertion mode";  
               }  
   
               ## ISSUE: does not agree with IE7 - it doesn't ignore </br>.  
               !!!parse-error (type => 'unmatched end tag',  
                               text => 'br', token => $token);  
               ## Ignore the token  
               !!!next-token;  
               next B;  
             } else {  
               !!!cp ('t145');  
               !!!parse-error (type => 'unmatched end tag',  
                               text => $token->{tag_name}, token => $token);  
               ## Ignore the token  
               !!!next-token;  
               next B;  
             }  
2579    
2580              if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {              ## Reprocess in the "in head" insertion mode...
2581                !!!cp ('t146');              ## As if </head>
2582                ## As if </noscript>              pop @{$self->{open_elements}};
2583                pop @{$self->{open_elements}};              $self->{insertion_mode} = AFTER_HEAD_IM;
               !!!parse-error (type => 'in noscript:/',  
                               text => $token->{tag_name}, token => $token);  
                 
               ## Reprocess in the "in head" insertion mode...  
               ## As if </head>  
               pop @{$self->{open_elements}};  
2584    
2585                ## Reprocess in the "after head" insertion mode...              ## Reprocess in the "after head" insertion mode...
2586              } elsif ($self->{insertion_mode} == IN_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
2587                !!!cp ('t147');              !!!cp ('t143.4');
2588                ## As if </head>              #
2589                pop @{$self->{open_elements}};            } else {
2590                die "$0: $self->{insertion_mode}: Unknown insertion mode";
2591              }
2592    
2593                ## Reprocess in the "after head" insertion mode...            ## "after head" insertion mode
2594              } elsif ($self->{insertion_mode} == BEFORE_HEAD_IM) {            ## As if <body>
2595  ## ISSUE: This case cannot be reached?            !!!insert-element ('body',, $token);
2596                !!!cp ('t148');            $self->{insertion_mode} = IN_BODY_IM;
2597                !!!parse-error (type => 'unmatched end tag',            ## The "frameset-ok" flag is left unchanged in this case.
2598                                text => $token->{tag_name}, token => $token);            ## Reprocess the token.
2599                ## Ignore the token ## ISSUE: An issue in the spec.            next B;
2600                !!!next-token;          }
               next B;  
             } else {  
               !!!cp ('t149');  
             }  
2601    
2602              ## "after head" insertion mode          ## End tags are ignored by default.
2603              ## As if <body>          !!!cp ('t145');
2604              !!!insert-element ('body',, $token);          !!!parse-error (type => 'unmatched end tag',
2605              $self->{insertion_mode} = IN_BODY_IM;                          text => $token->{tag_name}, token => $token);
2606              ## reprocess          ## Ignore the token.
2607              next B;          !!!next-token;
2608            next B;
2609        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
2610          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {          if ($self->{insertion_mode} == BEFORE_HEAD_IM) {
2611            !!!cp ('t149.1');            !!!cp ('t149.1');
# Line 2633  sub _tree_construction_main ($) { Line 2658  sub _tree_construction_main ($) {
2658          ## NOTE: As if <body>          ## NOTE: As if <body>
2659          !!!insert-element ('body',, $token);          !!!insert-element ('body',, $token);
2660          $self->{insertion_mode} = IN_BODY_IM;          $self->{insertion_mode} = IN_BODY_IM;
2661          ## NOTE: Reprocess.          ## The "frameset-ok" flag is left unchanged in this case.
2662            ## Reprocess the token.
2663          next B;          next B;
2664        } else {        } else {
2665          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
2666        }        }
2667      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
2668            if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
2669              !!!cp ('t150');          !!!cp ('t150');
2670              ## NOTE: There is a code clone of "character in body".          $reconstruct_active_formatting_elements->($insert_to_current);
2671              $reconstruct_active_formatting_elements->($insert_to_current);          
2672                        $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});
             $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});  
2673    
2674              !!!next-token;          if ($token->{data} =~ /[^\x09\x0A\x0C\x0D\x20]/) {
2675              next B;            delete $self->{frameset_ok};
2676            } elsif ($token->{type} == START_TAG_TOKEN) {          }
2677    
2678            !!!next-token;
2679            next B;
2680          } elsif ($token->{type} == START_TAG_TOKEN) {
2681              if ({              if ({
2682                   caption => 1, col => 1, colgroup => 1, tbody => 1,                   caption => 1, col => 1, colgroup => 1, tbody => 1,
2683                   td => 1, tfoot => 1, th => 1, thead => 1, tr => 1,                   td => 1, tfoot => 1, th => 1, thead => 1, tr => 1,
# Line 3008  sub _tree_construction_main ($) { Line 3037  sub _tree_construction_main ($) {
3037        $insert = $insert_to_current;        $insert = $insert_to_current;
3038        #        #
3039      } elsif ($self->{insertion_mode} & TABLE_IMS) {      } elsif ($self->{insertion_mode} & TABLE_IMS) {
3040        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == START_TAG_TOKEN) {
         if (not $open_tables->[-1]->[1] and # tainted  
             $token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {  
           $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);  
                 
           unless (length $token->{data}) {  
             !!!cp ('t194');  
             !!!next-token;  
             next B;  
           } else {  
             !!!cp ('t195');  
           }  
         }  
   
         !!!parse-error (type => 'in table:#text', token => $token);  
   
         ## NOTE: As if in body, but insert into the foster parent element.  
         $reconstruct_active_formatting_elements->($insert_to_foster);  
               
         if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {  
           # MUST  
           my $foster_parent_element;  
           my $next_sibling;  
           my $prev_sibling;  
           OE: for (reverse 0..$#{$self->{open_elements}}) {  
             if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {  
               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;  
               if (defined $parent and $parent->node_type == 1) {  
                 $foster_parent_element = $parent;  
                 !!!cp ('t196');  
                 $next_sibling = $self->{open_elements}->[$_]->[0];  
                 $prev_sibling = $next_sibling->previous_sibling;  
                 #  
               } else {  
                 !!!cp ('t197');  
                 $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];  
                 $prev_sibling = $foster_parent_element->last_child;  
                 #  
               }  
               last OE;  
             }  
           } # OE  
           $foster_parent_element = $self->{open_elements}->[0]->[0] and  
           $prev_sibling = $foster_parent_element->last_child  
               unless defined $foster_parent_element;  
           undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted  
           if (defined $prev_sibling and  
               $prev_sibling->node_type == 3) {  
             !!!cp ('t198');  
             $prev_sibling->manakai_append_text ($token->{data});  
           } else {  
             !!!cp ('t199');  
             $foster_parent_element->insert_before  
                 ($self->{document}->create_text_node ($token->{data}),  
                  $next_sibling);  
           }  
           $open_tables->[-1]->[1] = 1; # tainted  
           $open_tables->[-1]->[2] = 1; # ~node inserted  
         } else {  
           ## NOTE: Fragment case or in a foster parent'ed element  
           ## (e.g. |<table><span>a|).  In fragment case, whether the  
           ## character is appended to existing node or a new node is  
           ## created is irrelevant, since the foster parent'ed nodes  
           ## are discarded and fragment parsing does not invoke any  
           ## script.  
           !!!cp ('t200');  
           $self->{open_elements}->[-1]->[0]->manakai_append_text  
               ($token->{data});  
         }  
               
         !!!next-token;  
         next B;  
       } elsif ($token->{type} == START_TAG_TOKEN) {  
3041          if ({          if ({
3042               tr => (($self->{insertion_mode} & IM_MASK) != IN_ROW_IM),               tr => (($self->{insertion_mode} & IM_MASK) != IN_ROW_IM),
3043               th => 1, td => 1,               th => 1, td => 1,
# Line 3348  sub _tree_construction_main ($) { Line 3305  sub _tree_construction_main ($) {
3305            !!!ack-later;            !!!ack-later;
3306            next B;            next B;
3307          } elsif ($token->{tag_name} eq 'style') {          } elsif ($token->{tag_name} eq 'style') {
3308            if (not $open_tables->[-1]->[1]) { # tainted            !!!cp ('t227.8');
3309              !!!cp ('t227.8');            ## NOTE: This is a "as if in head" code clone.
3310              ## NOTE: This is a "as if in head" code clone.            $parse_rcdata->(CDATA_CONTENT_MODEL);
3311              $parse_rcdata->(CDATA_CONTENT_MODEL);            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
3312              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted            next B;
             next B;  
           } else {  
             !!!cp ('t227.7');  
             #  
           }  
3313          } elsif ($token->{tag_name} eq 'script') {          } elsif ($token->{tag_name} eq 'script') {
3314            if (not $open_tables->[-1]->[1]) { # tainted            !!!cp ('t227.6');
3315              !!!cp ('t227.6');            ## NOTE: This is a "as if in head" code clone.
3316              ## NOTE: This is a "as if in head" code clone.            $script_start_tag->();
3317              $script_start_tag->();            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
3318              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted            next B;
             next B;  
           } else {  
             !!!cp ('t227.5');  
             #  
           }  
3319          } elsif ($token->{tag_name} eq 'input') {          } elsif ($token->{tag_name} eq 'input') {
3320            if (not $open_tables->[-1]->[1]) { # tainted            if ($token->{attributes}->{type}) {
3321              if ($token->{attributes}->{type}) { ## TODO: case              my $type = $token->{attributes}->{type}->{value};
3322                my $type = lc $token->{attributes}->{type}->{value};              $type =~ tr/A-Z/a-z/; ## ASCII case-insensitive.
3323                if ($type eq 'hidden') {              if ($type eq 'hidden') {
3324                  !!!cp ('t227.3');                !!!cp ('t227.3');
3325                  !!!parse-error (type => 'in table',                !!!parse-error (type => 'in table',
3326                                  text => $token->{tag_name}, token => $token);                                text => $token->{tag_name}, token => $token);
3327    
3328                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
3329                  $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
3330    
3331                  ## TODO: form element pointer                ## TODO: form element pointer
3332    
3333                  pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
3334    
3335                  !!!next-token;                !!!next-token;
3336                  !!!ack ('t227.2.1');                !!!ack ('t227.2.1');
3337                  next B;                next B;
               } else {  
                 !!!cp ('t227.2');  
                 #  
               }  
3338              } else {              } else {
3339                !!!cp ('t227.1');                !!!cp ('t227.1');
3340                #                #
# Line 3846  sub _tree_construction_main ($) { Line 3789  sub _tree_construction_main ($) {
3789                     tbody => 1, tfoot => 1, thead => 1,                     tbody => 1, tfoot => 1, thead => 1,
3790                     tr => 1, td => 1, th => 1,                     tr => 1, td => 1, th => 1,
3791                    }->{$token->{tag_name}})) {                    }->{$token->{tag_name}})) {
3792            ## TODO: The type below is not good - <select> is replaced by </select>  
3793            !!!parse-error (type => 'not closed', text => 'select',            ## 1. Parse error.
3794                            token => $token);            if ($token->{tag_name} eq 'select') {
3795            ## NOTE: As if the token were </select> (<select> case) or                !!!parse-error (type => 'select in select', ## XXX: documentation
3796            ## as if there were </select> (otherwise).                                token => $token);
3797            ## have an element in table scope            } else {
3798                !!!parse-error (type => 'not closed', text => 'select',
3799                                token => $token);
3800              }
3801    
3802              ## 2./<select>-1. Unless "have an element in table scope" (select):
3803            my $i;            my $i;
3804            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
3805              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
# Line 3866  sub _tree_construction_main ($) { Line 3814  sub _tree_construction_main ($) {
3814            } # INSCOPE            } # INSCOPE
3815            unless (defined $i) {            unless (defined $i) {
3816              !!!cp ('t280');              !!!cp ('t280');
3817              !!!parse-error (type => 'unmatched end tag',              if ($token->{tag_name} eq 'select') {
3818                              text => 'select', token => $token);                ## NOTE: This error would be raised when
3819              ## Ignore the token                ## |select.innerHTML = '<select>'| is executed; in this
3820                  ## case two errors, "select in select" and "unmatched
3821                  ## end tags" are reported to the user, the latter might
3822                  ## be confusing but this is what the spec requires.
3823                  !!!parse-error (type => 'unmatched end tag',
3824                                  text => 'select',
3825                                  token => $token);
3826                }
3827                ## Ignore the token.
3828              !!!nack ('t280.1');              !!!nack ('t280.1');
3829              !!!next-token;              !!!next-token;
3830              next B;              next B;
3831            }            }
3832    
3833              ## 3. Otherwise, as if there were <select>:
3834                                
3835            !!!cp ('t281');            !!!cp ('t281');
3836            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
# Line 3889  sub _tree_construction_main ($) { Line 3847  sub _tree_construction_main ($) {
3847              ## Reprocess the token.              ## Reprocess the token.
3848              next B;              next B;
3849            }            }
3850            } elsif ($token->{tag_name} eq 'script') {
3851              !!!cp ('t281.3');
3852              ## NOTE: This is an "as if in head" code clone
3853              $script_start_tag->();
3854              next B;
3855          } else {          } else {
3856            !!!cp ('t282');            !!!cp ('t282');
3857            !!!parse-error (type => 'in select',            !!!parse-error (type => 'in select',
# Line 4300  sub _tree_construction_main ($) { Line 4263  sub _tree_construction_main ($) {
4263          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
4264          next B;          next B;
4265        } elsif ({        } elsif ({
4266                  base => 1, command => 1, eventsource => 1, link => 1,                  base => 1, command => 1, link => 1,
4267                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
4268          !!!cp ('t334');          !!!cp ('t334');
4269          ## 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
# Line 4390  sub _tree_construction_main ($) { Line 4353  sub _tree_construction_main ($) {
4353          !!!nack ('t343.1');          !!!nack ('t343.1');
4354          !!!next-token;          !!!next-token;
4355          next B;          next B;
4356          } elsif ($token->{tag_name} eq 'frameset') {
4357            !!!parse-error (type => 'in body', text => $token->{tag_name},
4358                            token => $token);
4359    
4360            if (@{$self->{open_elements}} == 1 or
4361                not ($self->{open_elements}->[1]->[1] == BODY_EL)) {
4362              !!!cp ('t343.2');
4363              ## Ignore the token.
4364            } elsif (not $self->{frameset_ok}) {
4365              !!!cp ('t343.3');
4366              ## Ignore the token.
4367            } else {
4368              !!!cp ('t343.4');
4369              
4370              ## 1. Remove the second element.
4371              my $body = $self->{open_elements}->[1]->[0];
4372              my $body_parent = $body->parent_node;
4373              $body_parent->remove_child ($body) if $body_parent;
4374    
4375              ## 2. Pop nodes.
4376              splice @{$self->{open_elements}}, 1;
4377    
4378              ## 3. Insert.
4379              !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4380    
4381              ## 4. Switch.
4382              $self->{insertion_mode} = IN_FRAMESET_IM;
4383            }
4384    
4385            !!!nack ('t343.5');
4386            !!!next-token;
4387            next B;
4388        } elsif ({        } elsif ({
4389                  ## NOTE: Start tags for non-phrasing flow content elements                  ## NOTE: Start tags for non-phrasing flow content elements
4390    
# Line 4398  sub _tree_construction_main ($) { Line 4393  sub _tree_construction_main ($) {
4393                  center => 1, datagrid => 1, details => 1, dialog => 1,                  center => 1, datagrid => 1, details => 1, dialog => 1,
4394                  dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,                  dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
4395                  footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,                  footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,
4396                  h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1,                  h6 => 1, header => 1, hgroup => 1,
4397                    menu => 1, nav => 1, ol => 1, p => 1,
4398                  section => 1, ul => 1,                  section => 1, ul => 1,
4399                  ## NOTE: As normal, but drops leading newline                  ## NOTE: As normal, but drops leading newline
4400                  pre => 1, listing => 1,                  pre => 1, listing => 1,
# Line 4408  sub _tree_construction_main ($) { Line 4404  sub _tree_construction_main ($) {
4404                  table => 1,                  table => 1,
4405                  hr => 1,                  hr => 1,
4406                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
4407    
4408            ## 1. When there is an opening |form| element:
4409          if ($token->{tag_name} eq 'form' and defined $self->{form_element}) {          if ($token->{tag_name} eq 'form' and defined $self->{form_element}) {
4410            !!!cp ('t350');            !!!cp ('t350');
4411            !!!parse-error (type => 'in form:form', token => $token);            !!!parse-error (type => 'in form:form', token => $token);
# Line 4417  sub _tree_construction_main ($) { Line 4415  sub _tree_construction_main ($) {
4415            next B;            next B;
4416          }          }
4417    
4418            ## 2. Close the |p| element, if any.
4419          if ($token->{tag_name} ne 'table' or # The Hixie Quirk          if ($token->{tag_name} ne 'table' or # The Hixie Quirk
4420              $self->{document}->manakai_compat_mode ne 'quirks') {              $self->{document}->manakai_compat_mode ne 'quirks') {
4421            ## has a p element in scope            ## has a p element in scope
# Line 4433  sub _tree_construction_main ($) { Line 4432  sub _tree_construction_main ($) {
4432              }              }
4433            } # INSCOPE            } # INSCOPE
4434          }          }
4435              
4436            ## 3. Close the opening <hn> element, if any.
4437            if ({h1 => 1, h2 => 1, h3 => 1,
4438                 h4 => 1, h5 => 1, h6 => 1}->{$token->{tag_name}}) {
4439              if ($self->{open_elements}->[-1]->[1] == HEADING_EL) {
4440                !!!parse-error (type => 'not closed',
4441                                text => $self->{open_elements}->[-1]->[0]->manakai_local_name,
4442                                token => $token);
4443                pop @{$self->{open_elements}};
4444              }
4445            }
4446    
4447            ## 4. Insertion.
4448          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4449          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {          if ($token->{tag_name} eq 'pre' or $token->{tag_name} eq 'listing') {
4450            !!!nack ('t346.1');            !!!nack ('t346.1');
# Line 4449  sub _tree_construction_main ($) { Line 4460  sub _tree_construction_main ($) {
4460            } else {            } else {
4461              !!!cp ('t348');              !!!cp ('t348');
4462            }            }
4463    
4464              delete $self->{frameset_ok};
4465          } elsif ($token->{tag_name} eq 'form') {          } elsif ($token->{tag_name} eq 'form') {
4466            !!!cp ('t347.1');            !!!cp ('t347.1');
4467            $self->{form_element} = $self->{open_elements}->[-1]->[0];            $self->{form_element} = $self->{open_elements}->[-1]->[0];
# Line 4458  sub _tree_construction_main ($) { Line 4471  sub _tree_construction_main ($) {
4471          } elsif ($token->{tag_name} eq 'table') {          } elsif ($token->{tag_name} eq 'table') {
4472            !!!cp ('t382');            !!!cp ('t382');
4473            push @{$open_tables}, [$self->{open_elements}->[-1]->[0]];            push @{$open_tables}, [$self->{open_elements}->[-1]->[0]];
4474    
4475              delete $self->{frameset_ok};
4476                        
4477            $self->{insertion_mode} = IN_TABLE_IM;            $self->{insertion_mode} = IN_TABLE_IM;
4478    
# Line 4466  sub _tree_construction_main ($) { Line 4481  sub _tree_construction_main ($) {
4481          } elsif ($token->{tag_name} eq 'hr') {          } elsif ($token->{tag_name} eq 'hr') {
4482            !!!cp ('t386');            !!!cp ('t386');
4483            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
4484                      
4485            !!!nack ('t386.1');            !!!ack ('t386.1');
4486    
4487              delete $self->{frameset_ok};
4488    
4489            !!!next-token;            !!!next-token;
4490          } else {          } else {
4491            !!!nack ('t347.1');            !!!nack ('t347.1');
# Line 4477  sub _tree_construction_main ($) { Line 4495  sub _tree_construction_main ($) {
4495        } elsif ($token->{tag_name} eq 'li') {        } elsif ($token->{tag_name} eq 'li') {
4496          ## NOTE: As normal, but imply </li> when there's another <li> ...          ## NOTE: As normal, but imply </li> when there's another <li> ...
4497    
4498          ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)          ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)::
4499            ## Interpreted as <li><foo/></li><li/> (non-conforming)            ## Interpreted as <li><foo/></li><li/> (non-conforming):
4500            ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),            ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
4501            ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),            ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
4502            ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),            ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
4503            ## object (Fx)            ## object (Fx)
4504            ## Generate non-tree (non-conforming)            ## Generate non-tree (non-conforming):
4505            ## basefont (IE7 (where basefont is non-void)), center (IE),            ## basefont (IE7 (where basefont is non-void)), center (IE),
4506            ## form (IE), hn (IE)            ## form (IE), hn (IE)
4507          ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)          ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)::
4508            ## Interpreted as <li><foo><li/></foo></li> (non-conforming)            ## Interpreted as <li><foo><li/></foo></li> (non-conforming):
4509            ## div (Fx, S)            ## div (Fx, S)
4510    
4511            ## 1. Frameset-ng
4512            delete $self->{frameset_ok};
4513    
4514          my $non_optional;          my $non_optional;
4515          my $i = -1;          my $i = -1;
4516    
4517          ## 1.          ## 2.
4518          for my $node (reverse @{$self->{open_elements}}) {          for my $node (reverse @{$self->{open_elements}}) {
4519            if ($node->[1] == LI_EL) {            if ($node->[1] == LI_EL) {
4520              ## 2. (a) As if </li>              ## 3. (a) As if </li>
4521              {              {
4522                ## If no </li> - not applied                ## If no </li> - not applied
4523                #                #
# Line 4520  sub _tree_construction_main ($) { Line 4541  sub _tree_construction_main ($) {
4541                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4542              }              }
4543    
4544              last; ## 2. (b) goto 5.              last; ## 3. (b) goto 5.
4545            } elsif (            } elsif (
4546                     ## NOTE: not "formatting" and not "phrasing"                     ## NOTE: not "formatting" and not "phrasing"
4547                     ($node->[1] & SPECIAL_EL or                     ($node->[1] & SPECIAL_EL or
# Line 4528  sub _tree_construction_main ($) { Line 4549  sub _tree_construction_main ($) {
4549                     ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.                     ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
4550                     (not $node->[1] & ADDRESS_DIV_P_EL)                     (not $node->[1] & ADDRESS_DIV_P_EL)
4551                    ) {                    ) {
4552              ## 3.              ## 4.
4553              !!!cp ('t357');              !!!cp ('t357');
4554              last; ## goto 5.              last; ## goto 6.
4555            } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {            } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
4556              !!!cp ('t358');              !!!cp ('t358');
4557              #              #
# Line 4539  sub _tree_construction_main ($) { Line 4560  sub _tree_construction_main ($) {
4560              $non_optional ||= $node;              $non_optional ||= $node;
4561              #              #
4562            }            }
4563            ## 4.            ## 5.
4564            ## goto 2.            ## goto 3.
4565            $i--;            $i--;
4566          }          }
4567    
4568          ## 5. (a) has a |p| element in scope          ## 6. (a) has a |p| element in scope
4569          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
4570            if ($_->[1] == P_EL) {            if ($_->[1] == P_EL) {
4571              !!!cp ('t353');              !!!cp ('t353');
# Line 4561  sub _tree_construction_main ($) { Line 4582  sub _tree_construction_main ($) {
4582            }            }
4583          } # INSCOPE          } # INSCOPE
4584    
4585          ## 5. (b) insert          ## 6. (b) insert
4586          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4587          !!!nack ('t359.1');          !!!nack ('t359.1');
4588          !!!next-token;          !!!next-token;
# Line 4570  sub _tree_construction_main ($) { Line 4591  sub _tree_construction_main ($) {
4591                 $token->{tag_name} eq 'dd') {                 $token->{tag_name} eq 'dd') {
4592          ## NOTE: As normal, but imply </dt> or </dd> when ...          ## NOTE: As normal, but imply </dt> or </dd> when ...
4593    
4594            ## 1. Frameset-ng
4595            delete $self->{frameset_ok};
4596    
4597          my $non_optional;          my $non_optional;
4598          my $i = -1;          my $i = -1;
4599    
4600          ## 1.          ## 2.
4601          for my $node (reverse @{$self->{open_elements}}) {          for my $node (reverse @{$self->{open_elements}}) {
4602            if ($node->[1] == DTDD_EL) {            if ($node->[1] == DTDD_EL) {
4603              ## 2. (a) As if </li>              ## 3. (a) As if </li>
4604              {              {
4605                ## If no </li> - not applied                ## If no </li> - not applied
4606                #                #
# Line 4600  sub _tree_construction_main ($) { Line 4624  sub _tree_construction_main ($) {
4624                splice @{$self->{open_elements}}, $i;                splice @{$self->{open_elements}}, $i;
4625              }              }
4626    
4627              last; ## 2. (b) goto 5.              last; ## 3. (b) goto 5.
4628            } elsif (            } elsif (
4629                     ## NOTE: not "formatting" and not "phrasing"                     ## NOTE: not "formatting" and not "phrasing"
4630                     ($node->[1] & SPECIAL_EL or                     ($node->[1] & SPECIAL_EL or
# Line 4609  sub _tree_construction_main ($) { Line 4633  sub _tree_construction_main ($) {
4633    
4634                     (not $node->[1] & ADDRESS_DIV_P_EL)                     (not $node->[1] & ADDRESS_DIV_P_EL)
4635                    ) {                    ) {
4636              ## 3.              ## 4.
4637              !!!cp ('t357.1');              !!!cp ('t357.1');
4638              last; ## goto 5.              last; ## goto 5.
4639            } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {            } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
# Line 4620  sub _tree_construction_main ($) { Line 4644  sub _tree_construction_main ($) {
4644              $non_optional ||= $node;              $non_optional ||= $node;
4645              #              #
4646            }            }
4647            ## 4.            ## 5.
4648            ## goto 2.            ## goto 3.
4649            $i--;            $i--;
4650          }          }
4651    
4652          ## 5. (a) has a |p| element in scope          ## 6. (a) has a |p| element in scope
4653          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
4654            if ($_->[1] == P_EL) {            if ($_->[1] == P_EL) {
4655              !!!cp ('t353.1');              !!!cp ('t353.1');
# Line 4639  sub _tree_construction_main ($) { Line 4663  sub _tree_construction_main ($) {
4663            }            }
4664          } # INSCOPE          } # INSCOPE
4665    
4666          ## 5. (b) insert          ## 6. (b) insert
4667          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4668          !!!nack ('t359.2');          !!!nack ('t359.2');
4669          !!!next-token;          !!!next-token;
# Line 4759  sub _tree_construction_main ($) { Line 4783  sub _tree_construction_main ($) {
4783    
4784          push @$active_formatting_elements, ['#marker', ''];          push @$active_formatting_elements, ['#marker', ''];
4785    
4786            delete $self->{frameset_ok};
4787    
4788          !!!nack ('t379.1');          !!!nack ('t379.1');
4789          !!!next-token;          !!!next-token;
4790          next B;          next B;
# Line 4772  sub _tree_construction_main ($) { Line 4798  sub _tree_construction_main ($) {
4798          if ($token->{tag_name} eq 'xmp') {          if ($token->{tag_name} eq 'xmp') {
4799            !!!cp ('t381');            !!!cp ('t381');
4800            $reconstruct_active_formatting_elements->($insert_to_current);            $reconstruct_active_formatting_elements->($insert_to_current);
4801    
4802              delete $self->{frameset_ok};
4803            } elsif ($token->{tag_name} eq 'iframe') {
4804              !!!cp ('t381.1');
4805              delete $self->{frameset_ok};
4806          } else {          } else {
4807            !!!cp ('t399');            !!!cp ('t399');
4808          }          }
# Line 4834  sub _tree_construction_main ($) { Line 4865  sub _tree_construction_main ($) {
4865            next B;            next B;
4866          }          }
4867        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
4868          ## Step 1          ## 1. Insert
4869          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
4870                    
4871          ## Step 2          ## Step 2 # XXX
4872          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
4873    
4874          ## Step 3          ## 2. Drop U+000A LINE FEED
4875          $self->{ignore_newline} = 1;          $self->{ignore_newline} = 1;
4876    
4877          ## Step 4          ## 3. RCDATA
         ## ISSUE: This step is wrong. (r2302 enbugged)  
   
         ## Step 5  
4878          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
4879          delete $self->{escape}; # MUST          delete $self->{escape}; # MUST
4880    
4881          ## Step 6-7          ## 4., 6. Insertion mode
4882          $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;          $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
4883    
4884            ## 5. Frameset-ng.
4885            delete $self->{frameset_ok};
4886    
4887          !!!nack ('t392.1');          !!!nack ('t392.1');
4888          !!!next-token;          !!!next-token;
4889          next B;          next B;
# Line 4943  sub _tree_construction_main ($) { Line 4974  sub _tree_construction_main ($) {
4974          next B;          next B;
4975        } elsif ({        } elsif ({
4976                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
4977                  frameset => 1, head => 1,                  head => 1,
4978                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
4979                  thead => 1, tr => 1,                  thead => 1, tr => 1,
4980                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 4980  sub _tree_construction_main ($) { Line 5011  sub _tree_construction_main ($) {
5011               applet => 1, marquee => 1, object => 1,               applet => 1, marquee => 1, object => 1,
5012              }->{$token->{tag_name}}) {              }->{$token->{tag_name}}) {
5013            !!!cp ('t380');            !!!cp ('t380');
5014    
5015            push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
5016    
5017              delete $self->{frameset_ok};
5018    
5019            !!!nack ('t380.1');            !!!nack ('t380.1');
5020          } elsif ({          } elsif ({
5021                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
# Line 4998  sub _tree_construction_main ($) { Line 5033  sub _tree_construction_main ($) {
5033          } elsif ({          } elsif ({
5034                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
5035                    embed => 1, img => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
5036                      keygen => 1,
5037                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
5038            !!!cp ('t388.1');            !!!cp ('t388.1');
5039    
5040            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
5041    
5042              delete $self->{frameset_ok};
5043    
5044            !!!ack ('t388.3');            !!!ack ('t388.3');
5045          } elsif ($token->{tag_name} eq 'select') {          } elsif ($token->{tag_name} eq 'select') {
5046            ## TODO: associate with $self->{form_element} if defined            ## TODO: associate with $self->{form_element} if defined
5047            
5048              delete $self->{frameset_ok};
5049              
5050            if ($self->{insertion_mode} & TABLE_IMS or            if ($self->{insertion_mode} & TABLE_IMS or
5051                $self->{insertion_mode} & BODY_TABLE_IMS or                $self->{insertion_mode} & BODY_TABLE_IMS or
5052                ($self->{insertion_mode} & IM_MASK) == IN_COLUMN_GROUP_IM) {                ($self->{insertion_mode} & IM_MASK) == IN_COLUMN_GROUP_IM) {
# Line 5023  sub _tree_construction_main ($) { Line 5065  sub _tree_construction_main ($) {
5065          next B;          next B;
5066        }        }
5067      } elsif ($token->{type} == END_TAG_TOKEN) {      } elsif ($token->{type} == END_TAG_TOKEN) {
5068        if ($token->{tag_name} eq 'body') {        if ($token->{tag_name} eq 'body' or $token->{tag_name} eq 'html') {
5069          ## has a |body| element in scope  
5070            ## 1. If not "have an element in scope":
5071            ## "has a |body| element in scope"
5072          my $i;          my $i;
5073          INSCOPE: {          INSCOPE: {
5074            for (reverse @{$self->{open_elements}}) {            for (reverse @{$self->{open_elements}}) {
# Line 5038  sub _tree_construction_main ($) { Line 5082  sub _tree_construction_main ($) {
5082              }              }
5083            }            }
5084    
5085            ## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|            ## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|,
5086              ## and fragment cases.
5087    
5088            !!!parse-error (type => 'unmatched end tag',            !!!parse-error (type => 'unmatched end tag',
5089                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
5090            ## NOTE: Ignore the token.            ## Ignore the token.  (</body> or </html>)
5091            !!!next-token;            !!!next-token;
5092            next B;            next B;
5093          } # INSCOPE          } # INSCOPE
5094    
5095            ## 2. If unclosed elements:
5096          for (@{$self->{open_elements}}) {          for (@{$self->{open_elements}}) {
5097            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL) {            unless ($_->[1] & ALL_END_TAG_OPTIONAL_EL ||
5098                      $_->[1] == OPTGROUP_EL ||
5099                      $_->[1] == OPTION_EL ||
5100                      $_->[1] == RUBY_COMPONENT_EL) {
5101              !!!cp ('t403');              !!!cp ('t403');
5102              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
5103                              text => $_->[0]->manakai_local_name,                              text => $_->[0]->manakai_local_name,
# Line 5059  sub _tree_construction_main ($) { Line 5108  sub _tree_construction_main ($) {
5108            }            }
5109          }          }
5110    
5111            ## 3. Switch the insertion mode.
5112          $self->{insertion_mode} = AFTER_BODY_IM;          $self->{insertion_mode} = AFTER_BODY_IM;
5113          !!!next-token;          if ($token->{tag_name} eq 'body') {
         next B;  
       } elsif ($token->{tag_name} eq 'html') {  
         ## TODO: Update this code.  It seems that the code below is not  
         ## up-to-date, though it has same effect as speced.  
         if (@{$self->{open_elements}} > 1 and  
             $self->{open_elements}->[1]->[1] == BODY_EL) {  
           unless ($self->{open_elements}->[-1]->[1] == BODY_EL) {  
             !!!cp ('t406');  
             !!!parse-error (type => 'not closed',  
                             text => $self->{open_elements}->[1]->[0]  
                                 ->manakai_local_name,  
                             token => $token);  
           } else {  
             !!!cp ('t407');  
           }  
           $self->{insertion_mode} = AFTER_BODY_IM;  
           ## reprocess  
           next B;  
         } else {  
           !!!cp ('t408');  
           !!!parse-error (type => 'unmatched end tag',  
                           text => $token->{tag_name}, token => $token);  
           ## Ignore the token  
5114            !!!next-token;            !!!next-token;
5115            next B;          } else { # html
5116              ## Reprocess.
5117          }          }
5118            next B;
5119        } elsif ({        } elsif ({
5120                  ## NOTE: End tags for non-phrasing flow content elements                  ## NOTE: End tags for non-phrasing flow content elements
5121    
# Line 5094  sub _tree_construction_main ($) { Line 5123  sub _tree_construction_main ($) {
5123                  address => 1, article => 1, aside => 1, blockquote => 1,                  address => 1, article => 1, aside => 1, blockquote => 1,
5124                  center => 1, datagrid => 1, details => 1, dialog => 1,                  center => 1, datagrid => 1, details => 1, dialog => 1,
5125                  dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,                  dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
5126                  footer => 1, header => 1, listing => 1, menu => 1, nav => 1,                  footer => 1, header => 1, hgroup => 1,
5127                    listing => 1, menu => 1, nav => 1,
5128                  ol => 1, pre => 1, section => 1, ul => 1,                  ol => 1, pre => 1, section => 1, ul => 1,
5129    
5130                  ## NOTE: As normal, but ... optional tags                  ## NOTE: As normal, but ... optional tags
# Line 5445  sub _tree_construction_main ($) { Line 5475  sub _tree_construction_main ($) {
5475    ## TODO: script stuffs    ## TODO: script stuffs
5476  } # _tree_construct_main  } # _tree_construct_main
5477    
5478    ## XXX: How this method is organized is somewhat out of date, although
5479    ## it still does what the current spec documents.
5480  sub set_inner_html ($$$$;$) {  sub set_inner_html ($$$$;$) {
5481    my $class = shift;    my $class = shift;
5482    my $node = shift;    my $node = shift; # /context/
5483    #my $s = \$_[0];    #my $s = \$_[0];
5484    my $onerror = $_[1];    my $onerror = $_[1];
5485    my $get_wrapper = $_[2] || sub ($) { return $_[0] };    my $get_wrapper = $_[2] || sub ($) { return $_[0] };
5486    
   ## ISSUE: Should {confident} be true?  
   
5487    my $nt = $node->node_type;    my $nt = $node->node_type;
5488    if ($nt == 9) {    if ($nt == 9) { # Document (invoke the algorithm with no /context/ element)
5489      # MUST      # MUST
5490            
5491      ## Step 1 # MUST      ## Step 1 # MUST
# Line 5470  sub set_inner_html ($$$$;$) { Line 5500  sub set_inner_html ($$$$;$) {
5500    
5501      ## Step 3, 4, 5 # MUST      ## Step 3, 4, 5 # MUST
5502      $class->parse_char_string ($_[0] => $node, $onerror, $get_wrapper);      $class->parse_char_string ($_[0] => $node, $onerror, $get_wrapper);
5503    } elsif ($nt == 1) {    } elsif ($nt == 1) { # Element (invoke the algorithm with /context/ element)
5504      ## TODO: If non-html element      ## TODO: If non-html element
5505    
5506      ## NOTE: Most of this code is copied from |parse_string|      ## NOTE: Most of this code is copied from |parse_string|
5507    
5508  ## TODO: Support for $get_wrapper  ## TODO: Support for $get_wrapper
5509    
5510      ## Step 1 # MUST      ## F1. Create an HTML document.
5511      my $this_doc = $node->owner_document;      my $this_doc = $node->owner_document;
5512      my $doc = $this_doc->implementation->create_document;      my $doc = $this_doc->implementation->create_document;
5513      $doc->manakai_is_html (1);      $doc->manakai_is_html (1);
5514    
5515        ## F2. Propagate quirkness flag
5516        my $node_doc = $node->owner_document;
5517        $doc->manakai_compat_mode ($node_doc->manakai_compat_mode);
5518    
5519        ## F3. Create an HTML parser
5520      my $p = $class->new;      my $p = $class->new;
5521      $p->{document} = $doc;      $p->{document} = $doc;
5522    
# Line 5608  sub set_inner_html ($$$$;$) { Line 5644  sub set_inner_html ($$$$;$) {
5644      $p->_initialize_tokenizer;      $p->_initialize_tokenizer;
5645      $p->_initialize_tree_constructor;      $p->_initialize_tree_constructor;
5646    
5647      ## Step 2      ## F4. If /context/ is not undef...
5648    
5649        ## F4.1. content model flag
5650      my $node_ln = $node->manakai_local_name;      my $node_ln = $node->manakai_local_name;
5651      $p->{content_model} = {      $p->{content_model} = {
5652        title => RCDATA_CONTENT_MODEL,        title => RCDATA_CONTENT_MODEL,
# Line 5628  sub set_inner_html ($$$$;$) { Line 5666  sub set_inner_html ($$$$;$) {
5666      $p->{inner_html_node} = [$node, $el_category->{$node_ln}];      $p->{inner_html_node} = [$node, $el_category->{$node_ln}];
5667        ## TODO: Foreign element OK?        ## TODO: Foreign element OK?
5668    
5669      ## Step 3      ## F4.2. Root |html| element
5670      my $root = $doc->create_element_ns      my $root = $doc->create_element_ns
5671        ('http://www.w3.org/1999/xhtml', [undef, 'html']);        ('http://www.w3.org/1999/xhtml', [undef, 'html']);
5672    
5673      ## Step 4 # MUST      ## F4.3.
5674      $doc->append_child ($root);      $doc->append_child ($root);
5675    
5676      ## Step 5 # MUST      ## F4.4.
5677      push @{$p->{open_elements}}, [$root, $el_category->{html}];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
5678    
5679      undef $p->{head_element};      undef $p->{head_element};
5680      undef $p->{head_element_inserted};      undef $p->{head_element_inserted};
5681    
5682      ## Step 6 # MUST      ## F4.5.
5683      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;
5684    
5685      ## Step 7 # MUST      ## F4.6.
5686      my $anode = $node;      my $anode = $node;
5687      AN: while (defined $anode) {      AN: while (defined $anode) {
5688        if ($anode->node_type == 1) {        if ($anode->node_type == 1) {
# Line 5659  sub set_inner_html ($$$$;$) { Line 5697  sub set_inner_html ($$$$;$) {
5697        }        }
5698        $anode = $anode->parent_node;        $anode = $anode->parent_node;
5699      } # AN      } # AN
5700        
5701      ## Step 9 # MUST      ## F.5. Set the input stream.
5702        $p->{confident} = 1; ## Confident: irrelevant.
5703    
5704        ## F.6. Start the parser.
5705      {      {
5706        my $self = $p;        my $self = $p;
5707        !!!next-token;        !!!next-token;
5708      }      }
5709      $p->_tree_construction_main;      $p->_tree_construction_main;
5710    
5711      ## Step 10 # MUST      ## F.7.
5712      my @cn = @{$node->child_nodes};      my @cn = @{$node->child_nodes};
5713      for (@cn) {      for (@cn) {
5714        $node->remove_child ($_);        $node->remove_child ($_);

Legend:
Removed from v.1.217  
changed lines
  Added in v.1.243

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24