Backed out 4 changesets (bug 1331322) for Android reftest failures in 1169331-1.html and forced-bg-color-outside-visible-region.html
authorPhil Ringnalda <philringnalda@gmail.com>
Wed, 15 Feb 2017 21:24:00 -0800
changeset 343258 8c8b54b13be7ec12cb8e104b772162a80b524497
parent 343257 e7e02e3c2e56edb9ba8bff03716052ae261ebb26
child 343259 2737f66ad6ac74a688bde788b319122f2001b92b
child 343282 7be8bbea728975cae9a838d7e84996792bd406ec
push id87066
push usercbook@mozilla.com
push dateThu, 16 Feb 2017 12:19:17 +0000
treeherdermozilla-inbound@42e6e6b27486 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1331322, 1169331
milestone54.0a1
backs out96c6b5a11284d663c1ffb8143e325c637f3b5dc2
15877d32de7d9a42fdbe4fa9dd6983dcbf6a0369
841d608704d72e6a4dfbd3ed9db6df45caa40b2c
02096c5eb029f38432311bd2175ed357092dfd58
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1331322) for Android reftest failures in 1169331-1.html and forced-bg-color-outside-visible-region.html Backed out changeset 96c6b5a11284 (bug 1331322) Backed out changeset 15877d32de7d (bug 1331322) Backed out changeset 841d608704d7 (bug 1331322) Backed out changeset 02096c5eb029 (bug 1331322)
dom/base/Element.cpp
dom/base/Element.h
dom/base/crashtests/crashtests.list
dom/base/nsGkAtomList.h
dom/base/nsIContent.h
dom/base/nsINode.cpp
dom/base/nsINode.h
dom/svg/nsSVGClass.cpp
dom/xul/nsXULElement.cpp
layout/base/GeckoRestyleManager.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/forms/nsColorControlFrame.cpp
layout/forms/nsMeterFrame.cpp
layout/forms/nsNumberControlFrame.cpp
layout/forms/nsNumberControlFrame.h
layout/forms/nsProgressFrame.cpp
layout/forms/nsRangeFrame.cpp
layout/forms/nsTextControlFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsIAnonymousContentCreator.h
layout/reftests/forms/input/number/number-style-inheritance-ref.html
layout/reftests/forms/input/number/number-style-inheritance.html
layout/reftests/forms/input/number/reftest.list
layout/style/res/forms.css
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -161,17 +161,18 @@ nsIContent::DoGetID() const
   MOZ_ASSERT(IsElement(), "Only elements can have IDs");
 
   return AsElement()->GetParsedAttr(nsGkAtoms::id)->GetAtomValue();
 }
 
 const nsAttrValue*
 Element::DoGetClasses() const
 {
-  MOZ_ASSERT(MayHaveClass(), "Unexpected call");
+  MOZ_ASSERT(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
+
   if (IsSVGElement()) {
     const nsAttrValue* animClass =
       static_cast<const nsSVGElement*>(this)->GetAnimatedClassName();
     if (animClass) {
       return animClass;
     }
   }
 
@@ -2543,17 +2544,17 @@ Element::BeforeSetAttr(int32_t aNamespac
 bool
 Element::ParseAttribute(int32_t aNamespaceID,
                         nsIAtom* aAttribute,
                         const nsAString& aValue,
                         nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::_class) {
-      SetMayHaveClass();
+      SetFlags(NODE_MAY_HAVE_CLASS);
       // Result should have been preparsed above.
       return true;
     }
     if (aAttribute == nsGkAtoms::id) {
       // Store id as an atom.  id="" means that the element has no id,
       // not that it has an emptystring as the id.
       RemoveFromIdTable();
       if (aValue.IsEmpty()) {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -618,17 +618,17 @@ public:
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   /**
    * Get the class list of this element (this corresponds to the value of the
    * class attribute).  This may be null if there are no classes, but that's not
    * guaranteed (e.g. we could have class="").
    */
   const nsAttrValue* GetClasses() const {
-    if (MayHaveClass()) {
+    if (HasFlag(NODE_MAY_HAVE_CLASS)) {
       return DoGetClasses();
     }
     return nullptr;
   }
 
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override
   {
@@ -788,35 +788,16 @@ public:
     GetElementsByTagName(const nsAString& aQualifiedName);
   already_AddRefed<nsIHTMLCollection>
     GetElementsByTagNameNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName,
                            ErrorResult& aError);
   already_AddRefed<nsIHTMLCollection>
     GetElementsByClassName(const nsAString& aClassNames);
 
-  CSSPseudoElementType GetPseudoElementType() const {
-    if (!HasProperties()) {
-      return CSSPseudoElementType::NotPseudo;
-    }
-    nsresult rv = NS_OK;
-    auto raw = GetProperty(nsGkAtoms::pseudoProperty, &rv);
-    if (rv == NS_PROPTABLE_PROP_NOT_THERE) {
-      return CSSPseudoElementType::NotPseudo;
-    }
-    return CSSPseudoElementType(reinterpret_cast<uintptr_t>(raw));
-  }
-
-  void SetPseudoElementType(CSSPseudoElementType aPseudo) {
-    static_assert(sizeof(CSSPseudoElementType) <= sizeof(uintptr_t),
-                  "Need to be able to store this in a void*");
-    MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo);
-    SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
-  }
-
 private:
   /**
    * Implement the algorithm specified at
    * https://dom.spec.whatwg.org/#insert-adjacent for both
    * |insertAdjacentElement()| and |insertAdjacentText()| APIs.
    */
   nsINode* InsertAdjacent(const nsAString& aWhere,
                           nsINode* aNode,
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -188,17 +188,17 @@ load 852381.html
 load 863950.html
 load 864448.html
 load 886213.html
 load 898906.html
 load 930250.html
 load 942979.html
 load 973401.html
 load 978646.html
-skip-if(stylo) pref(dom.webcomponents.enabled,true) load 1024428-1.html # bug 1340009
+asserts-if(stylo,1-11) pref(dom.webcomponents.enabled,true) load 1024428-1.html # bug 1324671
 load 1026714.html
 pref(dom.webcomponents.enabled,true) load 1027461-1.html
 pref(dom.webcomponents.enabled,true) load 1029710.html
 load 1154598.xhtml
 load 1157995.html
 load 1158412.html
 load 1181619.html
 load structured_clone_container_throws.html
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2147,17 +2147,16 @@ GK_ATOM(transitionsOfBeforeProperty, "Tr
 GK_ATOM(transitionsOfAfterProperty, "TransitionsOfAfterProperty") // FrameTransitions*
 GK_ATOM(genConInitializerProperty, "QuoteNodeProperty")
 GK_ATOM(labelMouseDownPtProperty, "LabelMouseDownPtProperty")
 GK_ATOM(baseURIProperty, "baseURIProperty")
 GK_ATOM(lockedStyleStates, "lockedStyleStates")
 GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
 GK_ATOM(restylableAnonymousNode, "restylableAnonymousNode")
 GK_ATOM(paintRequestTime, "PaintRequestTime")
-GK_ATOM(pseudoProperty, "PseudoProperty")  // CSSPseudoElementType
 
 // Languages for lang-specific transforms
 GK_ATOM(Japanese, "ja")
 GK_ATOM(Chinese, "zh-CN")
 GK_ATOM(Taiwanese, "zh-TW")
 GK_ATOM(HongKongChinese, "zh-HK")
 GK_ATOM(Unicode, "x-unicode")
 
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -189,17 +189,17 @@ public:
 
   /**
    * Makes this content anonymous
    * @see nsIAnonymousContentCreator
    */
   void SetIsNativeAnonymousRoot()
   {
     SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
-             NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_IS_NATIVE_ANONYMOUS);
+             NODE_IS_NATIVE_ANONYMOUS_ROOT);
   }
 
   /**
    * Returns |this| if it is not chrome-only/native anonymous, otherwise
    * first non chrome-only/native anonymous ancestor.
    */
   virtual nsIContent* FindFirstNonChromeOnlyAccessContent() const;
 
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1524,16 +1524,17 @@ ReleaseURI(void*, /* aObject*/
   NS_RELEASE(uri);
 }
 
 nsresult
 nsINode::SetExplicitBaseURI(nsIURI* aURI)
 {
   nsresult rv = SetProperty(nsGkAtoms::baseURIProperty, aURI, ReleaseURI);
   if (NS_SUCCEEDED(rv)) {
+    SetHasExplicitBaseURI();
     NS_ADDREF(aURI);
   }
   return rv;
 }
 
 static nsresult
 AdoptNodeIntoOwnerDoc(nsINode *aParent, nsINode *aNode)
 {
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -122,38 +122,19 @@ enum {
   // in the document and therefore should get bindings attached.
   NODE_FORCE_XBL_BINDINGS =               NODE_FLAG_BIT(5),
 
   // Whether a binding manager may have a pointer to this
   NODE_MAY_BE_IN_BINDING_MNGR =           NODE_FLAG_BIT(6),
 
   NODE_IS_EDITABLE =                      NODE_FLAG_BIT(7),
 
-  // This node was created by layout as native anonymous content. This
-  // generally corresponds to things created by nsIAnonymousContentCreator,
-  // though there are exceptions (svg:use content does not have this flag
-  // set, and any non-nsIAnonymousContentCreator callers of
-  // SetIsNativeAnonymousRoot also get this flag).
-  //
-  // One very important aspect here is that this node is not transitive over
-  // the subtree (if you want that, use NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE).
-  // If Gecko code somewhere attaches children to a node with this bit set,
-  // the children will not have the bit themselves unless the calling code sets
-  // it explicitly. This means that XBL content bound to NAC doesn't get this
-  // bit, nor do nodes inserted by editor.
-  //
-  // For now, this bit exists primarily to control style inheritance behavior,
-  // since the nodes for which we set it are often used to implement pseudo-
-  // elements, which need to inherit style from a script-visible element.
-  //
-  // A more general principle for this bit might be this: If the node is entirely
-  // a detail of layout, is not script-observable in any way, and other engines
-  // might accomplish the same task with a nodeless layout frame, then the node
-  // should have this bit set.
-  NODE_IS_NATIVE_ANONYMOUS =              NODE_FLAG_BIT(8),
+  // For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
+  // node in fact has a class, but may be set even if it doesn't.
+  NODE_MAY_HAVE_CLASS =                   NODE_FLAG_BIT(8),
 
   // Whether the node participates in a shadow tree.
   NODE_IS_IN_SHADOW_TREE =                NODE_FLAG_BIT(9),
 
   // Node has an :empty or :-moz-only-whitespace selector
   NODE_HAS_EMPTY_SELECTOR =               NODE_FLAG_BIT(10),
 
   // A child of the node has a selector such that any insertion,
@@ -1186,25 +1167,16 @@ public:
 #ifdef MOZILLA_INTERNAL_API
     return IsEditableInternal();
 #else
     return IsEditableExternal();
 #endif
   }
 
   /**
-   * Returns true if |this| is native anonymous (i.e. created by
-   * nsIAnonymousContentCreator);
-   */
-  bool IsNativeAnonymous() const
-  {
-    return HasFlag(NODE_IS_NATIVE_ANONYMOUS);
-  }
-
-  /**
    * Returns true if |this| or any of its ancestors is native anonymous.
    */
   bool IsInNativeAnonymousSubtree() const
   {
 #ifdef DEBUG
     if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) {
       return true;
     }
@@ -1326,21 +1298,20 @@ public:
   virtual bool IsHTMLShadowElement() const { return false; }
 
   // Elements named <content> may or may not be HTMLContentElement.  This is a
   // way to ask an element whether it's an HTMLContentElement.
   virtual bool IsHTMLContentElement() const { return false; }
 
 protected:
   nsIURI* GetExplicitBaseURI() const {
-    if (!HasProperties()) {
-      return nullptr;
+    if (HasExplicitBaseURI()) {
+      return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
     }
-
-    return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
+    return nullptr;
   }
 
 public:
   void GetTextContent(nsAString& aTextContent,
                       mozilla::OOMReporter& aError)
   {
     GetTextContentInternal(aTextContent, aError);
   }
@@ -1520,18 +1491,16 @@ private:
     // Set if mParent is an nsIContent
     ParentIsContent,
     // Set if this node is an Element
     NodeIsElement,
     // Set if the element has a non-empty id attribute. This can in rare
     // cases lie for nsXMLElement, such as when the node has been moved between
     // documents with different id mappings.
     ElementHasID,
-    // Set if the element might have a class.
-    ElementMayHaveClass,
     // Set if the element might have inline style.
     ElementMayHaveStyle,
     // Set if the element has a name attribute set.
     ElementHasName,
     // Set if the element might have a contenteditable attribute set.
     ElementMayHaveContentEditableAttr,
     // Set if the node is the common ancestor of the start/end nodes of a Range
     // that is in a Selection.
@@ -1540,16 +1509,18 @@ private:
     NodeIsDescendantOfCommonAncestorForRangeInSelection,
     // Set if CanSkipInCC check has been done for this subtree root.
     NodeIsCCMarkedRoot,
     // Maybe set if this node is in black subtree.
     NodeIsCCBlackTree,
     // Maybe set if the node is a root of a subtree
     // which needs to be kept in the purple buffer.
     NodeIsPurpleRoot,
+    // Set if the node has an explicit base URI stored
+    NodeHasExplicitBaseURI,
     // Set if the element has some style states locked
     ElementHasLockedStyleStates,
     // Set if element has pointer locked
     ElementHasPointerLock,
     // Set if the node may have DOMMutationObserver attached to it.
     NodeMayHaveDOMMutationObserver,
     // Set if node is Content
     NodeIsContent,
@@ -1616,18 +1587,16 @@ private:
 
 public:
   bool HasRenderingObservers() const
     { return GetBoolFlag(NodeHasRenderingObservers); }
   void SetHasRenderingObservers(bool aValue)
     { SetBoolFlag(NodeHasRenderingObservers, aValue); }
   bool IsContent() const { return GetBoolFlag(NodeIsContent); }
   bool HasID() const { return GetBoolFlag(ElementHasID); }
-  bool MayHaveClass() const { return GetBoolFlag(ElementMayHaveClass); }
-  void SetMayHaveClass() { SetBoolFlag(ElementMayHaveClass); }
   bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); }
   bool HasName() const { return GetBoolFlag(ElementHasName); }
   bool MayHaveContentEditableAttr() const
     { return GetBoolFlag(ElementMayHaveContentEditableAttr); }
   bool IsCommonAncestorForRangeInSelection() const
     { return GetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
   void SetCommonAncestorForRangeInSelection()
     { SetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
@@ -1747,16 +1716,18 @@ protected:
   void SetIsElement() { SetBoolFlag(NodeIsElement); }
   void SetHasID() { SetBoolFlag(ElementHasID); }
   void ClearHasID() { ClearBoolFlag(ElementHasID); }
   void SetMayHaveStyle() { SetBoolFlag(ElementMayHaveStyle); }
   void SetHasName() { SetBoolFlag(ElementHasName); }
   void ClearHasName() { ClearBoolFlag(ElementHasName); }
   void SetMayHaveContentEditableAttr()
     { SetBoolFlag(ElementMayHaveContentEditableAttr); }
+  bool HasExplicitBaseURI() const { return GetBoolFlag(NodeHasExplicitBaseURI); }
+  void SetHasExplicitBaseURI() { SetBoolFlag(NodeHasExplicitBaseURI); }
   void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
   void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
   bool HasLockedStyleStates() const
     { return GetBoolFlag(ElementHasLockedStyleStates); }
   void SetHasWeirdParserInsertionMode() { SetBoolFlag(ElementHasWeirdParserInsertionMode); }
   bool HasWeirdParserInsertionMode() const
   { return GetBoolFlag(ElementHasWeirdParserInsertionMode); }
   bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); }
--- a/dom/svg/nsSVGClass.cpp
+++ b/dom/svg/nsSVGClass.cpp
@@ -65,17 +65,17 @@ nsSVGClass::ToDOMAnimatedString(nsSVGEle
 
 void
 nsSVGClass::SetBaseValue(const nsAString& aValue,
                          nsSVGElement *aSVGElement,
                          bool aDoSetAttr)
 {
   NS_ASSERTION(aSVGElement, "Null element passed to SetBaseValue");
 
-  aSVGElement->SetMayHaveClass();
+  aSVGElement->SetFlags(NODE_MAY_HAVE_CLASS);
   if (aDoSetAttr) {
     aSVGElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aValue, true);
   }
   if (mAnimVal) {
     aSVGElement->AnimationNeedsResample();
   }
 }
 
@@ -101,17 +101,17 @@ nsSVGClass::SetAnimValue(const nsAString
 {
   if (mAnimVal && mAnimVal->Equals(aValue)) {
     return;
   }
   if (!mAnimVal) {
     mAnimVal = new nsString();
   }
   *mAnimVal = aValue;
-  aSVGElement->SetMayHaveClass();
+  aSVGElement->SetFlags(NODE_MAY_HAVE_CLASS);
   aSVGElement->DidAnimateClass();
 }
 
 void
 DOMAnimatedString::GetAnimVal(nsAString& aResult)
 {
   mSVGElement->FlushAnimations();
   mVal->GetAnimValue(aResult, mSVGElement);
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -226,17 +226,17 @@ nsXULElement::Create(nsXULPrototypeEleme
 {
     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     RefPtr<nsXULElement> element = new nsXULElement(ni.forget());
     if (element) {
         if (aPrototype->mHasIdAttribute) {
             element->SetHasID();
         }
         if (aPrototype->mHasClassAttribute) {
-            element->SetMayHaveClass();
+            element->SetFlags(NODE_MAY_HAVE_CLASS);
         }
         if (aPrototype->mHasStyleAttribute) {
             element->SetMayHaveStyle();
         }
 
         element->MakeHeavyweight(aPrototype);
         if (aIsScriptable) {
             // Check each attribute on the prototype to see if we need to do
@@ -400,17 +400,17 @@ nsXULElement::Clone(mozilla::dom::NodeIn
         }
         NS_ENSURE_SUCCESS(rv, rv);
         element->AddListenerFor(*originalName, true);
         if (originalName->Equals(nsGkAtoms::id) &&
             !originalValue->IsEmptyString()) {
             element->SetHasID();
         }
         if (originalName->Equals(nsGkAtoms::_class)) {
-            element->SetMayHaveClass();
+            element->SetFlags(NODE_MAY_HAVE_CLASS);
         }
         if (originalName->Equals(nsGkAtoms::style)) {
             element->SetMayHaveStyle();
         }
     }
 
     element.forget(aResult);
     return rv;
--- a/layout/base/GeckoRestyleManager.cpp
+++ b/layout/base/GeckoRestyleManager.cpp
@@ -2007,26 +2007,16 @@ ElementRestyler::ComputeRestyleResultFro
   // style contexts.
   if (aSelf->GetAdditionalStyleContext(0)) {
     LOG_RESTYLE_CONTINUE("there are additional style contexts");
     aRestyleResult = RestyleResult::eContinue;
     aCanStopWithStyleChange = false;
     return;
   }
 
-  // Each NAC element inherits from the first non-NAC ancestor, so child
-  // NAC may inherit from our parent instead of us. That means we can't
-  // cull traversal if our style context didn't change.
-  if (aSelf->GetContent() && aSelf->GetContent()->IsNativeAnonymous()) {
-    LOG_RESTYLE_CONTINUE("native anonymous content");
-    aRestyleResult = RestyleResult::eContinue;
-    aCanStopWithStyleChange = false;
-    return;
-  }
-
   // Style changes might have moved children between the two nsLetterFrames
   // (the one matching ::first-letter and the one containing the rest of the
   // content).  Continue restyling to the children of the nsLetterFrame so
   // that they get the correct style context parent.  Similarly for
   // nsLineFrames.
   nsIAtom* type = aSelf->GetType();
 
   if (type == nsGkAtoms::letterFrame) {
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1862,17 +1862,16 @@ nsCSSFrameConstructor::CreateGeneratedCo
   nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nullptr,
                                                        kNameSpaceID_None,
                                                        nsIDOMNode::ELEMENT_NODE);
   nsCOMPtr<Element> container;
   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
   if (NS_FAILED(rv))
     return;
   container->SetIsNativeAnonymousRoot();
-  container->SetPseudoElementType(aPseudoElement);
 
   // If the parent is in a shadow tree, make sure we don't
   // bind with a document because shadow roots and its descendants
   // are not in document.
   nsIDocument* bindDocument =
     aParentContent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
   rv = container->BindToTree(bindDocument, aParentContent, aParentContent, true);
   if (NS_FAILED(rv)) {
@@ -4183,23 +4182,16 @@ ConnectAnonymousTreeDescendants(nsIConte
     NS_ASSERTION(content, "null anonymous content?");
 
     ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
 
     aParent->AppendChildTo(content, false);
   }
 }
 
-void SetNativeAnonymousBitOnDescendants(nsIContent *aRoot)
-{
-  for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) {
-    curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
-  }
-}
-
 nsresult
 nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
                                            nsIFrame* aParentFrame,
                                            nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
 {
   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
   if (!creator)
     return NS_OK;
@@ -4211,26 +4203,25 @@ nsCSSFrameConstructor::GetAnonymousConte
   }
 
   uint32_t count = aContent.Length();
   for (uint32_t i=0; i < count; i++) {
     // get our child's content and set its parent to our content
     nsIContent* content = aContent[i].mContent;
     NS_ASSERTION(content, "null anonymous content?");
 
-    ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
-
     // least-surprise CSS binding until we do the SVG specified
     // cascading rules for <svg:use> - bug 265894
     if (aParentFrame->GetType() == nsGkAtoms::svgUseFrame) {
       content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
     } else {
       content->SetIsNativeAnonymousRoot();
-      SetNativeAnonymousBitOnDescendants(content);
-    }
+    }
+
+    ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
 
     bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
 
     // If the parent is in a shadow tree, make sure we don't
     // bind with a document because shadow roots and its descendants
     // are not in document.
     nsIDocument* bindDocument =
       aParent->HasFlag(NODE_IS_IN_SHADOW_TREE) ? nullptr : mDocument;
@@ -4246,19 +4237,21 @@ nsCSSFrameConstructor::GetAnonymousConte
     }
     if (NS_FAILED(rv)) {
       content->UnbindFromTree();
       return rv;
     }
   }
 
   if (ServoStyleSet* styleSet = mPresShell->StyleSet()->GetAsServo()) {
-    // Eagerly compute styles for the anonymous content tree.
+    // Eagerly compute styles for the anonymous content tree, but only do so
+    // if the content doesn't have an explicit style context (if it does, we
+    // don't need the normal computed values).
     for (auto& info : aContent) {
-      if (info.mContent->IsElement()) {
+      if (!info.mStyleContext && info.mContent->IsElement()) {
         styleSet->StyleNewSubtree(info.mContent->AsElement());
       }
     }
   }
 
   return NS_OK;
 }
 
@@ -5028,47 +5021,34 @@ nsCSSFrameConstructor::ResolveStyleConte
 {
   return ResolveStyleContext(aInsertion.mParentFrame, aInsertion.mContainer,
                              aChild, aState);
 }
 
 already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
                                            nsIContent* aContent,
-                                           nsFrameConstructorState* aState,
-                                           Element* aOriginatingElementOrNull)
+                                           nsFrameConstructorState* aState)
 {
   StyleSetHandle styleSet = mPresShell->StyleSet();
   aContent->OwnerDoc()->FlushPendingLinkUpdates();
 
   RefPtr<nsStyleContext> result;
   if (aContent->IsElement()) {
-    auto pseudoType = aContent->AsElement()->GetPseudoElementType();
-    if (pseudoType == CSSPseudoElementType::NotPseudo) {
-      MOZ_ASSERT(!aOriginatingElementOrNull);
-      if (aState) {
-        result = styleSet->ResolveStyleFor(aContent->AsElement(),
-                                           aParentStyleContext,
-                                           LazyComputeBehavior::Assert,
-                                           aState->mTreeMatchContext);
-      } else {
-        result = styleSet->ResolveStyleFor(aContent->AsElement(),
-                                           aParentStyleContext,
-                                           LazyComputeBehavior::Assert);
-      }
+    if (aState) {
+      result = styleSet->ResolveStyleFor(aContent->AsElement(),
+                                         aParentStyleContext,
+                                         LazyComputeBehavior::Assert,
+                                         aState->mTreeMatchContext);
     } else {
-      MOZ_ASSERT(aOriginatingElementOrNull);
-      MOZ_ASSERT(aContent->IsInNativeAnonymousSubtree());
-      result = styleSet->ResolvePseudoElementStyle(aOriginatingElementOrNull,
-                                                   pseudoType,
-                                                   aParentStyleContext,
-                                                   aContent->AsElement());
+      result = styleSet->ResolveStyleFor(aContent->AsElement(),
+                                         aParentStyleContext,
+                                         LazyComputeBehavior::Assert);
     }
   } else {
-    MOZ_ASSERT(!aOriginatingElementOrNull);
     NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
                  "shouldn't waste time creating style contexts for "
                  "comments and processing instructions");
     result = styleSet->ResolveStyleForText(aContent, aParentStyleContext);
   }
 
   // ServoRestyleManager does not handle transitions yet, and when it does
   // it probably won't need to track reframed style contexts to start
@@ -10732,105 +10712,34 @@ nsCSSFrameConstructor::AddFCItemsForAnon
                "Should have no existing frame");
     MOZ_ASSERT(!content->IsNodeOfType(nsINode::eCOMMENT) &&
                !content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION),
                "Why is someone creating garbage anonymous content");
 
     RefPtr<nsStyleContext> styleContext;
     TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper
       parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext);
-
-    // Make sure we eagerly performed the servo cascade when the anonymous
-    // nodes were created.
-    MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(),
-                  content->AsElement()->HasServoData());
-
-    // Determine whether this NAC is pseudo-implementing.
-    nsIAtom* pseudo = nullptr;
-    if (content->IsElement()) {
-      auto pseudoType = content->AsElement()->GetPseudoElementType();
-      if (pseudoType != CSSPseudoElementType::NotPseudo) {
-        pseudo = nsCSSPseudoElements::GetPseudoAtom(pseudoType);
-      }
-    }
-
-    // Determine the appropriate parent style for this NAC, and if the NAC
-    // implements a pseudo-element, the appropriate originating element
-    // (that is to say, the element to the left of the ::pseudo-element in
-    // the selector). This is all rather tricky, and merits some discussion.
-    //
-    // First, it's important to note that author stylesheets generally do not
-    // apply to elements in native-anonymous subtrees. The exceptions to
-    // this are web-exposed pseudo-elements, where authors can style the
-    // pseudo-implementing NAC if the originating element is not itself in a NAC
-    // subtree.
-    //
-    // For this reason, it's very important that we avoid using a style parent
-    // that is inside a NAC subtree together with an originating element that
-    // is not inside a NAC subtree, since that would allow authors to
-    // explicitly inherit styles from internal elements, potentially making
-    // the NAC hierarchy observable. To ensure this, and generally simplify
-    // things, we always set the originating element to the style parent.
-    //
-    // As a consequence of the above, all web-exposed pseudo-elements (which,
-    // by definition, must have a content-accessible originating element) must
-    // also inherit style from that same content-accessible element. To avoid
-    // unintuitive behavior differences between NAC elements that do and don't
-    // correspond to web-exposed pseudo-elements, we follow this protocol for
-    // all NAC, pseudo-implementing or not.
-    //
-    // However, things get tricky with the <video> element, where we have a
-    // bunch of XBL-generated anonymous content descending from a native-
-    // anonymous XULElement. The XBL elements inherit style from their
-    // flattened tree parent, because that's how XBL works. But then we need
-    // to figure out what to do when one of those anonymous XBL elements
-    // (like an <input> element) generates its own (possibly pseudo-element-
-    // implementing) NAC.
-    //
-    // In this case, we inherit style from the XBL-generated NAC-creating
-    // element, rather than the <video> element. There are a number of good
-    // reasons for this. First, inheriting from the great-grandparent while
-    // the parent inherits from the grandparent would be bizarre at best.
-    // Second, exposing pseudo-elements from elements within our particular
-    // XBL implementation would allow content styles to (un)intentionally
-    // alter the video controls, which would be very bad. Third, our UA
-    // stylesheets have selectors like:
-    //
-    // input[type=range][orient=horizontal]::-moz-range-track
-    //
-    // and we need to make sure that the originating element is the <input>,
-    // not the <video>, because that's where the |orient| attribute lives.
-    //
-    // The upshot of all of this is that, to find the style parent (and
-    // originating element, if applicable), we walk up our parent chain to the
-    // first element that is not itself NAC (distinct from whether it happens
-    // to be in a NAC subtree).
-    //
-    // To implement all this, we need to pass the correct parent style context
-    // here because SetPrimaryFrame() may not have been called on the content
-    // yet and thus ResolveStyleContext can't find it otherwise.
-    //
-    // We don't need to worry about display:contents here, because such
-    // elements don't get a frame and thus can't generate NAC. But we do need
-    // to worry about anonymous boxes, which CorrectStyleParentFrame handles
-    // for us.
-    nsIFrame* inheritFrame = aFrame;
-    while (inheritFrame->GetContent()->IsNativeAnonymous()) {
-      inheritFrame = inheritFrame->GetParent();
-    }
-    if (inheritFrame->GetType() == nsGkAtoms::canvasFrame) {
-      // CorrectStyleParentFrame returns nullptr if the prospective parent is
-      // the canvas frame, so avoid calling it in that situation.
+    if (aAnonymousItems[i].mStyleContext) {
+      // If we have an explicit style context, that means that the anonymous
+      // content creator had its own plan for the style, and doesn't need the
+      // computed style obtained by cascading this content as a normal node.
+      // This happens when a native anonymous node is used to implement a
+      // pseudo-element. Allowing Servo to traverse these nodes would be wasted
+      // work, so assert that we didn't do that.
+      MOZ_ASSERT_IF(content->IsStyledByServo(),
+                    !content->IsElement() || !content->AsElement()->HasServoData());
+      styleContext = aAnonymousItems[i].mStyleContext.forget();
     } else {
-      inheritFrame = nsFrame::CorrectStyleParentFrame(inheritFrame, pseudo);
-    }
-    Element* originating = pseudo ? inheritFrame->GetContent()->AsElement() : nullptr;
-
-    styleContext =
-      ResolveStyleContext(inheritFrame->StyleContext(), content, &aState, originating);
+      // If we don't have an explicit style context, that means we need the
+      // ordinary computed values. Make sure we eagerly cascaded them when the
+      // anonymous nodes were created.
+      MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(),
+                    content->AsElement()->HasServoData());
+      styleContext = ResolveStyleContext(aFrame, content, &aState);
+    }
 
     nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr;
     if (!aAnonymousItems[i].mChildren.IsEmpty()) {
       anonChildren = &aAnonymousItems[i].mChildren;
     }
 
     uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK |
                      ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT | aExtraFlags;
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -359,18 +359,17 @@ private:
                       nsFrameConstructorState* aState);
   already_AddRefed<nsStyleContext>
   ResolveStyleContext(const InsertionPoint&    aInsertion,
                       nsIContent*              aChild,
                       nsFrameConstructorState* aState);
   already_AddRefed<nsStyleContext>
   ResolveStyleContext(nsStyleContext*          aParentStyleContext,
                       nsIContent*              aContent,
-                      nsFrameConstructorState* aState,
-                      Element*                 aOriginatingElementOrNull = nullptr);
+                      nsFrameConstructorState* aState);
 
   // Add the frame construction items for the given aContent and aParentFrame
   // to the list.  This might add more than one item in some rare cases.
   // If aSuppressWhiteSpaceOptimizations is true, optimizations that
   // may suppress the construction of white-space-only text frames
   // must be skipped for these items and items around them.
   void AddFrameConstructionItems(nsFrameConstructorState& aState,
                                  nsIContent*              aContent,
--- a/layout/forms/nsColorControlFrame.cpp
+++ b/layout/forms/nsColorControlFrame.cpp
@@ -64,25 +64,28 @@ nsColorControlFrame::GetFrameName(nsAStr
 
 // Create the color area for the button.
 // The frame will be generated by the frame constructor.
 nsresult
 nsColorControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
   mColorContent = doc->CreateHTMLElement(nsGkAtoms::div);
-  mColorContent->SetPseudoElementType(CSSPseudoElementType::mozColorSwatch);
 
   // Mark the element to be native anonymous before setting any attributes.
   mColorContent->SetIsNativeAnonymousRoot();
 
   nsresult rv = UpdateColor();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (!aElements.AppendElement(mColorContent)) {
+  CSSPseudoElementType pseudoType = CSSPseudoElementType::mozColorSwatch;
+  RefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
+    ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
+                              StyleContext(), mColorContent->AsElement());
+  if (!aElements.AppendElement(ContentInfo(mColorContent, newStyleContext))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 void
 nsColorControlFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
--- a/layout/forms/nsMeterFrame.cpp
+++ b/layout/forms/nsMeterFrame.cpp
@@ -70,19 +70,24 @@ nsMeterFrame::CreateAnonymousContent(nsT
 {
   // Get the NodeInfoManager and tag necessary to create the meter bar div.
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
 
   // Create the div.
   mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
 
   // Associate ::-moz-meter-bar pseudo-element to the anonymous child.
-  mBarDiv->SetPseudoElementType(CSSPseudoElementType::mozMeterBar);
+  CSSPseudoElementType pseudoType = CSSPseudoElementType::mozMeterBar;
+  RefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
+    ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
+                              StyleContext(), mBarDiv->AsElement());
 
-  aElements.AppendElement(mBarDiv);
+  if (!aElements.AppendElement(ContentInfo(mBarDiv, newStyleContext))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   return NS_OK;
 }
 
 void
 nsMeterFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                        uint32_t aFilter)
 {
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -320,25 +320,37 @@ private:
   nsCOMPtr<nsIContent> mNumber;
   nsCOMPtr<nsIContent> mTextField;
 };
 
 nsresult
 nsNumberControlFrame::MakeAnonymousElement(Element** aResult,
                                            nsTArray<ContentInfo>& aElements,
                                            nsIAtom* aTagName,
-                                           CSSPseudoElementType aPseudoType)
+                                           CSSPseudoElementType aPseudoType,
+                                           nsStyleContext* aParentContext)
 {
   // Get the NodeInfoManager and tag necessary to create the anonymous divs.
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
   RefPtr<Element> resultElement = doc->CreateHTMLElement(aTagName);
-  resultElement->SetPseudoElementType(aPseudoType);
 
+  // If we legitimately fail this assertion and need to allow
+  // non-pseudo-element anonymous children, then we'll need to add a branch
+  // that calls ResolveStyleFor((*aResult)->AsElement(), aParentContext)") to
+  // set newStyleContext.
+  NS_ASSERTION(aPseudoType != CSSPseudoElementType::NotPseudo,
+               "Expecting anonymous children to all be pseudo-elements");
   // Associate the pseudo-element with the anonymous child
-  if (!aElements.AppendElement(resultElement)) {
+  RefPtr<nsStyleContext> newStyleContext =
+    PresContext()->StyleSet()->ResolvePseudoElementStyle(mContent->AsElement(),
+                                                         aPseudoType,
+                                                         aParentContext,
+                                                         resultElement);
+
+  if (!aElements.AppendElement(ContentInfo(resultElement, newStyleContext))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (aPseudoType == CSSPseudoElementType::mozNumberSpinDown ||
       aPseudoType == CSSPseudoElementType::mozNumberSpinUp) {
     resultElement->SetAttr(kNameSpaceID_None, nsGkAtoms::role,
                            NS_LITERAL_STRING("button"), false);
   }
@@ -365,26 +377,28 @@ nsNumberControlFrame::CreateAnonymousCon
   // If you change this, be careful to change the destruction order in
   // nsNumberControlFrame::DestroyFrom.
 
 
   // Create the anonymous outer wrapper:
   rv = MakeAnonymousElement(getter_AddRefs(mOuterWrapper),
                             aElements,
                             nsGkAtoms::div,
-                            CSSPseudoElementType::mozNumberWrapper);
+                            CSSPseudoElementType::mozNumberWrapper,
+                            mStyleContext);
   NS_ENSURE_SUCCESS(rv, rv);
 
   ContentInfo& outerWrapperCI = aElements.LastElement();
 
   // Create the ::-moz-number-text pseudo-element:
   rv = MakeAnonymousElement(getter_AddRefs(mTextField),
                             outerWrapperCI.mChildren,
                             nsGkAtoms::input,
-                            CSSPseudoElementType::mozNumberText);
+                            CSSPseudoElementType::mozNumberText,
+                            outerWrapperCI.mStyleContext);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                       NS_LITERAL_STRING("text"), PR_FALSE);
 
   HTMLInputElement* content = HTMLInputElement::FromContent(mContent);
   HTMLInputElement* textField = HTMLInputElement::FromContent(mTextField);
 
@@ -421,33 +435,36 @@ nsNumberControlFrame::CreateAnonymousCon
     // -moz-appearance. We will reframe if it changes.
     return rv;
   }
 
   // Create the ::-moz-number-spin-box pseudo-element:
   rv = MakeAnonymousElement(getter_AddRefs(mSpinBox),
                             outerWrapperCI.mChildren,
                             nsGkAtoms::div,
-                            CSSPseudoElementType::mozNumberSpinBox);
+                            CSSPseudoElementType::mozNumberSpinBox,
+                            outerWrapperCI.mStyleContext);
   NS_ENSURE_SUCCESS(rv, rv);
 
   ContentInfo& spinBoxCI = outerWrapperCI.mChildren.LastElement();
 
   // Create the ::-moz-number-spin-up pseudo-element:
   rv = MakeAnonymousElement(getter_AddRefs(mSpinUp),
                             spinBoxCI.mChildren,
                             nsGkAtoms::div,
-                            CSSPseudoElementType::mozNumberSpinUp);
+                            CSSPseudoElementType::mozNumberSpinUp,
+                            spinBoxCI.mStyleContext);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Create the ::-moz-number-spin-down pseudo-element:
   rv = MakeAnonymousElement(getter_AddRefs(mSpinDown),
                             spinBoxCI.mChildren,
                             nsGkAtoms::div,
-                            CSSPseudoElementType::mozNumberSpinDown);
+                            CSSPseudoElementType::mozNumberSpinDown,
+                            spinBoxCI.mStyleContext);
 
   SyncDisabledState();
 
   return rv;
 }
 
 nsIAtom*
 nsNumberControlFrame::GetType() const
