Bug 1268748 - Implement {Resolve,Probe}PseudoElementStyle. r=heycam
authorBobby Holley <bobbyholley@gmail.com>
Thu, 28 Apr 2016 17:56:37 -0700
changeset 295602 774c838c19e217e177ba22876d57a344b54c33e4
parent 295601 fdea8d099dbd8fee22f222f92bc784af46292239
child 295603 a12cdfe43e929dfa151e3ea1c35982cef674ff66
push id19015
push usercbook@mozilla.com
push dateMon, 02 May 2016 09:39:23 +0000
treeherderfx-team@2080375bc69d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1268748
milestone49.0a1
Bug 1268748 - Implement {Resolve,Probe}PseudoElementStyle. r=heycam
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -266,16 +266,27 @@ ServoComputedValues*
 Servo_GetComputedValuesForAnonymousBox(ServoComputedValues* parentStyleOrNull,
                                        nsIAtom* pseudoTag,
                                        RawServoStyleSet* set)
 {
   MOZ_CRASH("stylo: shouldn't be calling Servo_GetComputedValuesForAnonymousBox in a "
             "non-MOZ_STYLO build");
 }
 
+ServoComputedValues*
+Servo_GetComputedValuesForPseudoElement(ServoComputedValues* parent_style,
+                                        RawGeckoElement* match_element,
+                                        nsIAtom* pseudo_tag,
+                                        RawServoStyleSet* set,
+                                        bool is_probe)
+{
+  MOZ_CRASH("stylo: shouldn't be calling Servo_GetComputedValuesForPseudoElement in a "
+            "non-MOZ_STYLO build");
+}
+
 void
 Servo_AddRefComputedValues(ServoComputedValues*)
 {
   MOZ_CRASH("stylo: shouldn't be calling Servo_AddRefComputedValues in a "
             "non-MOZ_STYLO build");
 }
 
 void
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -80,16 +80,21 @@ bool Servo_StyleSheetHasRules(RawServoSt
 RawServoStyleSet* Servo_InitStyleSet();
 void Servo_DropStyleSet(RawServoStyleSet* set);
 
 // Computed style data.
 ServoComputedValues* Servo_GetComputedValues(RawGeckoNode* node);
 ServoComputedValues* Servo_GetComputedValuesForAnonymousBox(ServoComputedValues* parentStyleOrNull,
                                                             nsIAtom* pseudoTag,
                                                             RawServoStyleSet* set);
+ServoComputedValues* Servo_GetComputedValuesForPseudoElement(ServoComputedValues* parent_style,
+                                                             RawGeckoElement* match_element,
+                                                             nsIAtom* pseudo_tag,
+                                                             RawServoStyleSet* set,
+                                                             bool is_probe);
 void Servo_AddRefComputedValues(ServoComputedValues*);
 void Servo_ReleaseComputedValues(ServoComputedValues*);
 
 // Servo API.
 void Servo_RestyleDocument(RawGeckoDocument* doc, RawServoStyleSet* set);
 
 // Style-struct management.
 #define STYLE_STRUCT(name, checkdata_cb) \
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -80,26 +80,34 @@ ServoStyleSet::ResolveStyleFor(Element* 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::GetContext(nsIContent* aContent,
                           nsStyleContext* aParentContext,
                           nsIAtom* aPseudoTag,
                           CSSPseudoElementType aPseudoType)
 {
   RefPtr<ServoComputedValues> computedValues = dont_AddRef(Servo_GetComputedValues(aContent));
   MOZ_ASSERT(computedValues);
+  return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType);
+}
 
+already_AddRefed<nsStyleContext>
+ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
+                          nsStyleContext* aParentContext,
+                          nsIAtom* aPseudoTag,
+                          CSSPseudoElementType aPseudoType)
+{
   // XXXbholley: nsStyleSet does visited handling here.
 
   // XXXbholley: Figure out the correct thing to pass here. Does this fixup
   // duplicate something that servo already does?
   bool skipFixup = false;
 
   return NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
                             aPseudoType,
-                            computedValues.forget(), skipFixup);
+                            Move(aComputedValues), skipFixup);
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveStyleFor(Element* aElement,
                                nsStyleContext* aParentContext,
                                TreeMatchContext& aTreeMatchContext)
 {
   // aTreeMatchContext is used to speed up selector matching,
@@ -124,17 +132,29 @@ ServoStyleSet::ResolveStyleForOtherNonEl
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
                                          CSSPseudoElementType aType,
                                          nsStyleContext* aParentContext,
                                          Element* aPseudoElement)
 {
-  MOZ_CRASH("stylo: not implemented");
+  MOZ_ASSERT(!aPseudoElement,
+             "stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
+  MOZ_ASSERT(aParentContext);
+  MOZ_ASSERT(aType < CSSPseudoElementType::Count);
+  nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
+
+  RefPtr<ServoComputedValues> computedValues =
+    Servo_GetComputedValuesForPseudoElement(
+      aParentContext->StyleSource().AsServoComputedValues(),
+      aParentElement, pseudoTag, mRawSet.get(), /* is_probe = */ false);
+  MOZ_ASSERT(computedValues);
+
+  return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
 }
 
 // aFlags is an nsStyleSet flags bitfield
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
                                         nsStyleContext* aParentContext,
                                         uint32_t aFlags)
 {
@@ -285,27 +305,57 @@ ServoStyleSet::AddDocStyleSheet(ServoSty
   return NS_OK;
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ProbePseudoElementStyle(Element* aParentElement,
                                        CSSPseudoElementType aType,
                                        nsStyleContext* aParentContext)
 {
-  MOZ_CRASH("stylo: not implemented");
+  MOZ_ASSERT(aParentContext);
+  MOZ_ASSERT(aType < CSSPseudoElementType::Count);
+  nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
+
+  RefPtr<ServoComputedValues> computedValues =
+    Servo_GetComputedValuesForPseudoElement(
+      aParentContext->StyleSource().AsServoComputedValues(),
+      aParentElement, pseudoTag, mRawSet.get(), /* is_probe = */ true);
+
+  if (!computedValues) {
+    return nullptr;
+  }
+
+  // For :before and :after pseudo-elements, having display: none or no
+  // 'content' property is equivalent to not having the pseudo-element
+  // at all.
+  if (computedValues &&
+      (pseudoTag == nsCSSPseudoElements::before ||
+       pseudoTag == nsCSSPseudoElements::after)) {
+    const nsStyleDisplay *display = Servo_GetStyleDisplay(computedValues);
+    const nsStyleContent *content = Servo_GetStyleContent(computedValues);
+    // XXXldb What is contentCount for |content: ""|?
+    if (display->mDisplay == NS_STYLE_DISPLAY_NONE ||
+        content->ContentCount() == 0) {
+      return nullptr;
+    }
+  }
+
+  return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ProbePseudoElementStyle(Element* aParentElement,
                                        CSSPseudoElementType aType,
                                        nsStyleContext* aParentContext,
                                        TreeMatchContext& aTreeMatchContext,
                                        Element* aPseudoElement)
 {
-  MOZ_CRASH("stylo: not implemented");
+  MOZ_ASSERT(!aPseudoElement,
+             "stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
+  return ProbePseudoElementStyle(aParentElement, aType, aParentContext);
 }
 
 nsRestyleHint
 ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
                                       EventStates aStateMask)
 {
   MOZ_CRASH("stylo: not implemented");
 }
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -112,16 +112,21 @@ public:
   nsRestyleHint HasStateDependentStyle(dom::Element* aElement,
                                        EventStates aStateMask);
   nsRestyleHint HasStateDependentStyle(dom::Element* aElement,
                                        mozilla::CSSPseudoElementType aPseudoType,
                                        dom::Element* aPseudoElement,
                                        EventStates aStateMask);
 
 private:
+  already_AddRefed<nsStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
+                                              nsStyleContext* aParentContext,
+                                              nsIAtom* aPseudoTag,
+                                              CSSPseudoElementType aPseudoType);
+
   already_AddRefed<nsStyleContext> GetContext(nsIContent* aContent,
                                               nsStyleContext* aParentContext,
                                               nsIAtom* aPseudoTag,
                                               CSSPseudoElementType aPseudoType);
 
   nsPresContext* mPresContext;
   UniquePtr<RawServoStyleSet> mRawSet;
   EnumeratedArray<SheetType, SheetType::Count,