Bug 1233135 - Do not touch display value of anonymous box for ruby. draft
authorXidorn Quan <quanxunzhen@gmail.com>
Thu, 17 Dec 2015 14:21:08 +1100
changeset 324961 73c1295b431023b541c98eb23340727f4a728cb7
parent 324958 a7f4a6c9f84da131c7d3feca4677d6eb5e637a96
child 513429 b25425cef90328ec066cde1095a7acb9e26f8783
push id9957
push userxquan@mozilla.com
push dateMon, 25 Jan 2016 05:41:45 +0000
bugs1233135
milestone46.0a1
Bug 1233135 - Do not touch display value of anonymous box for ruby.
layout/base/nsCSSFrameConstructor.cpp
layout/generic/RubyUtils.h
layout/style/crashtests/1233135-1.html
layout/style/crashtests/1233135-2.html
layout/style/crashtests/crashtests.list
layout/style/nsStyleContext.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1860,23 +1860,17 @@ IsTablePseudo(nsIFrame* aFrame)
          nsCSSAnonBoxes::table ||
        aFrame->GetFirstPrincipalChild()->StyleContext()->GetPseudo() ==
          nsCSSAnonBoxes::inlineTable)));
 }
 
 static bool
 IsRubyPseudo(nsIFrame* aFrame)
 {
-  nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
-  return pseudoType &&
-    (pseudoType == nsCSSAnonBoxes::ruby ||
-     pseudoType == nsCSSAnonBoxes::rubyBase ||
-     pseudoType == nsCSSAnonBoxes::rubyText ||
-     pseudoType == nsCSSAnonBoxes::rubyBaseContainer ||
-     pseudoType == nsCSSAnonBoxes::rubyTextContainer);
+  return RubyUtils::IsRubyPseudo(aFrame->StyleContext()->GetPseudo());
 }
 
 static bool
 IsTableOrRubyPseudo(nsIFrame* aFrame)
 {
   return IsTablePseudo(aFrame) || IsRubyPseudo(aFrame);
 }
 
--- a/layout/generic/RubyUtils.h
+++ b/layout/generic/RubyUtils.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_RubyUtils_h_
 #define mozilla_RubyUtils_h_
 
 #include "nsTArray.h"
 #include "nsGkAtoms.h"
+#include "nsCSSAnonBoxes.h"
 
 #define RTC_ARRAY_SIZE 1
 
 class nsRubyFrame;
 class nsRubyBaseFrame;
 class nsRubyTextFrame;
 class nsRubyContentFrame;
 class nsRubyBaseContainerFrame;
@@ -72,16 +73,25 @@ public:
   }
 
   static inline bool IsExpandableRubyBox(nsIFrame* aFrame)
   {
     nsIAtom* type = aFrame->GetType();
     return IsRubyContentBox(type) || IsRubyContainerBox(type);
   }
 
