Bug 1388625 part 4. Add a concept of wrapper anon boxes to nsCSSAnonBoxes. r?heycam draft
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 11 Aug 2017 00:07:12 -0400
changeset 644573 63e5e889b1a436ab4a6faf863738262956500736
parent 644255 2865e902b0558aeb00d0dd8232196968dac80b33
child 644574 e846c5a2f4c48e051351736599248a71ba7f50f2
push id73471
push userbzbarsky@mozilla.com
push dateFri, 11 Aug 2017 04:10:55 +0000
reviewersheycam
bugs1388625
milestone57.0a1
Bug 1388625 part 4. Add a concept of wrapper anon boxes to nsCSSAnonBoxes. r?heycam MozReview-Commit-ID: 39i5eHlrrON
layout/style/nsCSSAnonBoxList.h
layout/style/nsCSSAnonBoxes.h
layout/style/nsStyleContext.h
--- a/layout/style/nsCSSAnonBoxList.h
+++ b/layout/style/nsCSSAnonBoxList.h
@@ -5,107 +5,118 @@
 
 /* atom list for CSS anonymous boxes */
 
 /*
  * This file contains the list of nsIAtoms and their values for CSS
  * pseudo-element-ish things used internally for anonymous boxes.  It is
  * designed to be used as inline input to nsCSSAnonBoxes.cpp *only* through the
  * magic of C preprocessing.  All entries must be enclosed in the macros
- * CSS_ANON_BOX and CSS_NON_INHERITING_ANON_BOX which will have cruel and
- * unusual things done to it.  The entries should be kept in some sort of
- * logical order.
+ * CSS_ANON_BOX, CSS_WRAPPER_ANON_BOX, or CSS_NON_INHERITING_ANON_BOX which will
+ * have cruel and unusual things done to it.  The entries should be kept in some
+ * sort of logical order.
  *
- * The first argument to CSS_ANON_BOX/CSS_NON_INHERITING_ANON_BOX is the C++
+ * The first argument to
+ * CSS_ANON_BOX/CSS_WRAPPER_ANON_BOX/CSS_NON_INHERITING_ANON_BOX is the C++
  * identifier of the atom.
  *
  * The second argument is the string value of the atom.
  *
- * The third argument to CSS_ANON_BOX is whether the anonymous box skips parent-
- * based display fixups (such as blockification inside flex containers).  This
- * is implicitly true for CSS_NON_INHERITING_ANON_BOX.
- *
  * CSS_NON_INHERITING_ANON_BOX is used for anon boxes that never inherit style
  * from anything.  This means all their property values are the initial values
  * of those properties.
+ *
+ * CSS_WRAPPER_ANON_BOX is used for anon boxes that are used as wrappers around
+ * other frames during frametree fixup (e.g. table anonymous boxes, ruby
+ * anonymous boxes, anonymous flex item blocks, etc).  These are also inheriting
+ * anon boxes, just like CSS_ANON_BOX.  If this macro is not defined, it will
+ * default to CSS_ANON_BOX.
  */
 
 // OUTPUT_CLASS=nsCSSAnonBoxes
-// MACRO_NAME=CSS_ANON_BOX/CSS_NON_INHERITING_ANON_BOX
+// MACRO_NAME=CSS_ANON_BOX/CSS_NON_INHERITING_ANON_BOX/CSS_WRAPPER_ANON_BOX
 
 #ifndef CSS_NON_INHERITING_ANON_BOX
 #  ifdef DEFINED_CSS_NON_INHERITING_ANON_BOX
 #    error "Recursive includes of nsCSSAnonBoxList.h?"
 #  endif /* DEFINED_CSS_NON_INHERITING_ANON_BOX */
 #  define CSS_NON_INHERITING_ANON_BOX(name_, value_) CSS_ANON_BOX(name_, value_)
 #  define DEFINED_CSS_NON_INHERITING_ANON_BOX
 #endif /* CSS_NON_INHERITING_ANON_BOX */
 
+#ifndef CSS_WRAPPER_ANON_BOX
+#  ifdef DEFINED_CSS_WRAPPER_ANON_BOX
+#    error "Recursive includes of nsCSSAnonBoxList.h?"
+#  endif /* DEFINED_CSS_WRAPPER_ANON_BOX */
+#  define CSS_WRAPPER_ANON_BOX(name_, value_) CSS_ANON_BOX(name_, value_)
+#  define DEFINED_CSS_WRAPPER_ANON_BOX
+#endif /* CSS_WRAPPER_ANON_BOX */
+
 // ::-moz-text, ::-moz-oof-placeholder, and ::-moz-first-letter-continuation are
 // non-elements which no rule will match.
 CSS_ANON_BOX(mozText, ":-moz-text")
 // placeholder frames for out of flows.  Note that :-moz-placeholder is used for
 // the pseudo-element that represents the placeholder text in <input
 // placeholder="foo">, so we need a different string here.
 CSS_NON_INHERITING_ANON_BOX(oofPlaceholder, ":-moz-oof-placeholder")
 // nsFirstLetterFrames for content outside the ::first-letter.
 CSS_ANON_BOX(firstLetterContinuation, ":-moz-first-letter-continuation")
 
 CSS_ANON_BOX(mozBlockInsideInlineWrapper, ":-moz-block-inside-inline-wrapper")
