Bug 1407952: Use stylo for Element::Closest. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 12 Oct 2017 11:42:17 +0200
changeset 680116 f7fc1e9c47e9169386d416541dd55471d34d0ae4
parent 680115 f930a2432a7cf46f91b2488ef414bec8803473b2
child 735768 0f204c0e0f37b86c76d35436bf1847715ce4bff4
push id84402
push userbmo:emilio@crisal.io
push dateFri, 13 Oct 2017 15:25:11 +0000
reviewersheycam
bugs1407952
milestone58.0a1
Bug 1407952: Use stylo for Element::Closest. r?heycam MozReview-Commit-ID: 3H2piFT2CfF
dom/base/Element.cpp
layout/style/ServoBindingList.h
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3462,37 +3462,48 @@ Element::GetTokenList(nsAtom* aAtom,
     SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
   }
   return list;
 }
 
 Element*
 Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
 {
-  nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aResult);
-  if (!selectorList) {
-    // Either we failed (and aResult already has the exception), or this
-    // is a pseudo-element-only selector that matches nothing.
-    return nullptr;
-  }
-  TreeMatchContext matchingContext(false,
-                                   nsRuleWalker::eRelevantLinkUnvisited,
-                                   OwnerDoc(),
-                                   TreeMatchContext::eNeverMatchVisited);
-  matchingContext.SetHasSpecifiedScope();
-  matchingContext.AddScopeElement(this);
-  for (nsINode* node = this; node; node = node->GetParentNode()) {
-    if (node->IsElement() &&
-        nsCSSRuleProcessor::SelectorListMatches(node->AsElement(),
-                                                matchingContext,
-                                                selectorList)) {
-      return node->AsElement();
+  return WithSelectorList<Element*>(
+    aSelector,
+    aResult,
+    [&](const RawServoSelectorList* aList) -> Element* {
+      if (!aList) {
+        return nullptr;
+      }
+      return const_cast<Element*>(Servo_SelectorList_Closest(this, aList));
+    },
+    [&](nsCSSSelectorList* aList) -> Element* {
+      if (!aList) {
+        // Either we failed (and aError already has the exception), or this
+        // is a pseudo-element-only selector that matches nothing.
+        return nullptr;
+      }
+      TreeMatchContext matchingContext(false,
+                                       nsRuleWalker::eRelevantLinkUnvisited,
+                                       OwnerDoc(),
+                                       TreeMatchContext::eNeverMatchVisited);
+      matchingContext.SetHasSpecifiedScope();
+      matchingContext.AddScopeElement(this);
+      for (nsINode* node = this; node; node = node->GetParentNode()) {
+        if (node->IsElement() &&
+            nsCSSRuleProcessor::SelectorListMatches(node->AsElement(),
+                                                    matchingContext,
+                                                    aList)) {
+          return node->AsElement();
+        }
+      }
+      return nullptr;
     }
-  }
-  return nullptr;
+  );
 }
 
 bool
 Element::Matches(const nsAString& aSelector, ErrorResult& aError)
 {
   return WithSelectorList<bool>(
     aSelector,
     aError,
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -131,16 +131,18 @@ SERVO_BINDING_FUNC(Servo_StyleSet_Resolv
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_SelectorList_Drop, void,
                    RawServoSelectorListOwned selector_list)
 SERVO_BINDING_FUNC(Servo_SelectorList_Parse,
                    RawServoSelectorList*,
                    const nsACString* selector_list)
 SERVO_BINDING_FUNC(Servo_SelectorList_Matches, bool,
                    RawGeckoElementBorrowed, RawServoSelectorListBorrowed)
+SERVO_BINDING_FUNC(Servo_SelectorList_Closest, RawGeckoElementBorrowedOrNull,
+                   RawGeckoElementBorrowed, RawServoSelectorListBorrowed)
 SERVO_BINDING_FUNC(Servo_StyleSet_AddSizeOfExcludingThis, void,
                    mozilla::MallocSizeOf malloc_size_of,
                    mozilla::MallocSizeOf malloc_enclosing_size_of,
                    mozilla::ServoStyleSetSizes* sizes,
                    RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_UACache_AddSizeOf, void,
                    mozilla::MallocSizeOf malloc_size_of,
                    mozilla::MallocSizeOf malloc_enclosing_size_of,