Ejemplo n.º 1
0
void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& features)
{
    for (const CSSSelector* current = &selector; current; current = current->tagHistory()) {
        if (InvalidationSet* invalidationSet = invalidationSetForSelector(*current)) {
            addFeaturesToInvalidationSet(*invalidationSet, features);
        } else {
            if (current->isTreeBoundaryCrossing())
                features.treeBoundaryCrossing = true;
            if (current->isInsertionPointCrossing())
                features.insertionPointCrossing = true;
            if (const CSSSelectorList* selectorList = current->selectorList()) {
                ASSERT(supportsInvalidationWithSelectorList(current->pseudoType()));
                for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector))
                    addFeaturesToInvalidationSets(*subSelector, features);
            }
        }

        if (current->relation() == CSSSelector::SubSelector)
            continue;

        if (current->isShadowSelector())
            features.treeBoundaryCrossing = true;

        features.adjacent = current->isAdjacentSelector();
    }
}
Ejemplo n.º 2
0
std::pair<const CSSSelector*, RuleFeatureSet::UseFeaturesType>
RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, InvalidationSetFeatures& features, PositionType position, CSSSelector::PseudoType pseudo)
{
    bool foundFeatures = false;
    for (const CSSSelector* current = &selector; current; current = current->tagHistory()) {
        if (pseudo != CSSSelector::PseudoNot)
            foundFeatures |= extractInvalidationSetFeature(*current, features);
        // Initialize the entry in the invalidation set map, if supported.
        if (InvalidationSet* invalidationSet = invalidationSetForSelector(*current, InvalidateDescendants)) {
            if (position == Subject)
                invalidationSet->setInvalidatesSelf();
        } else {
            if (requiresSubtreeInvalidation(*current)) {
                // Fall back to use subtree invalidations, even for features in the
                // rightmost compound selector. Returning the start &selector here
                // will make addFeaturesToInvalidationSets start marking invalidation
                // sets for subtree recalc for features in the rightmost compound
                // selector.
                return std::make_pair(&selector, ForceSubtree);
            }
            if (const CSSSelectorList* selectorList = current->selectorList()) {
                ASSERT(supportsInvalidationWithSelectorList(current->pseudoType()));
                const CSSSelector* subSelector = selectorList->first();
                bool allSubSelectorsHaveFeatures = !!subSelector;
                for (; subSelector; subSelector = CSSSelectorList::next(*subSelector)) {
                    auto result = extractInvalidationSetFeatures(*subSelector, features, position, current->pseudoType());
                    if (result.first) {
                        // A non-null selector return means the sub-selector contained a
                        // selector which requiresSubtreeInvalidation(). Return the rightmost
                        // selector to mark for subtree recalcs like above.
                        return std::make_pair(&selector, ForceSubtree);
                    }
                    allSubSelectorsHaveFeatures &= result.second == UseFeatures;
                }
                foundFeatures |= allSubSelectorsHaveFeatures;
            }
        }

        if (current->relation() == CSSSelector::SubSelector)
            continue;

        features.treeBoundaryCrossing = current->isShadowSelector();
        features.adjacent = current->isAdjacentSelector();
        if (current->relation() == CSSSelector::DirectAdjacent)
            features.maxDirectAdjacentSelectors = 1;
        return std::make_pair(current->tagHistory(), foundFeatures ? UseFeatures : ForceSubtree);
    }
    return std::make_pair(nullptr,  foundFeatures ? UseFeatures : ForceSubtree);
}
Ejemplo n.º 3
0
// selector is the selector immediately to the left of the rightmost combinator.
// siblingFeatures is null if selector is not immediately to the left of a sibling combinator.
// descendantFeatures has the features of the rightmost compound selector.
void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector* selector, InvalidationSetFeatures* siblingFeatures, InvalidationSetFeatures& descendantFeatures)
{
    const CSSSelector* lastCompoundSelectorInAdjacentChain = selector;

    // We set siblingFeatures to &localFeatures if we find a rightmost sibling combinator.
    InvalidationSetFeatures localFeatures;

    for (const CSSSelector* current = selector; current; current = current->tagHistory()) {
        InvalidationType type = siblingFeatures ? InvalidateSiblings : InvalidateDescendants;
        if (InvalidationSet* invalidationSet = invalidationSetForSelector(*current, type)) {
            if (siblingFeatures) {
                SiblingInvalidationSet* siblingInvalidationSet = toSiblingInvalidationSet(invalidationSet);
                siblingInvalidationSet->updateMaxDirectAdjacentSelectors(siblingFeatures->maxDirectAdjacentSelectors);

                addFeaturesToInvalidationSet(*invalidationSet, *siblingFeatures);
                if (siblingFeatures == &descendantFeatures)
                    siblingInvalidationSet->descendants().setInvalidatesSelf();
                else
                    addFeaturesToInvalidationSet(siblingInvalidationSet->descendants(), descendantFeatures);
            } else {
                addFeaturesToInvalidationSet(*invalidationSet, descendantFeatures);
            }
        } else {
            if (current->isHostPseudoClass())
                descendantFeatures.treeBoundaryCrossing = true;
            if (current->isInsertionPointCrossing())
                descendantFeatures.insertionPointCrossing = true;
            if (const CSSSelectorList* selectorList = current->selectorList()) {
                ASSERT(supportsInvalidationWithSelectorList(current->pseudoType()));
                for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector))
                    addFeaturesToInvalidationSets(subSelector, siblingFeatures, descendantFeatures);
            }
        }

        if (current->relation() == CSSSelector::SubSelector)
            continue;

        if (current->isShadowSelector())
            descendantFeatures.treeBoundaryCrossing = true;

        if (!current->isAdjacentSelector()) {
            lastCompoundSelectorInAdjacentChain = current->tagHistory();
            siblingFeatures = nullptr;
            continue;
        }

        if (siblingFeatures) {
            if (siblingFeatures->maxDirectAdjacentSelectors == UINT_MAX)
                continue;

            if (current->relation() == CSSSelector::DirectAdjacent)
                siblingFeatures->maxDirectAdjacentSelectors++;
            else
                siblingFeatures->maxDirectAdjacentSelectors = UINT_MAX;
            continue;
        }

        localFeatures = InvalidationSetFeatures();
        auto result = extractInvalidationSetFeatures(*lastCompoundSelectorInAdjacentChain, localFeatures, Ancestor);
        ASSERT(result.first);
        localFeatures.forceSubtree = result.second == ForceSubtree;
        siblingFeatures = &localFeatures;
    }
}