--- a/layout/forms/nsNumberControlFrame.h
+++ b/layout/forms/nsNumberControlFrame.h
@@ -165,17 +165,18 @@ public:
   bool ShouldUseNativeStyleForSpinner() const;
 
 private:
 
   nsITextControlFrame* GetTextFieldFrame();
   nsresult MakeAnonymousElement(Element** aResult,
                                 nsTArray<ContentInfo>& aElements,
                                 nsIAtom* aTagName,
-                                CSSPseudoElementType aPseudoType);
+                                CSSPseudoElementType aPseudoType,
+                                nsStyleContext* aParentContext);
 
   class SyncDisabledStateEvent;
   friend class SyncDisabledStateEvent;
   class SyncDisabledStateEvent : public mozilla::Runnable
   {
   public:
     explicit SyncDisabledStateEvent(nsNumberControlFrame* aFrame)
     : mFrame(aFrame)
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -67,19 +67,22 @@ nsProgressFrame::GetType() const
 nsresult
 nsProgressFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   // Create the progress bar div.
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
   mBarDiv = doc->CreateHTMLElement(nsGkAtoms::div);
 
   // Associate ::-moz-progress-bar pseudo-element to the anonymous child.
-  mBarDiv->SetPseudoElementType(CSSPseudoElementType::mozProgressBar);
+  CSSPseudoElementType pseudoType = CSSPseudoElementType::mozProgressBar;
+  RefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
+    ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
+                              StyleContext(), mBarDiv->AsElement());
 