-CSS_ANON_BOX(mozMathMLAnonymousBlock, ":-moz-mathml-anonymous-block")
+CSS_WRAPPER_ANON_BOX(mozMathMLAnonymousBlock, ":-moz-mathml-anonymous-block")
 CSS_ANON_BOX(mozXULAnonymousBlock, ":-moz-xul-anonymous-block")
 
 // Framesets
 CSS_NON_INHERITING_ANON_BOX(horizontalFramesetBorder, ":-moz-hframeset-border")
 CSS_NON_INHERITING_ANON_BOX(verticalFramesetBorder, ":-moz-vframeset-border")
 
 CSS_ANON_BOX(mozLineFrame, ":-moz-line-frame")
 
 CSS_ANON_BOX(buttonContent, ":-moz-button-content")
 CSS_ANON_BOX(cellContent, ":-moz-cell-content")
 CSS_ANON_BOX(dropDownList, ":-moz-dropdown-list")
 CSS_ANON_BOX(fieldsetContent, ":-moz-fieldset-content")
 CSS_NON_INHERITING_ANON_BOX(framesetBlank, ":-moz-frameset-blank")
 CSS_ANON_BOX(mozDisplayComboboxControlFrame, ":-moz-display-comboboxcontrol-frame")
 CSS_ANON_BOX(htmlCanvasContent, ":-moz-html-canvas-content")
 
-CSS_ANON_BOX(inlineTable, ":-moz-inline-table")
-CSS_ANON_BOX(table, ":-moz-table")
-CSS_ANON_BOX(tableCell, ":-moz-table-cell")
-CSS_ANON_BOX(tableColGroup, ":-moz-table-column-group")
+CSS_WRAPPER_ANON_BOX(inlineTable, ":-moz-inline-table")
+CSS_WRAPPER_ANON_BOX(table, ":-moz-table")
+CSS_WRAPPER_ANON_BOX(tableCell, ":-moz-table-cell")
+CSS_WRAPPER_ANON_BOX(tableColGroup, ":-moz-table-column-group")
 CSS_ANON_BOX(tableCol, ":-moz-table-column")
 CSS_ANON_BOX(tableWrapper, ":-moz-table-wrapper")
-CSS_ANON_BOX(tableRowGroup, ":-moz-table-row-group")
-CSS_ANON_BOX(tableRow, ":-moz-table-row")
+CSS_WRAPPER_ANON_BOX(tableRowGroup, ":-moz-table-row-group")
+CSS_WRAPPER_ANON_BOX(tableRow, ":-moz-table-row")
 
 CSS_ANON_BOX(canvas, ":-moz-canvas")
 CSS_NON_INHERITING_ANON_BOX(pageBreak, ":-moz-pagebreak")
 CSS_ANON_BOX(page, ":-moz-page")
 CSS_ANON_BOX(pageContent, ":-moz-pagecontent")
 CSS_ANON_BOX(pageSequence, ":-moz-page-sequence")
 CSS_ANON_BOX(scrolledContent, ":-moz-scrolled-content")
 CSS_ANON_BOX(scrolledCanvas, ":-moz-scrolled-canvas")
 CSS_ANON_BOX(scrolledPageSequence, ":-moz-scrolled-page-sequence")
 CSS_ANON_BOX(columnContent, ":-moz-column-content")
 CSS_ANON_BOX(viewport, ":-moz-viewport")
 CSS_ANON_BOX(viewportScroll, ":-moz-viewport-scroll")
 
 // Inside a flex container, a contiguous run of text gets wrapped in
 // an anonymous block, which is then treated as a flex item.
-CSS_ANON_BOX(anonymousFlexItem, ":-moz-anonymous-flex-item")
+CSS_WRAPPER_ANON_BOX(anonymousFlexItem, ":-moz-anonymous-flex-item")
 
 // Inside a grid container, a contiguous run of text gets wrapped in
 // an anonymous block, which is then treated as a grid item.
-CSS_ANON_BOX(anonymousGridItem, ":-moz-anonymous-grid-item")
+CSS_WRAPPER_ANON_BOX(anonymousGridItem, ":-moz-anonymous-grid-item")
 
-CSS_ANON_BOX(ruby, ":-moz-ruby")
-CSS_ANON_BOX(rubyBase, ":-moz-ruby-base")
-CSS_ANON_BOX(rubyBaseContainer, ":-moz-ruby-base-container")
-CSS_ANON_BOX(rubyText, ":-moz-ruby-text")
-CSS_ANON_BOX(rubyTextContainer, ":-moz-ruby-text-container")
+CSS_WRAPPER_ANON_BOX(ruby, ":-moz-ruby")
+CSS_WRAPPER_ANON_BOX(rubyBase, ":-moz-ruby-base")
+CSS_WRAPPER_ANON_BOX(rubyBaseContainer, ":-moz-ruby-base-container")
+CSS_WRAPPER_ANON_BOX(rubyText, ":-moz-ruby-text")
+CSS_WRAPPER_ANON_BOX(rubyTextContainer, ":-moz-ruby-text-container")
 
 #ifdef MOZ_XUL
 CSS_ANON_BOX(mozTreeColumn, ":-moz-tree-column")
 CSS_ANON_BOX(mozTreeRow, ":-moz-tree-row")
 CSS_ANON_BOX(mozTreeSeparator, ":-moz-tree-separator")
 CSS_ANON_BOX(mozTreeCell, ":-moz-tree-cell")
 CSS_ANON_BOX(mozTreeIndentation, ":-moz-tree-indentation")
 CSS_ANON_BOX(mozTreeLine, ":-moz-tree-line")
