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/RuleSet.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/css/RuleSet.cpp')
-rw-r--r-- | Source/WebCore/css/RuleSet.cpp | 467 |
1 files changed, 280 insertions, 187 deletions
diff --git a/Source/WebCore/css/RuleSet.cpp b/Source/WebCore/css/RuleSet.cpp index c2752d9d1..9e6b7e93f 100644 --- a/Source/WebCore/css/RuleSet.cpp +++ b/Source/WebCore/css/RuleSet.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-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,19 +30,19 @@ #include "RuleSet.h" #include "CSSFontSelector.h" +#include "CSSKeyframesRule.h" #include "CSSSelector.h" #include "CSSSelectorList.h" #include "HTMLNames.h" #include "MediaQueryEvaluator.h" #include "SecurityOrigin.h" #include "SelectorChecker.h" -#include "SelectorCheckerFastPath.h" #include "SelectorFilter.h" #include "StyleResolver.h" #include "StyleRule.h" #include "StyleRuleImport.h" #include "StyleSheetContents.h" -#include "WebKitCSSKeyframesRule.h" +#include "ViewportStyleResolver.h" #if ENABLE(VIDEO_TRACK) #include "TextTrackCue.h" @@ -54,33 +54,46 @@ using namespace HTMLNames; // ----------------------------------------------------------------- -static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector) +static inline MatchBasedOnRuleHash computeMatchBasedOnRuleHash(const CSSSelector& selector) { - ASSERT(selector); - if (selector->m_match == CSSSelector::Tag) { - const AtomicString& selectorNamespace = selector->tagQName().namespaceURI(); - if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) - return false; - if (selector->relation() == CSSSelector::SubSelector) - return isSelectorMatchingHTMLBasedOnRuleHash(selector->tagHistory()); - return true; + if (selector.tagHistory()) + return MatchBasedOnRuleHash::None; + + if (selector.match() == CSSSelector::Tag) { + const QualifiedName& tagQualifiedName = selector.tagQName(); + const AtomicString& selectorNamespace = tagQualifiedName.namespaceURI(); + if (selectorNamespace == starAtom || selectorNamespace == xhtmlNamespaceURI) { + if (tagQualifiedName == anyQName()) + return MatchBasedOnRuleHash::Universal; + return MatchBasedOnRuleHash::ClassC; + } + return MatchBasedOnRuleHash::None; } - if (SelectorChecker::isCommonPseudoClassSelector(selector)) - return true; - return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class; + if (SelectorChecker::isCommonPseudoClassSelector(&selector)) + return MatchBasedOnRuleHash::ClassB; + if (selector.match() == CSSSelector::Id) + return MatchBasedOnRuleHash::ClassA; + if (selector.match() == CSSSelector::Class) + return MatchBasedOnRuleHash::ClassB; + return MatchBasedOnRuleHash::None; } -static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector) +static bool selectorCanMatchPseudoElement(const CSSSelector& rootSelector) { - const CSSSelectorList* selectorList = selector->selectorList(); - if (!selectorList) - return false; - for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) { - for (const CSSSelector* component = selector; component; component = component->tagHistory()) { - if (component->isAttributeSelector()) - return true; + const CSSSelector* selector = &rootSelector; + do { + if (selector->matchesPseudoElement()) + return true; + + if (const CSSSelectorList* selectorList = selector->selectorList()) { + for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + if (selectorCanMatchPseudoElement(*subSelector)) + return true; + } } - } + + selector = selector->tagHistory(); + } while (selector); return false; } @@ -90,36 +103,45 @@ static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attri return attribute == typeAttr || attribute == readonlyAttr; } -static inline bool containsUncommonAttributeSelector(const CSSSelector* selector) +static bool containsUncommonAttributeSelector(const CSSSelector& rootSelector, bool matchesRightmostElement) { - for (; selector; selector = selector->tagHistory()) { - // Allow certain common attributes (used in the default style) in the selectors that match the current element. - if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute())) - return true; - if (selectorListContainsUncommonAttributeSelector(selector)) - return true; - if (selector->relation() != CSSSelector::SubSelector) { - selector = selector->tagHistory(); - break; + const CSSSelector* selector = &rootSelector; + do { + if (selector->isAttributeSelector()) { + // FIXME: considering non-rightmost simple selectors is necessary because of the style sharing of cousins. + // It is a primitive solution which disable a lot of style sharing on pages that rely on attributes for styling. + // We should investigate better ways of doing this. + if (!isCommonAttributeSelectorAttribute(selector->attribute()) || !matchesRightmostElement) + return true; } - } - for (; selector; selector = selector->tagHistory()) { - if (selector->isAttributeSelector()) - return true; - if (selectorListContainsUncommonAttributeSelector(selector)) - return true; - } + if (const CSSSelectorList* selectorList = selector->selectorList()) { + for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + if (containsUncommonAttributeSelector(*subSelector, matchesRightmostElement)) + return true; + } + } + + if (selector->relation() != CSSSelector::Subselector) + matchesRightmostElement = false; + + selector = selector->tagHistory(); + } while (selector); return false; } +static inline bool containsUncommonAttributeSelector(const CSSSelector& rootSelector) +{ + return containsUncommonAttributeSelector(rootSelector, true); +} + static inline PropertyWhitelistType determinePropertyWhitelistType(const AddRuleFlags addRuleFlags, const CSSSelector* selector) { if (addRuleFlags & RuleIsInRegionRule) return PropertyWhitelistRegion; #if ENABLE(VIDEO_TRACK) for (const CSSSelector* component = selector; component; component = component->tagHistory()) { - if (component->pseudoType() == CSSSelector::PseudoCue || (component->m_match == CSSSelector::PseudoElement && component->value() == TextTrackCue::cueShadowPseudoId())) + if (component->match() == CSSSelector::PseudoElement && (component->pseudoElementType() == CSSSelector::PseudoElementCue || component->value() == TextTrackCue::cueShadowPseudoId())) return PropertyWhitelistCue; } #else @@ -131,114 +153,195 @@ static inline PropertyWhitelistType determinePropertyWhitelistType(const AddRule RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, AddRuleFlags addRuleFlags) : m_rule(rule) , m_selectorIndex(selectorIndex) + , m_hasDocumentSecurityOrigin(addRuleFlags & RuleHasDocumentSecurityOrigin) , m_position(position) - , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorCheckerFastPath::canUse(selector())) - , m_specificity(selector()->specificity()) - , m_hasMultipartSelector(!!selector()->tagHistory()) - , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector())) - , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector())) + , m_matchBasedOnRuleHash(static_cast<unsigned>(computeMatchBasedOnRuleHash(*selector()))) + , m_canMatchPseudoElement(selectorCanMatchPseudoElement(*selector())) + , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(*selector())) , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector())) - , m_hasDocumentSecurityOrigin(addRuleFlags & RuleHasDocumentSecurityOrigin) , m_propertyWhitelistType(determinePropertyWhitelistType(addRuleFlags, selector())) +#if ENABLE(CSS_SELECTOR_JIT) && CSS_SELECTOR_JIT_PROFILING + , m_compiledSelectorUseCount(0) +#endif { ASSERT(m_position == position); ASSERT(m_selectorIndex == selectorIndex); SelectorFilter::collectIdentifierHashes(selector(), m_descendantSelectorIdentifierHashes, maximumIdentifierCount); } -static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData& ruleData) +RuleSet::RuleSet() { - bool foundSiblingSelector = false; - for (const CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { - features.collectFeaturesFromSelector(selector); - - if (const CSSSelectorList* selectorList = selector->selectorList()) { - for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { - if (!foundSiblingSelector && selector->isSiblingSelector()) - foundSiblingSelector = true; - features.collectFeaturesFromSelector(subSelector); - } - } else if (!foundSiblingSelector && selector->isSiblingSelector()) - foundSiblingSelector = true; - } - if (foundSiblingSelector) - features.siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); - if (ruleData.containsUncommonAttributeSelector()) - features.uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); } - -void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleData& ruleData) + +RuleSet::~RuleSet() +{ +} + +void RuleSet::addToRuleSet(const AtomicString& key, AtomRuleMap& map, const RuleData& ruleData) { - if (!key) + if (key.isNull()) return; - OwnPtr<Vector<RuleData>>& rules = map.add(key, nullptr).iterator->value; + auto& rules = map.add(key, nullptr).iterator->value; if (!rules) - rules = adoptPtr(new Vector<RuleData>); + rules = std::make_unique<RuleDataVector>(); rules->append(ruleData); } -bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& ruleData) +static unsigned rulesCountForName(const RuleSet::AtomRuleMap& map, const AtomicString& name) { - if (component->m_match == CSSSelector::Id) { - addToRuleSet(component->value().impl(), m_idRules, ruleData); - return true; - } - if (component->m_match == CSSSelector::Class) { - addToRuleSet(component->value().impl(), m_classRules, ruleData); - return true; - } - if (component->isCustomPseudoElement()) { - addToRuleSet(component->value().impl(), m_shadowPseudoElementRules, ruleData); - return true; - } + if (const auto* rules = map.get(name)) + return rules->size(); + return 0; +} + +void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) +{ + RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); + m_features.collectFeatures(ruleData); + + unsigned classBucketSize = 0; + const CSSSelector* idSelector = nullptr; + const CSSSelector* tagSelector = nullptr; + const CSSSelector* classSelector = nullptr; + const CSSSelector* linkSelector = nullptr; + const CSSSelector* focusSelector = nullptr; + const CSSSelector* hostPseudoClassSelector = nullptr; + const CSSSelector* customPseudoElementSelector = nullptr; + const CSSSelector* slottedPseudoElementSelector = nullptr; +#if ENABLE(VIDEO_TRACK) + const CSSSelector* cuePseudoElementSelector = nullptr; +#endif + const CSSSelector* selector = ruleData.selector(); + do { + switch (selector->match()) { + case CSSSelector::Id: + idSelector = selector; + break; + case CSSSelector::Class: { + auto& className = selector->value(); + if (!classSelector) { + classSelector = selector; + classBucketSize = rulesCountForName(m_classRules, className); + } else if (classBucketSize) { + unsigned newClassBucketSize = rulesCountForName(m_classRules, className); + if (newClassBucketSize < classBucketSize) { + classSelector = selector; + classBucketSize = newClassBucketSize; + } + } + break; + } + case CSSSelector::Tag: + if (selector->tagQName().localName() != starAtom) + tagSelector = selector; + break; + case CSSSelector::PseudoElement: + switch (selector->pseudoElementType()) { + case CSSSelector::PseudoElementUserAgentCustom: + case CSSSelector::PseudoElementWebKitCustom: + case CSSSelector::PseudoElementWebKitCustomLegacyPrefixed: + customPseudoElementSelector = selector; + break; + case CSSSelector::PseudoElementSlotted: + slottedPseudoElementSelector = selector; + break; #if ENABLE(VIDEO_TRACK) - if (component->pseudoType() == CSSSelector::PseudoCue) { + case CSSSelector::PseudoElementCue: + cuePseudoElementSelector = selector; + break; +#endif + default: + break; + } + break; + case CSSSelector::PseudoClass: + switch (selector->pseudoClassType()) { + case CSSSelector::PseudoClassLink: + case CSSSelector::PseudoClassVisited: + case CSSSelector::PseudoClassAnyLink: + case CSSSelector::PseudoClassAnyLinkDeprecated: + linkSelector = selector; + break; + case CSSSelector::PseudoClassFocus: + focusSelector = selector; + break; + case CSSSelector::PseudoClassHost: + hostPseudoClassSelector = selector; + break; + default: + break; + } + break; + case CSSSelector::Unknown: + case CSSSelector::Exact: + case CSSSelector::Set: + case CSSSelector::List: + case CSSSelector::Hyphen: + case CSSSelector::Contain: + case CSSSelector::Begin: + case CSSSelector::End: + case CSSSelector::PagePseudoClass: + break; + } + if (selector->relation() != CSSSelector::Subselector) + break; + selector = selector->tagHistory(); + } while (selector); + +#if ENABLE(VIDEO_TRACK) + if (cuePseudoElementSelector) { m_cuePseudoRules.append(ruleData); - return true; + return; } #endif - if (SelectorChecker::isCommonPseudoClassSelector(component)) { - switch (component->pseudoType()) { - case CSSSelector::PseudoLink: - case CSSSelector::PseudoVisited: - case CSSSelector::PseudoAnyLink: - m_linkPseudoClassRules.append(ruleData); - return true; - case CSSSelector::PseudoFocus: - m_focusPseudoClassRules.append(ruleData); - return true; - default: - ASSERT_NOT_REACHED(); - return true; - } + + if (slottedPseudoElementSelector) { + // ::slotted pseudo elements work accross shadow boundary making filtering difficult. + ruleData.disableSelectorFiltering(); + m_slottedPseudoElementRules.append(ruleData); + return; } - if (component->m_match == CSSSelector::Tag) { - // If this is part of a subselector chain, recurse ahead to find a narrower set (ID/class/:pseudo) - if (component->relation() == CSSSelector::SubSelector) { - const CSSSelector* nextComponent = component->tagHistory(); - if (nextComponent->m_match == CSSSelector::Class || nextComponent->m_match == CSSSelector::Id || SelectorChecker::isCommonPseudoClassSelector(nextComponent)) { - if (findBestRuleSetAndAdd(nextComponent, ruleData)) - return true; - } - } - if (component->tagQName().localName() != starAtom) { - addToRuleSet(component->tagQName().localName().impl(), m_tagRules, ruleData); - return true; - } + if (customPseudoElementSelector) { + // FIXME: Custom pseudo elements are handled by the shadow tree's selector filter. It doesn't know about the main DOM. + ruleData.disableSelectorFiltering(); + addToRuleSet(customPseudoElementSelector->value(), m_shadowPseudoElementRules, ruleData); + return; } - return false; -} -void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) -{ - RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); - collectFeaturesFromRuleData(m_features, ruleData); + if (hostPseudoClassSelector) { + m_hostPseudoClassRules.append(ruleData); + return; + } + + if (idSelector) { + addToRuleSet(idSelector->value(), m_idRules, ruleData); + return; + } - if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) { - // If we didn't find a specialized map to stick it in, file under universal rules. - m_universalRules.append(ruleData); + if (classSelector) { + addToRuleSet(classSelector->value(), m_classRules, ruleData); + return; } + + if (linkSelector) { + m_linkPseudoClassRules.append(ruleData); + return; + } + + if (focusSelector) { + m_focusPseudoClassRules.append(ruleData); + return; + } + + if (tagSelector) { + addToRuleSet(tagSelector->tagQName().localName(), m_tagLocalNameRules, ruleData); + addToRuleSet(tagSelector->tagLowercaseLocalName(), m_tagLowercaseLocalNameRules, ruleData); + return; + } + + // If we didn't find a specialized map to stick it in, file under universal rules. + m_universalRules.append(ruleData); } void RuleSet::addPageRule(StyleRulePage* rule) @@ -248,7 +351,7 @@ void RuleSet::addPageRule(StyleRulePage* rule) void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurityOrigin) { - OwnPtr<RuleSet> regionRuleSet = RuleSet::create(); + auto regionRuleSet = std::make_unique<RuleSet>(); // The region rule set should take into account the position inside the parent rule set. // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from // the stylesheet that contains the region block. @@ -258,88 +361,63 @@ void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit // FIXME: Should this add other types of rules? (i.e. use addChildRules() directly?) const Vector<RefPtr<StyleRuleBase>>& childRules = regionRule->childRules(); AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState; - addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckSelector | RuleIsInRegionRule); - for (unsigned i = 0; i < childRules.size(); ++i) { - StyleRuleBase* regionStylingRule = childRules[i].get(); - if (regionStylingRule->isStyleRule()) - regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), addRuleFlags); + addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleIsInRegionRule); + for (auto& childRule : childRules) { + if (is<StyleRule>(*childRule)) + regionRuleSet->addStyleRule(downcast<StyleRule>(childRule.get()), addRuleFlags); } // Update the "global" rule count so that proper order is maintained m_ruleCount = regionRuleSet->m_ruleCount; - m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(regionRule->selectorList().first(), regionRuleSet.release())); + m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(regionRule->selectorList().first(), WTFMove(regionRuleSet))); } -void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase>>& rules, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope, bool hasDocumentSecurityOrigin, AddRuleFlags addRuleFlags) +void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase>>& rules, const MediaQueryEvaluator& medium, StyleResolver* resolver, bool hasDocumentSecurityOrigin, bool isInitiatingElementInUserAgentShadowTree, AddRuleFlags addRuleFlags) { - for (unsigned i = 0; i < rules.size(); ++i) { - StyleRuleBase* rule = rules[i].get(); - - if (rule->isStyleRule()) { - StyleRule* styleRule = static_cast<StyleRule*>(rule); - addStyleRule(styleRule, addRuleFlags); - } else if (rule->isPageRule()) - addPageRule(static_cast<StyleRulePage*>(rule)); - else if (rule->isMediaRule()) { - StyleRuleMedia* mediaRule = static_cast<StyleRuleMedia*>(rule); - if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), resolver))) - addChildRules(mediaRule->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags); - } else if (rule->isFontFaceRule() && resolver) { + for (auto& rule : rules) { + if (is<StyleRule>(*rule)) + addStyleRule(downcast<StyleRule>(rule.get()), addRuleFlags); + else if (is<StyleRulePage>(*rule)) + addPageRule(downcast<StyleRulePage>(rule.get())); + else if (is<StyleRuleMedia>(*rule)) { + auto& mediaRule = downcast<StyleRuleMedia>(*rule); + if ((!mediaRule.mediaQueries() || medium.evaluate(*mediaRule.mediaQueries(), resolver))) + addChildRules(mediaRule.childRules(), medium, resolver, hasDocumentSecurityOrigin, isInitiatingElementInUserAgentShadowTree, addRuleFlags); + } else if (is<StyleRuleFontFace>(*rule) && resolver) { // Add this font face to our set. - // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. - if (scope) - continue; - const StyleRuleFontFace* fontFaceRule = static_cast<StyleRuleFontFace*>(rule); - resolver->fontSelector()->addFontFaceRule(fontFaceRule); + resolver->document().fontSelector().addFontFaceRule(downcast<StyleRuleFontFace>(*rule.get()), isInitiatingElementInUserAgentShadowTree); resolver->invalidateMatchedPropertiesCache(); - } else if (rule->isKeyframesRule() && resolver) { - // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment. - if (scope) - continue; - resolver->addKeyframeStyle(static_cast<StyleRuleKeyframes*>(rule)); - } + } else if (is<StyleRuleKeyframes>(*rule) && resolver) + resolver->addKeyframeStyle(downcast<StyleRuleKeyframes>(*rule)); + else if (is<StyleRuleSupports>(*rule) && downcast<StyleRuleSupports>(*rule).conditionIsSupported()) + addChildRules(downcast<StyleRuleSupports>(*rule).childRules(), medium, resolver, hasDocumentSecurityOrigin, isInitiatingElementInUserAgentShadowTree, addRuleFlags); #if ENABLE(CSS_REGIONS) - else if (rule->isRegionRule() && resolver) { - // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment. - if (scope) - continue; - addRegionRule(static_cast<StyleRuleRegion*>(rule), hasDocumentSecurityOrigin); + else if (is<StyleRuleRegion>(*rule) && resolver) { + addRegionRule(downcast<StyleRuleRegion>(rule.get()), hasDocumentSecurityOrigin); } #endif -#if ENABLE(SHADOW_DOM) - else if (rule->isHostRule()) - resolver->addHostRule(static_cast<StyleRuleHost*>(rule), hasDocumentSecurityOrigin, scope); -#endif #if ENABLE(CSS_DEVICE_ADAPTATION) - else if (rule->isViewportRule() && resolver) { - // @viewport should not be scoped. - if (scope) - continue; - resolver->viewportStyleResolver()->addViewportRule(static_cast<StyleRuleViewport*>(rule)); + else if (is<StyleRuleViewport>(*rule) && resolver) { + resolver->viewportStyleResolver()->addViewportRule(downcast<StyleRuleViewport>(rule.get())); } #endif -#if ENABLE(CSS3_CONDITIONAL_RULES) - else if (rule->isSupportsRule() && static_cast<StyleRuleSupports*>(rule)->conditionIsSupported()) - addChildRules(static_cast<StyleRuleSupports*>(rule)->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags); -#endif } } -void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope) +void RuleSet::addRulesFromSheet(StyleSheetContents& sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver) { - ASSERT(sheet); - - const Vector<RefPtr<StyleRuleImport>>& importRules = sheet->importRules(); - for (unsigned i = 0; i < importRules.size(); ++i) { - StyleRuleImport* importRule = importRules[i].get(); - if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), resolver))) - addRulesFromSheet(importRule->styleSheet(), medium, resolver, scope); + for (auto& rule : sheet.importRules()) { + if (rule->styleSheet() && (!rule->mediaQueries() || medium.evaluate(*rule->mediaQueries(), resolver))) + addRulesFromSheet(*rule->styleSheet(), medium, resolver); } - bool hasDocumentSecurityOrigin = resolver && resolver->document().securityOrigin()->canRequest(sheet->baseURL()); - AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0)); + bool hasDocumentSecurityOrigin = resolver && resolver->document().securityOrigin().canRequest(sheet.baseURL()); + AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0)); - addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags); + // FIXME: Skip Content Security Policy check when stylesheet is in a user agent shadow tree. + // See <https://bugs.webkit.org/show_bug.cgi?id=146663>. + bool isInitiatingElementInUserAgentShadowTree = false; + addChildRules(sheet.childRules(), medium, resolver, hasDocumentSecurityOrigin, isInitiatingElementInUserAgentShadowTree, addRuleFlags); if (m_autoShrinkToFitEnabled) shrinkToFit(); @@ -351,26 +429,41 @@ void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) addRule(rule, selectorIndex, addRuleFlags); } +bool RuleSet::hasShadowPseudoElementRules() const +{ + if (!m_shadowPseudoElementRules.isEmpty()) + return true; +#if ENABLE(VIDEO_TRACK) + if (!m_cuePseudoRules.isEmpty()) + return true; +#endif + return false; +} + static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map) { - RuleSet::AtomRuleMap::iterator end = map.end(); - for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it) - it->value->shrinkToFit(); + for (auto& vector : map.values()) + vector->shrinkToFit(); } void RuleSet::shrinkToFit() { shrinkMapVectorsToFit(m_idRules); shrinkMapVectorsToFit(m_classRules); - shrinkMapVectorsToFit(m_tagRules); + shrinkMapVectorsToFit(m_tagLocalNameRules); + shrinkMapVectorsToFit(m_tagLowercaseLocalNameRules); shrinkMapVectorsToFit(m_shadowPseudoElementRules); m_linkPseudoClassRules.shrinkToFit(); #if ENABLE(VIDEO_TRACK) m_cuePseudoRules.shrinkToFit(); #endif + m_hostPseudoClassRules.shrinkToFit(); + m_slottedPseudoElementRules.shrinkToFit(); m_focusPseudoClassRules.shrinkToFit(); m_universalRules.shrinkToFit(); m_pageRules.shrinkToFit(); + m_features.shrinkToFit(); + m_regionSelectorsAndRuleSets.shrinkToFit(); } } // namespace WebCore |