Bug 558302 - Make <button> non-scoping in the HTML5 parser. r=bnewman.
authorHenri Sivonen <hsivonen@iki.fi>
Fri, 16 Apr 2010 13:52:06 +0300
changeset 40920 739aec32e63e558029ffdee558ae509bf20ae6ef
parent 40919 47f478e436adaa0d50923cb121d735b1b66fee85
child 40921 8a4ad4811877e96d2e65e41d1a78024cecba9e6f
push id12833
push userhsivonen@iki.fi
push dateFri, 16 Apr 2010 11:21:34 +0000
treeherdermozilla-central@739aec32e63e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbnewman
bugs558302
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Bug 558302 - Make <button> non-scoping in the HTML5 parser. r=bnewman.
parser/html/javasrc/ElementName.java
parser/html/javasrc/TreeBuilder.java
parser/html/nsHtml5AtomList.h
parser/html/nsHtml5ElementName.cpp
parser/html/nsHtml5TreeBuilder.cpp
parser/htmlparser/tests/mochitest/html5lib_tree_dat1.txt
--- a/parser/html/javasrc/ElementName.java
+++ b/parser/html/javasrc/ElementName.java
@@ -534,17 +534,17 @@ public final class ElementName
     public static final ElementName ARCSEC = new ElementName("arcsec", "arcsec", TreeBuilder.OTHER, false, false, false);
     public static final ElementName ARCCSC = new ElementName("arccsc", "arccsc", TreeBuilder.OTHER, false, false, false);
     public static final ElementName ARCTAN = new ElementName("arctan", "arctan", TreeBuilder.OTHER, false, false, false);
     public static final ElementName ARCSIN = new ElementName("arcsin", "arcsin", TreeBuilder.OTHER, false, false, false);
     public static final ElementName ARCCOS = new ElementName("arccos", "arccos", TreeBuilder.OTHER, false, false, false);
     public static final ElementName APPLET = new ElementName("applet", "applet", TreeBuilder.MARQUEE_OR_APPLET, false, true, false);
     public static final ElementName ARCCOT = new ElementName("arccot", "arccot", TreeBuilder.OTHER, false, false, false);
     public static final ElementName APPROX = new ElementName("approx", "approx", TreeBuilder.OTHER, false, false, false);
-    public static final ElementName BUTTON = new ElementName("button", "button", TreeBuilder.BUTTON, false, true, false);
+    public static final ElementName BUTTON = new ElementName("button", "button", TreeBuilder.BUTTON, false, false, false);
     public static final ElementName CIRCLE = new ElementName("circle", "circle", TreeBuilder.OTHER, false, false, false);
     public static final ElementName CENTER = new ElementName("center", "center", TreeBuilder.DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU, true, false, false);
     public static final ElementName CURSOR = new ElementName("cursor", "cursor", TreeBuilder.OTHER, false, false, false);
     public static final ElementName CANVAS = new ElementName("canvas", "canvas", TreeBuilder.OTHER, false, false, false);
     public static final ElementName DIVIDE = new ElementName("divide", "divide", TreeBuilder.OTHER, false, false, false);
     public static final ElementName DEGREE = new ElementName("degree", "degree", TreeBuilder.OTHER, false, false, false);
     public static final ElementName DOMAIN = new ElementName("domain", "domain", TreeBuilder.OTHER, false, false, false);
     public static final ElementName EXISTS = new ElementName("exists", "exists", TreeBuilder.OTHER, false, false, false);
