Bug 591619. Don't create frames for non-option kids of <optgroup> or non-option and non-optgroup kids of <select>. r=dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 03 Dec 2010 22:43:42 -0500
changeset 58592 e0285b393e11bf3a2fd7cb39538477af83e051ef
parent 58591 70cb20ed0813dc2ab15652ae5887b8eef21d590f
child 58593 e6267230056e50d19ea3f104fa03a343e4d9409e
push idunknown
push userunknown
push dateunknown
reviewersdbaron
bugs591619
milestone2.0b8pre
Bug 591619. Don't create frames for non-option kids of <optgroup> or non-option and non-optgroup kids of <select>. r=dbaron
layout/base/nsCSSFrameConstructor.cpp
layout/reftests/forms/reftest.list
layout/reftests/forms/select-boguskids-ref.html
layout/reftests/forms/select-boguskids.html
layout/reftests/forms/select-dynamic-boguskids.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -5156,16 +5156,40 @@ nsCSSFrameConstructor::AddFrameConstruct
   // any frame at all
   if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
     SetAsUndisplayedContent(aState.mFrameManager, aContent, styleContext,
                             isGeneratedContent);
     return;
   }
 
   PRBool isText = aContent->IsNodeOfType(nsINode::eTEXT);
+
+  // never create frames for non-option/optgroup kids of <select> and
+  // non-option kids of <optgroup> inside a <select>.
+  // XXXbz it's not clear how this should best work with XBL.
+  nsIContent *parent = aContent->GetParent();
+  if (parent) {
+    // Check tag first, since that check will usually fail
+    nsIAtom* parentTag = parent->Tag();
+    if ((parentTag == nsGkAtoms::select || parentTag == nsGkAtoms::optgroup) &&
+        parent->IsHTML() &&
+        // <option> is ok no matter what
+        !aContent->IsHTML(nsGkAtoms::option) &&
+        // <optgroup> is OK in <select> but not in <optgroup>
+        (!aContent->IsHTML(nsGkAtoms::optgroup) ||
+         parentTag != nsGkAtoms::select)) {
+      // No frame for aContent
+      if (!isText) {
+        SetAsUndisplayedContent(aState.mFrameManager, aContent, styleContext,
+                                isGeneratedContent);
+      }
+      return;
+    }
+  }
+
   PRBool isPopup = PR_FALSE;
   // Try to find frame construction data for this content
   const FrameConstructionData* data;
   if (isText) {
     data = FindTextData(aParentFrame);
 #ifdef MOZ_SVG
     if (!data) {
       // Nothing to do here; suppressed text inside SVG
--- a/layout/reftests/forms/reftest.list
+++ b/layout/reftests/forms/reftest.list
@@ -40,16 +40,18 @@ skip-if(winWidget) == textarea-resize-ba
 != radio-checked.html about:blank
 != radio-checked-notref.html about:blank
 != checkbox-checked-native.html about:blank
 != checkbox-checked-native-notref.html about:blank
 != radio-checked-native.html about:blank
 != radio-checked-native-notref.html about:blank
 
 == select-multiple.html select-multiple-ref.html
+== select-boguskids.html select-boguskids-ref.html
+== select-dynamic-boguskids.html select-boguskids-ref.html
 
 # placeholder
 include placeholder/reftest.list
 
 # input
 include input/reftest.list
 
 # output element
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select-boguskids-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <select size="10">
+      <option>one</option>
+      <option>two</option>
+      <optgroup>
+        <option>three</option>
+        <option>four</option>
+      </optgroup>
+    </select>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select-boguskids.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <select size="10">
+      Shouldn't see me
+      <option>one</option>
+      Or me
+      <option>two</option>
+      <optgroup>
+        I should hide too
+        <option>three</option>
+        And me too
+        <option>four</option>
+      </optgroup>
+      And I
+    </select>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/select-dynamic-boguskids.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <script>
+    function doIt() {
+      var insertions = [
+        [ "opt1", "Shouldn't see me" ],
+        [ "opt2", "Or me" ],
+        [ "opt3", "I should hide too" ],
+        [ "opt4", "And me too" ]
+      ];
+      for (var i = 0; i < insertions.length; ++i) {
+        var next = document.getElementById(insertions[i][0]);
+        next.parentNode.insertBefore(document.createTextNode(insertions[i][1]),
+                                     next);
+      }
+      document.getElementById("sel").appendChild(document.createTextNode("And I"));
+    }
+    </script>
+  </head>
+  <body onload="doIt()">
+    <select size="10" id="sel">
+      <option id="opt1">one</option>
+      <option id="opt2">two</option>
+      <optgroup>
+        <option id="opt3">three</option>
+        <option id="opt4">four</option>
+      </optgroup>
+    </select>
+  </body>
+</html>