Esempio n. 1
0
RenderStyle* SharedStyleFinder::findSharedStyle()
{
    INCREMENT_STYLE_STATS_COUNTER(m_styleResolver, sharedStyleLookups);

    if (!element().supportsStyleSharing())
        return 0;

    if (attributesAffectedByRules(element())) {
        INCREMENT_STYLE_STATS_COUNTER(m_styleResolver, sharedStyleRejectedByAttributeRules);
        return 0;
    }

    // Cache whether context.element() is affected by any known class selectors.
    m_elementAffectedByClassRules = element().hasClass() && classNamesAffectedByRules(element());
    m_renderingParent = NodeRenderingTraversal::parent(&element());

    Element* shareElement = findElementForStyleSharing();

    if (!shareElement) {
        if (m_styleResolver.stats() && m_styleResolver.stats()->printMissedCandidateCount && documentContainsValidCandidate())
            INCREMENT_STYLE_STATS_COUNTER(m_styleResolver, sharedStyleMissed);
        return 0;
    }

    INCREMENT_STYLE_STATS_COUNTER(m_styleResolver, sharedStyleFound);

    return shareElement->renderStyle();
}
void ElementRuleCollector::collectMatchingRulesForList(const RuleDataListType* rules, CascadeOrder cascadeOrder, const MatchRequest& matchRequest)
{
    if (!rules)
        return;

    SelectorChecker::Init init;
    init.mode = m_mode;
    init.isUARule = m_matchingUARules;
    init.elementStyle = m_style.get();
    init.scrollbar = m_pseudoStyleRequest.scrollbar;
    init.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
    SelectorChecker checker(init);
    SelectorChecker::SelectorCheckingContext context(m_context.element(), SelectorChecker::VisitedMatchEnabled);
    context.scope = matchRequest.scope;
    context.pseudoId = m_pseudoStyleRequest.pseudoId;

    unsigned rejected = 0;
    unsigned fastRejected = 0;
    unsigned matched = 0;

    for (const auto& ruleData : *rules) {
        if (m_canUseFastReject && m_selectorFilter.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes())) {
            fastRejected++;
            continue;
        }

        // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
        if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin())
            continue;

        StyleRule* rule = ruleData.rule();

        // If the rule has no properties to apply, then ignore it in the non-debug mode.
        const StylePropertySet& properties = rule->properties();
        if (properties.isEmpty() && !m_includeEmptyRules)
            continue;

        SelectorChecker::MatchResult result;
        context.selector = &ruleData.selector();
        if (!checker.match(context, result)) {
            rejected++;
            continue;
        }
        if (m_pseudoStyleRequest.pseudoId != PseudoIdNone && m_pseudoStyleRequest.pseudoId != result.dynamicPseudo) {
            rejected++;
            continue;
        }

        matched++;
        didMatchRule(ruleData, result, cascadeOrder, matchRequest);
    }

    StyleEngine& styleEngine = m_context.element()->document().styleEngine();
    if (!styleEngine.stats())
        return;

    INCREMENT_STYLE_STATS_COUNTER(styleEngine, rulesRejected, rejected);
    INCREMENT_STYLE_STATS_COUNTER(styleEngine, rulesFastRejected, fastRejected);
    INCREMENT_STYLE_STATS_COUNTER(styleEngine, rulesMatched, matched);
}
Esempio n. 3
0
void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult)
{
    const Element* element = state.element();
    ASSERT(element);

    INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply);

    unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
    bool applyInheritedOnly = false;
    const CachedMatchedProperties* cachedMatchedProperties = cacheHash ? m_matchedPropertiesCache.find(cacheHash, state, matchResult) : 0;

    if (cachedMatchedProperties && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
        INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit);
        // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
        // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
        // element context. This is fast and saves memory by reusing the style data structures.
        state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get());
        if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) &&
            (state.style()->userModify() == READ_ONLY)) {
            INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit);

            // If the cache item parent style has identical inherited properties to the current parent style then the
            // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
            state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get());

            return;
        }
        applyInheritedOnly = true;
    }

    state.setLineHeightValue(0);
    applyMatchedProperties<HighPriorityProperties>(state, matchResult, applyInheritedOnly);

    // If our font got dirtied, go ahead and update it now.
    updateFont(state);

    // Line-height is set when we are sure we decided on the font-size.
    if (state.lineHeightValue())
        StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());

    // Many properties depend on the font. If it changes we just apply all properties.
    if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription())
        applyInheritedOnly = false;

    applyMatchedProperties<LowPriorityProperties>(state, matchResult, applyInheritedOnly);

    if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
        INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded);
        m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult);
    }

    ASSERT(!state.fontBuilder().fontDirty());
}
Esempio n. 4
0
void StyleResolver::addToStyleSharingList(Element& element)
{
    // Never add elements to the style sharing list if we're not in a recalcStyle,
    // otherwise we could leave stale pointers in there.
    if (!m_document.inStyleRecalc())
        return;
    ASSERT(element.supportsStyleSharing());
    INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates);
    StyleSharingList& list = styleSharingList();
    if (list.size() >= styleSharingListSize)
        list.removeLast();
    list.prepend(&element);
}