Title: [229255] releases/WebKitGTK/webkit-2.20/Source/WebCore
Revision
229255
Author
[email protected]
Date
2018-03-05 03:55:45 -0800 (Mon, 05 Mar 2018)

Log Message

Merge r229090 - Filter attribute selectors with selector filter
https://bugs.webkit.org/show_bug.cgi?id=183200

Reviewed by Zalan Bujtas.

Currently selector filtering is done based on tags, classes and ids. We should include attributes too.

This patch adds filtering based on attribute name (but not content).

* css/SelectorFilter.cpp:
(WebCore::isExcludedAttribute):

    Ignore id, class and style attributes. First two are already handled and the last is common but is rarely
    used in selectors.

(WebCore::collectElementIdentifierHashes):

    Collect attributes.
    Remove the unnecessary StyledElement casting.

(WebCore::collectSimpleSelectorHash):

    Collect attribute selectors.

(WebCore::chooseSelectorHashesForFilter):

    Pick attributes with high priority for the filter as it is likely a good signal.

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.20/Source/WebCore/ChangeLog (229254 => 229255)


--- releases/WebKitGTK/webkit-2.20/Source/WebCore/ChangeLog	2018-03-05 11:55:33 UTC (rev 229254)
+++ releases/WebKitGTK/webkit-2.20/Source/WebCore/ChangeLog	2018-03-05 11:55:45 UTC (rev 229255)
@@ -1,3 +1,33 @@
+2018-02-28  Antti Koivisto  <[email protected]>
+
+        Filter attribute selectors with selector filter
+        https://bugs.webkit.org/show_bug.cgi?id=183200
+
+        Reviewed by Zalan Bujtas.
+
+        Currently selector filtering is done based on tags, classes and ids. We should include attributes too.
+
+        This patch adds filtering based on attribute name (but not content).
+
+        * css/SelectorFilter.cpp:
+        (WebCore::isExcludedAttribute):
+
+            Ignore id, class and style attributes. First two are already handled and the last is common but is rarely
+            used in selectors.
+
+        (WebCore::collectElementIdentifierHashes):
+
+            Collect attributes.
+            Remove the unnecessary StyledElement casting.
+
+        (WebCore::collectSimpleSelectorHash):
+
+            Collect attribute selectors.
+
+        (WebCore::chooseSelectorHashesForFilter):
+
+            Pick attributes with high priority for the filter as it is likely a good signal.
+
 2018-02-27  Daniel Bates  <[email protected]>
 
         Standardize terminology for marked text

Modified: releases/WebKitGTK/webkit-2.20/Source/WebCore/css/SelectorFilter.cpp (229254 => 229255)