-  if (!aElements.AppendElement(mBarDiv)) {
+  if (!aElements.AppendElement(ContentInfo(mBarDiv, newStyleContext))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 void
 nsProgressFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -114,19 +114,23 @@ nsresult
 nsRangeFrame::MakeAnonymousDiv(Element** aResult,
                                CSSPseudoElementType aPseudoType,
                                nsTArray<ContentInfo>& aElements)
 {
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
   RefPtr<Element> resultElement = doc->CreateHTMLElement(nsGkAtoms::div);
 
   // Associate the pseudo-element with the anonymous child.
-  resultElement->SetPseudoElementType(aPseudoType);
+  RefPtr<nsStyleContext> newStyleContext =
+    PresContext()->StyleSet()->ResolvePseudoElementStyle(mContent->AsElement(),
+                                                         aPseudoType,
+                                                         StyleContext(),
+                                                         resultElement);
 
-  if (!aElements.AppendElement(resultElement)) {
+  if (!aElements.AppendElement(ContentInfo(resultElement, newStyleContext))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   resultElement.forget(aResult);
   return NS_OK;
 }
 
 nsresult
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -342,22 +342,42 @@ nsTextControlFrame::CreateAnonymousConte
   nsAutoString placeholderTxt;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder,
                     placeholderTxt);
   nsContentUtils::RemoveNewlines(placeholderTxt);
   mUsePlaceholder = !placeholderTxt.IsEmpty();
 
   // Create the placeholder anonymous content if needed.
   if (mUsePlaceholder) {
-    Element* placeholderNode = txtCtrl->CreatePlaceholderNode();
+    nsIContent* placeholderNode = txtCtrl->CreatePlaceholderNode();
     NS_ENSURE_TRUE(placeholderNode, NS_ERROR_OUT_OF_MEMORY);
 
     // Associate ::placeholder pseudo-element with the placeholder node.
-    placeholderNode->SetPseudoElementType(CSSPseudoElementType::placeholder);
-    aElements.AppendElement(placeholderNode);
+    CSSPseudoElementType pseudoType = CSSPseudoElementType::placeholder;
+
+    // If this is a text input inside a number input then we want to use the
+    // main number input as the source of style for the placeholder frame.
+    nsIFrame* mainInputFrame = this;
+    if (StyleContext()->GetPseudoType() == CSSPseudoElementType::mozNumberText) {
+      do {
+        mainInputFrame = mainInputFrame->GetParent();
+      } while (mainInputFrame &&
+               mainInputFrame->GetType() != nsGkAtoms::numberControlFrame);
+      MOZ_ASSERT(mainInputFrame);
+    }
+
+    RefPtr<nsStyleContext> placeholderStyleContext =
+      PresContext()->StyleSet()->ResolvePseudoElementStyle(
+          mainInputFrame->GetContent()->AsElement(), pseudoType, StyleContext(),
+          placeholderNode->AsElement());
+
+    if (!aElements.AppendElement(ContentInfo(placeholderNode,
+                                 placeholderStyleContext))) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
 
     if (!IsSingleLineTextControl()) {
       // For textareas, UpdateValueDisplay doesn't initialize the visibility
       // status of the placeholder because it returns early, so we have to
       // do that manually here.
       txtCtrl->UpdatePlaceholderVisibility(true);
     }
   }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -9060,18 +9060,16 @@ GetIBSplitSiblingForAnonymousBlock(const
  * Get the parent, corrected for the mangled frame tree resulting from
  * having a block within an inline.  The result only differs from the
  * result of |GetParent| when |GetParent| returns an anonymous block
  * that was created for an element that was 'display: inline' because
  * that element contained a block.
  *
  * Also skip anonymous scrolled-content parents; inherit directly from the
  * outer scroll frame.
- *
- * Also skip NAC parents if the child frame is NAC.
  */
 static nsIFrame*
 GetCorrectedParent(const nsIFrame* aFrame)
 {
   nsIFrame* parent = aFrame->GetParent();
   if (!parent) {
     return nullptr;
   }
@@ -9087,41 +9085,16 @@ GetCorrectedParent(const nsIFrame* aFram
 
   // Table wrappers are always anon boxes; if we're in here for an outer
   // table, that actually means its the _inner_ table that wants to
   // know its parent. So get the pseudo of the inner in that case.
   nsIAtom* pseudo = aFrame->StyleContext()->GetPseudo();
   if (pseudo == nsCSSAnonBoxes::tableWrapper) {
     pseudo = aFrame->PrincipalChildList().FirstChild()->StyleContext()->GetPseudo();
   }
-
-  // Prevent NAC from inheriting NAC. This partially duplicates the logic
-  // implemented in nsCSSFrameConstructor::AddFCItemsForAnonymousContent, and is
-  // necessary so that restyle inherits style contexts in the same way as the
-  // initial styling performed in frame construction.
-  //
-  // It would be nice to put it in CorrectStyleParentFrame and therefore share
-  // it, but that would lose the information of whether the _child_ is NAC,
-  // since CorrectStyleParentFrame only knows about the prospective _parent_.
-  // This duplication and complexity will go away when we fully switch to the
-  // Servo style system, where all this can be handled much more naturally.
-  //
-  // We need to take special care not to disrupt the style inheritance of frames
-  // whose content is NAC but who implement a pseudo (like an anonymous
-  // box, or a non-NAC-backed pseudo like ::first-line) that does not match the
-  // one that the NAC implements, if any.
-  nsIContent* content = aFrame->GetContent();
-  Element* element = content->IsElement() ? content->AsElement() : nullptr;
-  if (element && element->IsNativeAnonymous() &&
-      element->GetPseudoElementType() == aFrame->StyleContext()->GetPseudoType()) {
-    while (parent->GetContent() && parent->GetContent()->IsNativeAnonymous()) {
-      parent = parent->GetParent();
-    }
-  }
-
   return nsFrame::CorrectStyleParentFrame(parent, pseudo);
 }
 
 /* static */
 nsIFrame*
 nsFrame::CorrectStyleParentFrame(nsIFrame* aProspectiveParent,
                                  nsIAtom* aChildPseudo)
 {
@@ -9182,19 +9155,16 @@ nsFrame::CorrectStyleParentFrame(nsIFram
   return nullptr;
 }
 
 nsStyleContext*
 nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const
 {
   *aProviderFrame = nullptr;
   nsFrameManager* fm = PresContext()->FrameManager();
-
-  // Handle display:contents and the root frame, when there's no parent frame
-  // to inherit from.
   if (MOZ_LIKELY(mContent)) {
     nsIContent* parentContent = mContent->GetFlattenedTreeParent();
     if (MOZ_LIKELY(parentContent)) {
       nsIAtom* pseudo = StyleContext()->GetPseudo();
       if (!pseudo || !mContent->IsElement() ||
           (!nsCSSAnonBoxes::IsAnonBox(pseudo) &&
            // Ensure that we don't return the display:contents style
            // of the parent content for pseudos that have the same content
--- a/layout/generic/nsIAnonymousContentCreator.h
+++ b/layout/generic/nsIAnonymousContentCreator.h
@@ -29,17 +29,22 @@ class nsIAnonymousContentCreator
 public:
   NS_DECL_QUERYFRAME_TARGET(nsIAnonymousContentCreator)
 
   struct ContentInfo {
     explicit ContentInfo(nsIContent* aContent) :
       mContent(aContent)
     {}
 
+    ContentInfo(nsIContent* aContent, nsStyleContext* aStyleContext) :
+      mContent(aContent), mStyleContext(aStyleContext)
+    {}
+
     nsIContent* mContent;
+    RefPtr<nsStyleContext> mStyleContext;
     nsTArray<ContentInfo> mChildren;
   };
 
   /**
    * Creates "native" anonymous content and adds the created content to
    * the aElements array. None of the returned elements can be nullptr.
    *
    * If the anonymous content creator sets the editable flag on some
deleted file mode 100644
--- a/layout/reftests/forms/input/number/number-style-inheritance-ref.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <body>
-    <input type="text" style="width: 100px; text-decoration: underline;" value="1234">
-  </body>
-</html>
deleted file mode 100644
--- a/layout/reftests/forms/input/number/number-style-inheritance.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <body>
-    <input type="number" style="width: 100px; -moz-appearance: textfield; text-decoration: underline;" value="1234">
-  </body>
-</html>
--- a/layout/reftests/forms/input/number/reftest.list
+++ b/layout/reftests/forms/input/number/reftest.list
@@ -47,11 +47,8 @@ fuzzy-if(skiaContent,2,5) needs-focus ==
 == number-placeholder.html number-placeholder-ref.html
 
 # check that if the anonymous text control is reframed, we reframe the whole
 # number control (the fuzzy is for the top-right and bottom-left of the border
 # bevel which gets slightly different antialiasing after invalidation):
 fuzzy(128,4) == number-reframe-anon-text-field.html number-reframe-anon-text-field-ref.html
 
 == pseudo-classes.html about:blank
-
-# Style inheritance:
-== number-style-inheritance.html number-style-inheritance-ref.html
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -1167,17 +1167,16 @@ input[type=number]::-moz-number-spin-box
    * if the font-size is made substantially larger or smaller. (Bug 1175074.)
    */
   max-height: 1em;
   align-self: center;
   justify-content: center;
 }
 
 input[type=number]::-moz-number-spin-up {
-  writing-mode: horizontal-tb;
   -moz-appearance: spinner-upbutton;
   display: block; /* bug 926670 */
   flex: none;
   cursor: default;
   /* Style for when native theming is off: */
   background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="5"><path d="M1,4 L3,0 5,4" fill="dimgrey"/></svg>');
   background-repeat: no-repeat;
   background-position: center bottom;
@@ -1185,17 +1184,16 @@ input[type=number]::-moz-number-spin-up 
   border-bottom: none;
   /* [JK] I think the border-*-*-radius properties here can remain physical,
      as we probably don't want to turn the spinner sideways in vertical writing mode */
   border-top-left-radius: 4px;
   border-top-right-radius: 4px;
 }
 
 input[type=number]::-moz-number-spin-down {
-  writing-mode: horizontal-tb;
   -moz-appearance: spinner-downbutton;
   display: block; /* bug 926670 */
   flex: none;
   cursor: default;
   /* Style for when native theming is off: */
   background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="5"><path d="M1,1 L3,5 5,1" fill="dimgrey"/></svg>');
   background-repeat: no-repeat;
   background-position: center top;