From d441d6f39bb846989d95bcf5caf387b42414718d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 13 Sep 2013 12:51:20 +0200 Subject: Import Qt5x2 branch of QtWebkit for Qt 5.2 Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen --- Source/WebCore/css/RuleSet.cpp | 255 +++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 134 deletions(-) (limited to 'Source/WebCore/css/RuleSet.cpp') diff --git a/Source/WebCore/css/RuleSet.cpp b/Source/WebCore/css/RuleSet.cpp index 9a78c0ff9..300c7a125 100644 --- a/Source/WebCore/css/RuleSet.cpp +++ b/Source/WebCore/css/RuleSet.cpp @@ -36,15 +36,17 @@ #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 "WebCoreMemoryInstrumentation.h" #include "WebKitCSSKeyframesRule.h" -#include -#include -#include + +#if ENABLE(VIDEO_TRACK) +#include "TextTrackCue.h" +#endif namespace WebCore { @@ -54,13 +56,15 @@ using namespace HTMLNames; static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector) { - const AtomicString& selectorNamespace = selector->tag().namespaceURI(); - if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) - return false; - if (selector->m_match == CSSSelector::None) + 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->tag() != starAtom) - return false; + } if (SelectorChecker::isCommonPseudoClassSelector(selector)) return true; return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class; @@ -68,12 +72,14 @@ static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* sele static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector) { - CSSSelectorList* selectorList = selector->selectorList(); + const CSSSelectorList* selectorList = selector->selectorList(); if (!selectorList) return false; - for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { - if (subSelector->isAttributeSelector()) - return true; + 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; + } } return false; } @@ -107,64 +113,47 @@ static inline bool containsUncommonAttributeSelector(const CSSSelector* selector return false; } +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())) + return PropertyWhitelistCue; + } +#else + UNUSED_PARAM(selector); +#endif + return PropertyWhitelistNone; +} + RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, AddRuleFlags addRuleFlags) : m_rule(rule) , m_selectorIndex(selectorIndex) , m_position(position) + , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorCheckerFastPath::canUse(selector())) , m_specificity(selector()->specificity()) - , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorChecker::isFastCheckableSelector(selector())) , m_hasMultipartSelector(!!selector()->tagHistory()) , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector())) , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector())) , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector())) , m_hasDocumentSecurityOrigin(addRuleFlags & RuleHasDocumentSecurityOrigin) - , m_isInRegionRule(!!(addRuleFlags & RuleIsInRegionRule)) + , m_propertyWhitelistType(determinePropertyWhitelistType(addRuleFlags, selector())) { ASSERT(m_position == position); ASSERT(m_selectorIndex == selectorIndex); - SelectorChecker::collectIdentifierHashes(selector(), m_descendantSelectorIdentifierHashes, maximumIdentifierCount); -} - -void RuleData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const -{ - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); -} - -static void reportAtomRuleMap(MemoryClassInfo* info, const RuleSet::AtomRuleMap& atomicRuleMap) -{ - info->addMember(atomicRuleMap); - for (RuleSet::AtomRuleMap::const_iterator it = atomicRuleMap.begin(); it != atomicRuleMap.end(); ++it) - info->addMember(*it->value); -} - -void RuleSet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const -{ - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - reportAtomRuleMap(&info, m_idRules); - reportAtomRuleMap(&info, m_classRules); - reportAtomRuleMap(&info, m_tagRules); - reportAtomRuleMap(&info, m_shadowPseudoElementRules); - info.addMember(m_linkPseudoClassRules); - info.addMember(m_focusPseudoClassRules); - info.addMember(m_universalRules); - info.addMember(m_pageRules); - info.addMember(m_regionSelectorsAndRuleSets); -} - -void RuleSet::RuleSetSelectorPair::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const -{ - MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addMember(ruleSet); + SelectorFilter::collectIdentifierHashes(selector(), m_descendantSelectorIdentifierHashes, maximumIdentifierCount); } static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData& ruleData) { bool foundSiblingSelector = false; - for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { + for (const CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { features.collectFeaturesFromSelector(selector); - if (CSSSelectorList* selectorList = selector->selectorList()) { - for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + 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); @@ -188,51 +177,68 @@ void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleDa rules->append(ruleData); } -void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) +bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& ruleData) { - RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); - static const unsigned athostRuleSpecificity = 0x100000; - - if (addRuleFlags & RuleIsHostRule) - ruleData.increaseSpecificity(athostRuleSpecificity); - - collectFeaturesFromRuleData(m_features, ruleData); - - CSSSelector* selector = ruleData.selector(); - - if (selector->m_match == CSSSelector::Id) { - addToRuleSet(selector->value().impl(), m_idRules, ruleData); - return; + if (component->m_match == CSSSelector::Id) { + addToRuleSet(component->value().impl(), m_idRules, ruleData); + return true; } - if (selector->m_match == CSSSelector::Class) { - addToRuleSet(selector->value().impl(), m_classRules, ruleData); - return; + if (component->m_match == CSSSelector::Class) { + addToRuleSet(component->value().impl(), m_classRules, ruleData); + return true; } - if (selector->isCustomPseudoElement()) { - addToRuleSet(selector->value().impl(), m_shadowPseudoElementRules, ruleData); - return; + if (component->isCustomPseudoElement()) { + addToRuleSet(component->value().impl(), m_shadowPseudoElementRules, ruleData); + return true; + } +#if ENABLE(VIDEO_TRACK) + if (component->pseudoType() == CSSSelector::PseudoCue) { + m_cuePseudoRules.append(ruleData); + return true; } - if (SelectorChecker::isCommonPseudoClassSelector(selector)) { - switch (selector->pseudoType()) { +#endif + if (SelectorChecker::isCommonPseudoClassSelector(component)) { + switch (component->pseudoType()) { case CSSSelector::PseudoLink: case CSSSelector::PseudoVisited: case CSSSelector::PseudoAnyLink: m_linkPseudoClassRules.append(ruleData); - return; + return true; case CSSSelector::PseudoFocus: m_focusPseudoClassRules.append(ruleData); - return; + return true; default: ASSERT_NOT_REACHED(); + return true; } - return; } - const AtomicString& localName = selector->tag().localName(); - if (localName != starAtom) { - addToRuleSet(localName.impl(), m_tagRules, 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; + } + } + return false; +} + +void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) +{ + RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); + collectFeaturesFromRuleData(m_features, ruleData); + + 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); } - m_universalRules.append(ruleData); } void RuleSet::addPageRule(StyleRulePage* rule) @@ -249,6 +255,7 @@ void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit regionRuleSet->m_ruleCount = m_ruleCount; // Collect the region rules into a rule set + // FIXME: Should this add other types of rules? (i.e. use addChildRules() directly?) const Vector >& childRules = regionRule->childRules(); AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState; addRuleFlags = static_cast(addRuleFlags | RuleCanUseFastCheckSelector | RuleIsInRegionRule); @@ -263,65 +270,20 @@ void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(regionRule->selectorList().first(), regionRuleSet.release())); } -void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope) +void RuleSet::addChildRules(const Vector >& rules, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope, bool hasDocumentSecurityOrigin, AddRuleFlags addRuleFlags) { - ASSERT(sheet); - - const Vector >& 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); - } - bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL()); - AddRuleFlags addRuleFlags = static_cast((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0)); - - const Vector >& rules = sheet->childRules(); for (unsigned i = 0; i < rules.size(); ++i) { StyleRuleBase* rule = rules[i].get(); - ASSERT(!rule->isImportRule()); - if (rule->isStyleRule()) - addStyleRule(static_cast(rule), addRuleFlags); - else if (rule->isPageRule()) + if (rule->isStyleRule()) { + StyleRule* styleRule = static_cast(rule); + addStyleRule(styleRule, addRuleFlags); + } else if (rule->isPageRule()) addPageRule(static_cast(rule)); else if (rule->isMediaRule()) { StyleRuleMedia* mediaRule = static_cast(rule); - - if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), resolver))) { - // Traverse child elements of the @media rule. - const Vector >& childRules = mediaRule->childRules(); - for (unsigned j = 0; j < childRules.size(); ++j) { - StyleRuleBase* childRule = childRules[j].get(); - if (childRule->isStyleRule()) - addStyleRule(static_cast(childRule), addRuleFlags); - else if (childRule->isPageRule()) - addPageRule(static_cast(childRule)); - else if (childRule->isFontFaceRule() && 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(childRule); - resolver->fontSelector()->addFontFaceRule(fontFaceRule); - resolver->invalidateMatchedPropertiesCache(); - } else if (childRule->isKeyframesRule() && resolver) { - // Add this keyframe rule to our set. - // FIXME(BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment. - if (scope) - continue; - resolver->addKeyframeStyle(static_cast(childRule)); - } -#if ENABLE(CSS_DEVICE_ADAPTATION) - else if (childRule->isViewportRule() && resolver && !resolver->affectedByViewportChange()) { - // @viewport should not be scoped. - if (scope) - continue; - resolver->viewportStyleResolver()->addViewportRule(static_cast(childRule)); - } -#endif - } // for rules - } // if rules + if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), resolver))) + addChildRules(mediaRule->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags); } else if (rule->isFontFaceRule() && 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. @@ -355,8 +317,30 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu continue; resolver->viewportStyleResolver()->addViewportRule(static_cast(rule)); } +#endif +#if ENABLE(CSS3_CONDITIONAL_RULES) + else if (rule->isSupportsRule() && static_cast(rule)->conditionIsSupported()) + addChildRules(static_cast(rule)->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags); #endif } +} + +void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope) +{ + ASSERT(sheet); + + const Vector >& 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); + } + + bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL()); + AddRuleFlags addRuleFlags = static_cast((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0)); + + addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags); + if (m_autoShrinkToFitEnabled) shrinkToFit(); } @@ -381,6 +365,9 @@ void RuleSet::shrinkToFit() shrinkMapVectorsToFit(m_tagRules); shrinkMapVectorsToFit(m_shadowPseudoElementRules); m_linkPseudoClassRules.shrinkToFit(); +#if ENABLE(VIDEO_TRACK) + m_cuePseudoRules.shrinkToFit(); +#endif m_focusPseudoClassRules.shrinkToFit(); m_universalRules.shrinkToFit(); m_pageRules.shrinkToFit(); -- cgit v1.2.1