void ScopedStyleResolver::collectMatchingTreeBoundaryCrossingRules(ElementRuleCollector& collector, CascadeOrder cascadeOrder)
{
    for (const auto& rules : *m_treeBoundaryCrossingRuleSet) {
        MatchRequest request(rules->m_ruleSet.get(), &treeScope().rootNode(), rules->m_parentStyleSheet, rules->m_parentIndex);
        collector.collectMatchingRules(request, cascadeOrder, true);
    }
}
void TreeBoundaryCrossingRules::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
{
    if (m_treeBoundaryCrossingRuleSetMap.isEmpty())
        return;

    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();

    // When comparing rules declared in outer treescopes, outer's rules win.
    CascadeOrder outerCascadeOrder = size() + size();
    // When comparing rules declared in inner treescopes, inner's rules win.
    CascadeOrder innerCascadeOrder = size();

    for (DocumentOrderedList::iterator it = m_scopingNodes.begin(); it != m_scopingNodes.end(); ++it) {
        const ContainerNode* scopingNode = toContainerNode(*it);
        CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode);
        bool isInnerTreeScope = element->treeScope().isInclusiveAncestorOf(scopingNode->treeScope());

        CascadeOrder cascadeOrder = isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder;
        for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) {
            CSSStyleSheet* parentStyleSheet = it->first;
            RuleSet* ruleSet = it->second.get();
            collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, SelectorChecker::ScopeContainsLastMatchedElement, ignoreCascadeScope, cascadeOrder);
        }
        ++innerCascadeOrder;
        --outerCascadeOrder;
    }
}
Example #3
0
void ScopedStyleResolver::matchHostRules(ElementRuleCollector& collector, bool includeEmptyRules)
{
    if (m_atHostRules.isEmpty() || !m_scopingNode->isElementNode())
        return;

    ElementShadow* shadow = toElement(m_scopingNode)->shadow();
    if (!shadow)
        return;

    collector.clearMatchedRules();
    collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;

    // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
    // add a new flag to ElementShadow and cache whether any @host @-rules are
    // applied to the element or not. So we can quickly exit this method
    // by using the flag.
    ShadowRoot* shadowRoot = shadow->youngestShadowRoot();
    for (; shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
        if (!ScopeContentDistribution::hasShadowElement(shadowRoot))
            break;
    // All shadow roots have <shadow>.
    if (!shadowRoot)
        shadowRoot = shadow->oldestShadowRoot();

    StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
    collector.setBehaviorAtBoundary(static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::DoesNotCrossBoundary | SelectorChecker::ScopeContainsLastMatchedElement));
    for (; shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) {
        if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot))
            collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, m_scopingNode), ruleRange);
    }

    collector.sortAndTransferMatchedRules();
}
void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, CascadeOrder cascadeOrder)
{
    for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
        ASSERT(m_authorStyleSheets[i]->ownerNode());
        MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), &m_scope->rootNode(), m_authorStyleSheets[i], i);
        collector.collectMatchingRules(matchRequest, cascadeOrder);
    }
}
void ScopedStyleResolver::collectMatchingTreeBoundaryCrossingRules(ElementRuleCollector& collector, bool includeEmptyRules, CascadeOrder cascadeOrder)
{
    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
    for (const auto& rules : *m_treeBoundaryCrossingRuleSet) {
        MatchRequest request(rules->m_ruleSet.get(), includeEmptyRules, &treeScope().rootNode(), rules->m_parentStyleSheet, rules->m_parentIndex);
        collector.collectMatchingRules(request, ruleRange, cascadeOrder, true);
    }
}
void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, CascadeOrder cascadeOrder)
{
    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
    ASSERT(!collector.scopeContainsLastMatchedElement());
    collector.setScopeContainsLastMatchedElement(true);
    for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
        ASSERT(m_authorStyleSheets[i]->ownerNode());
        MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), includeEmptyRules, &m_scope->rootNode(), m_authorStyleSheets[i], i);
        collector.collectMatchingRules(matchRequest, ruleRange, cascadeOrder);
    }
    collector.setScopeContainsLastMatchedElement(false);
}
Example #7
0
void ScopedStyleResolver::matchAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles)
{
    if (m_authorStyle) {
        collector.clearMatchedRules();
        collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;

        // Match author rules.
        MatchRequest matchRequest(m_authorStyle.get(), includeEmptyRules, m_scopingNode);
        StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
        collector.setBehaviorAtBoundary(applyAuthorStyles ? SelectorChecker::DoesNotCrossBoundary : static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::DoesNotCrossBoundary | SelectorChecker::ScopeContainsLastMatchedElement));
        collector.collectMatchingRules(matchRequest, ruleRange);
        collector.collectMatchingRulesForRegion(matchRequest, ruleRange);
        collector.sortAndTransferMatchedRules();
    }
}
Example #8
0
void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope cascadeScope, CascadeOrder cascadeOrder)
{
    const ContainerNode* scopingNode = &m_scopingNode;
    unsigned behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary;

    if (!applyAuthorStyles)
        behaviorAtBoundary |= SelectorChecker::ScopeContainsLastMatchedElement;

    if (m_scopingNode.isShadowRoot()) {
        scopingNode = toShadowRoot(m_scopingNode).host();
        behaviorAtBoundary |= SelectorChecker::ScopeIsShadowHost;
    }

    for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
        MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), includeEmptyRules, scopingNode, applyAuthorStyles, i, m_authorStyleSheets[i]);
        collector.collectMatchingRules(matchRequest, collector.matchedResult().ranges.authorRuleRange(), static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder);
    }
}
Example #9
0
void StyleResolver::matchRules(Element& element, ElementRuleCollector& collector)
{
    collector.clearMatchedRules();

    CascadeOrder cascadeOrder = 0;

    collector.collectMatchingRules(MatchRequest(&defaultStyles()), ++cascadeOrder);

    ScopedStyleResolver& resolver = element.treeScope().scopedStyleResolver();
    resolver.collectMatchingAuthorRules(collector, ++cascadeOrder);

    collector.sortAndTransferMatchedRules();

    if (const StylePropertySet* inlineStyle = element.inlineStyle()) {
        // Inline style is immutable as long as there is no CSSOM wrapper.
        bool isInlineStyleCacheable = !inlineStyle->isMutable();
        collector.addElementStyleProperties(inlineStyle, isInlineStyleCacheable);
    }
}
void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& collector, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope cascadeScope, CascadeOrder cascadeOrder)
{
    if (!m_authorStyle)
        return;

    const ContainerNode* scopingNode = &m_scopingNode;
    unsigned behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary;

    if (!applyAuthorStyles)
        behaviorAtBoundary |= SelectorChecker::ScopeContainsLastMatchedElement;

    if (m_scopingNode.isShadowRoot()) {
        scopingNode = toShadowRoot(m_scopingNode).host();
        behaviorAtBoundary |= SelectorChecker::ScopeIsShadowHost;
    }

    MatchRequest matchRequest(m_authorStyle.get(), includeEmptyRules, scopingNode, applyAuthorStyles);
    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
    collector.collectMatchingRules(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder);
    collector.collectMatchingRulesForRegion(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder);
}
void TreeBoundaryCrossingRules::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
{
    if (m_treeBoundaryCrossingRuleSetMap.isEmpty())
        return;

    RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();

    // When comparing rules declared in outer treescopes, outer's rules win.
    CascadeOrder outerCascadeOrder = size() + size();
    // When comparing rules declared in inner treescopes, inner's rules win.
    CascadeOrder innerCascadeOrder = size();

    for (DocumentOrderedList::iterator it = m_scopingNodes.begin(); it != m_scopingNodes.end(); ++it) {
        const ContainerNode* scopingNode = toContainerNode(*it);
        CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode);
        unsigned boundaryBehavior = SelectorChecker::ScopeContainsLastMatchedElement;
        bool isInnerTreeScope = element->treeScope().isInclusiveAncestorOf(scopingNode->treeScope());

        // If a given scoping node is a shadow root and a given element is in a descendant tree of tree hosted by
        // the scoping node's shadow host, we should use ScopeIsShadowHost.
        if (scopingNode && scopingNode->isShadowRoot()) {
            if (element->isInDescendantTreeOf(toShadowRoot(scopingNode)->host()))
                boundaryBehavior |= SelectorChecker::ScopeIsShadowHost;
            scopingNode = toShadowRoot(scopingNode)->host();
        }

        CascadeOrder cascadeOrder = isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder;
        for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) {
            CSSStyleSheet* parentStyleSheet = it->first;
            RuleSet* ruleSet = it->second.get();
            collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder);
        }
        ++innerCascadeOrder;
        --outerCascadeOrder;
    }
}