/[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.191 by wakaba, Mon Sep 22 06:04:29 2008 UTC revision 1.206 by wakaba, Mon Oct 13 08:22:30 2008 UTC
# Line 28  my $XLINK_NS = q<http://www.w3.org/1999/ Line 28  my $XLINK_NS = q<http://www.w3.org/1999/
28  my $XML_NS = q<http://www.w3.org/XML/1998/namespace>;  my $XML_NS = q<http://www.w3.org/XML/1998/namespace>;
29  my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>;  my $XMLNS_NS = q<http://www.w3.org/2000/xmlns/>;
30    
31  sub A_EL () { 0b1 }  ## Bits 12-15
32  sub ADDRESS_EL () { 0b10 }  sub SPECIAL_EL () { 0b1_000000000000000 }
33  sub BODY_EL () { 0b100 }  sub SCOPING_EL () { 0b1_00000000000000 }
34  sub BUTTON_EL () { 0b1000 }  sub FORMATTING_EL () { 0b1_0000000000000 }
35  sub CAPTION_EL () { 0b10000 }  sub PHRASING_EL () { 0b1_000000000000 }
36  sub DD_EL () { 0b100000 }  
37  sub DIV_EL () { 0b1000000 }  ## Bits 10-11
38  sub DT_EL () { 0b10000000 }  sub FOREIGN_EL () { 0b1_00000000000 }
39  sub FORM_EL () { 0b100000000 }  sub FOREIGN_FLOW_CONTENT_EL () { 0b1_0000000000 }
40  sub FORMATTING_EL () { 0b1000000000 }  
41  sub FRAMESET_EL () { 0b10000000000 }  ## Bits 6-9
42  sub HEADING_EL () { 0b100000000000 }  sub TABLE_SCOPING_EL () { 0b1_000000000 }
43  sub HTML_EL () { 0b1000000000000 }  sub TABLE_ROWS_SCOPING_EL () { 0b1_00000000 }
44  sub LI_EL () { 0b10000000000000 }  sub TABLE_ROW_SCOPING_EL () { 0b1_0000000 }
45  sub NOBR_EL () { 0b100000000000000 }  sub TABLE_ROWS_EL () { 0b1_000000 }
 sub OPTION_EL () { 0b1000000000000000 }  
 sub OPTGROUP_EL () { 0b10000000000000000 }  
 sub P_EL () { 0b100000000000000000 }  
 sub SELECT_EL () { 0b1000000000000000000 }  
 sub TABLE_EL () { 0b10000000000000000000 }  
 sub TABLE_CELL_EL () { 0b100000000000000000000 }  
 sub TABLE_ROW_EL () { 0b1000000000000000000000 }  
 sub TABLE_ROW_GROUP_EL () { 0b10000000000000000000000 }  
 sub MISC_SCOPING_EL () { 0b100000000000000000000000 }  
 sub MISC_SPECIAL_EL () { 0b1000000000000000000000000 }  
 sub FOREIGN_EL () { 0b10000000000000000000000000 }  
 sub FOREIGN_FLOW_CONTENT_EL () { 0b100000000000000000000000000 }  
 sub MML_AXML_EL () { 0b1000000000000000000000000000 }  
 sub RUBY_EL () { 0b10000000000000000000000000000 }  
 sub RUBY_COMPONENT_EL () { 0b100000000000000000000000000000 }  
   
 sub TABLE_ROWS_EL () {  
   TABLE_EL |  
   TABLE_ROW_EL |  
   TABLE_ROW_GROUP_EL  
 }  
46    
47  ## NOTE: Used in "generate implied end tags" algorithm.  ## Bit 5
48  ## NOTE: There is a code where a modified version of END_TAG_OPTIONAL_EL  sub ADDRESS_DIV_P_EL () { 0b1_00000 }
 ## is used in "generate implied end tags" implementation (search for the  
 ## function mae).  
 sub END_TAG_OPTIONAL_EL () {  
   DD_EL |  
   DT_EL |  
   LI_EL |  
   P_EL |  
   RUBY_COMPONENT_EL  
 }  
49    
50  ## NOTE: Used in </body> and EOF algorithms.  ## NOTE: Used in </body> and EOF algorithms.
51  sub ALL_END_TAG_OPTIONAL_EL () {  ## Bit 4
52    DD_EL |  sub ALL_END_TAG_OPTIONAL_EL () { 0b1_0000 }
   DT_EL |  
   LI_EL |  
   P_EL |  
   
   BODY_EL |  
   HTML_EL |  
   TABLE_CELL_EL |  
   TABLE_ROW_EL |  
   TABLE_ROW_GROUP_EL  
 }  
53    
54  sub SCOPING_EL () {  ## NOTE: Used in "generate implied end tags" algorithm.
55    BUTTON_EL |  ## NOTE: There is a code where a modified version of
56    CAPTION_EL |  ## END_TAG_OPTIONAL_EL is used in "generate implied end tags"
57    HTML_EL |  ## implementation (search for the algorithm name).
58    TABLE_EL |  ## Bit 3
59    TABLE_CELL_EL |  sub END_TAG_OPTIONAL_EL () { 0b1_000 }
60    MISC_SCOPING_EL  
61    ## Bits 0-2
62    
63    sub MISC_SPECIAL_EL () { SPECIAL_EL | 0b000 }
64    sub FORM_EL () { SPECIAL_EL | 0b001 }
65    sub FRAMESET_EL () { SPECIAL_EL | 0b010 }
66    sub HEADING_EL () { SPECIAL_EL | 0b011 }
67    sub SELECT_EL () { SPECIAL_EL | 0b100 }
68    sub SCRIPT_EL () { SPECIAL_EL | 0b101 }
69    
70    sub ADDRESS_DIV_EL () { SPECIAL_EL | ADDRESS_DIV_P_EL | 0b001 }
71    sub BODY_EL () { SPECIAL_EL | ALL_END_TAG_OPTIONAL_EL | 0b001 }
72    
73    sub DD_EL () {
74      SPECIAL_EL |
75      END_TAG_OPTIONAL_EL |
76      ALL_END_TAG_OPTIONAL_EL |
77      0b001
78  }  }
79    sub DT_EL () {
80  sub TABLE_SCOPING_EL () {    SPECIAL_EL |
81    HTML_EL |    END_TAG_OPTIONAL_EL |
82    TABLE_EL    ALL_END_TAG_OPTIONAL_EL |
83      0b010
84  }  }
85    sub LI_EL () {
86  sub TABLE_ROWS_SCOPING_EL () {    SPECIAL_EL |
87    HTML_EL |    END_TAG_OPTIONAL_EL |
88    TABLE_ROW_GROUP_EL    ALL_END_TAG_OPTIONAL_EL |
89      0b100
90    }
91    sub P_EL () {
92      SPECIAL_EL |
93      ADDRESS_DIV_P_EL |
94      END_TAG_OPTIONAL_EL |
95      ALL_END_TAG_OPTIONAL_EL |
96      0b001
97  }  }
98    
99  sub TABLE_ROW_SCOPING_EL () {  sub TABLE_ROW_EL () {
100    HTML_EL |    SPECIAL_EL |
101    TABLE_ROW_EL    TABLE_ROWS_EL |
102      TABLE_ROW_SCOPING_EL |
103      ALL_END_TAG_OPTIONAL_EL |
104      0b001
105    }
106    sub TABLE_ROW_GROUP_EL () {
107      SPECIAL_EL |
108      TABLE_ROWS_EL |
109      TABLE_ROWS_SCOPING_EL |
110      ALL_END_TAG_OPTIONAL_EL |
111      0b001
112  }  }
113    
114  sub SPECIAL_EL () {  sub MISC_SCOPING_EL () { SCOPING_EL | 0b000 }
115    ADDRESS_EL |  sub BUTTON_EL () { SCOPING_EL | 0b001 }
116    BODY_EL |  sub CAPTION_EL () { SCOPING_EL | 0b010 }
117    DIV_EL |  sub HTML_EL () {
118      SCOPING_EL |
119    DD_EL |    TABLE_SCOPING_EL |
120    DT_EL |    TABLE_ROWS_SCOPING_EL |
121    LI_EL |    TABLE_ROW_SCOPING_EL |
122    P_EL |    ALL_END_TAG_OPTIONAL_EL |
123      0b001
124    FORM_EL |  }
125    FRAMESET_EL |  sub TABLE_EL () {
126    HEADING_EL |    SCOPING_EL |
127    OPTION_EL |    TABLE_ROWS_EL |
128    OPTGROUP_EL |    TABLE_SCOPING_EL |
129    SELECT_EL |    0b001
   TABLE_ROW_EL |  
   TABLE_ROW_GROUP_EL |  
   MISC_SPECIAL_EL  
130  }  }
131    sub TABLE_CELL_EL () {
132      SCOPING_EL |
133      TABLE_ROW_SCOPING_EL |
134      ALL_END_TAG_OPTIONAL_EL |
135      0b001
136    }
137    
138    sub MISC_FORMATTING_EL () { FORMATTING_EL | 0b000 }
139    sub A_EL () { FORMATTING_EL | 0b001 }
140    sub NOBR_EL () { FORMATTING_EL | 0b010 }
141    
142    sub RUBY_EL () { PHRASING_EL | 0b001 }
143    
144    ## ISSUE: ALL_END_TAG_OPTIONAL_EL?
145    sub OPTGROUP_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b001 }
146    sub OPTION_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b010 }
147    sub RUBY_COMPONENT_EL () { PHRASING_EL | END_TAG_OPTIONAL_EL | 0b100 }
148    
149    sub MML_AXML_EL () { PHRASING_EL | FOREIGN_EL | 0b001 }
150    
151  my $el_category = {  my $el_category = {
152    a => A_EL | FORMATTING_EL,    a => A_EL,
153    address => ADDRESS_EL,    address => ADDRESS_DIV_EL,
154    applet => MISC_SCOPING_EL,    applet => MISC_SCOPING_EL,
155    area => MISC_SPECIAL_EL,    area => MISC_SPECIAL_EL,
156      article => MISC_SPECIAL_EL,
157      aside => MISC_SPECIAL_EL,
158    b => FORMATTING_EL,    b => FORMATTING_EL,
159    base => MISC_SPECIAL_EL,    base => MISC_SPECIAL_EL,
160    basefont => MISC_SPECIAL_EL,    basefont => MISC_SPECIAL_EL,
# Line 154  my $el_category = { Line 168  my $el_category = {
168    center => MISC_SPECIAL_EL,    center => MISC_SPECIAL_EL,
169    col => MISC_SPECIAL_EL,    col => MISC_SPECIAL_EL,
170    colgroup => MISC_SPECIAL_EL,    colgroup => MISC_SPECIAL_EL,
171      command => MISC_SPECIAL_EL,
172      datagrid => MISC_SPECIAL_EL,
173    dd => DD_EL,    dd => DD_EL,
174      details => MISC_SPECIAL_EL,
175      dialog => MISC_SPECIAL_EL,
176    dir => MISC_SPECIAL_EL,    dir => MISC_SPECIAL_EL,
177    div => DIV_EL,    div => ADDRESS_DIV_EL,
178    dl => MISC_SPECIAL_EL,    dl => MISC_SPECIAL_EL,
179    dt => DT_EL,    dt => DT_EL,
180    em => FORMATTING_EL,    em => FORMATTING_EL,
181    embed => MISC_SPECIAL_EL,    embed => MISC_SPECIAL_EL,
182      eventsource => MISC_SPECIAL_EL,
183    fieldset => MISC_SPECIAL_EL,    fieldset => MISC_SPECIAL_EL,
184      figure => MISC_SPECIAL_EL,
185    font => FORMATTING_EL,    font => FORMATTING_EL,
186      footer => MISC_SPECIAL_EL,
187    form => FORM_EL,    form => FORM_EL,
188    frame => MISC_SPECIAL_EL,    frame => MISC_SPECIAL_EL,
189    frameset => FRAMESET_EL,    frameset => FRAMESET_EL,
# Line 173  my $el_category = { Line 194  my $el_category = {
194    h5 => HEADING_EL,    h5 => HEADING_EL,
195    h6 => HEADING_EL,    h6 => HEADING_EL,
196    head => MISC_SPECIAL_EL,    head => MISC_SPECIAL_EL,
197      header => 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,
201    iframe => MISC_SPECIAL_EL,    iframe => MISC_SPECIAL_EL,
202    img => MISC_SPECIAL_EL,    img => MISC_SPECIAL_EL,
203      #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    li => LI_EL,    li => LI_EL,
# Line 186  my $el_category = { Line 209  my $el_category = {
209    marquee => MISC_SCOPING_EL,    marquee => MISC_SCOPING_EL,
210    menu => MISC_SPECIAL_EL,    menu => MISC_SPECIAL_EL,
211    meta => MISC_SPECIAL_EL,    meta => MISC_SPECIAL_EL,
212    nobr => NOBR_EL | FORMATTING_EL,    nav => MISC_SPECIAL_EL,
213      nobr => NOBR_EL,
214    noembed => MISC_SPECIAL_EL,    noembed => MISC_SPECIAL_EL,
215    noframes => MISC_SPECIAL_EL,    noframes => MISC_SPECIAL_EL,
216    noscript => MISC_SPECIAL_EL,    noscript => MISC_SPECIAL_EL,
# Line 204  my $el_category = { Line 228  my $el_category = {
228    s => FORMATTING_EL,    s => FORMATTING_EL,
229    script => MISC_SPECIAL_EL,    script => MISC_SPECIAL_EL,
230    select => SELECT_EL,    select => SELECT_EL,
231      section => MISC_SPECIAL_EL,
232    small => FORMATTING_EL,    small => FORMATTING_EL,
233    spacer => MISC_SPECIAL_EL,    spacer => MISC_SPECIAL_EL,
234    strike => FORMATTING_EL,    strike => FORMATTING_EL,
# Line 227  my $el_category = { Line 252  my $el_category = {
252  my $el_category_f = {  my $el_category_f = {
253    $MML_NS => {    $MML_NS => {
254      'annotation-xml' => MML_AXML_EL,      'annotation-xml' => MML_AXML_EL,
255      mi => FOREIGN_FLOW_CONTENT_EL,      mi => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
256      mo => FOREIGN_FLOW_CONTENT_EL,      mo => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
257      mn => FOREIGN_FLOW_CONTENT_EL,      mn => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
258      ms => FOREIGN_FLOW_CONTENT_EL,      ms => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
259      mtext => FOREIGN_FLOW_CONTENT_EL,      mtext => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
260    },    },
261    $SVG_NS => {    $SVG_NS => {
262      foreignObject => FOREIGN_FLOW_CONTENT_EL,      foreignObject => SCOPING_EL | FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
263      desc => FOREIGN_FLOW_CONTENT_EL,      desc => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
264      title => FOREIGN_FLOW_CONTENT_EL,      title => FOREIGN_EL | FOREIGN_FLOW_CONTENT_EL,
265    },    },
266    ## NOTE: In addition, FOREIGN_EL is set to non-HTML elements.    ## NOTE: In addition, FOREIGN_EL is set to non-HTML elements.
267  };  };
# Line 367  $charref_map->{$_} = 0xFFFD Line 392  $charref_map->{$_} = 0xFFFD
392          0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE,          0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xEFFFE,
393          0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF;          0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF;
394    
395    ## TODO: Invoke the reset algorithm when a resettable element is
396    ## created (cf. HTML5 revision 2259).
397    
398  sub parse_byte_string ($$$$;$) {  sub parse_byte_string ($$$$;$) {
399    my $self = shift;    my $self = shift;
400    my $charset_name = shift;    my $charset_name = shift;
# Line 470  sub parse_byte_stream ($$$$;$$) { Line 498  sub parse_byte_stream ($$$$;$$) {
498      if (defined $charset_name) {      if (defined $charset_name) {
499        $charset = Message::Charset::Info->get_by_html_name ($charset_name);        $charset = Message::Charset::Info->get_by_html_name ($charset_name);
500    
       ## ISSUE: Unsupported encoding is not ignored according to the spec.  
501        require Whatpm::Charset::DecodeHandle;        require Whatpm::Charset::DecodeHandle;
502        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new        $buffer = Whatpm::Charset::DecodeHandle::ByteBuffer->new
503            ($byte_stream);            ($byte_stream);
# Line 901  sub IN_FOREIGN_CONTENT_IM () { 0b1000000 Line 928  sub IN_FOREIGN_CONTENT_IM () { 0b1000000
928      ## NOTE: "in foreign content" insertion mode is special; it is combined      ## NOTE: "in foreign content" insertion mode is special; it is combined
929      ## with the secondary insertion mode.  In this parser, they are stored      ## with the secondary insertion mode.  In this parser, they are stored
930      ## together in the bit-or'ed form.      ## together in the bit-or'ed form.
931    sub IN_CDATA_RCDATA_IM () { 0b1000000000000 }
932        ## NOTE: "in CDATA/RCDATA" insertion mode is also special; it is
933        ## combined with the original insertion mode.  In thie parser,
934        ## they are stored together in the bit-or'ed form.
935    
936  ## NOTE: "initial" and "before html" insertion modes have no constants.  ## NOTE: "initial" and "before html" insertion modes have no constants.
937    
# Line 2467  sub _get_next_token ($) { Line 2498  sub _get_next_token ($) {
2498          !!!cp (160);          !!!cp (160);
2499          $self->{ct}->{name} = chr $self->{nc};          $self->{ct}->{name} = chr $self->{nc};
2500          delete $self->{ct}->{quirks};          delete $self->{ct}->{quirks};
 ## ISSUE: "Set the token's name name to the" in the spec  
2501          $self->{state} = DOCTYPE_NAME_STATE;          $self->{state} = DOCTYPE_NAME_STATE;
2502          !!!next-input-character;          !!!next-input-character;
2503          redo A;          redo A;
# Line 2971  sub _get_next_token ($) { Line 3001  sub _get_next_token ($) {
3001          redo A;          redo A;
3002        } elsif ($self->{nc} == -1) {        } elsif ($self->{nc} == -1) {
3003          !!!cp (220);          !!!cp (220);
         !!!parse-error (type => 'unclosed DOCTYPE');  
3004          $self->{state} = DATA_STATE;          $self->{state} = DATA_STATE;
3005          ## reconsume          ## reconsume
3006    
# Line 3451  sub _construct_tree ($) { Line 3480  sub _construct_tree ($) {
3480    ## When an interactive UA render the $self->{document} available    ## When an interactive UA render the $self->{document} available
3481    ## to the user, or when it begin accepting user input, are    ## to the user, or when it begin accepting user input, are
3482    ## not defined.    ## not defined.
   
   ## Append a character: collect it and all subsequent consecutive  
   ## characters and insert one Text node whose data is concatenation  
   ## of all those characters. # MUST  
3483        
3484    !!!next-token;    !!!next-token;
3485    
3486    undef $self->{form_element};    undef $self->{form_element};
3487    undef $self->{head_element};    undef $self->{head_element};
3488      undef $self->{head_element_inserted};
3489    $self->{open_elements} = [];    $self->{open_elements} = [];
3490    undef $self->{inner_html_node};    undef $self->{inner_html_node};
3491      undef $self->{ignore_newline};
3492    
3493    ## NOTE: The "initial" insertion mode.    ## NOTE: The "initial" insertion mode.
3494    $self->_tree_construction_initial; # MUST    $self->_tree_construction_initial; # MUST
# Line 3767  sub _tree_construction_root_element ($) Line 3794  sub _tree_construction_root_element ($)
3794      ## NOTE: Reprocess the token.      ## NOTE: Reprocess the token.
3795      !!!ack-later;      !!!ack-later;
3796      return; ## Go to the "before head" insertion mode.      return; ## Go to the "before head" insertion mode.
   
     ## ISSUE: There is an issue in the spec  
3797    } # B    } # B
3798    
3799    die "$0: _tree_construction_root_element: This should never be reached";    die "$0: _tree_construction_root_element: This should never be reached";
# Line 3804  sub _reset_insertion_mode ($) { Line 3829  sub _reset_insertion_mode ($) {
3829          ## SVG elements.  Currently the HTML syntax supports only MathML and          ## SVG elements.  Currently the HTML syntax supports only MathML and
3830          ## SVG elements as foreigners.          ## SVG elements as foreigners.
3831          $new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM;          $new_mode = IN_BODY_IM | IN_FOREIGN_CONTENT_IM;
3832        } elsif ($node->[1] & TABLE_CELL_EL) {        } elsif ($node->[1] == TABLE_CELL_EL) {
3833          if ($last) {          if ($last) {
3834            !!!cp ('t28.2');            !!!cp ('t28.2');
3835            #            #
# Line 3833  sub _reset_insertion_mode ($) { Line 3858  sub _reset_insertion_mode ($) {
3858        $self->{insertion_mode} = $new_mode and return if defined $new_mode;        $self->{insertion_mode} = $new_mode and return if defined $new_mode;
3859                
3860        ## Step 15        ## Step 15
3861        if ($node->[1] & HTML_EL) {        if ($node->[1] == HTML_EL) {
3862          unless (defined $self->{head_element}) {          unless (defined $self->{head_element}) {
3863            !!!cp ('t29');            !!!cp ('t29');
3864            $self->{insertion_mode} = BEFORE_HEAD_IM;            $self->{insertion_mode} = BEFORE_HEAD_IM;
# Line 3965  sub _tree_construction_main ($) { Line 3990  sub _tree_construction_main ($) {
3990    
3991      ## Step 1      ## Step 1
3992      my $start_tag_name = $token->{tag_name};      my $start_tag_name = $token->{tag_name};
3993      my $el;      !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
     !!!create-element ($el, $HTML_NS, $start_tag_name, $token->{attributes}, $token);  
3994    
3995      ## Step 2      ## Step 2
     $insert->($el);  
   
     ## Step 3  
3996      $self->{content_model} = $content_model_flag; # CDATA or RCDATA      $self->{content_model} = $content_model_flag; # CDATA or RCDATA
3997      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
3998    
3999      ## Step 4      ## Step 3, 4
4000      my $text = '';      $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
     !!!nack ('t40.1');  
     !!!next-token;  
     while ($token->{type} == CHARACTER_TOKEN) { # or until stop tokenizing  
       !!!cp ('t40');  
       $text .= $token->{data};  
       !!!next-token;  
     }  
4001    
4002      ## Step 5      !!!nack ('t40.1');
     if (length $text) {  
       !!!cp ('t41');  
       my $text = $self->{document}->create_text_node ($text);  
       $el->append_child ($text);  
     }  
   
     ## Step 6  
     $self->{content_model} = PCDATA_CONTENT_MODEL;  
   
     ## Step 7  
     if ($token->{type} == END_TAG_TOKEN and  
         $token->{tag_name} eq $start_tag_name) {  
       !!!cp ('t42');  
       ## Ignore the token  
     } else {  
       ## NOTE: An end-of-file token.  
       if ($content_model_flag == CDATA_CONTENT_MODEL) {  
         !!!cp ('t43');  
         !!!parse-error (type => 'in CDATA:#eof', token => $token);  
       } elsif ($content_model_flag == RCDATA_CONTENT_MODEL) {  
         !!!cp ('t44');  
         !!!parse-error (type => 'in RCDATA:#eof', token => $token);  
       } else {  
         die "$0: $content_model_flag in parse_rcdata";  
       }  
     }  
4003      !!!next-token;      !!!next-token;
4004    }; # $parse_rcdata    }; # $parse_rcdata
4005    
4006    my $script_start_tag = sub () {    my $script_start_tag = sub () {
4007        ## Step 1
4008      my $script_el;      my $script_el;
4009      !!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token);      !!!create-element ($script_el, $HTML_NS, 'script', $token->{attributes}, $token);
4010    
4011        ## Step 2
4012      ## TODO: mark as "parser-inserted"      ## TODO: mark as "parser-inserted"
4013    
4014        ## Step 3
4015        ## TODO: Mark as "already executed", if ...
4016    
4017        ## Step 4
4018        $insert->($script_el);
4019    
4020        ## ISSUE: $script_el is not put into the stack
4021        push @{$self->{open_elements}}, [$script_el, $el_category->{script}];
4022    
4023        ## Step 5
4024      $self->{content_model} = CDATA_CONTENT_MODEL;      $self->{content_model} = CDATA_CONTENT_MODEL;
4025      delete $self->{escape}; # MUST      delete $self->{escape}; # MUST
       
     my $text = '';  
     !!!nack ('t45.1');  
     !!!next-token;  
     while ($token->{type} == CHARACTER_TOKEN) {  
       !!!cp ('t45');  
       $text .= $token->{data};  
       !!!next-token;  
     } # stop if non-character token or tokenizer stops tokenising  
     if (length $text) {  
       !!!cp ('t46');  
       $script_el->manakai_append_text ($text);  
     }  
                 
     $self->{content_model} = PCDATA_CONTENT_MODEL;  
4026    
4027      if ($token->{type} == END_TAG_TOKEN and      ## Step 6-7
4028          $token->{tag_name} eq 'script') {      $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
       !!!cp ('t47');  
       ## Ignore the token  
     } else {  
       !!!cp ('t48');  
       !!!parse-error (type => 'in CDATA:#eof', token => $token);  
       ## ISSUE: And ignore?  
       ## TODO: mark as "already executed"  
     }  
       
     if (defined $self->{inner_html_node}) {  
       !!!cp ('t49');  
       ## TODO: mark as "already executed"  
     } else {  
       !!!cp ('t50');  
       ## TODO: $old_insertion_point = current insertion point  
       ## TODO: insertion point = just before the next input character  
4029    
4030        $insert->($script_el);      !!!nack ('t40.2');
         
       ## TODO: insertion point = $old_insertion_point (might be "undefined")  
         
       ## TODO: if there is a script that will execute as soon as the parser resume, then...  
     }  
       
4031      !!!next-token;      !!!next-token;
4032    }; # $script_start_tag    }; # $script_start_tag
4033    
4034    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.    ## NOTE: $open_tables->[-1]->[0] is the "current table" element node.
4035    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.    ## NOTE: $open_tables->[-1]->[1] is the "tainted" flag.
4036      ## NOTE: $open_tables->[-1]->[2] is set false when non-Text node inserted.
4037    my $open_tables = [[$self->{open_elements}->[0]->[0]]];    my $open_tables = [[$self->{open_elements}->[0]->[0]]];
4038    
4039    my $formatting_end_tag = sub {    my $formatting_end_tag = sub {
# Line 4153  sub _tree_construction_main ($) { Line 4118  sub _tree_construction_main ($) {
4118            !!!cp ('t59');            !!!cp ('t59');
4119            $furthest_block = $node;            $furthest_block = $node;
4120            $furthest_block_i_in_open = $_;            $furthest_block_i_in_open = $_;
4121              ## NOTE: The topmost (eldest) node.
4122          } elsif ($node->[0] eq $formatting_element->[0]) {          } elsif ($node->[0] eq $formatting_element->[0]) {
4123            !!!cp ('t60');            !!!cp ('t60');
4124            last OE;            last OE;
# Line 4239  sub _tree_construction_main ($) { Line 4205  sub _tree_construction_main ($) {
4205          my $foster_parent_element;          my $foster_parent_element;
4206          my $next_sibling;          my $next_sibling;
4207          OE: for (reverse 0..$#{$self->{open_elements}}) {          OE: for (reverse 0..$#{$self->{open_elements}}) {
4208            if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {            if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
4209                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4210                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
4211                                 !!!cp ('t65.1');                                 !!!cp ('t65.1');
# Line 4299  sub _tree_construction_main ($) { Line 4265  sub _tree_construction_main ($) {
4265            $i = $_;            $i = $_;
4266          }          }
4267        } # OE        } # OE
4268        splice @{$self->{open_elements}}, $i + 1, 1, $clone;        splice @{$self->{open_elements}}, $i + 1, 0, $clone;
4269                
4270        ## Step 14        ## Step 14
4271        redo FET;        redo FET;
# Line 4317  sub _tree_construction_main ($) { Line 4283  sub _tree_construction_main ($) {
4283        my $foster_parent_element;        my $foster_parent_element;
4284        my $next_sibling;        my $next_sibling;
4285        OE: for (reverse 0..$#{$self->{open_elements}}) {        OE: for (reverse 0..$#{$self->{open_elements}}) {
4286          if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {          if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
4287                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                               my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
4288                               if (defined $parent and $parent->node_type == 1) {                               if (defined $parent and $parent->node_type == 1) {
4289                                 !!!cp ('t70');                                 !!!cp ('t70');
# Line 4342  sub _tree_construction_main ($) { Line 4308  sub _tree_construction_main ($) {
4308      }      }
4309    }; # $insert_to_foster    }; # $insert_to_foster
4310    
4311      ## NOTE: Insert a character (MUST): When a character is inserted, if
4312      ## the last node that was inserted by the parser is a Text node and
4313      ## the character has to be inserted after that node, then the
4314      ## character is appended to the Text node.  However, if any other
4315      ## node is inserted by the parser, then a new Text node is created
4316      ## and the character is appended as that Text node.  If I'm not
4317      ## wrong, for a parser with scripting disabled, there are only two
4318      ## cases where this occurs.  One is the case where an element node
4319      ## is inserted to the |head| element.  This is covered by using the
4320      ## |$self->{head_element_inserted}| flag.  Another is the case where
4321      ## an element or comment is inserted into the |table| subtree while
4322      ## foster parenting happens.  This is covered by using the [2] flag
4323      ## of the |$open_tables| structure.  All other cases are handled
4324      ## simply by calling |manakai_append_text| method.
4325    
4326      ## TODO: |<body><script>document.write("a<br>");
4327      ## document.body.removeChild (document.body.lastChild);
4328      ## document.write ("b")</script>|
4329    
4330    B: while (1) {    B: while (1) {
4331      if ($token->{type} == DOCTYPE_TOKEN) {      if ($token->{type} == DOCTYPE_TOKEN) {
4332        !!!cp ('t73');        !!!cp ('t73');
# Line 4389  sub _tree_construction_main ($) { Line 4374  sub _tree_construction_main ($) {
4374        } else {        } else {
4375          !!!cp ('t87');          !!!cp ('t87');
4376          $self->{open_elements}->[-1]->[0]->append_child ($comment);          $self->{open_elements}->[-1]->[0]->append_child ($comment);
4377            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
4378        }        }
4379        !!!next-token;        !!!next-token;
4380        next B;        next B;
4381        } elsif ($self->{insertion_mode} & IN_CDATA_RCDATA_IM) {
4382          if ($token->{type} == CHARACTER_TOKEN) {
4383            $token->{data} =~ s/^\x0A// if $self->{ignore_newline};
4384            delete $self->{ignore_newline};
4385    
4386            if (length $token->{data}) {
4387              !!!cp ('t43');
4388              $self->{open_elements}->[-1]->[0]->manakai_append_text
4389                  ($token->{data});
4390            } else {
4391              !!!cp ('t43.1');
4392            }
4393            !!!next-token;
4394            next B;
4395          } elsif ($token->{type} == END_TAG_TOKEN) {
4396            delete $self->{ignore_newline};
4397    
4398            if ($token->{tag_name} eq 'script') {
4399              !!!cp ('t50');
4400              
4401              ## Para 1-2
4402              my $script = pop @{$self->{open_elements}};
4403              
4404              ## Para 3
4405              $self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM;
4406    
4407              ## Para 4
4408              ## TODO: $old_insertion_point = $current_insertion_point;
4409              ## TODO: $current_insertion_point = just before $self->{nc};
4410    
4411              ## Para 5
4412              ## TODO: Run the $script->[0].
4413    
4414              ## Para 6
4415              ## TODO: $current_insertion_point = $old_insertion_point;
4416    
4417              ## Para 7
4418              ## TODO: if ($pending_external_script) {
4419                ## TODO: ...
4420              ## TODO: }
4421    
4422              !!!next-token;
4423              next B;
4424            } else {
4425              !!!cp ('t42');
4426    
4427              pop @{$self->{open_elements}};
4428    
4429              $self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM;
4430              !!!next-token;
4431              next B;
4432            }
4433          } elsif ($token->{type} == END_OF_FILE_TOKEN) {
4434            delete $self->{ignore_newline};
4435    
4436            !!!cp ('t44');
4437            !!!parse-error (type => 'not closed',
4438                            text => $self->{open_elements}->[-1]->[0]
4439                                ->manakai_local_name,
4440                            token => $token);
4441    
4442            #if ($self->{open_elements}->[-1]->[1] == SCRIPT_EL) {
4443            #  ## TODO: Mark as "already executed"
4444            #}
4445    
4446            pop @{$self->{open_elements}};
4447    
4448            $self->{insertion_mode} &= ~ IN_CDATA_RCDATA_IM;
4449            ## Reprocess.
4450            next B;
4451          } else {
4452            die "$0: $token->{type}: In CDATA/RCDATA: Unknown token type";        
4453          }
4454      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {      } elsif ($self->{insertion_mode} & IN_FOREIGN_CONTENT_IM) {
4455        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4456          !!!cp ('t87.1');          !!!cp ('t87.1');
# Line 4403  sub _tree_construction_main ($) { Line 4462  sub _tree_construction_main ($) {
4462               $self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or               $self->{open_elements}->[-1]->[1] & FOREIGN_FLOW_CONTENT_EL) or
4463              not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or              not ($self->{open_elements}->[-1]->[1] & FOREIGN_EL) or
4464              ($token->{tag_name} eq 'svg' and              ($token->{tag_name} eq 'svg' and
4465               $self->{open_elements}->[-1]->[1] & MML_AXML_EL)) {               $self->{open_elements}->[-1]->[1] == MML_AXML_EL)) {
4466            ## NOTE: "using the rules for secondary insertion mode"then"continue"            ## NOTE: "using the rules for secondary insertion mode"then"continue"
4467            !!!cp ('t87.2');            !!!cp ('t87.2');
4468            #            #
# Line 4504  sub _tree_construction_main ($) { Line 4563  sub _tree_construction_main ($) {
4563          pop @{$self->{open_elements}}          pop @{$self->{open_elements}}
4564              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;              while $self->{open_elements}->[-1]->[1] & FOREIGN_EL;
4565    
4566            ## NOTE: |<span><svg>| ... two parse errors, |<svg>| ... a parse error.
4567    
4568          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;          $self->{insertion_mode} &= ~ IN_FOREIGN_CONTENT_IM;
4569          ## Reprocess.          ## Reprocess.
4570          next B;          next B;
# Line 4516  sub _tree_construction_main ($) { Line 4577  sub _tree_construction_main ($) {
4577        if ($token->{type} == CHARACTER_TOKEN) {        if ($token->{type} == CHARACTER_TOKEN) {
4578          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {          if ($token->{data} =~ s/^([\x09\x0A\x0C\x20]+)//) {
4579            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {            unless ($self->{insertion_mode} == BEFORE_HEAD_IM) {
4580              !!!cp ('t88.2');              if ($self->{head_element_inserted}) {
4581              $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);                !!!cp ('t88.3');
4582              #                $self->{open_elements}->[-1]->[0]->append_child
4583                    ($self->{document}->create_text_node ($1));
4584                  delete $self->{head_element_inserted};
4585                  ## NOTE: |</head> <link> |
4586                  #
4587                } else {
4588                  !!!cp ('t88.2');
4589                  $self->{open_elements}->[-1]->[0]->manakai_append_text ($1);
4590                  ## NOTE: |</head> &#x20;|
4591                  #
4592                }
4593            } else {            } else {
4594              !!!cp ('t88.1');              !!!cp ('t88.1');
4595              ## Ignore the token.              ## Ignore the token.
# Line 4614  sub _tree_construction_main ($) { Line 4685  sub _tree_construction_main ($) {
4685            !!!cp ('t97');            !!!cp ('t97');
4686          }          }
4687    
4688              if ($token->{tag_name} eq 'base') {          if ($token->{tag_name} eq 'base') {
4689                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4690                  !!!cp ('t98');              !!!cp ('t98');
4691                  ## As if </noscript>              ## As if </noscript>
4692                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4693                  !!!parse-error (type => 'in noscript', text => 'base',              !!!parse-error (type => 'in noscript', text => 'base',
4694                                  token => $token);                              token => $token);
4695                            
4696                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4697                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4698                } else {            } else {
4699                  !!!cp ('t99');              !!!cp ('t99');
4700                }            }
4701    
4702                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4703                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4704                  !!!cp ('t100');              !!!cp ('t100');
4705                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4706                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4707                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4708                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4709                } else {              $self->{head_element_inserted} = 1;
4710                  !!!cp ('t101');            } else {
4711                }              !!!cp ('t101');
4712                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            }
4713                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4714                pop @{$self->{open_elements}} # <head>            pop @{$self->{open_elements}};
4715                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}} # <head>
4716                !!!nack ('t101.1');                if $self->{insertion_mode} == AFTER_HEAD_IM;
4717                !!!next-token;            !!!nack ('t101.1');
4718                next B;            !!!next-token;
4719              } elsif ($token->{tag_name} eq 'link') {            next B;
4720                ## NOTE: There is a "as if in head" code clone.          } elsif ($token->{tag_name} eq 'link') {
4721                if ($self->{insertion_mode} == AFTER_HEAD_IM) {            ## NOTE: There is a "as if in head" code clone.
4722                  !!!cp ('t102');            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4723                  !!!parse-error (type => 'after head',              !!!cp ('t102');
4724                                  text => $token->{tag_name}, token => $token);              !!!parse-error (type => 'after head',
4725                  push @{$self->{open_elements}},                              text => $token->{tag_name}, token => $token);
4726                      [$self->{head_element}, $el_category->{head}];              push @{$self->{open_elements}},
4727                } else {                  [$self->{head_element}, $el_category->{head}];
4728                  !!!cp ('t103');              $self->{head_element_inserted} = 1;
4729                }            } else {
4730                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!cp ('t103');
4731                pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.            }
4732                pop @{$self->{open_elements}} # <head>            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4733                    if $self->{insertion_mode} == AFTER_HEAD_IM;            pop @{$self->{open_elements}};
4734                !!!ack ('t103.1');            pop @{$self->{open_elements}} # <head>
4735                !!!next-token;                if $self->{insertion_mode} == AFTER_HEAD_IM;
4736                next B;            !!!ack ('t103.1');
4737              } elsif ($token->{tag_name} eq 'meta') {            !!!next-token;
4738                ## NOTE: There is a "as if in head" code clone.            next B;
4739                if ($self->{insertion_mode} == AFTER_HEAD_IM) {          } elsif ($token->{tag_name} eq 'command' or
4740                  !!!cp ('t104');                   $token->{tag_name} eq 'eventsource') {
4741                  !!!parse-error (type => 'after head',            if ($self->{insertion_mode} == IN_HEAD_IM) {
4742                                  text => $token->{tag_name}, token => $token);              ## NOTE: If the insertion mode at the time of the emission
4743                  push @{$self->{open_elements}},              ## of the token was "before head", $self->{insertion_mode}
4744                      [$self->{head_element}, $el_category->{head}];              ## is already changed to |IN_HEAD_IM|.
4745                } else {  
4746                  !!!cp ('t105');              ## NOTE: There is a "as if in head" code clone.
4747                }              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4748                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              pop @{$self->{open_elements}};
4749                my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.              pop @{$self->{open_elements}} # <head>
4750                    if $self->{insertion_mode} == AFTER_HEAD_IM;
4751                !!!ack ('t103.2');
4752                !!!next-token;
4753                next B;
4754              } else {
4755                ## NOTE: "in head noscript" or "after head" insertion mode
4756                ## - in these cases, these tags are treated as same as
4757                ## normal in-body tags.
4758                !!!cp ('t103.3');
4759                #
4760              }
4761            } elsif ($token->{tag_name} eq 'meta') {
4762              ## NOTE: There is a "as if in head" code clone.
4763              if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4764                !!!cp ('t104');
4765                !!!parse-error (type => 'after head',
4766                                text => $token->{tag_name}, token => $token);
4767                push @{$self->{open_elements}},
4768                    [$self->{head_element}, $el_category->{head}];
4769                $self->{head_element_inserted} = 1;
4770              } else {
4771                !!!cp ('t105');
4772              }
4773              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
4774              my $meta_el = pop @{$self->{open_elements}};
4775    
4776                unless ($self->{confident}) {                unless ($self->{confident}) {
4777                  if ($token->{attributes}->{charset}) {                  if ($token->{attributes}->{charset}) {
# Line 4733  sub _tree_construction_main ($) { Line 4829  sub _tree_construction_main ($) {
4829                !!!ack ('t110.1');                !!!ack ('t110.1');
4830                !!!next-token;                !!!next-token;
4831                next B;                next B;
4832              } elsif ($token->{tag_name} eq 'title') {          } elsif ($token->{tag_name} eq 'title') {
4833                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4834                  !!!cp ('t111');              !!!cp ('t111');
4835                  ## As if </noscript>              ## As if </noscript>
4836                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4837                  !!!parse-error (type => 'in noscript', text => 'title',              !!!parse-error (type => 'in noscript', text => 'title',
4838                                  token => $token);                              token => $token);
4839                            
4840                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4841                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4842                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4843                  !!!cp ('t112');              !!!cp ('t112');
4844                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4845                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4846                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4847                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4848                } else {              $self->{head_element_inserted} = 1;
4849                  !!!cp ('t113');            } else {
4850                }              !!!cp ('t113');
4851              }
4852    
4853                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4854                my $parent = defined $self->{head_element} ? $self->{head_element}            $parse_rcdata->(RCDATA_CONTENT_MODEL);
4855                    : $self->{open_elements}->[-1]->[0];            ## ISSUE: A spec bug [Bug 6038]
4856                $parse_rcdata->(RCDATA_CONTENT_MODEL);            splice @{$self->{open_elements}}, -2, 1, () # <head>
4857                pop @{$self->{open_elements}} # <head>                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;
4858                    if $self->{insertion_mode} == AFTER_HEAD_IM;            next B;
4859                next B;          } elsif ($token->{tag_name} eq 'style' or
4860              } elsif ($token->{tag_name} eq 'style' or                   $token->{tag_name} eq 'noframes') {
4861                       $token->{tag_name} eq 'noframes') {            ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and
4862                ## NOTE: Or (scripting is enabled and tag_name eq 'noscript' and            ## insertion mode IN_HEAD_IM)
4863                ## insertion mode IN_HEAD_IM)            ## NOTE: There is a "as if in head" code clone.
4864                ## NOTE: There is a "as if in head" code clone.            if ($self->{insertion_mode} == AFTER_HEAD_IM) {
4865                if ($self->{insertion_mode} == AFTER_HEAD_IM) {              !!!cp ('t114');
4866                  !!!cp ('t114');              !!!parse-error (type => 'after head',
4867                  !!!parse-error (type => 'after head',                              text => $token->{tag_name}, token => $token);
4868                                  text => $token->{tag_name}, token => $token);              push @{$self->{open_elements}},
4869                  push @{$self->{open_elements}},                  [$self->{head_element}, $el_category->{head}];
4870                      [$self->{head_element}, $el_category->{head}];              $self->{head_element_inserted} = 1;
4871                } else {            } else {
4872                  !!!cp ('t115');              !!!cp ('t115');
4873                }            }
4874                $parse_rcdata->(CDATA_CONTENT_MODEL);            $parse_rcdata->(CDATA_CONTENT_MODEL);
4875                pop @{$self->{open_elements}} # <head>            ## ISSUE: A spec bug [Bug 6038]
4876                    if $self->{insertion_mode} == AFTER_HEAD_IM;            splice @{$self->{open_elements}}, -2, 1, () # <head>
4877                next B;                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;
4878              } elsif ($token->{tag_name} eq 'noscript') {            next B;
4879            } elsif ($token->{tag_name} eq 'noscript') {
4880                if ($self->{insertion_mode} == IN_HEAD_IM) {                if ($self->{insertion_mode} == IN_HEAD_IM) {
4881                  !!!cp ('t116');                  !!!cp ('t116');
4882                  ## NOTE: and scripting is disalbed                  ## NOTE: and scripting is disalbed
# Line 4799  sub _tree_construction_main ($) { Line 4897  sub _tree_construction_main ($) {
4897                  !!!cp ('t118');                  !!!cp ('t118');
4898                  #                  #
4899                }                }
4900              } elsif ($token->{tag_name} eq 'script') {          } elsif ($token->{tag_name} eq 'script') {
4901                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {            if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4902                  !!!cp ('t119');              !!!cp ('t119');
4903                  ## As if </noscript>              ## As if </noscript>
4904                  pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
4905                  !!!parse-error (type => 'in noscript', text => 'script',              !!!parse-error (type => 'in noscript', text => 'script',
4906                                  token => $token);                              token => $token);
4907                            
4908                  $self->{insertion_mode} = IN_HEAD_IM;              $self->{insertion_mode} = IN_HEAD_IM;
4909                  ## Reprocess in the "in head" insertion mode...              ## Reprocess in the "in head" insertion mode...
4910                } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {            } elsif ($self->{insertion_mode} == AFTER_HEAD_IM) {
4911                  !!!cp ('t120');              !!!cp ('t120');
4912                  !!!parse-error (type => 'after head',              !!!parse-error (type => 'after head',
4913                                  text => $token->{tag_name}, token => $token);                              text => $token->{tag_name}, token => $token);
4914                  push @{$self->{open_elements}},              push @{$self->{open_elements}},
4915                      [$self->{head_element}, $el_category->{head}];                  [$self->{head_element}, $el_category->{head}];
4916                } else {              $self->{head_element_inserted} = 1;
4917                  !!!cp ('t121');            } else {
4918                }              !!!cp ('t121');
4919              }
4920    
4921                ## NOTE: There is a "as if in head" code clone.            ## NOTE: There is a "as if in head" code clone.
4922                $script_start_tag->();            $script_start_tag->();
4923                pop @{$self->{open_elements}} # <head>            ## ISSUE: A spec bug  [Bug 6038]
4924                    if $self->{insertion_mode} == AFTER_HEAD_IM;            splice @{$self->{open_elements}}, -2, 1 # <head>
4925                next B;                if ($self->{insertion_mode} & AFTER_HEAD_IM) == AFTER_HEAD_IM;
4926              } elsif ($token->{tag_name} eq 'body' or            next B;
4927                       $token->{tag_name} eq 'frameset') {          } elsif ($token->{tag_name} eq 'body' or
4928                     $token->{tag_name} eq 'frameset') {
4929                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                if ($self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
4930                  !!!cp ('t122');                  !!!cp ('t122');
4931                  ## As if </noscript>                  ## As if </noscript>
# Line 4960  sub _tree_construction_main ($) { Line 5060  sub _tree_construction_main ($) {
5060              } elsif ({              } elsif ({
5061                        body => 1, html => 1,                        body => 1, html => 1,
5062                       }->{$token->{tag_name}}) {                       }->{$token->{tag_name}}) {
5063                if ($self->{insertion_mode} == BEFORE_HEAD_IM or                ## TODO: This branch is entirely redundant.
5064                  if ($self->{insertion_mode} == BEFORE_HEAD_IM or
5065                    $self->{insertion_mode} == IN_HEAD_IM or                    $self->{insertion_mode} == IN_HEAD_IM or
5066                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {                    $self->{insertion_mode} == IN_HEAD_NOSCRIPT_IM) {
5067                  !!!cp ('t140');                  !!!cp ('t140');
# Line 5132  sub _tree_construction_main ($) { Line 5233  sub _tree_construction_main ($) {
5233        } else {        } else {
5234          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
5235        }        }
   
           ## ISSUE: An issue in the spec.  
5236      } elsif ($self->{insertion_mode} & BODY_IMS) {      } elsif ($self->{insertion_mode} & BODY_IMS) {
5237            if ($token->{type} == CHARACTER_TOKEN) {            if ($token->{type} == CHARACTER_TOKEN) {
5238              !!!cp ('t150');              !!!cp ('t150');
# Line 5153  sub _tree_construction_main ($) { Line 5252  sub _tree_construction_main ($) {
5252                  ## have an element in table scope                  ## have an element in table scope
5253                  for (reverse 0..$#{$self->{open_elements}}) {                  for (reverse 0..$#{$self->{open_elements}}) {
5254                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5255                    if ($node->[1] & TABLE_CELL_EL) {                    if ($node->[1] == TABLE_CELL_EL) {
5256                      !!!cp ('t151');                      !!!cp ('t151');
5257    
5258                      ## Close the cell                      ## Close the cell
# Line 5187  sub _tree_construction_main ($) { Line 5286  sub _tree_construction_main ($) {
5286                  INSCOPE: {                  INSCOPE: {
5287                    for (reverse 0..$#{$self->{open_elements}}) {                    for (reverse 0..$#{$self->{open_elements}}) {
5288                      my $node = $self->{open_elements}->[$_];                      my $node = $self->{open_elements}->[$_];
5289                      if ($node->[1] & CAPTION_EL) {                      if ($node->[1] == CAPTION_EL) {
5290                        !!!cp ('t155');                        !!!cp ('t155');
5291                        $i = $_;                        $i = $_;
5292                        last INSCOPE;                        last INSCOPE;
# Line 5213  sub _tree_construction_main ($) { Line 5312  sub _tree_construction_main ($) {
5312                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5313                  }                  }
5314    
5315                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                  unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) {
5316                    !!!cp ('t159');                    !!!cp ('t159');
5317                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
5318                                    text => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
# Line 5310  sub _tree_construction_main ($) { Line 5409  sub _tree_construction_main ($) {
5409                  INSCOPE: {                  INSCOPE: {
5410                    for (reverse 0..$#{$self->{open_elements}}) {                    for (reverse 0..$#{$self->{open_elements}}) {
5411                      my $node = $self->{open_elements}->[$_];                      my $node = $self->{open_elements}->[$_];
5412                      if ($node->[1] & CAPTION_EL) {                      if ($node->[1] == CAPTION_EL) {
5413                        !!!cp ('t171');                        !!!cp ('t171');
5414                        $i = $_;                        $i = $_;
5415                        last INSCOPE;                        last INSCOPE;
# Line 5335  sub _tree_construction_main ($) { Line 5434  sub _tree_construction_main ($) {
5434                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5435                  }                  }
5436                                    
5437                  unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                  unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) {
5438                    !!!cp ('t175');                    !!!cp ('t175');
5439                    !!!parse-error (type => 'not closed',                    !!!parse-error (type => 'not closed',
5440                                    text => $self->{open_elements}->[-1]->[0]                                    text => $self->{open_elements}->[-1]->[0]
# Line 5385  sub _tree_construction_main ($) { Line 5484  sub _tree_construction_main ($) {
5484                                line => $token->{line},                                line => $token->{line},
5485                                column => $token->{column}};                                column => $token->{column}};
5486                      next B;                      next B;
5487                    } elsif ($node->[1] & TABLE_CELL_EL) {                    } elsif ($node->[1] == TABLE_CELL_EL) {
5488                      !!!cp ('t180');                      !!!cp ('t180');
5489                      $tn = $node->[0]->manakai_local_name;                      $tn = $node->[0]->manakai_local_name;
5490                      ## NOTE: There is exactly one |td| or |th| element                      ## NOTE: There is exactly one |td| or |th| element
# Line 5414  sub _tree_construction_main ($) { Line 5513  sub _tree_construction_main ($) {
5513                my $i;                my $i;
5514                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5515                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5516                  if ($node->[1] & CAPTION_EL) {                  if ($node->[1] == CAPTION_EL) {
5517                    !!!cp ('t184');                    !!!cp ('t184');
5518                    $i = $_;                    $i = $_;
5519                    last INSCOPE;                    last INSCOPE;
# Line 5438  sub _tree_construction_main ($) { Line 5537  sub _tree_construction_main ($) {
5537                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5538                }                }
5539    
5540                unless ($self->{open_elements}->[-1]->[1] & CAPTION_EL) {                unless ($self->{open_elements}->[-1]->[1] == CAPTION_EL) {
5541                  !!!cp ('t188');                  !!!cp ('t188');
5542                  !!!parse-error (type => 'not closed',                  !!!parse-error (type => 'not closed',
5543                                  text => $self->{open_elements}->[-1]->[0]                                  text => $self->{open_elements}->[-1]->[0]
# Line 5519  sub _tree_construction_main ($) { Line 5618  sub _tree_construction_main ($) {
5618    
5619          !!!parse-error (type => 'in table:#text', token => $token);          !!!parse-error (type => 'in table:#text', token => $token);
5620    
5621              ## As if in body, but insert into foster parent element          ## NOTE: As if in body, but insert into the foster parent element.
5622              ## ISSUE: Spec says that "whenever a node would be inserted          $reconstruct_active_formatting_elements->($insert_to_foster);
             ## into the current node" while characters might not be  
             ## result in a new Text node.  
             $reconstruct_active_formatting_elements->($insert_to_foster);  
5623                            
5624              if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {          if ($self->{open_elements}->[-1]->[1] & TABLE_ROWS_EL) {
5625                # MUST            # MUST
5626                my $foster_parent_element;            my $foster_parent_element;
5627                my $next_sibling;            my $next_sibling;
5628                my $prev_sibling;            my $prev_sibling;
5629                OE: for (reverse 0..$#{$self->{open_elements}}) {            OE: for (reverse 0..$#{$self->{open_elements}}) {
5630                  if ($self->{open_elements}->[$_]->[1] & TABLE_EL) {              if ($self->{open_elements}->[$_]->[1] == TABLE_EL) {
5631                    my $parent = $self->{open_elements}->[$_]->[0]->parent_node;                my $parent = $self->{open_elements}->[$_]->[0]->parent_node;
5632                    if (defined $parent and $parent->node_type == 1) {                if (defined $parent and $parent->node_type == 1) {
5633                      !!!cp ('t196');                  $foster_parent_element = $parent;
5634                      $foster_parent_element = $parent;                  !!!cp ('t196');
5635                      $next_sibling = $self->{open_elements}->[$_]->[0];                  $next_sibling = $self->{open_elements}->[$_]->[0];
5636                      $prev_sibling = $next_sibling->previous_sibling;                  $prev_sibling = $next_sibling->previous_sibling;
5637                    } 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;  
               if (defined $prev_sibling and  
                   $prev_sibling->node_type == 3) {  
                 !!!cp ('t198');  
                 $prev_sibling->manakai_append_text ($token->{data});  
5638                } else {                } else {
5639                  !!!cp ('t199');                  !!!cp ('t197');
5640                  $foster_parent_element->insert_before                  $foster_parent_element = $self->{open_elements}->[$_ - 1]->[0];
5641                    ($self->{document}->create_text_node ($token->{data}),                  $prev_sibling = $foster_parent_element->last_child;
5642                     $next_sibling);                  #
5643                }                }
5644                  last OE;
5645                }
5646              } # OE
5647              $foster_parent_element = $self->{open_elements}->[0]->[0] and
5648              $prev_sibling = $foster_parent_element->last_child
5649                  unless defined $foster_parent_element;
5650              undef $prev_sibling unless $open_tables->[-1]->[2]; # ~node inserted
5651              if (defined $prev_sibling and
5652                  $prev_sibling->node_type == 3) {
5653                !!!cp ('t198');
5654                $prev_sibling->manakai_append_text ($token->{data});
5655              } else {
5656                !!!cp ('t199');
5657                $foster_parent_element->insert_before
5658                    ($self->{document}->create_text_node ($token->{data}),
5659                     $next_sibling);
5660              }
5661            $open_tables->[-1]->[1] = 1; # tainted            $open_tables->[-1]->[1] = 1; # tainted
5662              $open_tables->[-1]->[2] = 1; # ~node inserted
5663          } else {          } else {
5664              ## NOTE: Fragment case or in a foster parent'ed element
5665              ## (e.g. |<table><span>a|).  In fragment case, whether the
5666              ## character is appended to existing node or a new node is
5667              ## created is irrelevant, since the foster parent'ed nodes
5668              ## are discarded and fragment parsing does not invoke any
5669              ## script.
5670            !!!cp ('t200');            !!!cp ('t200');
5671            $self->{open_elements}->[-1]->[0]->manakai_append_text ($token->{data});            $self->{open_elements}->[-1]->[0]->manakai_append_text
5672                  ($token->{data});
5673          }          }
5674                            
5675          !!!next-token;          !!!next-token;
# Line 5599  sub _tree_construction_main ($) { Line 5706  sub _tree_construction_main ($) {
5706                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5707              }              }
5708                                    
5709                  $self->{insertion_mode} = IN_ROW_IM;              $self->{insertion_mode} = IN_ROW_IM;
5710                  if ($token->{tag_name} eq 'tr') {              if ($token->{tag_name} eq 'tr') {
5711                    !!!cp ('t204');                !!!cp ('t204');
5712                    !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5713                    !!!nack ('t204');                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5714                    !!!next-token;                !!!nack ('t204');
5715                    next B;                !!!next-token;
5716                  } else {                next B;
5717                    !!!cp ('t205');              } else {
5718                    !!!insert-element ('tr',, $token);                !!!cp ('t205');
5719                    ## reprocess in the "in row" insertion mode                !!!insert-element ('tr',, $token);
5720                  }                ## reprocess in the "in row" insertion mode
5721                } else {              }
5722                  !!!cp ('t206');            } else {
5723                }              !!!cp ('t206');
5724              }
5725    
5726                ## Clear back to table row context                ## Clear back to table row context
5727                while (not ($self->{open_elements}->[-1]->[1]                while (not ($self->{open_elements}->[-1]->[1]
# Line 5622  sub _tree_construction_main ($) { Line 5730  sub _tree_construction_main ($) {
5730                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5731                }                }
5732                                
5733                !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);            !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5734                $self->{insertion_mode} = IN_CELL_IM;            $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5735              $self->{insertion_mode} = IN_CELL_IM;
5736    
5737                push @$active_formatting_elements, ['#marker', ''];            push @$active_formatting_elements, ['#marker', ''];
5738                                
5739                !!!nack ('t207.1');            !!!nack ('t207.1');
5740              !!!next-token;
5741              next B;
5742            } elsif ({
5743                      caption => 1, col => 1, colgroup => 1,
5744                      tbody => 1, tfoot => 1, thead => 1,
5745                      tr => 1, # $self->{insertion_mode} == IN_ROW_IM
5746                     }->{$token->{tag_name}}) {
5747              if ($self->{insertion_mode} == IN_ROW_IM) {
5748                ## As if </tr>
5749                ## have an element in table scope
5750                my $i;
5751                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5752                  my $node = $self->{open_elements}->[$_];
5753                  if ($node->[1] == TABLE_ROW_EL) {
5754                    !!!cp ('t208');
5755                    $i = $_;
5756                    last INSCOPE;
5757                  } elsif ($node->[1] & TABLE_SCOPING_EL) {
5758                    !!!cp ('t209');
5759                    last INSCOPE;
5760                  }
5761                } # INSCOPE
5762                unless (defined $i) {
5763                  !!!cp ('t210');
5764                  ## TODO: This type is wrong.
5765                  !!!parse-error (type => 'unmacthed end tag',
5766                                  text => $token->{tag_name}, token => $token);
5767                  ## Ignore the token
5768                  !!!nack ('t210.1');
5769                !!!next-token;                !!!next-token;
5770                next B;                next B;
5771              } elsif ({              }
                       caption => 1, col => 1, colgroup => 1,  
                       tbody => 1, tfoot => 1, thead => 1,  
                       tr => 1, # $self->{insertion_mode} == IN_ROW_IM  
                      }->{$token->{tag_name}}) {  
               if ($self->{insertion_mode} == IN_ROW_IM) {  
                 ## As if </tr>  
                 ## have an element in table scope  
                 my $i;  
                 INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {  
                   my $node = $self->{open_elements}->[$_];  
                   if ($node->[1] & TABLE_ROW_EL) {  
                     !!!cp ('t208');  
                     $i = $_;  
                     last INSCOPE;  
                   } elsif ($node->[1] & TABLE_SCOPING_EL) {  
                     !!!cp ('t209');  
                     last INSCOPE;  
                   }  
                 } # INSCOPE  
                 unless (defined $i) {  
                   !!!cp ('t210');  
 ## TODO: This type is wrong.  
                   !!!parse-error (type => 'unmacthed end tag',  
                                   text => $token->{tag_name}, token => $token);  
                   ## Ignore the token  
                   !!!nack ('t210.1');  
                   !!!next-token;  
                   next B;  
                 }  
5772                                    
5773                  ## Clear back to table row context                  ## Clear back to table row context
5774                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
# Line 5687  sub _tree_construction_main ($) { Line 5796  sub _tree_construction_main ($) {
5796                  my $i;                  my $i;
5797                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5798                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
5799                    if ($node->[1] & TABLE_ROW_GROUP_EL) {                    if ($node->[1] == TABLE_ROW_GROUP_EL) {
5800                      !!!cp ('t214');                      !!!cp ('t214');
5801                      $i = $_;                      $i = $_;
5802                      last INSCOPE;                      last INSCOPE;
# Line 5729  sub _tree_construction_main ($) { Line 5838  sub _tree_construction_main ($) {
5838                  !!!cp ('t218');                  !!!cp ('t218');
5839                }                }
5840    
5841                if ($token->{tag_name} eq 'col') {            if ($token->{tag_name} eq 'col') {
5842                  ## Clear back to table context              ## Clear back to table context
5843                  while (not ($self->{open_elements}->[-1]->[1]              while (not ($self->{open_elements}->[-1]->[1]
5844                                  & TABLE_SCOPING_EL)) {                              & TABLE_SCOPING_EL)) {
5845                    !!!cp ('t219');                !!!cp ('t219');
5846                    ## ISSUE: Can this state be reached?                ## ISSUE: Can this state be reached?
5847                    pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
5848                  }              }
5849                                
5850                  !!!insert-element ('colgroup',, $token);              !!!insert-element ('colgroup',, $token);
5851                  $self->{insertion_mode} = IN_COLUMN_GROUP_IM;              $self->{insertion_mode} = IN_COLUMN_GROUP_IM;
5852                  ## reprocess              ## reprocess
5853                  !!!ack-later;              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5854                  next B;              !!!ack-later;
5855                } elsif ({              next B;
5856                          caption => 1,            } elsif ({
5857                          colgroup => 1,                      caption => 1,
5858                          tbody => 1, tfoot => 1, thead => 1,                      colgroup => 1,
5859                         }->{$token->{tag_name}}) {                      tbody => 1, tfoot => 1, thead => 1,
5860                  ## Clear back to table context                     }->{$token->{tag_name}}) {
5861                ## Clear back to table context
5862                  while (not ($self->{open_elements}->[-1]->[1]                  while (not ($self->{open_elements}->[-1]->[1]
5863                                  & TABLE_SCOPING_EL)) {                                  & TABLE_SCOPING_EL)) {
5864                    !!!cp ('t220');                    !!!cp ('t220');
# Line 5756  sub _tree_construction_main ($) { Line 5866  sub _tree_construction_main ($) {
5866                    pop @{$self->{open_elements}};                    pop @{$self->{open_elements}};
5867                  }                  }
5868                                    
5869                  push @$active_formatting_elements, ['#marker', '']              push @$active_formatting_elements, ['#marker', '']
5870                      if $token->{tag_name} eq 'caption';                  if $token->{tag_name} eq 'caption';
5871                                    
5872                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);              !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5873                  $self->{insertion_mode} = {              $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5874                                             caption => IN_CAPTION_IM,              $self->{insertion_mode} = {
5875                                             colgroup => IN_COLUMN_GROUP_IM,                                         caption => IN_CAPTION_IM,
5876                                             tbody => IN_TABLE_BODY_IM,                                         colgroup => IN_COLUMN_GROUP_IM,
5877                                             tfoot => IN_TABLE_BODY_IM,                                         tbody => IN_TABLE_BODY_IM,
5878                                             thead => IN_TABLE_BODY_IM,                                         tfoot => IN_TABLE_BODY_IM,
5879                                            }->{$token->{tag_name}};                                         thead => IN_TABLE_BODY_IM,
5880                  !!!next-token;                                        }->{$token->{tag_name}};
5881                  !!!nack ('t220.1');              !!!next-token;
5882                  next B;              !!!nack ('t220.1');
5883                } else {              next B;
5884                  die "$0: in table: <>: $token->{tag_name}";            } else {
5885                }              die "$0: in table: <>: $token->{tag_name}";
5886              }
5887              } elsif ($token->{tag_name} eq 'table') {              } elsif ($token->{tag_name} eq 'table') {
5888                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
5889                                text => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
# Line 5784  sub _tree_construction_main ($) { Line 5895  sub _tree_construction_main ($) {
5895                my $i;                my $i;
5896                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
5897                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
5898                  if ($node->[1] & TABLE_EL) {                  if ($node->[1] == TABLE_EL) {
5899                    !!!cp ('t221');                    !!!cp ('t221');
5900                    $i = $_;                    $i = $_;
5901                    last INSCOPE;                    last INSCOPE;
# Line 5811  sub _tree_construction_main ($) { Line 5922  sub _tree_construction_main ($) {
5922                  pop @{$self->{open_elements}};                  pop @{$self->{open_elements}};
5923                }                }
5924    
5925                unless ($self->{open_elements}->[-1]->[1] & TABLE_EL) {                unless ($self->{open_elements}->[-1]->[1] == TABLE_EL) {
5926                  !!!cp ('t225');                  !!!cp ('t225');
5927                  ## NOTE: |<table><tr><table>|                  ## NOTE: |<table><tr><table>|
5928                  !!!parse-error (type => 'not closed',                  !!!parse-error (type => 'not closed',
# Line 5835  sub _tree_construction_main ($) { Line 5946  sub _tree_construction_main ($) {
5946              !!!cp ('t227.8');              !!!cp ('t227.8');
5947              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5948              $parse_rcdata->(CDATA_CONTENT_MODEL);              $parse_rcdata->(CDATA_CONTENT_MODEL);
5949                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5950              next B;              next B;
5951            } else {            } else {
5952              !!!cp ('t227.7');              !!!cp ('t227.7');
# Line 5845  sub _tree_construction_main ($) { Line 5957  sub _tree_construction_main ($) {
5957              !!!cp ('t227.6');              !!!cp ('t227.6');
5958              ## NOTE: This is a "as if in head" code clone.              ## NOTE: This is a "as if in head" code clone.
5959              $script_start_tag->();              $script_start_tag->();
5960                $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5961              next B;              next B;
5962            } else {            } else {
5963              !!!cp ('t227.5');              !!!cp ('t227.5');
# Line 5860  sub _tree_construction_main ($) { Line 5973  sub _tree_construction_main ($) {
5973                                  text => $token->{tag_name}, token => $token);                                  text => $token->{tag_name}, token => $token);
5974    
5975                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);                  !!!insert-element ($token->{tag_name}, $token->{attributes}, $token);
5976                    $open_tables->[-1]->[2] = 0 if @$open_tables; # ~node inserted
5977    
5978                  ## TODO: form element pointer                  ## TODO: form element pointer
5979    
# Line 5897  sub _tree_construction_main ($) { Line 6011  sub _tree_construction_main ($) {
6011                my $i;                my $i;
6012                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6013                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
6014                  if ($node->[1] & TABLE_ROW_EL) {                  if ($node->[1] == TABLE_ROW_EL) {
6015                    !!!cp ('t228');                    !!!cp ('t228');
6016                    $i = $_;                    $i = $_;
6017                    last INSCOPE;                    last INSCOPE;
# Line 5938  sub _tree_construction_main ($) { Line 6052  sub _tree_construction_main ($) {
6052                  my $i;                  my $i;
6053                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6054                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
6055                    if ($node->[1] & TABLE_ROW_EL) {                    if ($node->[1] == TABLE_ROW_EL) {
6056                      !!!cp ('t233');                      !!!cp ('t233');
6057                      $i = $_;                      $i = $_;
6058                      last INSCOPE;                      last INSCOPE;
# Line 5976  sub _tree_construction_main ($) { Line 6090  sub _tree_construction_main ($) {
6090                  my $i;                  my $i;
6091                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6092                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
6093                    if ($node->[1] & TABLE_ROW_GROUP_EL) {                    if ($node->[1] == TABLE_ROW_GROUP_EL) {
6094                      !!!cp ('t237');                      !!!cp ('t237');
6095                      $i = $_;                      $i = $_;
6096                      last INSCOPE;                      last INSCOPE;
# Line 6023  sub _tree_construction_main ($) { Line 6137  sub _tree_construction_main ($) {
6137                my $i;                my $i;
6138                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6139                  my $node = $self->{open_elements}->[$_];                  my $node = $self->{open_elements}->[$_];
6140                  if ($node->[1] & TABLE_EL) {                  if ($node->[1] == TABLE_EL) {
6141                    !!!cp ('t241');                    !!!cp ('t241');
6142                    $i = $_;                    $i = $_;
6143                    last INSCOPE;                    last INSCOPE;
# Line 6082  sub _tree_construction_main ($) { Line 6196  sub _tree_construction_main ($) {
6196                  my $i;                  my $i;
6197                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {                  INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6198                    my $node = $self->{open_elements}->[$_];                    my $node = $self->{open_elements}->[$_];
6199                    if ($node->[1] & TABLE_ROW_EL) {                    if ($node->[1] == TABLE_ROW_EL) {
6200                      !!!cp ('t250');                      !!!cp ('t250');
6201                      $i = $_;                      $i = $_;
6202                      last INSCOPE;                      last INSCOPE;
# Line 6172  sub _tree_construction_main ($) { Line 6286  sub _tree_construction_main ($) {
6286            #            #
6287          }          }
6288        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6289          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] == HTML_EL and
6290                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
6291            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
6292            !!!cp ('t259.1');            !!!cp ('t259.1');
# Line 6214  sub _tree_construction_main ($) { Line 6328  sub _tree_construction_main ($) {
6328              }              }
6329            } elsif ($token->{type} == END_TAG_TOKEN) {            } elsif ($token->{type} == END_TAG_TOKEN) {
6330              if ($token->{tag_name} eq 'colgroup') {              if ($token->{tag_name} eq 'colgroup') {
6331                if ($self->{open_elements}->[-1]->[1] & HTML_EL) {                if ($self->{open_elements}->[-1]->[1] == HTML_EL) {
6332                  !!!cp ('t264');                  !!!cp ('t264');
6333                  !!!parse-error (type => 'unmatched end tag',                  !!!parse-error (type => 'unmatched end tag',
6334                                  text => 'colgroup', token => $token);                                  text => 'colgroup', token => $token);
# Line 6240  sub _tree_construction_main ($) { Line 6354  sub _tree_construction_main ($) {
6354                #                #
6355              }              }
6356        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6357          if ($self->{open_elements}->[-1]->[1] & HTML_EL and          if ($self->{open_elements}->[-1]->[1] == HTML_EL and
6358              @{$self->{open_elements}} == 1) { # redundant, maybe              @{$self->{open_elements}} == 1) { # redundant, maybe
6359            !!!cp ('t270.2');            !!!cp ('t270.2');
6360            ## Stop parsing.            ## Stop parsing.
# Line 6258  sub _tree_construction_main ($) { Line 6372  sub _tree_construction_main ($) {
6372        }        }
6373    
6374            ## As if </colgroup>            ## As if </colgroup>
6375            if ($self->{open_elements}->[-1]->[1] & HTML_EL) {            if ($self->{open_elements}->[-1]->[1] == HTML_EL) {
6376              !!!cp ('t269');              !!!cp ('t269');
6377  ## TODO: Wrong error type?  ## TODO: Wrong error type?
6378              !!!parse-error (type => 'unmatched end tag',              !!!parse-error (type => 'unmatched end tag',
# Line 6283  sub _tree_construction_main ($) { Line 6397  sub _tree_construction_main ($) {
6397          next B;          next B;
6398        } elsif ($token->{type} == START_TAG_TOKEN) {        } elsif ($token->{type} == START_TAG_TOKEN) {
6399          if ($token->{tag_name} eq 'option') {          if ($token->{tag_name} eq 'option') {
6400            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTION_EL) {
6401              !!!cp ('t272');              !!!cp ('t272');
6402              ## As if </option>              ## As if </option>
6403              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6296  sub _tree_construction_main ($) { Line 6410  sub _tree_construction_main ($) {
6410            !!!next-token;            !!!next-token;
6411            next B;            next B;
6412          } elsif ($token->{tag_name} eq 'optgroup') {          } elsif ($token->{tag_name} eq 'optgroup') {
6413            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTION_EL) {
6414              !!!cp ('t274');              !!!cp ('t274');
6415              ## As if </option>              ## As if </option>
6416              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6304  sub _tree_construction_main ($) { Line 6418  sub _tree_construction_main ($) {
6418              !!!cp ('t275');              !!!cp ('t275');
6419            }            }
6420    
6421            if ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTGROUP_EL) {
6422              !!!cp ('t276');              !!!cp ('t276');
6423              ## As if </optgroup>              ## As if </optgroup>
6424              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
# Line 6334  sub _tree_construction_main ($) { Line 6448  sub _tree_construction_main ($) {
6448            my $i;            my $i;
6449            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6450              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
6451              if ($node->[1] & SELECT_EL) {              if ($node->[1] == SELECT_EL) {
6452                !!!cp ('t278');                !!!cp ('t278');
6453                $i = $_;                $i = $_;
6454                last INSCOPE;                last INSCOPE;
# Line 6379  sub _tree_construction_main ($) { Line 6493  sub _tree_construction_main ($) {
6493          }          }
6494        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6495          if ($token->{tag_name} eq 'optgroup') {          if ($token->{tag_name} eq 'optgroup') {
6496            if ($self->{open_elements}->[-1]->[1] & OPTION_EL and            if ($self->{open_elements}->[-1]->[1] == OPTION_EL and
6497                $self->{open_elements}->[-2]->[1] & OPTGROUP_EL) {                $self->{open_elements}->[-2]->[1] == OPTGROUP_EL) {
6498              !!!cp ('t283');              !!!cp ('t283');
6499              ## As if </option>              ## As if </option>
6500              splice @{$self->{open_elements}}, -2;              splice @{$self->{open_elements}}, -2;
6501            } elsif ($self->{open_elements}->[-1]->[1] & OPTGROUP_EL) {            } elsif ($self->{open_elements}->[-1]->[1] == OPTGROUP_EL) {
6502              !!!cp ('t284');              !!!cp ('t284');
6503              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6504            } else {            } else {
# Line 6397  sub _tree_construction_main ($) { Line 6511  sub _tree_construction_main ($) {
6511            !!!next-token;            !!!next-token;
6512            next B;            next B;
6513          } elsif ($token->{tag_name} eq 'option') {          } elsif ($token->{tag_name} eq 'option') {
6514            if ($self->{open_elements}->[-1]->[1] & OPTION_EL) {            if ($self->{open_elements}->[-1]->[1] == OPTION_EL) {
6515              !!!cp ('t286');              !!!cp ('t286');
6516              pop @{$self->{open_elements}};              pop @{$self->{open_elements}};
6517            } else {            } else {
# Line 6414  sub _tree_construction_main ($) { Line 6528  sub _tree_construction_main ($) {
6528            my $i;            my $i;
6529            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6530              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
6531              if ($node->[1] & SELECT_EL) {              if ($node->[1] == SELECT_EL) {
6532                !!!cp ('t288');                !!!cp ('t288');
6533                $i = $_;                $i = $_;
6534                last INSCOPE;                last INSCOPE;
# Line 6476  sub _tree_construction_main ($) { Line 6590  sub _tree_construction_main ($) {
6590            undef $i;            undef $i;
6591            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {            INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
6592              my $node = $self->{open_elements}->[$_];              my $node = $self->{open_elements}->[$_];
6593              if ($node->[1] & SELECT_EL) {              if ($node->[1] == SELECT_EL) {
6594                !!!cp ('t295');                !!!cp ('t295');
6595                $i = $_;                $i = $_;
6596                last INSCOPE;                last INSCOPE;
# Line 6515  sub _tree_construction_main ($) { Line 6629  sub _tree_construction_main ($) {
6629            next B;            next B;
6630          }          }
6631        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6632          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] == HTML_EL and
6633                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
6634            !!!cp ('t299.1');            !!!cp ('t299.1');
6635            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
# Line 6702  sub _tree_construction_main ($) { Line 6816  sub _tree_construction_main ($) {
6816        } elsif ($token->{type} == END_TAG_TOKEN) {        } elsif ($token->{type} == END_TAG_TOKEN) {
6817          if ($token->{tag_name} eq 'frameset' and          if ($token->{tag_name} eq 'frameset' and
6818              $self->{insertion_mode} == IN_FRAMESET_IM) {              $self->{insertion_mode} == IN_FRAMESET_IM) {
6819            if ($self->{open_elements}->[-1]->[1] & HTML_EL and            if ($self->{open_elements}->[-1]->[1] == HTML_EL and
6820                @{$self->{open_elements}} == 1) {                @{$self->{open_elements}} == 1) {
6821              !!!cp ('t325');              !!!cp ('t325');
6822              !!!parse-error (type => 'unmatched end tag',              !!!parse-error (type => 'unmatched end tag',
# Line 6716  sub _tree_construction_main ($) { Line 6830  sub _tree_construction_main ($) {
6830            }            }
6831    
6832            if (not defined $self->{inner_html_node} and            if (not defined $self->{inner_html_node} and
6833                not ($self->{open_elements}->[-1]->[1] & FRAMESET_EL)) {                not ($self->{open_elements}->[-1]->[1] == FRAMESET_EL)) {
6834              !!!cp ('t327');              !!!cp ('t327');
6835              $self->{insertion_mode} = AFTER_FRAMESET_IM;              $self->{insertion_mode} = AFTER_FRAMESET_IM;
6836            } else {            } else {
# Line 6748  sub _tree_construction_main ($) { Line 6862  sub _tree_construction_main ($) {
6862            next B;            next B;
6863          }          }
6864        } elsif ($token->{type} == END_OF_FILE_TOKEN) {        } elsif ($token->{type} == END_OF_FILE_TOKEN) {
6865          unless ($self->{open_elements}->[-1]->[1] & HTML_EL and          unless ($self->{open_elements}->[-1]->[1] == HTML_EL and
6866                  @{$self->{open_elements}} == 1) { # redundant, maybe                  @{$self->{open_elements}} == 1) { # redundant, maybe
6867            !!!cp ('t331.1');            !!!cp ('t331.1');
6868            !!!parse-error (type => 'in body:#eof', token => $token);            !!!parse-error (type => 'in body:#eof', token => $token);
# Line 6761  sub _tree_construction_main ($) { Line 6875  sub _tree_construction_main ($) {
6875        } else {        } else {
6876          die "$0: $token->{type}: Unknown token type";          die "$0: $token->{type}: Unknown token type";
6877        }        }
   
       ## ISSUE: An issue in spec here  
6878      } else {      } else {
6879        die "$0: $self->{insertion_mode}: Unknown insertion mode";        die "$0: $self->{insertion_mode}: Unknown insertion mode";
6880      }      }
# Line 6780  sub _tree_construction_main ($) { Line 6892  sub _tree_construction_main ($) {
6892          $parse_rcdata->(CDATA_CONTENT_MODEL);          $parse_rcdata->(CDATA_CONTENT_MODEL);
6893          next B;          next B;
6894        } elsif ({        } elsif ({
6895                  base => 1, link => 1,                  base => 1, command => 1, eventsource => 1, link => 1,
6896                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
6897          !!!cp ('t334');          !!!cp ('t334');
6898          ## 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
6899          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6900          pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          pop @{$self->{open_elements}};
6901          !!!ack ('t334.1');          !!!ack ('t334.1');
6902          !!!next-token;          !!!next-token;
6903          next B;          next B;
6904        } elsif ($token->{tag_name} eq 'meta') {        } elsif ($token->{tag_name} eq 'meta') {
6905          ## 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
6906          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
6907          my $meta_el = pop @{$self->{open_elements}}; ## ISSUE: This step is missing in the spec.          my $meta_el = pop @{$self->{open_elements}};
6908    
6909          unless ($self->{confident}) {          unless ($self->{confident}) {
6910            if ($token->{attributes}->{charset}) {            if ($token->{attributes}->{charset}) {
# Line 6853  sub _tree_construction_main ($) { Line 6965  sub _tree_construction_main ($) {
6965          !!!parse-error (type => 'in body', text => 'body', token => $token);          !!!parse-error (type => 'in body', text => 'body', token => $token);
6966                                
6967          if (@{$self->{open_elements}} == 1 or          if (@{$self->{open_elements}} == 1 or
6968              not ($self->{open_elements}->[1]->[1] & BODY_EL)) {              not ($self->{open_elements}->[1]->[1] == BODY_EL)) {
6969            !!!cp ('t342');            !!!cp ('t342');
6970            ## Ignore the token            ## Ignore the token
6971          } else {          } else {
# Line 6871  sub _tree_construction_main ($) { Line 6983  sub _tree_construction_main ($) {
6983          !!!next-token;          !!!next-token;
6984          next B;          next B;
6985        } elsif ({        } elsif ({
6986                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: Start tags for non-phrasing flow content elements
6987                  div => 1, dl => 1, fieldset => 1,  
6988                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  ## NOTE: The normal one
6989                  menu => 1, ol => 1, p => 1, ul => 1,                  address => 1, article => 1, aside => 1, blockquote => 1,
6990                    center => 1, datagrid => 1, details => 1, dialog => 1,
6991                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
6992                    footer => 1, h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1,
6993                    h6 => 1, header => 1, menu => 1, nav => 1, ol => 1, p => 1,
6994                    section => 1, ul => 1,
6995                    ## NOTE: As normal, but drops leading newline
6996                  pre => 1, listing => 1,                  pre => 1, listing => 1,
6997                    ## NOTE: As normal, but interacts with the form element pointer
6998                  form => 1,                  form => 1,
6999                    
7000                  table => 1,                  table => 1,
7001                  hr => 1,                  hr => 1,
7002                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 6891  sub _tree_construction_main ($) { Line 7011  sub _tree_construction_main ($) {
7011    
7012          ## has a p element in scope          ## has a p element in scope
7013          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7014            if ($_->[1] & P_EL) {            if ($_->[1] == P_EL) {
7015              !!!cp ('t344');              !!!cp ('t344');
7016              !!!back-token; # <form>              !!!back-token; # <form>
7017              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
# Line 6943  sub _tree_construction_main ($) { Line 7063  sub _tree_construction_main ($) {
7063            !!!next-token;            !!!next-token;
7064          }          }
7065          next B;          next B;
7066        } elsif ({li => 1, dt => 1, dd => 1}->{$token->{tag_name}}) {        } elsif ($token->{tag_name} eq 'li') {
7067          ## has a p element in scope          ## NOTE: As normal, but imply </li> when there's another <li> ...
7068    
7069            ## NOTE: Special, Scope (<li><foo><li> == <li><foo><li/></foo></li>)
7070              ## Interpreted as <li><foo/></li><li/> (non-conforming)
7071              ## blockquote (O9.27), center (O), dd (Fx3, O, S3.1.2, IE7),
7072              ## dt (Fx, O, S, IE), dl (O), fieldset (O, S, IE), form (Fx, O, S),
7073              ## hn (O), pre (O), applet (O, S), button (O, S), marquee (Fx, O, S),
7074              ## object (Fx)
7075              ## Generate non-tree (non-conforming)
7076              ## basefont (IE7 (where basefont is non-void)), center (IE),
7077              ## form (IE), hn (IE)
7078            ## address, div, p (<li><foo><li> == <li><foo/></li><li/>)
7079              ## Interpreted as <li><foo><li/></foo></li> (non-conforming)
7080              ## div (Fx, S)
7081    
7082            my $non_optional;
7083            my $i = -1;
7084    
7085            ## 1.
7086            for my $node (reverse @{$self->{open_elements}}) {
7087              if ($node->[1] == LI_EL) {
7088                ## 2. (a) As if </li>
7089                {
7090                  ## If no </li> - not applied
7091                  #
7092    
7093                  ## Otherwise
7094    
7095                  ## 1. generate implied end tags, except for </li>
7096                  #
7097    
7098                  ## 2. If current node != "li", parse error
7099                  if ($non_optional) {
7100                    !!!parse-error (type => 'not closed',
7101                                    text => $non_optional->[0]->manakai_local_name,
7102                                    token => $token);
7103                    !!!cp ('t355');
7104                  } else {
7105                    !!!cp ('t356');
7106                  }
7107    
7108                  ## 3. Pop
7109                  splice @{$self->{open_elements}}, $i;
7110                }
7111    
7112                last; ## 2. (b) goto 5.
7113              } elsif (
7114                       ## NOTE: not "formatting" and not "phrasing"
7115                       ($node->[1] & SPECIAL_EL or
7116                        $node->[1] & SCOPING_EL) and
7117                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7118                       (not $node->[1] & ADDRESS_DIV_P_EL)
7119                      ) {
7120                ## 3.
7121                !!!cp ('t357');
7122                last; ## goto 5.
7123              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7124                !!!cp ('t358');
7125                #
7126              } else {
7127                !!!cp ('t359');
7128                $non_optional ||= $node;
7129                #
7130              }
7131              ## 4.
7132              ## goto 2.
7133              $i--;
7134            }
7135    
7136            ## 5. (a) has a |p| element in scope
7137          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7138            if ($_->[1] & P_EL) {            if ($_->[1] == P_EL) {
7139              !!!cp ('t353');              !!!cp ('t353');
7140    
7141                ## NOTE: |<p><li>|, for example.
7142    
7143              !!!back-token; # <x>              !!!back-token; # <x>
7144              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
7145                        line => $token->{line}, column => $token->{column}};                        line => $token->{line}, column => $token->{column}};
# Line 6957  sub _tree_construction_main ($) { Line 7149  sub _tree_construction_main ($) {
7149              last INSCOPE;              last INSCOPE;
7150            }            }
7151          } # INSCOPE          } # INSCOPE
7152              
7153          ## Step 1          ## 5. (b) insert
7154            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7155            !!!nack ('t359.1');
7156            !!!next-token;
7157            next B;
7158          } elsif ($token->{tag_name} eq 'dt' or
7159                   $token->{tag_name} eq 'dd') {
7160            ## NOTE: As normal, but imply </dt> or </dd> when ...
7161    
7162            my $non_optional;
7163          my $i = -1;          my $i = -1;
7164          my $node = $self->{open_elements}->[$i];  
7165          my $li_or_dtdd = {li => {li => 1},          ## 1.
7166                            dt => {dt => 1, dd => 1},          for my $node (reverse @{$self->{open_elements}}) {
7167                            dd => {dt => 1, dd => 1}}->{$token->{tag_name}};            if ($node->[1] == DT_EL or $node->[1] == DD_EL) {
7168          LI: {              ## 2. (a) As if </li>
7169            ## Step 2              {
7170            if ($li_or_dtdd->{$node->[0]->manakai_local_name}) {                ## If no </li> - not applied
7171              if ($i != -1) {                #
7172                !!!cp ('t355');  
7173                !!!parse-error (type => 'not closed',                ## Otherwise
7174                                text => $self->{open_elements}->[-1]->[0]  
7175                                    ->manakai_local_name,                ## 1. generate implied end tags, except for </dt> or </dd>
7176                                token => $token);                #
7177              } else {  
7178                !!!cp ('t356');                ## 2. If current node != "dt"|"dd", parse error
7179                  if ($non_optional) {
7180                    !!!parse-error (type => 'not closed',
7181                                    text => $non_optional->[0]->manakai_local_name,
7182                                    token => $token);
7183                    !!!cp ('t355.1');
7184                  } else {
7185                    !!!cp ('t356.1');
7186                  }
7187    
7188                  ## 3. Pop
7189                  splice @{$self->{open_elements}}, $i;
7190              }              }
7191              splice @{$self->{open_elements}}, $i;  
7192              last LI;              last; ## 2. (b) goto 5.
7193              } elsif (
7194                       ## NOTE: not "formatting" and not "phrasing"
7195                       ($node->[1] & SPECIAL_EL or
7196                        $node->[1] & SCOPING_EL) and
7197                       ## NOTE: "li", "dt", and "dd" are in |SPECIAL_EL|.
7198    
7199                       (not $node->[1] & ADDRESS_DIV_P_EL)
7200                      ) {
7201                ## 3.
7202                !!!cp ('t357.1');
7203                last; ## goto 5.
7204              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7205                !!!cp ('t358.1');
7206                #
7207            } else {            } else {
7208              !!!cp ('t357');              !!!cp ('t359.1');
7209            }              $non_optional ||= $node;
7210                          #
           ## Step 3  
           if (not ($node->[1] & FORMATTING_EL) and  
               #not $phrasing_category->{$node->[1]} and  
               ($node->[1] & SPECIAL_EL or  
                $node->[1] & SCOPING_EL) and  
               not ($node->[1] & ADDRESS_EL) and  
               not ($node->[1] & DIV_EL)) {  
             !!!cp ('t358');  
             last LI;  
7211            }            }
7212                        ## 4.
7213            !!!cp ('t359');            ## goto 2.
           ## Step 4  
7214            $i--;            $i--;
7215            $node = $self->{open_elements}->[$i];          }
7216            redo LI;  
7217          } # LI          ## 5. (a) has a |p| element in scope
7218                      INSCOPE: for (reverse @{$self->{open_elements}}) {
7219              if ($_->[1] == P_EL) {
7220                !!!cp ('t353.1');
7221                !!!back-token; # <x>
7222                $token = {type => END_TAG_TOKEN, tag_name => 'p',
7223                          line => $token->{line}, column => $token->{column}};
7224                next B;
7225              } elsif ($_->[1] & SCOPING_EL) {
7226                !!!cp ('t354.1');
7227                last INSCOPE;
7228              }
7229            } # INSCOPE
7230    
7231            ## 5. (b) insert
7232          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7233          !!!nack ('t359.1');          !!!nack ('t359.2');
7234          !!!next-token;          !!!next-token;
7235          next B;          next B;
7236        } elsif ($token->{tag_name} eq 'plaintext') {        } elsif ($token->{tag_name} eq 'plaintext') {
7237            ## NOTE: As normal, but effectively ends parsing
7238    
7239          ## has a p element in scope          ## has a p element in scope
7240          INSCOPE: for (reverse @{$self->{open_elements}}) {          INSCOPE: for (reverse @{$self->{open_elements}}) {
7241            if ($_->[1] & P_EL) {            if ($_->[1] == P_EL) {
7242              !!!cp ('t367');              !!!cp ('t367');
7243              !!!back-token; # <plaintext>              !!!back-token; # <plaintext>
7244              $token = {type => END_TAG_TOKEN, tag_name => 'p',              $token = {type => END_TAG_TOKEN, tag_name => 'p',
# Line 7029  sub _tree_construction_main ($) { Line 7260  sub _tree_construction_main ($) {
7260        } elsif ($token->{tag_name} eq 'a') {        } elsif ($token->{tag_name} eq 'a') {
7261          AFE: for my $i (reverse 0..$#$active_formatting_elements) {          AFE: for my $i (reverse 0..$#$active_formatting_elements) {
7262            my $node = $active_formatting_elements->[$i];            my $node = $active_formatting_elements->[$i];
7263            if ($node->[1] & A_EL) {            if ($node->[1] == A_EL) {
7264              !!!cp ('t371');              !!!cp ('t371');
7265              !!!parse-error (type => 'in a:a', token => $token);              !!!parse-error (type => 'in a:a', token => $token);
7266                            
# Line 7073  sub _tree_construction_main ($) { Line 7304  sub _tree_construction_main ($) {
7304          ## has a |nobr| element in scope          ## has a |nobr| element in scope
7305          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7306            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7307            if ($node->[1] & NOBR_EL) {            if ($node->[1] == NOBR_EL) {
7308              !!!cp ('t376');              !!!cp ('t376');
7309              !!!parse-error (type => 'in nobr:nobr', token => $token);              !!!parse-error (type => 'in nobr:nobr', token => $token);
7310              !!!back-token; # <nobr>              !!!back-token; # <nobr>
# Line 7096  sub _tree_construction_main ($) { Line 7327  sub _tree_construction_main ($) {
7327          ## has a button element in scope          ## has a button element in scope
7328          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7329            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7330            if ($node->[1] & BUTTON_EL) {            if ($node->[1] == BUTTON_EL) {
7331              !!!cp ('t378');              !!!cp ('t378');
7332              !!!parse-error (type => 'in button:button', token => $token);              !!!parse-error (type => 'in button:button', token => $token);
7333              !!!back-token; # <button>              !!!back-token; # <button>
# Line 7196  sub _tree_construction_main ($) { Line 7427  sub _tree_construction_main ($) {
7427            next B;            next B;
7428          }          }
7429        } elsif ($token->{tag_name} eq 'textarea') {        } elsif ($token->{tag_name} eq 'textarea') {
7430          my $tag_name = $token->{tag_name};          ## Step 1
7431          my $el;          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
         !!!create-element ($el, $HTML_NS, $token->{tag_name}, $token->{attributes}, $token);  
7432                    
7433            ## Step 2
7434          ## TODO: $self->{form_element} if defined          ## TODO: $self->{form_element} if defined
7435    
7436            ## Step 3
7437            $self->{ignore_newline} = 1;
7438    
7439            ## Step 4
7440            ## ISSUE: This step is wrong. (r2302 enbugged)
7441    
7442            ## Step 5
7443          $self->{content_model} = RCDATA_CONTENT_MODEL;          $self->{content_model} = RCDATA_CONTENT_MODEL;
7444          delete $self->{escape}; # MUST          delete $self->{escape}; # MUST
7445            
7446          $insert->($el);          ## Step 6-7
7447                    $self->{insertion_mode} |= IN_CDATA_RCDATA_IM;
7448          my $text = '';  
7449          !!!nack ('t392.1');          !!!nack ('t392.1');
7450          !!!next-token;          !!!next-token;
7451          if ($token->{type} == CHARACTER_TOKEN) {          next B;
7452            $token->{data} =~ s/^\x0A//;        } elsif ($token->{tag_name} eq 'optgroup' or
7453            unless (length $token->{data}) {                 $token->{tag_name} eq 'option') {
7454              !!!cp ('t392');          ## has an |option| element in scope
7455              !!!next-token;          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7456            } else {            my $node = $self->{open_elements}->[$_];
7457              !!!cp ('t393');            if ($node->[1] == OPTION_EL) {
7458                !!!cp ('t397.1');
7459                ## NOTE: As if </option>
7460                !!!back-token; # <option> or <optgroup>
7461                $token = {type => END_TAG_TOKEN, tag_name => 'option',
7462                          line => $token->{line}, column => $token->{column}};
7463                next B;
7464              } elsif ($node->[1] & SCOPING_EL) {
7465                !!!cp ('t397.2');
7466                last INSCOPE;
7467            }            }
7468          } else {          } # INSCOPE
7469            !!!cp ('t394');  
7470          }          $reconstruct_active_formatting_elements->($insert_to_current);
7471          while ($token->{type} == CHARACTER_TOKEN) {  
7472            !!!cp ('t395');          !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7473            $text .= $token->{data};  
7474            !!!next-token;          !!!nack ('t397.3');
         }  
         if (length $text) {  
           !!!cp ('t396');  
           $el->manakai_append_text ($text);  
         }  
           
         $self->{content_model} = PCDATA_CONTENT_MODEL;  
           
         if ($token->{type} == END_TAG_TOKEN and  
             $token->{tag_name} eq $tag_name) {  
           !!!cp ('t397');  
           ## Ignore the token  
         } else {  
           !!!cp ('t398');  
           !!!parse-error (type => 'in RCDATA:#eof', token => $token);  
         }  
7475          !!!next-token;          !!!next-token;
7476          next B;          redo B;
7477        } elsif ($token->{tag_name} eq 'rt' or        } elsif ($token->{tag_name} eq 'rt' or
7478                 $token->{tag_name} eq 'rp') {                 $token->{tag_name} eq 'rp') {
7479          ## has a |ruby| element in scope          ## has a |ruby| element in scope
7480          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7481            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7482            if ($node->[1] & RUBY_EL) {            if ($node->[1] == RUBY_EL) {
7483              !!!cp ('t398.1');              !!!cp ('t398.1');
7484              ## generate implied end tags              ## generate implied end tags
7485              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
7486                !!!cp ('t398.2');                !!!cp ('t398.2');
7487                pop @{$self->{open_elements}};                pop @{$self->{open_elements}};
7488              }              }
7489              unless ($self->{open_elements}->[-1]->[1] & RUBY_EL) {              unless ($self->{open_elements}->[-1]->[1] == RUBY_EL) {
7490                !!!cp ('t398.3');                !!!cp ('t398.3');
7491                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
7492                                text => $self->{open_elements}->[-1]->[0]                                text => $self->{open_elements}->[-1]->[0]
7493                                    ->manakai_local_name,                                    ->manakai_local_name,
7494                                token => $token);                                token => $token);
7495                pop @{$self->{open_elements}}                pop @{$self->{open_elements}}
7496                    while not $self->{open_elements}->[-1]->[1] & RUBY_EL;                    while not $self->{open_elements}->[-1]->[1] == RUBY_EL;
7497              }              }
7498              last INSCOPE;              last INSCOPE;
7499            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
# Line 7289  sub _tree_construction_main ($) { Line 7521  sub _tree_construction_main ($) {
7521                    
7522          if ($self->{self_closing}) {          if ($self->{self_closing}) {
7523            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
7524            !!!ack ('t398.1');            !!!ack ('t398.6');
7525          } else {          } else {
7526            !!!cp ('t398.2');            !!!cp ('t398.7');
7527            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;            $self->{insertion_mode} |= IN_FOREIGN_CONTENT_IM;
7528            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion            ## NOTE: |<body><math><mi><svg>| -> "in foreign content" insertion
7529            ## mode, "in body" (not "in foreign content") secondary insertion            ## mode, "in body" (not "in foreign content") secondary insertion
# Line 7302  sub _tree_construction_main ($) { Line 7534  sub _tree_construction_main ($) {
7534          next B;          next B;
7535        } elsif ({        } elsif ({
7536                  caption => 1, col => 1, colgroup => 1, frame => 1,                  caption => 1, col => 1, colgroup => 1, frame => 1,
7537                  frameset => 1, head => 1, option => 1, optgroup => 1,                  frameset => 1, head => 1,
7538                  tbody => 1, td => 1, tfoot => 1, th => 1,                  tbody => 1, td => 1, tfoot => 1, th => 1,
7539                  thead => 1, tr => 1,                  thead => 1, tr => 1,
7540                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
# Line 7313  sub _tree_construction_main ($) { Line 7545  sub _tree_construction_main ($) {
7545          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.          !!!nack ('t401.1'); ## NOTE: |<col/>| or |<frame/>| here is an error.
7546          !!!next-token;          !!!next-token;
7547          next B;          next B;
7548                  } elsif ($token->{tag_name} eq 'param' or
7549          ## ISSUE: An issue on HTML5 new elements in the spec.                 $token->{tag_name} eq 'source') {
7550            !!!insert-element-t ($token->{tag_name}, $token->{attributes}, $token);
7551            pop @{$self->{open_elements}};
7552    
7553            !!!ack ('t398.5');
7554            !!!next-token;
7555            redo B;
7556        } else {        } else {
7557          if ($token->{tag_name} eq 'image') {          if ($token->{tag_name} eq 'image') {
7558            !!!cp ('t384');            !!!cp ('t384');
# Line 7337  sub _tree_construction_main ($) { Line 7575  sub _tree_construction_main ($) {
7575            !!!nack ('t380.1');            !!!nack ('t380.1');
7576          } elsif ({          } elsif ({
7577                    b => 1, big => 1, em => 1, font => 1, i => 1,                    b => 1, big => 1, em => 1, font => 1, i => 1,
7578                    s => 1, small => 1, strile => 1,                    s => 1, small => 1, strike => 1,
7579                    strong => 1, tt => 1, u => 1,                    strong => 1, tt => 1, u => 1,
7580                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7581            !!!cp ('t375');            !!!cp ('t375');
# Line 7350  sub _tree_construction_main ($) { Line 7588  sub _tree_construction_main ($) {
7588            !!!ack ('t388.2');            !!!ack ('t388.2');
7589          } elsif ({          } elsif ({
7590                    area => 1, basefont => 1, bgsound => 1, br => 1,                    area => 1, basefont => 1, bgsound => 1, br => 1,
7591                    embed => 1, img => 1, param => 1, spacer => 1, wbr => 1,                    embed => 1, img => 1, spacer => 1, wbr => 1,
                   #image => 1,  
7592                   }->{$token->{tag_name}}) {                   }->{$token->{tag_name}}) {
7593            !!!cp ('t388.1');            !!!cp ('t388.1');
7594            pop @{$self->{open_elements}};            pop @{$self->{open_elements}};
# Line 7382  sub _tree_construction_main ($) { Line 7619  sub _tree_construction_main ($) {
7619          my $i;          my $i;
7620          INSCOPE: {          INSCOPE: {
7621            for (reverse @{$self->{open_elements}}) {            for (reverse @{$self->{open_elements}}) {
7622              if ($_->[1] & BODY_EL) {              if ($_->[1] == BODY_EL) {
7623                !!!cp ('t405');                !!!cp ('t405');
7624                $i = $_;                $i = $_;
7625                last INSCOPE;                last INSCOPE;
# Line 7392  sub _tree_construction_main ($) { Line 7629  sub _tree_construction_main ($) {
7629              }              }
7630            }            }
7631    
7632            !!!parse-error (type => 'start tag not allowed',            ## NOTE: |<marquee></body>|, |<svg><foreignobject></body>|
7633    
7634              !!!parse-error (type => 'unmatched end tag',
7635                            text => $token->{tag_name}, token => $token);                            text => $token->{tag_name}, token => $token);
7636            ## NOTE: Ignore the token.            ## NOTE: Ignore the token.
7637            !!!next-token;            !!!next-token;
# Line 7418  sub _tree_construction_main ($) { Line 7657  sub _tree_construction_main ($) {
7657          ## TODO: Update this code.  It seems that the code below is not          ## TODO: Update this code.  It seems that the code below is not
7658          ## up-to-date, though it has same effect as speced.          ## up-to-date, though it has same effect as speced.
7659          if (@{$self->{open_elements}} > 1 and          if (@{$self->{open_elements}} > 1 and
7660              $self->{open_elements}->[1]->[1] & BODY_EL) {              $self->{open_elements}->[1]->[1] == BODY_EL) {
7661            ## ISSUE: There is an issue in the spec.            unless ($self->{open_elements}->[-1]->[1] == BODY_EL) {
           unless ($self->{open_elements}->[-1]->[1] & BODY_EL) {  
7662              !!!cp ('t406');              !!!cp ('t406');
7663              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7664                              text => $self->{open_elements}->[1]->[0]                              text => $self->{open_elements}->[1]->[0]
# Line 7441  sub _tree_construction_main ($) { Line 7679  sub _tree_construction_main ($) {
7679            next B;            next B;
7680          }          }
7681        } elsif ({        } elsif ({
7682                  address => 1, blockquote => 1, center => 1, dir => 1,                  ## NOTE: End tags for non-phrasing flow content elements
7683                  div => 1, dl => 1, fieldset => 1, listing => 1,  
7684                  menu => 1, ol => 1, pre => 1, ul => 1,                  ## NOTE: The normal ones
7685                    address => 1, article => 1, aside => 1, blockquote => 1,
7686                    center => 1, datagrid => 1, details => 1, dialog => 1,
7687                    dir => 1, div => 1, dl => 1, fieldset => 1, figure => 1,
7688                    footer => 1, header => 1, listing => 1, menu => 1, nav => 1,
7689                    ol => 1, pre => 1, section => 1, ul => 1,
7690    
7691                    ## NOTE: As normal, but ... optional tags
7692                  dd => 1, dt => 1, li => 1,                  dd => 1, dt => 1, li => 1,
7693    
7694                  applet => 1, button => 1, marquee => 1, object => 1,                  applet => 1, button => 1, marquee => 1, object => 1,
7695                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7696            ## NOTE: Code for <li> start tags includes "as if </li>" code.
7697            ## Code for <dt> or <dd> start tags includes "as if </dt> or
7698            ## </dd>" code.
7699    
7700          ## has an element in scope          ## has an element in scope
7701          my $i;          my $i;
7702          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
# Line 7473  sub _tree_construction_main ($) { Line 7723  sub _tree_construction_main ($) {
7723                    dd => ($token->{tag_name} ne 'dd'),                    dd => ($token->{tag_name} ne 'dd'),
7724                    dt => ($token->{tag_name} ne 'dt'),                    dt => ($token->{tag_name} ne 'dt'),
7725                    li => ($token->{tag_name} ne 'li'),                    li => ($token->{tag_name} ne 'li'),
7726                      option => 1,
7727                      optgroup => 1,
7728                    p => 1,                    p => 1,
7729                    rt => 1,                    rt => 1,
7730                    rp => 1,                    rp => 1,
# Line 7505  sub _tree_construction_main ($) { Line 7757  sub _tree_construction_main ($) {
7757          !!!next-token;          !!!next-token;
7758          next B;          next B;
7759        } elsif ($token->{tag_name} eq 'form') {        } elsif ($token->{tag_name} eq 'form') {
7760            ## NOTE: As normal, but interacts with the form element pointer
7761    
7762          undef $self->{form_element};          undef $self->{form_element};
7763    
7764          ## has an element in scope          ## has an element in scope
7765          my $i;          my $i;
7766          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7767            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7768            if ($node->[1] & FORM_EL) {            if ($node->[1] == FORM_EL) {
7769              !!!cp ('t418');              !!!cp ('t418');
7770              $i = $_;              $i = $_;
7771              last INSCOPE;              last INSCOPE;
# Line 7552  sub _tree_construction_main ($) { Line 7806  sub _tree_construction_main ($) {
7806          !!!next-token;          !!!next-token;
7807          next B;          next B;
7808        } elsif ({        } elsif ({
7809                    ## NOTE: As normal, except acts as a closer for any ...
7810                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,                  h1 => 1, h2 => 1, h3 => 1, h4 => 1, h5 => 1, h6 => 1,
7811                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7812          ## has an element in scope          ## has an element in scope
7813          my $i;          my $i;
7814          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7815            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7816            if ($node->[1] & HEADING_EL) {            if ($node->[1] == HEADING_EL) {
7817              !!!cp ('t423');              !!!cp ('t423');
7818              $i = $_;              $i = $_;
7819              last INSCOPE;              last INSCOPE;
# Line 7597  sub _tree_construction_main ($) { Line 7852  sub _tree_construction_main ($) {
7852          !!!next-token;          !!!next-token;
7853          next B;          next B;
7854        } elsif ($token->{tag_name} eq 'p') {        } elsif ($token->{tag_name} eq 'p') {
7855            ## NOTE: As normal, except </p> implies <p> and ...
7856    
7857          ## has an element in scope          ## has an element in scope
7858            my $non_optional;
7859          my $i;          my $i;
7860          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {          INSCOPE: for (reverse 0..$#{$self->{open_elements}}) {
7861            my $node = $self->{open_elements}->[$_];            my $node = $self->{open_elements}->[$_];
7862            if ($node->[1] & P_EL) {            if ($node->[1] == P_EL) {
7863              !!!cp ('t410.1');              !!!cp ('t410.1');
7864              $i = $_;              $i = $_;
7865              last INSCOPE;              last INSCOPE;
7866            } elsif ($node->[1] & SCOPING_EL) {            } elsif ($node->[1] & SCOPING_EL) {
7867              !!!cp ('t411.1');              !!!cp ('t411.1');
7868              last INSCOPE;              last INSCOPE;
7869              } elsif ($node->[1] & END_TAG_OPTIONAL_EL) {
7870                ## NOTE: |END_TAG_OPTIONAL_EL| includes "p"
7871                !!!cp ('t411.2');
7872                #
7873              } else {
7874                !!!cp ('t411.3');
7875                $non_optional ||= $node;
7876                #
7877            }            }
7878          } # INSCOPE          } # INSCOPE
7879    
7880          if (defined $i) {          if (defined $i) {
7881            if ($self->{open_elements}->[-1]->[0]->manakai_local_name            ## 1. Generate implied end tags
7882                    ne $token->{tag_name}) {            #
7883    
7884              ## 2. If current node != "p", parse error
7885              if ($non_optional) {
7886              !!!cp ('t412.1');              !!!cp ('t412.1');
7887              !!!parse-error (type => 'not closed',              !!!parse-error (type => 'not closed',
7888                              text => $self->{open_elements}->[-1]->[0]                              text => $non_optional->[0]->manakai_local_name,
                                 ->manakai_local_name,  
7889                              token => $token);                              token => $token);
7890            } else {            } else {
7891              !!!cp ('t414.1');              !!!cp ('t414.1');
7892            }            }
7893    
7894              ## 3. Pop
7895            splice @{$self->{open_elements}}, $i;            splice @{$self->{open_elements}}, $i;
7896          } else {          } else {
7897            !!!cp ('t413.1');            !!!cp ('t413.1');
# Line 7642  sub _tree_construction_main ($) { Line 7911  sub _tree_construction_main ($) {
7911        } elsif ({        } elsif ({
7912                  a => 1,                  a => 1,
7913                  b => 1, big => 1, em => 1, font => 1, i => 1,                  b => 1, big => 1, em => 1, font => 1, i => 1,
7914                  nobr => 1, s => 1, small => 1, strile => 1,                  nobr => 1, s => 1, small => 1, strike => 1,
7915                  strong => 1, tt => 1, u => 1,                  strong => 1, tt => 1, u => 1,
7916                 }->{$token->{tag_name}}) {                 }->{$token->{tag_name}}) {
7917          !!!cp ('t427');          !!!cp ('t427');
# Line 7663  sub _tree_construction_main ($) { Line 7932  sub _tree_construction_main ($) {
7932          ## Ignore the token.          ## Ignore the token.
7933          !!!next-token;          !!!next-token;
7934          next B;          next B;
       } elsif ({  
                 caption => 1, col => 1, colgroup => 1, frame => 1,  
                 frameset => 1, head => 1, option => 1, optgroup => 1,  
                 tbody => 1, td => 1, tfoot => 1, th => 1,  
                 thead => 1, tr => 1,  
                 area => 1, basefont => 1, bgsound => 1,  
                 embed => 1, hr => 1, iframe => 1, image => 1,  
                 img => 1, input => 1, isindex => 1, noembed => 1,  
                 noframes => 1, param => 1, select => 1, spacer => 1,  
                 table => 1, textarea => 1, wbr => 1,  
                 noscript => 0, ## TODO: if scripting is enabled  
                }->{$token->{tag_name}}) {  
         !!!cp ('t429');  
         !!!parse-error (type => 'unmatched end tag',  
                         text => $token->{tag_name}, token => $token);  
         ## Ignore the token  
         !!!next-token;  
         next B;  
           
         ## ISSUE: Issue on HTML5 new elements in spec  
           
7935        } else {        } else {
7936            if ($token->{tag_name} eq 'sarcasm') {
7937              sleep 0.001; # take a deep breath
7938            }
7939    
7940          ## Step 1          ## Step 1
7941          my $node_i = -1;          my $node_i = -1;
7942          my $node = $self->{open_elements}->[$node_i];          my $node = $self->{open_elements}->[$node_i];
7943    
7944          ## Step 2          ## Step 2
7945          S2: {          S2: {
7946            if ($node->[0]->manakai_local_name eq $token->{tag_name}) {            my $node_tag_name = $node->[0]->manakai_local_name;
7947              $node_tag_name =~ tr/A-Z/a-z/; # for SVG camelCase tag names
7948              if ($node_tag_name eq $token->{tag_name}) {
7949              ## Step 1              ## Step 1
7950              ## generate implied end tags              ## generate implied end tags
7951              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {              while ($self->{open_elements}->[-1]->[1] & END_TAG_OPTIONAL_EL) {
# Line 7704  sub _tree_construction_main ($) { Line 7958  sub _tree_construction_main ($) {
7958              }              }
7959                    
7960              ## Step 2              ## Step 2
7961              if ($self->{open_elements}->[-1]->[0]->manakai_local_name              my $current_tag_name
7962                      ne $token->{tag_name}) {                  = $self->{open_elements}->[-1]->[0]->manakai_local_name;
7963                $current_tag_name =~ tr/A-Z/a-z/;
7964                if ($current_tag_name ne $token->{tag_name}) {
7965                !!!cp ('t431');                !!!cp ('t431');
7966                ## NOTE: <x><y></x>                ## NOTE: <x><y></x>
7967                !!!parse-error (type => 'not closed',                !!!parse-error (type => 'not closed',
# Line 7733  sub _tree_construction_main ($) { Line 7989  sub _tree_construction_main ($) {
7989                ## Ignore the token                ## Ignore the token
7990                !!!next-token;                !!!next-token;
7991                last S2;                last S2;
             }  
7992    
7993                  ## NOTE: |<span><dd></span>a|: In Safari 3.1.2 and Opera
7994                  ## 9.27, "a" is a child of <dd> (conforming).  In
7995                  ## Firefox 3.0.2, "a" is a child of <body>.  In WinIE 7,
7996                  ## "a" is a child of both <body> and <dd>.
7997                }
7998                
7999              !!!cp ('t434');              !!!cp ('t434');
8000            }            }
8001                        
# Line 7970  sub set_inner_html ($$$$;$) { Line 8231  sub set_inner_html ($$$$;$) {
8231      push @{$p->{open_elements}}, [$root, $el_category->{html}];      push @{$p->{open_elements}}, [$root, $el_category->{html}];
8232    
8233      undef $p->{head_element};      undef $p->{head_element};
8234        undef $p->{head_element_inserted};
8235    
8236      ## Step 6 # MUST      ## Step 6 # MUST
8237      $p->_reset_insertion_mode;      $p->_reset_insertion_mode;

Legend:
Removed from v.1.191  
changed lines
  Added in v.1.206

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24