@@ -121,8 +132,13 @@ CSS_ANON_BOX(mozSVGMarkerAnonChild, ":-m
 CSS_ANON_BOX(mozSVGOuterSVGAnonChild, ":-moz-svg-outer-svg-anon-child")
 CSS_ANON_BOX(mozSVGForeignContent, ":-moz-svg-foreign-content")
 CSS_ANON_BOX(mozSVGText, ":-moz-svg-text")
 
 #ifdef DEFINED_CSS_NON_INHERITING_ANON_BOX
 #  undef DEFINED_CSS_NON_INHERITING_ANON_BOX
 #  undef CSS_NON_INHERITING_ANON_BOX
 #endif /* DEFINED_CSS_NON_INHERITING_ANON_BOX */
+
+#ifdef DEFINED_CSS_WRAPPER_ANON_BOX
+#  undef DEFINED_CSS_WRAPPER_ANON_BOX
+#  undef CSS_WRAPPER_ANON_BOX
+#endif /* DEFINED_CSS_NON_INHERITING_ANON_BOX */
--- a/layout/style/nsCSSAnonBoxes.h
+++ b/layout/style/nsCSSAnonBoxes.h
@@ -57,28 +57,46 @@ public:
 #undef CSS_NON_INHERITING_ANON_BOX
 #undef CSS_ANON_BOX
       false;
   }
 
 #ifdef DEBUG
   // NOTE(emilio): DEBUG only because this does a pretty slow linear search. Try
   // to use IsNonInheritingAnonBox if you know the atom is an anon box already
-  // or, even better, nothing like this.
+  // or, even better, nothing like this.  Note that this function returns true
+  // for wrapper anon boxes as well, since they're all inheriting.
   static bool IsInheritingAnonBox(nsIAtom* aPseudo)
   {
     return
 #define CSS_ANON_BOX(_name, _value) _name == aPseudo ||
 #define CSS_NON_INHERITING_ANON_BOX(_name, _value) /* nothing */
 #include "nsCSSAnonBoxList.h"
 #undef CSS_NON_INHERITING_ANON_BOX
 #undef CSS_ANON_BOX
       false;
   }
-#endif
+#endif // DEBUG
+
+  // This function is rather slow; you probably don't want to use it outside
+  // asserts unless you have to.
+  static bool IsWrapperAnonBox(nsIAtom* aPseudo) {
+    // We commonly get null passed here, and want to quickly return false for
+    // it.
+    return aPseudo &&
+      (
+#define CSS_ANON_BOX(_name, _value) /* nothing */
+#define CSS_WRAPPER_ANON_BOX(_name, _value) _name == aPseudo ||
+#define CSS_NON_INHERITING_ANON_BOX(_name, _value) /* nothing */
+#include "nsCSSAnonBoxList.h"
+#undef CSS_NON_INHERITING_ANON_BOX
+#undef CSS_WRAPPER_ANON_BOX
+#undef CSS_ANON_BOX
+       false);
+  }
 
   // Get the NonInheriting type for a given pseudo tag.  The pseudo tag must
   // test true for IsNonInheritingAnonBox.
   static NonInheriting NonInheritingTypeForPseudoTag(nsIAtom* aPseudo);
 
   // Get the atom for a given non-inheriting anon box type.  aBoxType must be <
   // NonInheriting::_Count.
   static nsIAtom* GetNonInheritingPseudoAtom(NonInheriting aBoxType);
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -97,16 +97,24 @@ public:
   bool IsInheritingAnonBox() const {
     return GetPseudoType() == mozilla::CSSPseudoElementType::InheritingAnonBox;
   }
 
   bool IsNonInheritingAnonBox() const {
     return GetPseudoType() == mozilla::CSSPseudoElementType::NonInheritingAnonBox;
   }
 
+  // This function is rather slow; you probably don't want to use it outside
+  // asserts unless you have to.  We _could_ add a new CSSPseudoElementType for
+  // wrapper anon boxes, but that adds a bunch of complexity everywhere we
+  // resolve anonymous box styles...
+  bool IsWrapperAnonBox() const {
+    return nsCSSAnonBoxes::IsWrapperAnonBox(GetPseudo());
+  }
+
   bool IsAnonBox() const {
     return IsInheritingAnonBox() || IsNonInheritingAnonBox();
   }
 
   bool IsPseudoElement() const { return mPseudoTag && !IsAnonBox(); }
 
 
   // Does this style context or any of its ancestors have text