Bug 1366157 - stylo: Implement getDefaultComputedStyle. r=emilio draft
authorCameron McCormack <cam@mcc.id.au>
Wed, 24 May 2017 14:37:47 +0800
changeset 584248 e9695fe57d7cdce76a2160be26c3566d3ef208e0
parent 584247 4ffd099ef32231cd63ecffced9762457f72da447
child 630310 88cd2cf3d254650a6e9d1a0d51b0532b4f2e0824
push id60662
push userbmo:cam@mcc.id.au
push dateThu, 25 May 2017 02:52:45 +0000
reviewersemilio
bugs1366157
milestone55.0a1
Bug 1366157 - stylo: Implement getDefaultComputedStyle. r=emilio MozReview-Commit-ID: GKr06ylK4tA
layout/style/ServoBindingList.h
layout/style/ServoBindings.toml
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/ServoTypes.h
layout/style/nsComputedDOMStyle.cpp
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -449,16 +449,17 @@ SERVO_BINDING_FUNC(Servo_HasAuthorSpecif
 // though caching is not possible within display:none subtrees, and the styles
 // may be invalidated by already-scheduled restyles.
 //
 // The tree must be in a consistent state such that a normal traversal could be
 // performed, and this function maintains that invariant.
 SERVO_BINDING_FUNC(Servo_ResolveStyleLazily, ServoComputedValuesStrong,
                    RawGeckoElementBorrowed element,
                    mozilla::CSSPseudoElementType pseudo_type,
+                   mozilla::StyleRuleInclusion rule_inclusion,
                    const mozilla::ServoElementSnapshotTable* snapshots,
                    RawServoStyleSetBorrowed set)
 
 // Use ServoStyleSet::PrepareAndTraverseSubtree instead of calling this
 // directly
 SERVO_BINDING_FUNC(Servo_TraverseSubtree,
                    bool,
                    RawGeckoElementBorrowed root,
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -245,16 +245,17 @@ whitelist-types = [
     "StyleShapeSource",
     "StyleTransition",
     "mozilla::UniquePtr",
     "mozilla::DefaultDelete",
     "mozilla::Side",
     "mozilla::binding_danger::AssertAndSuppressCleanupPolicy",
     "mozilla::ParsingMode",
     "mozilla::InheritTarget",
+    "mozilla::StyleRuleInclusion",
 ]
 opaque-types = [
     "std::pair__PCCP",
     "std::namespace::atomic___base", "std::atomic__My_base",
     "std::atomic",
     "std::atomic___base",
     "mozilla::gfx::.*",
     "FallibleTArray",
@@ -421,16 +422,17 @@ structs-types = [
     "nsresult",
     "Loader",
     "ServoStyleSheet",
     "EffectCompositor_CascadeLevel",
     "UpdateAnimationsTasks",
     "ParsingMode",
     "InheritTarget",
     "URLMatchingFunction",
+    "StyleRuleInclusion",
 ]
 array-types = [
     { cpp-type = "uintptr_t", rust-type = "usize" },
 ]
 servo-owned-types = [
     { name = "RawServoStyleSet", opaque = true },
     { name = "StyleChildrenIterator", opaque = true },
     { name = "ServoElementSnapshot", opaque = false },
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -509,33 +509,36 @@ ServoStyleSet::ResolvePseudoElementStyle
   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
   return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
                     isBeforeOrAfter ? aOriginatingElement : nullptr);
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveTransientStyle(Element* aElement,
                                      nsIAtom* aPseudoTag,
-                                     CSSPseudoElementType aPseudoType)
+                                     CSSPseudoElementType aPseudoType,
+                                     StyleRuleInclusion aRuleInclusion)
 {
   RefPtr<ServoComputedValues> computedValues =
-    ResolveTransientServoStyle(aElement, aPseudoType);
+    ResolveTransientServoStyle(aElement, aPseudoType, aRuleInclusion);
 
   return GetContext(computedValues.forget(),
                     nullptr,
                     aPseudoTag,
                     aPseudoType, nullptr);
 }
 
 already_AddRefed<ServoComputedValues>
-ServoStyleSet::ResolveTransientServoStyle(Element* aElement,
-                                          CSSPseudoElementType aPseudoType)
+ServoStyleSet::ResolveTransientServoStyle(
+    Element* aElement,
+    CSSPseudoElementType aPseudoType,
+    StyleRuleInclusion aRuleInclusion)
 {
   PreTraverseSync();
-  return ResolveStyleLazily(aElement, aPseudoType);
+  return ResolveStyleLazily(aElement, aPseudoType, aRuleInclusion);
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
                                                   nsStyleContext* aParentContext)
 {
   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
              !nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
@@ -1050,17 +1053,18 @@ ServoStyleSet::ClearNonInheritingStyleCo
 {
   for (RefPtr<nsStyleContext>& ptr : mNonInheritingStyleContexts) {
     ptr = nullptr;
   }
 }
 
 already_AddRefed<ServoComputedValues>
 ServoStyleSet::ResolveStyleLazily(Element* aElement,
-                                  CSSPseudoElementType aPseudoType)
+                                  CSSPseudoElementType aPseudoType,
+                                  StyleRuleInclusion aRuleInclusion)
 {
   mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType);
   MOZ_ASSERT(!StylistNeedsUpdate());
 
   AutoSetInServoTraversal guard(this);
 
   /**
    * NB: This is needed because we process animations and transitions on the
@@ -1085,23 +1089,25 @@ ServoStyleSet::ResolveStyleLazily(Elemen
       elementForStyleResolution = pseudo;
       pseudoTypeForStyleResolution = CSSPseudoElementType::NotPseudo;
     }
   }
 
   RefPtr<ServoComputedValues> computedValues =
     Servo_ResolveStyleLazily(elementForStyleResolution,
                              pseudoTypeForStyleResolution,
+                             aRuleInclusion,
                              &Snapshots(),
                              mRawSet.get()).Consume();
 
   if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType)) {
     computedValues =
       Servo_ResolveStyleLazily(elementForStyleResolution,
                                pseudoTypeForStyleResolution,
+                               aRuleInclusion,
                                &Snapshots(),
                                mRawSet.get()).Consume();
   }
 
   return computedValues.forget();
 }
 
 bool
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -167,23 +167,27 @@ public:
 
   // Resolves style for a (possibly-pseudo) Element without assuming that the
   // style has been resolved, and without worrying about setting the style
   // context up to live in the style context tree (a null parent is used).
   // |aPeudoTag| and |aPseudoType| must match.
   already_AddRefed<nsStyleContext>
   ResolveTransientStyle(dom::Element* aElement,
                         nsIAtom* aPseudoTag,
-                        CSSPseudoElementType aPseudoType);
+                        CSSPseudoElementType aPseudoType,
+                        StyleRuleInclusion aRules =
+                          StyleRuleInclusion::All);
 
   // Similar to ResolveTransientStyle() but returns ServoComputedValues.
   // Unlike ResolveServoStyle() this function calls PreTraverseSync().
   already_AddRefed<ServoComputedValues>
   ResolveTransientServoStyle(dom::Element* aElement,
-                             CSSPseudoElementType aPseudoTag);
+                             CSSPseudoElementType aPseudoTag,
+                             StyleRuleInclusion aRules =
+                               StyleRuleInclusion::All);
 
   // Get a style context for an anonymous box.  aPseudoTag is the pseudo-tag to
   // use and must be non-null.  It must be an anon box, and must be one that
   // inherits style from the given aParentContext.
   already_AddRefed<nsStyleContext>
   ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
                                      nsStyleContext* aParentContext);
 
@@ -476,17 +480,20 @@ private:
   void UpdateStylistIfNeeded()
   {
     if (StylistNeedsUpdate()) {
       UpdateStylist();
     }
   }
 
   already_AddRefed<ServoComputedValues>
-    ResolveStyleLazily(dom::Element* aElement, CSSPseudoElementType aPseudoType);
+    ResolveStyleLazily(dom::Element* aElement,
+                       CSSPseudoElementType aPseudoType,
+                       StyleRuleInclusion aRules =
+                         StyleRuleInclusion::All);
 
   void RunPostTraversalTasks();
 
   void PrependSheetOfType(SheetType aType,
                           ServoStyleSheet* aSheet);
 
   void AppendSheetOfType(SheetType aType,
                          ServoStyleSheet* aSheet);
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -68,16 +68,25 @@ enum class TraversalRestyleBehavior {
   // are unneeded, since the old frames have already been destroyed.
   ForReconstruct,
   // Processes animation-only restyle.
   ForAnimationOnly,
   // Traverses as normal mode but tries to update all CSS animations.
   ForCSSRuleChanges,
 };
 
+// Indicates which rules should be included when performing selecting matching
+// on an element.  DefaultOnly is used to exclude all rules except for those
+// that come from UA style sheets, and is used to implemented
+// getDefaultComputedStyle.
+enum class StyleRuleInclusion {
+  All,
+  DefaultOnly,
+};
+
 // Represents which tasks are performed in a SequentialTask of UpdateAnimations.
 enum class UpdateAnimationsTasks : uint8_t {
   CSSAnimations    = 1 << 0,
   CSSTransitions   = 1 << 1,
   EffectProperties = 1 << 2,
   CascadeResults   = 1 << 3,
 };
 
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -657,21 +657,20 @@ nsComputedDOMStyle::DoGetStyleContextNoF
     if (type >= CSSPseudoElementType::Count) {
       return nullptr;
     }
   }
 
   // For Servo, compute the result directly without recursively building up
   // a throwaway style context chain.
   if (ServoStyleSet* servoSet = styleSet->GetAsServo()) {
-    if (aStyleType == eDefaultOnly) {
-      NS_WARNING("stylo: ServoStyleSets cannot supply UA-only styles yet");
-      return nullptr;
-    }
-    return servoSet->ResolveTransientStyle(aElement, aPseudo, type);
+    StyleRuleInclusion rules = aStyleType == eDefaultOnly
+                               ? StyleRuleInclusion::DefaultOnly
+                               : StyleRuleInclusion::All;
+    return servoSet->ResolveTransientStyle(aElement, aPseudo, type, rules);
   }
 
   RefPtr<nsStyleContext> parentContext;
   nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
   // Don't resolve parent context for document fragments.
   if (parent && parent->IsElement()) {
     parentContext = GetStyleContextNoFlush(parent->AsElement(), nullptr,
                                            aPresShell, aStyleType);