--- a/parser/html/javasrc/TreeBuilder.java
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -1953,32 +1953,31 @@ public abstract class TreeBuilder<T> imp
                                                 "http://www.w3.org/1999/xhtml",
                                                 elementName, attributes);
                                         attributes = null; // CPP
                                         break starttagloop;
                                     case BUTTON:
                                         eltPos = findLastInScope(name);
                                         if (eltPos != TreeBuilder.NOT_FOUND_ON_STACK) {
                                             err("\u201Cbutton\u201D start tag seen when there was an open \u201Cbutton\u201D element in scope.");
+
                                             generateImpliedEndTags();
-                                            if (!isCurrent("button")) {
-                                                err("There was an open \u201Cbutton\u201D element in scope with unclosed children.");
+                                            if (!isCurrent(name)) {
+                                                err("End tag \u201Cbutton\u201D seen but there were unclosed elements.");
                                             }
                                             while (currentPtr >= eltPos) {
                                                 pop();
                                             }
-                                            clearTheListOfActiveFormattingElementsUpToTheLastMarker();
                                             continue starttagloop;
                                         } else {
                                             reconstructTheActiveFormattingElements();
                                             appendToCurrentNodeAndPushElementMayFoster(
                                                     "http://www.w3.org/1999/xhtml",
                                                     elementName, attributes,
                                                     formPointer);
-                                            insertMarker();
                                             attributes = null; // CPP
                                             break starttagloop;
                                         }
                                     case OBJECT:
                                         reconstructTheActiveFormattingElements();
                                         appendToCurrentNodeAndPushElementMayFoster(
                                                 "http://www.w3.org/1999/xhtml",
                                                 elementName, attributes,
@@ -3370,16 +3369,17 @@ public abstract class TreeBuilder<T> imp
                                 }
                             }
                             mode = AFTER_BODY;
                             continue;
                         case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
                         case UL_OR_OL_OR_DL:
                         case PRE_OR_LISTING:
                         case FIELDSET:
