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().impl(), [] { 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); } }
static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData& ruleData) { bool hasSiblingSelector; features.collectFeaturesFromSelector(*ruleData.selector(), hasSiblingSelector); if (hasSiblingSelector) features.siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); if (ruleData.containsUncommonAttributeSelector()) features.uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); }
void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) { updateInvalidationSets(ruleData); FeatureMetadata metadata; collectFeaturesFromSelector(ruleData.selector(), metadata); m_metadata.add(metadata); if (metadata.foundSiblingSelector) siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); if (ruleData.containsUncommonAttributeSelector()) uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); }
void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) { FeatureMetadata metadata; InvalidationSetMode mode = UseSubtreeStyleChange; if (m_targetedStyleRecalcEnabled) mode = updateInvalidationSets(ruleData.selector()); collectFeaturesFromSelector(ruleData.selector(), metadata, mode); m_metadata.add(metadata); if (metadata.foundSiblingSelector) siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); if (ruleData.containsUncommonAttributeSelector()) uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); }
void ElementRuleCollector::didMatchRule( const RuleData& ruleData, const SelectorChecker::MatchResult& result, CascadeOrder cascadeOrder, const MatchRequest& matchRequest) { PseudoId dynamicPseudo = result.dynamicPseudo; // If we're matching normal rules, set a pseudo bit if we really just matched // a pseudo-element. if (dynamicPseudo != PseudoIdNone && m_pseudoStyleRequest.pseudoId == PseudoIdNone) { if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorChecker::CollectingStyleRules) return; // FIXME: Matching should not modify the style directly. if (!m_style || dynamicPseudo >= FirstInternalPseudoId) return; if ((dynamicPseudo == PseudoIdBefore || dynamicPseudo == PseudoIdAfter) && !ruleData.rule()->properties().hasProperty(CSSPropertyContent)) return; m_style->setHasPseudoStyle(dynamicPseudo); } else { if (m_style && ruleData.containsUncommonAttributeSelector()) m_style->setUnique(); m_matchedRules.append( MatchedRule(&ruleData, result.specificity, cascadeOrder, matchRequest.styleSheetIndex, matchRequest.styleSheet)); } }
void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange) { if (m_canUseFastReject && m_selectorFilter.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes())) return; StyleRule* rule = ruleData.rule(); PseudoId dynamicPseudo = NOPSEUDO; if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo, behaviorAtBoundary)) { // If the rule has no properties to apply, then ignore it in the non-debug mode. const StylePropertySet* properties = rule->properties(); if (!properties || (properties->isEmpty() && !matchRequest.includeEmptyRules)) return; // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed. if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin()) return; // If we're matching normal rules, set a pseudo bit if // we really just matched a pseudo-element. if (dynamicPseudo != NOPSEUDO && m_pseudoStyleRequest.pseudoId == NOPSEUDO) { if (m_mode == SelectorChecker::CollectingCSSRules || m_mode == SelectorChecker::CollectingStyleRules) return; // FIXME: Matching should not modify the style directly. if (m_style && dynamicPseudo < FIRST_INTERNAL_PSEUDOID) m_style->setHasPseudoStyle(dynamicPseudo); } else { // Update our first/last rule indices in the matched rules array. ++ruleRange.lastRuleIndex; if (ruleRange.firstRuleIndex == -1) ruleRange.firstRuleIndex = ruleRange.lastRuleIndex; // Add this rule to our list of matched rules. addMatchedRule(&ruleData, cascadeScope, cascadeOrder); return; } } }
static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData& ruleData) { 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 RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) { FeatureMetadata metadata; bool selectorUsesClassInvalidationSet = false; if (m_targetedStyleRecalcEnabled) selectorUsesClassInvalidationSet = updateClassInvalidationSets(ruleData.selector()); SelectorFeatureCollectionMode collectionMode; if (selectorUsesClassInvalidationSet) collectionMode = DontProcessClasses; else collectionMode = ProcessClasses; collectFeaturesFromSelector(ruleData.selector(), metadata, collectionMode); m_metadata.add(metadata); if (metadata.foundSiblingSelector) siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); if (ruleData.containsUncommonAttributeSelector()) uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); }
void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, CascadeOrder cascadeOrder, const MatchRequest& matchRequest) { StyleRule* rule = ruleData.rule(); if (ruleMatches(ruleData)) { // If the rule has no properties to apply, then ignore it in the non-debug mode. const StylePropertySet& properties = rule->properties(); if (properties.isEmpty()) return; // Add this rule to our list of matched rules. addMatchedRule(&ruleData, cascadeOrder, matchRequest.styleSheetIndex, matchRequest.styleSheet); } }
void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, SelectorChecker::ContextFlags contextFlags, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange) { StyleRule* rule = ruleData.rule(); if (ruleMatches(ruleData, matchRequest.scope, contextFlags)) { // If the rule has no properties to apply, then ignore it in the non-debug mode. const StylePropertySet& properties = rule->properties(); if (properties.isEmpty() && !matchRequest.includeEmptyRules) return; // Update our first/last rule indices in the matched rules array. ++ruleRange.lastRuleIndex; if (ruleRange.firstRuleIndex == -1) ruleRange.firstRuleIndex = ruleRange.lastRuleIndex; // Add this rule to our list of matched rules. addMatchedRule(&ruleData, cascadeScope, cascadeOrder, matchRequest.styleSheetIndex, matchRequest.styleSheet); } }
void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& ruleData) { const StylePropertySet& propertySet = ruleData.rule()->properties(); int propertyIndex = propertySet.findPropertyIndex(CSSPropertyContent); if (propertyIndex == -1) return; StylePropertySet::PropertyReference contentProperty = propertySet.propertyAt(propertyIndex); CSSValue* contentValue = contentProperty.value(); if (!contentValue->isValueList()) return; for (auto& item : toCSSValueList(*contentValue)) { if (!item->isFunctionValue()) continue; CSSFunctionValue* functionValue = toCSSFunctionValue(item.get()); if (functionValue->functionType() != CSSValueAttr) continue; ensureAttributeInvalidationSet(AtomicString(toCSSPrimitiveValue(functionValue->item(0))->getStringValue())).setInvalidatesSelf(); } }