+  static inline bool IsRubyPseudo(nsIAtom* aPseudo)
+  {
+    return aPseudo == nsCSSAnonBoxes::ruby ||
+           aPseudo == nsCSSAnonBoxes::rubyBase ||
+           aPseudo == nsCSSAnonBoxes::rubyText ||
+           aPseudo == nsCSSAnonBoxes::rubyBaseContainer ||
+           aPseudo == nsCSSAnonBoxes::rubyTextContainer;
+  }
+
   static void SetReservedISize(nsIFrame* aFrame, nscoord aISize);
   static void ClearReservedISize(nsIFrame* aFrame);
   static nscoord GetReservedISize(nsIFrame* aFrame);
 };
 
 /**
  * This array stores all ruby text containers of the ruby segment
  * of the given ruby base container.
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1233135-1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+  fieldset, input, select {
+    display: ruby;
+  }
+</style>
+<fieldset></fieldset>
+<input type="color">
+<input type="file">
+<input type="number">
+<input type="range">
+<select></select>
+<select size="2"></select>
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1233135-2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<ruby>
+  <fieldset></fieldset>
+  <input type="color">
+  <input type="file">
+  <input type="number">
+  <input type="range">
+  <select></select>
+  <select size="2"></select>
+  <span style="display: block; overflow: scroll"></span>
+</ruby>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -128,13 +128,15 @@ load 1167782-1.html
 load 1186768-1.xhtml
 load 1200568-1.html
 load 1206105-1.html
 load 1223688-1.html
 load 1223694-1.html
 load 1226400-1.html
 load 1227501-1.html
 load 1230408-1.html
+load 1233135-1.html
+load 1233135-2.html
 load 1238660-1.html
 load border-image-visited-link.html
 load font-face-truncated-src.html 
 load large_border_image_width.html
 load long-url-list-stack-overflow.html
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -19,16 +19,17 @@
 #include "nsIPresShell.h"
 
 #include "nsRuleNode.h"
 #include "nsStyleContext.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "GeckoProfiler.h"
 #include "nsIDocument.h"
 #include "nsPrintfCString.h"
+#include "RubyUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ArenaObjectID.h"
 
 #ifdef DEBUG
 // #define NOISY_DEBUG
 #endif
 
 using namespace mozilla;
@@ -506,22 +507,33 @@ nsStyleContext::SetStyle(nsStyleStructID
     dataSlot = &mCachedInheritedData.mStyleStructs[aSID];
   }
   NS_ASSERTION(!*dataSlot || (mBits & nsCachedStyleData::GetBitForSID(aSID)),
                "Going to leak style data");
   *dataSlot = aStruct;
 }
 
 static bool
-ShouldSuppressLineBreak(const nsStyleDisplay* aStyleDisplay,
+ShouldSuppressLineBreak(const nsStyleContext* aContext,
+                        const nsStyleDisplay* aDisplay,
                         const nsStyleContext* aParentContext,
                         const nsStyleDisplay* aParentDisplay)
 {
   // The display change should only occur for "in-flow" children
-  if (aStyleDisplay->IsOutOfFlowStyle()) {
+  if (aDisplay->IsOutOfFlowStyle()) {
+    return false;
+  }
+  // Display value of any anonymous box should not be touched. In most
+  // cases, anonymous boxes are actually not in ruby frame, but instead,
+  // some other frame with a ruby display value. Non-element pseudos
+  // which represents text frames, as well as ruby pseudos are excluded
+  // because we still want to set the flag for them.
+  if (aContext->GetPseudoType() == nsCSSPseudoElements::ePseudo_AnonBox &&
+      aContext->GetPseudo() != nsCSSAnonBoxes::mozNonElement &&
+      !RubyUtils::IsRubyPseudo(aContext->GetPseudo())) {
     return false;
   }
   if (aParentContext->ShouldSuppressLineBreak()) {
     // Line break suppressing bit is propagated to any children of
     // line participants, which include inline, contents, and inline
     // ruby boxes.
     if (aParentDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE ||
         aParentDisplay->mDisplay == NS_STYLE_DISPLAY_CONTENTS ||
@@ -545,22 +557,22 @@ ShouldSuppressLineBreak(const nsStyleDis
   //    any, won't be able to break the line its ruby ancestor lays; and
   // 3. their parent frame is always a ruby content frame (due to
   //    anonymous ruby box generation), which makes line layout suppress
   //    any optional line break around this frame.
   // However, there is one special case which is BR tag, because it
   // directly affects the line layout. This case is handled by the BR
   // frame which checks the flag of its parent frame instead of itself.
   if ((aParentDisplay->IsRubyDisplayType() &&
-       aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER &&
-       aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) ||
+       aDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER &&
+       aDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) ||
       // Since ruby base and ruby text may exist themselves without any
       // non-anonymous frame outside, we should also check them.
-      aStyleDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE ||
-      aStyleDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_TEXT) {
+      aDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE ||
+      aDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_TEXT) {
     return true;
   }
   return false;
 }
 
 void
 nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
 {
@@ -709,17 +721,17 @@ nsStyleContext::ApplyStyleFixups(bool aS
   }
 
   // Set the NS_STYLE_IN_DISPLAY_NONE_SUBTREE bit
   if ((mParent && mParent->IsInDisplayNoneSubtree()) ||
       disp->mDisplay == NS_STYLE_DISPLAY_NONE) {
     mBits |= NS_STYLE_IN_DISPLAY_NONE_SUBTREE;
   }
 
-  if (mParent && ::ShouldSuppressLineBreak(disp, mParent,
+  if (mParent && ::ShouldSuppressLineBreak(this, disp, mParent,
                                            mParent->StyleDisplay())) {
     mBits |= NS_STYLE_SUPPRESS_LINEBREAK;
     uint8_t displayVal = disp->mDisplay;
     nsRuleNode::EnsureInlineDisplay(displayVal);
     if (displayVal != disp->mDisplay) {
       nsStyleDisplay* mutable_display =
         static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display));
       disp = mutable_display;