--- releases/WebKitGTK/webkit-2.20/Source/WebCore/css/SelectorFilter.cpp	2018-03-05 11:55:33 UTC (rev 229254)
+++ releases/WebKitGTK/webkit-2.20/Source/WebCore/css/SelectorFilter.cpp	2018-03-05 11:55:45 UTC (rev 229255)
@@ -36,23 +36,37 @@
 namespace WebCore {
 
 // Salt to separate otherwise identical string hashes so a class-selector like .article won't match <article> elements.
-enum { TagNameSalt = 13, IdAttributeSalt = 17, ClassAttributeSalt = 19 };
+enum { TagNameSalt = 13, IdSalt = 17, ClassSalt = 19, AttributeSalt = 23 };
 
-static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes)
+static bool isExcludedAttribute(const AtomicString& name)
 {
-    AtomicString tagLowercaseLocalName = element->localName().convertToASCIILowercase();
+    return name == HTMLNames::classAttr->localName() || name == HTMLNames::idAttr->localName() || name == HTMLNames::styleAttr->localName();
+}
+
+static inline void collectElementIdentifierHashes(const Element& element, Vector<unsigned, 4>& identifierHashes)
+{
+    AtomicString tagLowercaseLocalName = element.localName().convertToASCIILowercase();
     identifierHashes.append(tagLowercaseLocalName.impl()->existingHash() * TagNameSalt);
 
-    auto& id = element->idForStyleResolution();
+    auto& id = element.idForStyleResolution();
     if (!id.isNull())
-        identifierHashes.append(id.impl()->existingHash() * IdAttributeSalt);
-    const StyledElement* styledElement = element->isStyledElement() ? static_cast<const StyledElement*>(element) : 0;
-    if (styledElement && styledElement->hasClass()) {
-        const SpaceSplitString& classNames = styledElement->classNames();
+        identifierHashes.append(id.impl()->existingHash() * IdSalt);
+
+    if (element.hasClass()) {
+        const SpaceSplitString& classNames = element.classNames();
         size_t count = classNames.size();
         for (size_t i = 0; i < count; ++i)
-            identifierHashes.append(classNames[i].impl()->existingHash() * ClassAttributeSalt);
+            identifierHashes.append(classNames[i].impl()->existingHash() * ClassSalt);
     }
+    
+    if (element.hasAttributesWithoutUpdate()) {
+        for (auto& attribute : element.attributesIterator()) {
+            auto attributeName = element.isHTMLElement() ? attribute.localName() : attribute.localName().convertToASCIILowercase();
+            if (isExcludedAttribute(attributeName))
+                continue;
+            identifierHashes.append(attributeName.impl()->existingHash() * AttributeSalt);
+        }
+    }
 }
 
 bool SelectorFilter::parentStackIsConsistent(const ContainerNode* parentNode) const
@@ -80,7 +94,7 @@
     ParentStackFrame& parentFrame = m_parentStack.last();
     // Mix tags, class names and ids into some sort of weird bouillabaisse.
     // The filter is used for fast rejection of child and descendant selectors.
-    collectElementIdentifierHashes(parent, parentFrame.identifierHashes);
+    collectElementIdentifierHashes(*parent, parentFrame.identifierHashes);
     size_t count = parentFrame.identifierHashes.size();
     for (size_t i = 0; i < count; ++i)
         m_ancestorIdentifierFilter.add(parentFrame.identifierHashes[i]);
@@ -123,6 +137,7 @@
     HashVector ids;
     HashVector classes;
     HashVector tags;
+    HashVector attributes;
 };
 
 static inline void collectSimpleSelectorHash(CollectedSelectorHashes& collectedHashes, const CSSSelector& selector)
@@ -130,11 +145,11 @@
     switch (selector.match()) {
     case CSSSelector::Id:
         if (!selector.value().isEmpty())
-            collectedHashes.ids.append(selector.value().impl()->existingHash() * IdAttributeSalt);
+            collectedHashes.ids.append(selector.value().impl()->existingHash() * IdSalt);
         break;
     case CSSSelector::Class:
         if (!selector.value().isEmpty())
-            collectedHashes.classes.append(selector.value().impl()->existingHash() * ClassAttributeSalt);
+            collectedHashes.classes.append(selector.value().impl()->existingHash() * ClassSalt);
         break;
     case CSSSelector::Tag: {
         auto& tagLowercaseLocalName = selector.tagLowercaseLocalName();
@@ -142,6 +157,18 @@
             collectedHashes.tags.append(tagLowercaseLocalName.impl()->existingHash() * TagNameSalt);
         break;
     }
+    case CSSSelector::Exact:
+    case CSSSelector::Set:
+    case CSSSelector::List:
+    case CSSSelector::Hyphen:
+    case CSSSelector::Contain:
+    case CSSSelector::Begin:
+    case CSSSelector::End: {
+        auto attributeName = selector.attributeCanonicalLocalName().convertToASCIILowercase();
+        if (!isExcludedAttribute(attributeName))
+            collectedHashes.attributes.append(attributeName.impl()->existingHash() * AttributeSalt);
+        break;
+    }
     default:
         break;
     }
@@ -204,6 +231,8 @@
     // There is a limited number of slots. Prefer more specific selector types.
     if (copyHashes(collectedSelectorHashes.ids))
         return resultHashes;
+    if (copyHashes(collectedSelectorHashes.attributes))
+        return resultHashes;
     if (copyHashes(collectedSelectorHashes.classes))
         return resultHashes;
     if (copyHashes(collectedSelectorHashes.tags))
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to