+                        case BUTTON:
                         case ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION:
                             eltPos = findLastInScope(name);
                             if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
                                 err("Stray end tag \u201C" + name + "\u201D.");
                             } else {
                                 generateImpliedEndTags();
                                 if (!isCurrent(name)) {
                                     err("End tag \u201C"
@@ -3490,17 +3490,16 @@ public abstract class TreeBuilder<T> imp
                             }
                             break endtagloop;
                         case A:
                         case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
                         case FONT:
                         case NOBR:
                             adoptionAgencyEndTag(name);
                             break endtagloop;
-                        case BUTTON:
                         case OBJECT:
                         case MARQUEE_OR_APPLET:
                             eltPos = findLastInScope(name);
                             if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
                                 err("Stray end tag \u201C" + name + "\u201D.");
                             } else {
                                 generateImpliedEndTags();
                                 if (!isCurrent(name)) {
--- a/parser/html/nsHtml5AtomList.h
+++ b/parser/html/nsHtml5AtomList.h
@@ -11,17 +11,16 @@ HTML5_ATOM(plaintext, "plaintext")
 HTML5_ATOM(script, "script")
 HTML5_ATOM(table, "table")
 HTML5_ATOM(caption, "caption")
 HTML5_ATOM(p, "p")
 HTML5_ATOM(address, "address")
 HTML5_ATOM(div, "div")
 HTML5_ATOM(a, "a")
 HTML5_ATOM(nobr, "nobr")
-HTML5_ATOM(button, "button")
 HTML5_ATOM(input, "input")
 HTML5_ATOM(option, "option")
 HTML5_ATOM(ruby, "ruby")
 HTML5_ATOM(select, "select")
 HTML5_ATOM(optgroup, "optgroup")
 HTML5_ATOM(frameset, "frameset")
 HTML5_ATOM(ul, "ul")
 HTML5_ATOM(ol, "ol")
@@ -831,16 +830,17 @@ HTML5_ATOM(video, "video")
 HTML5_ATOM(arcsec, "arcsec")
 HTML5_ATOM(arccsc, "arccsc")
 HTML5_ATOM(arctan, "arctan")
 HTML5_ATOM(arcsin, "arcsin")
 HTML5_ATOM(arccos, "arccos")
 HTML5_ATOM(applet, "applet")
 HTML5_ATOM(arccot, "arccot")
 HTML5_ATOM(approx, "approx")
+HTML5_ATOM(button, "button")
 HTML5_ATOM(circle, "circle")
 HTML5_ATOM(center, "center")
 HTML5_ATOM(canvas, "canvas")
 HTML5_ATOM(divide, "divide")
 HTML5_ATOM(degree, "degree")
 HTML5_ATOM(domain, "domain")
 HTML5_ATOM(exists, "exists")
 HTML5_ATOM(fetile, "fetile")
--- a/parser/html/nsHtml5ElementName.cpp
+++ b/parser/html/nsHtml5ElementName.cpp
@@ -325,17 +325,17 @@ nsHtml5ElementName::initializeStatics()
   ELT_ARCSEC = new nsHtml5ElementName(nsHtml5Atoms::arcsec, nsHtml5Atoms::arcsec, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_ARCCSC = new nsHtml5ElementName(nsHtml5Atoms::arccsc, nsHtml5Atoms::arccsc, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_ARCTAN = new nsHtml5ElementName(nsHtml5Atoms::arctan, nsHtml5Atoms::arctan, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_ARCSIN = new nsHtml5ElementName(nsHtml5Atoms::arcsin, nsHtml5Atoms::arcsin, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_ARCCOS = new nsHtml5ElementName(nsHtml5Atoms::arccos, nsHtml5Atoms::arccos, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_APPLET = new nsHtml5ElementName(nsHtml5Atoms::applet, nsHtml5Atoms::applet, NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET, PR_FALSE, PR_TRUE, PR_FALSE);
   ELT_ARCCOT = new nsHtml5ElementName(nsHtml5Atoms::arccot, nsHtml5Atoms::arccot, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_APPROX = new nsHtml5ElementName(nsHtml5Atoms::approx, nsHtml5Atoms::approx, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
-  ELT_BUTTON = new nsHtml5ElementName(nsHtml5Atoms::button, nsHtml5Atoms::button, NS_HTML5TREE_BUILDER_BUTTON, PR_FALSE, PR_TRUE, PR_FALSE);
+  ELT_BUTTON = new nsHtml5ElementName(nsHtml5Atoms::button, nsHtml5Atoms::button, NS_HTML5TREE_BUILDER_BUTTON, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_CIRCLE = new nsHtml5ElementName(nsHtml5Atoms::circle, nsHtml5Atoms::circle, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_CENTER = new nsHtml5ElementName(nsHtml5Atoms::center, nsHtml5Atoms::center, NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU, PR_TRUE, PR_FALSE, PR_FALSE);
   ELT_CURSOR = new nsHtml5ElementName(nsHtml5Atoms::cursor, nsHtml5Atoms::cursor, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_CANVAS = new nsHtml5ElementName(nsHtml5Atoms::canvas, nsHtml5Atoms::canvas, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_DIVIDE = new nsHtml5ElementName(nsHtml5Atoms::divide, nsHtml5Atoms::divide, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_DEGREE = new nsHtml5ElementName(nsHtml5Atoms::degree, nsHtml5Atoms::degree, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_DOMAIN = new nsHtml5ElementName(nsHtml5Atoms::domain, nsHtml5Atoms::domain, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
   ELT_EXISTS = new nsHtml5ElementName(nsHtml5Atoms::exists, nsHtml5Atoms::exists, NS_HTML5TREE_BUILDER_OTHER, PR_FALSE, PR_FALSE, PR_FALSE);
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -1047,28 +1047,26 @@ nsHtml5TreeBuilder::startTag(nsHtml5Elem
                   attributes = nsnull;
                   goto starttagloop_end;
                 }
                 case NS_HTML5TREE_BUILDER_BUTTON: {
                   eltPos = findLastInScope(name);
                   if (eltPos != NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
 
                     generateImpliedEndTags();
-                    if (!isCurrent(nsHtml5Atoms::button)) {
+                    if (!isCurrent(name)) {
 
                     }
                     while (currentPtr >= eltPos) {
                       pop();
                     }
-                    clearTheListOfActiveFormattingElementsUpToTheLastMarker();
                     goto starttagloop;
                   } else {
                     reconstructTheActiveFormattingElements();
                     appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer);
-                    insertMarker();
                     attributes = nsnull;
                     goto starttagloop_end;
                   }
                 }
                 case NS_HTML5TREE_BUILDER_OBJECT: {
                   reconstructTheActiveFormattingElements();
                   appendToCurrentNodeAndPushElementMayFoster(kNameSpaceID_XHTML, elementName, attributes, formPointer);
                   insertMarker();
@@ -2266,16 +2264,17 @@ nsHtml5TreeBuilder::endTag(nsHtml5Elemen
 
             mode = NS_HTML5TREE_BUILDER_AFTER_BODY;
             continue;
           }
           case NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
           case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL:
           case NS_HTML5TREE_BUILDER_PRE_OR_LISTING:
           case NS_HTML5TREE_BUILDER_FIELDSET:
+          case NS_HTML5TREE_BUILDER_BUTTON:
           case NS_HTML5TREE_BUILDER_ADDRESS_OR_DIR_OR_ARTICLE_OR_ASIDE_OR_DATAGRID_OR_DETAILS_OR_HGROUP_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_NAV_OR_SECTION: {
             eltPos = findLastInScope(name);
             if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
 
             } else {
               generateImpliedEndTags();
               if (!isCurrent(name)) {
 
@@ -2376,17 +2375,16 @@ nsHtml5TreeBuilder::endTag(nsHtml5Elemen
           }
           case NS_HTML5TREE_BUILDER_A:
           case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
           case NS_HTML5TREE_BUILDER_FONT:
           case NS_HTML5TREE_BUILDER_NOBR: {
             adoptionAgencyEndTag(name);
             goto endtagloop_end;
           }
-          case NS_HTML5TREE_BUILDER_BUTTON:
           case NS_HTML5TREE_BUILDER_OBJECT:
           case NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET: {
             eltPos = findLastInScope(name);
             if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
 
             } else {
               generateImpliedEndTags();
               if (!isCurrent(name)) {
--- a/parser/htmlparser/tests/mochitest/html5lib_tree_dat1.txt
+++ b/parser/htmlparser/tests/mochitest/html5lib_tree_dat1.txt
@@ -222,17 +222,17 @@ Line: 1 Col: 30 Expected closing tag. Un
 |           <tr>
 |             <td>
 |               <i>
 |       "X"
 
 #data
 <h1>Hello<h2>World
 #errors
-4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+4: Start tag seen without seeing a doctype first. Expected β€œ<!DOCTYPE html>”.
 13: Heading cannot be a child of another heading.
 18: End of file seen and there were open elements.
 #document
 | <html>
 |   <head>
 |   <body>
 |     <h1>
 |       "Hello"
@@ -266,16 +266,30 @@ Line: 1 Col: 15 End tag (b) violates ste
 #document
 | <html>
 |   <head>
 |   <body>
 |     <b>
 |       <button>
 
 #data
+<!DOCTYPE html><span><button>foo</span>bar
+#errors
+39: End tag β€œspan” seen but there were unclosed elements.
+#document
+| <!DOCTYPE html>
+| <html>
+|   <head>
+|   <body>
+|     <span>
+|       <button>
+|         "foo"
+|     "bar"
+
+#data
 <p><b><div><marquee></p></b></div>X
 #errors
 Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE.
 Line: 1 Col: 11 Unexpected end tag (p). Ignored.
 Line: 1 Col: 24 Unexpected end tag (p). Ignored.
 Line: 1 Col: 28 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm.
 Line: 1 Col: 34 End tag (div) seen too early. Expected other end tag.
 Line: 1 Col: 35 Expected closing tag. Unexpected end of file.
@@ -1433,17 +1447,17 @@ Line: 1 Col: 29 Expected closing tag. Un
 |         <tbody>
 |           <tr>
 |             <td>
 |               <i>
 
 #data
 <h1><h2>
 #errors
-4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
+4: Start tag seen without seeing a doctype first. Expected β€œ<!DOCTYPE html>”.
 8: Heading cannot be a child of another heading.
 8: End of file seen and there were open elements.
 #document
 | <html>
 |   <head>
 |   <body>
 |     <h1>
 |     <h2>
@@ -1629,21 +1643,21 @@ Line: 1 Col: 10 Unexpected start tag (fr
 |     <frame>
 |     <frameset>
 |       <frame>
 |     <noframes>
 
 #data
 <h1><table><td><h3></table><h3></h1>
 #errors
-4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
-15: “td” start tag in table body.
+4: Start tag seen without seeing a doctype first. Expected β€œ<!DOCTYPE html>”.
+15: β€œtd” start tag in table body.
 27: Unclosed elements.
 31: Heading cannot be a child of another heading.
-36: End tag “h1” seen but there were unclosed elements.
+36: End tag β€œh1” seen but there were unclosed elements.
 #document
 | <html>
 |   <head>
 |   <body>
 |     <h1>
 |       <table>
 |         <tbody>
 |           <tr>