diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/css/RuleFeature.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/css/RuleFeature.cpp')
-rw-r--r-- | Source/WebCore/css/RuleFeature.cpp | 148 |
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 |