summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/RuleFeature.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/css/RuleFeature.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/css/RuleFeature.cpp')
-rw-r--r--Source/WebCore/css/RuleFeature.cpp148
1 files changed, 118 insertions, 30 deletions
diff --git a/Source/WebCore/css/RuleFeature.cpp b/Source/WebCore/css/RuleFeature.cpp
index 93a8ec8f2..133de4866 100644
--- a/Source/WebCore/css/RuleFeature.cpp
+++ b/Source/WebCore/css/RuleFeature.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
* Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2012, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
* Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
@@ -30,56 +30,144 @@
#include "RuleFeature.h"
#include "CSSSelector.h"
+#include "CSSSelectorList.h"
+#include "RuleSet.h"
namespace WebCore {
-void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector* selector)
+void RuleFeatureSet::recursivelyCollectFeaturesFromSelector(SelectorFeatures& selectorFeatures, const CSSSelector& firstSelector, bool matchesAncestor)
{
- if (selector->m_match == CSSSelector::Id)
- idsInRules.add(selector->value().impl());
- else if (selector->m_match == CSSSelector::Class)
- classesInRules.add(selector->value().impl());
- else if (selector->isAttributeSelector())
- attrsInRules.add(selector->attribute().localName().impl());
- switch (selector->pseudoType()) {
- case CSSSelector::PseudoFirstLine:
- usesFirstLineRules = true;
- break;
- case CSSSelector::PseudoBefore:
- case CSSSelector::PseudoAfter:
- usesBeforeAfterRules = true;
- break;
- default:
- break;
+ const CSSSelector* selector = &firstSelector;
+ do {
+ if (selector->match() == CSSSelector::Id) {
+ idsInRules.add(selector->value());
+ if (matchesAncestor)
+ idsMatchingAncestorsInRules.add(selector->value());
+ } else if (selector->match() == CSSSelector::Class) {
+ classesInRules.add(selector->value());
+ if (matchesAncestor)
+ selectorFeatures.classesMatchingAncestors.append(selector->value());
+ } else if (selector->isAttributeSelector()) {
+ auto& canonicalLocalName = selector->attributeCanonicalLocalName();
+ auto& localName = selector->attribute().localName();
+ attributeCanonicalLocalNamesInRules.add(canonicalLocalName);
+ attributeLocalNamesInRules.add(localName);
+ if (matchesAncestor)
+ selectorFeatures.attributeSelectorsMatchingAncestors.append(selector);
+ } else if (selector->match() == CSSSelector::PseudoElement) {
+ switch (selector->pseudoElementType()) {
+ case CSSSelector::PseudoElementFirstLine:
+ usesFirstLineRules = true;
+ break;
+ case CSSSelector::PseudoElementFirstLetter:
+ usesFirstLetterRules = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!selectorFeatures.hasSiblingSelector && selector->isSiblingSelector())
+ selectorFeatures.hasSiblingSelector = true;
+
+ if (const CSSSelectorList* selectorList = selector->selectorList()) {
+ for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
+ if (!selectorFeatures.hasSiblingSelector && selector->isSiblingSelector())
+ selectorFeatures.hasSiblingSelector = true;
+ recursivelyCollectFeaturesFromSelector(selectorFeatures, *subSelector, matchesAncestor);
+ }
+ }
+ if (selector->hasDescendantOrChildRelation())
+ matchesAncestor = true;
+
+ selector = selector->tagHistory();
+ } while (selector);
+}
+
+static RuleFeatureSet::AttributeRules::SelectorKey makeAttributeSelectorKey(const CSSSelector& selector)
+{
+ bool caseInsensitive = selector.attributeValueMatchingIsCaseInsensitive();
+ unsigned matchAndCase = static_cast<unsigned>(selector.match()) << 1 | (caseInsensitive ? 1 : 0);
+ return std::make_pair(selector.attributeCanonicalLocalName().impl(), std::make_pair(selector.value().impl(), matchAndCase));
+}
+
+void RuleFeatureSet::collectFeatures(const RuleData& ruleData)
+{
+ SelectorFeatures selectorFeatures;
+ recursivelyCollectFeaturesFromSelector(selectorFeatures, *ruleData.selector());
+ if (selectorFeatures.hasSiblingSelector)
+ siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin()));
+ if (ruleData.containsUncommonAttributeSelector())
+ uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin()));
+ for (auto& className : selectorFeatures.classesMatchingAncestors) {
+ auto addResult = ancestorClassRules.ensure(className, [] {
+ return std::make_unique<Vector<RuleFeature>>();
+ });
+ addResult.iterator->value->append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin()));
+ }
+ for (auto* selector : selectorFeatures.attributeSelectorsMatchingAncestors) {
+ // Hashing by attributeCanonicalLocalName makes this HTML specific.
+ auto addResult = ancestorAttributeRulesForHTML.ensure(selector->attributeCanonicalLocalName(), [] {
+ return std::make_unique<AttributeRules>();
+ });
+ auto& rules = *addResult.iterator->value;
+ rules.features.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin()));
+ // Deduplicate selectors.
+ rules.selectors.add(makeAttributeSelectorKey(*selector), selector);
}
}
void RuleFeatureSet::add(const RuleFeatureSet& other)
{
- HashSet<AtomicStringImpl*>::const_iterator end = other.idsInRules.end();
- for (HashSet<AtomicStringImpl*>::const_iterator it = other.idsInRules.begin(); it != end; ++it)
- idsInRules.add(*it);
- end = other.classesInRules.end();
- for (HashSet<AtomicStringImpl*>::const_iterator it = other.classesInRules.begin(); it != end; ++it)
- classesInRules.add(*it);
- end = other.attrsInRules.end();
- for (HashSet<AtomicStringImpl*>::const_iterator it = other.attrsInRules.begin(); it != end; ++it)
- attrsInRules.add(*it);
+ idsInRules.add(other.idsInRules.begin(), other.idsInRules.end());
+ idsMatchingAncestorsInRules.add(other.idsMatchingAncestorsInRules.begin(), other.idsMatchingAncestorsInRules.end());
+ classesInRules.add(other.classesInRules.begin(), other.classesInRules.end());
+ attributeCanonicalLocalNamesInRules.add(other.attributeCanonicalLocalNamesInRules.begin(), other.attributeCanonicalLocalNamesInRules.end());
+ attributeLocalNamesInRules.add(other.attributeLocalNamesInRules.begin(), other.attributeLocalNamesInRules.end());
siblingRules.appendVector(other.siblingRules);
uncommonAttributeRules.appendVector(other.uncommonAttributeRules);
+ for (auto& keyValuePair : other.ancestorClassRules) {
+ auto addResult = ancestorClassRules.ensure(keyValuePair.key, [] {
+ return std::make_unique<Vector<RuleFeature>>();
+ });
+ addResult.iterator->value->appendVector(*keyValuePair.value);
+ }
+ for (auto& keyValuePair : other.ancestorAttributeRulesForHTML) {
+ auto addResult = ancestorAttributeRulesForHTML.ensure(keyValuePair.key, [] {
+ return std::make_unique<AttributeRules>();
+ });
+ auto& rules = *addResult.iterator->value;
+ rules.features.appendVector(keyValuePair.value->features);
+ for (auto& selectorPair : keyValuePair.value->selectors)
+ rules.selectors.add(selectorPair.key, selectorPair.value);
+ }
usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
- usesBeforeAfterRules = usesBeforeAfterRules || other.usesBeforeAfterRules;
+ usesFirstLetterRules = usesFirstLetterRules || other.usesFirstLetterRules;
}
void RuleFeatureSet::clear()
{
idsInRules.clear();
+ idsMatchingAncestorsInRules.clear();
classesInRules.clear();
- attrsInRules.clear();
+ attributeCanonicalLocalNamesInRules.clear();
+ attributeLocalNamesInRules.clear();
siblingRules.clear();
uncommonAttributeRules.clear();
+ ancestorClassRules.clear();
+ ancestorAttributeRulesForHTML.clear();
usesFirstLineRules = false;
- usesBeforeAfterRules = false;
+ usesFirstLetterRules = false;
+}
+
+void RuleFeatureSet::shrinkToFit()
+{
+ siblingRules.shrinkToFit();
+ uncommonAttributeRules.shrinkToFit();
+ for (auto& rules : ancestorClassRules.values())
+ rules->shrinkToFit();
+ for (auto& rules : ancestorAttributeRulesForHTML.values())
+ rules->features.shrinkToFit();
}
} // namespace WebCore