/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
 * All rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/css/resolver/StyleResolver.h"

#include "core/CSSPropertyNames.h"
#include "core/HTMLNames.h"
#include "core/MediaTypeNames.h"
#include "core/StylePropertyShorthand.h"
#include "core/animation/AnimationTimeline.h"
#include "core/animation/ElementAnimations.h"
#include "core/animation/InterpolationEnvironment.h"
#include "core/animation/InvalidatableInterpolation.h"
#include "core/animation/KeyframeEffect.h"
#include "core/animation/StyleInterpolation.h"
#include "core/animation/animatable/AnimatableValue.h"
#include "core/animation/css/CSSAnimatableValueFactory.h"
#include "core/animation/css/CSSAnimations.h"
#include "core/css/CSSCalculationValue.h"
#include "core/css/CSSCustomIdentValue.h"
#include "core/css/CSSDefaultStyleSheets.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/CSSIdentifierValue.h"
#include "core/css/CSSKeyframeRule.h"
#include "core/css/CSSKeyframesRule.h"
#include "core/css/CSSReflectValue.h"
#include "core/css/CSSRuleList.h"
#include "core/css/CSSSelector.h"
#include "core/css/CSSStyleRule.h"
#include "core/css/CSSValueList.h"
#include "core/css/ElementRuleCollector.h"
#include "core/css/FontFace.h"
#include "core/css/MediaQueryEvaluator.h"
#include "core/css/PageRuleCollector.h"
#include "core/css/StylePropertySet.h"
#include "core/css/StyleRuleImport.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/resolver/AnimatedStyleBuilder.h"
#include "core/css/resolver/CSSVariableResolver.h"
#include "core/css/resolver/MatchResult.h"
#include "core/css/resolver/MediaQueryResult.h"
#include "core/css/resolver/ScopedStyleResolver.h"
#include "core/css/resolver/SelectorFilterParentScope.h"
#include "core/css/resolver/SharedStyleFinder.h"
#include "core/css/resolver/StyleAdjuster.h"
#include "core/css/resolver/StyleResolverState.h"
#include "core/css/resolver/StyleResolverStats.h"
#include "core/css/resolver/ViewportStyleResolver.h"
#include "core/dom/CSSSelectorWatch.h"
#include "core/dom/FirstLetterPseudoElement.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLSlotElement.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/layout/GeneratedChildren.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/style/StyleInheritedVariables.h"
#include "core/svg/SVGDocumentExtensions.h"
#include "core/svg/SVGElement.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "wtf/StdLibExtras.h"

namespace {

using namespace blink;

void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) {
  // If any changes to CSS Animations were detected, stash the update away for
  // application after the layout object is updated if we're in the appropriate
  // scope.
  if (!state.animationUpdate().isEmpty())
    element.ensureElementAnimations().cssAnimations().setPendingUpdate(
        state.animationUpdate());
}

// Returns whether any @apply rule sets a custom property
bool cacheCustomPropertiesForApplyAtRules(StyleResolverState& state,
                                          const MatchedPropertiesRange& range) {
  bool ruleSetsCustomProperty = false;
  // TODO(timloh): @apply should also work with properties registered as
  // non-inherited.
  if (!state.style()->inheritedVariables())
    return false;
  for (const auto& matchedProperties : range) {
    const StylePropertySet& properties = *matchedProperties.properties;
    unsigned propertyCount = properties.propertyCount();
    for (unsigned i = 0; i < propertyCount; ++i) {
      StylePropertySet::PropertyReference current = properties.propertyAt(i);
      if (current.id() != CSSPropertyApplyAtRule)
        continue;
      AtomicString name(toCSSCustomIdentValue(current.value()).value());
      CSSVariableData* variableData =
          state.style()->inheritedVariables()->getVariable(name);
      if (!variableData)
        continue;
      StylePropertySet* customPropertySet = variableData->propertySet();
      if (!customPropertySet)
        continue;
      if (customPropertySet->findPropertyIndex(CSSPropertyVariable) != -1)
        ruleSetsCustomProperty = true;
      state.setCustomPropertySetForApplyAtRule(name, customPropertySet);
    }
  }
  return ruleSetsCustomProperty;
}

}  // namespace

namespace blink {

using namespace HTMLNames;

ComputedStyle* StyleResolver::s_styleNotYetAvailable;

static StylePropertySet* leftToRightDeclaration() {
  DEFINE_STATIC_LOCAL(MutableStylePropertySet, leftToRightDecl,
                      (MutableStylePropertySet::create(HTMLQuirksMode)));
  if (leftToRightDecl.isEmpty())
    leftToRightDecl.setProperty(CSSPropertyDirection, CSSValueLtr);
  return &leftToRightDecl;
}

static StylePropertySet* rightToLeftDeclaration() {
  DEFINE_STATIC_LOCAL(MutableStylePropertySet, rightToLeftDecl,
                      (MutableStylePropertySet::create(HTMLQuirksMode)));
  if (rightToLeftDecl.isEmpty())
    rightToLeftDecl.setProperty(CSSPropertyDirection, CSSValueRtl);
  return &rightToLeftDecl;
}

static void collectScopedResolversForHostedShadowTrees(
    const Element& element,
    HeapVector<Member<ScopedStyleResolver>, 8>& resolvers) {
  ElementShadow* shadow = element.shadow();
  if (!shadow)
    return;

  // Adding scoped resolver for active shadow roots for shadow host styling.
  for (ShadowRoot* shadowRoot = &shadow->youngestShadowRoot(); shadowRoot;
       shadowRoot = shadowRoot->olderShadowRoot()) {
    if (shadowRoot->numberOfStyles() > 0) {
      if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver())
        resolvers.append(resolver);
    }
  }
}

StyleResolver::StyleResolver(Document& document)
    : m_document(document),
      m_viewportStyleResolver(ViewportStyleResolver::create(&document)),
      m_needCollectFeatures(false),
      m_printMediaType(false),
      m_styleSharingDepth(0) {
  FrameView* view = document.view();
  if (view) {
    m_medium = new MediaQueryEvaluator(&view->frame());
    m_printMediaType =
        equalIgnoringCase(view->mediaType(), MediaTypeNames::print);
  } else {
    m_medium = new MediaQueryEvaluator("all");
  }

  initWatchedSelectorRules();
}

StyleResolver::~StyleResolver() {}

void StyleResolver::dispose() {
  m_matchedPropertiesCache.clear();
}

void StyleResolver::initWatchedSelectorRules() {
  m_watchedSelectorsRules = nullptr;
  CSSSelectorWatch* watch = CSSSelectorWatch::fromIfExists(*m_document);
  if (!watch)
    return;
  const HeapVector<Member<StyleRule>>& watchedSelectors =
      watch->watchedCallbackSelectors();
  if (!watchedSelectors.size())
    return;
  m_watchedSelectorsRules = RuleSet::create();
  for (unsigned i = 0; i < watchedSelectors.size(); ++i)
    m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(),
                                          RuleHasNoSpecialState);
}

void StyleResolver::lazyAppendAuthorStyleSheets(
    unsigned firstNew,
    const HeapVector<Member<CSSStyleSheet>>& styleSheets) {
  unsigned size = styleSheets.size();
  for (unsigned i = firstNew; i < size; ++i)
    m_pendingStyleSheets.add(styleSheets[i].get());
}

void StyleResolver::removePendingAuthorStyleSheets(
    const HeapVector<Member<CSSStyleSheet>>& styleSheets) {
  for (unsigned i = 0; i < styleSheets.size(); ++i)
    m_pendingStyleSheets.remove(styleSheets[i].get());
}

void StyleResolver::appendCSSStyleSheet(CSSStyleSheet& cssSheet) {
  DCHECK(!cssSheet.disabled());
  DCHECK(cssSheet.ownerDocument());
  DCHECK(cssSheet.ownerNode());
  DCHECK(isHTMLStyleElement(cssSheet.ownerNode()) ||
         isSVGStyleElement(cssSheet.ownerNode()) ||
         cssSheet.ownerNode()->isConnected());

  if (cssSheet.mediaQueries() &&
      !m_medium->eval(cssSheet.mediaQueries(),
                      &m_viewportDependentMediaQueryResults,
                      &m_deviceDependentMediaQueryResults))
    return;

  TreeScope* treeScope = &cssSheet.ownerNode()->treeScope();
  // TODO(rune@opera.com): This is a workaround for crbug.com/559292
  // when we're in the middle of removing a subtree with a style element
  // and the treescope has been changed but inDocument and isInShadowTree
  // are not.
  //
  // This check can be removed when crbug.com/567021 is fixed.
  if (cssSheet.ownerNode()->isInShadowTree() &&
      treeScope->rootNode().isDocumentNode())
    return;

  // Sheets in the document scope of HTML imports apply to the main document
  // (m_document), so we override it for all document scoped sheets.
  if (treeScope->rootNode().isDocumentNode())
    treeScope = m_document;
  treeScope->ensureScopedStyleResolver().appendCSSStyleSheet(cssSheet,
                                                             *m_medium);
}

void StyleResolver::appendPendingAuthorStyleSheets() {
  for (const auto& styleSheet : m_pendingStyleSheets)
    appendCSSStyleSheet(*styleSheet);

  m_pendingStyleSheets.clear();
  finishAppendAuthorStyleSheets();
}

void StyleResolver::appendAuthorStyleSheets(
    const HeapVector<Member<CSSStyleSheet>>& styleSheets) {
  // This handles sheets added to the end of the stylesheet list only. In other
  // cases the style resolver needs to be reconstructed. To handle insertions
  // too the rule order numbers would need to be updated.
  for (const auto& styleSheet : styleSheets)
    appendCSSStyleSheet(*styleSheet);
}

void StyleResolver::finishAppendAuthorStyleSheets() {
  collectFeatures();

  if (!document().layoutViewItem().isNull() &&
      document().layoutViewItem().style())
    document().layoutViewItem().style()->font().update(
        document().styleEngine().fontSelector());

  m_viewportStyleResolver->collectViewportRules();

  document().styleEngine().resetCSSFeatureFlags(m_features);
}

void StyleResolver::resetRuleFeatures() {
  // Need to recreate RuleFeatureSet.
  m_features.clear();
  m_siblingRuleSet.clear();
  m_uncommonAttributeRuleSet.clear();
  m_needCollectFeatures = true;
}

void StyleResolver::addTreeBoundaryCrossingScope(ContainerNode& scope) {
  m_treeBoundaryCrossingScopes.add(&scope);
}

void StyleResolver::resetAuthorStyle(TreeScope& treeScope) {
  m_treeBoundaryCrossingScopes.remove(&treeScope.rootNode());

  ScopedStyleResolver* resolver = treeScope.scopedStyleResolver();
  if (!resolver)
    return;

  resetRuleFeatures();

  if (treeScope.rootNode().isDocumentNode()) {
    resolver->resetAuthorStyle();
    return;
  }

  // resolver is going to be freed below.
  treeScope.clearScopedStyleResolver();
}

static RuleSet* makeRuleSet(const HeapVector<RuleFeature>& rules) {
  size_t size = rules.size();
  if (!size)
    return nullptr;
  RuleSet* ruleSet = RuleSet::create();
  for (size_t i = 0; i < size; ++i)
    ruleSet->addRule(rules[i].rule, rules[i].selectorIndex,
                     rules[i].hasDocumentSecurityOrigin
                         ? RuleHasDocumentSecurityOrigin
                         : RuleHasNoSpecialState);
  return ruleSet;
}

void StyleResolver::collectFeatures() {
  m_features.clear();
  // Collect all ids and rules using sibling selectors (:first-child and
  // similar) in the current set of stylesheets. Style sharing code uses this
  // information to reject sharing candidates.
  CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
  if (defaultStyleSheets.defaultStyle()) {
    m_features.add(defaultStyleSheets.defaultStyle()->features());
    m_hasFullscreenUAStyle = defaultStyleSheets.fullscreenStyleSheet();
  }

  if (document().isViewSource())
    m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features());

  if (m_watchedSelectorsRules)
    m_features.add(m_watchedSelectorsRules->features());

  document().styleEngine().collectScopedStyleFeaturesTo(m_features);

  m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
  m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
  m_needCollectFeatures = false;
}

bool StyleResolver::hasRulesForId(const AtomicString& id) const {
  return m_features.hasSelectorForId(id);
}

void StyleResolver::addToStyleSharingList(Element& element) {
  ASSERT(RuntimeEnabledFeatures::styleSharingEnabled());
  // Never add elements to the style sharing list if we're not in a recalcStyle,
  // otherwise we could leave stale pointers in there.
  if (!document().inStyleRecalc())
    return;
  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), sharedStyleCandidates,
                                1);
  StyleSharingList& list = styleSharingList();
  if (list.size() >= styleSharingListSize)
    list.removeLast();
  list.prepend(&element);
}

StyleSharingList& StyleResolver::styleSharingList() {
  m_styleSharingLists.resize(styleSharingMaxDepth);

  // We never put things at depth 0 into the list since that's only the <html>
  // element and it has no siblings or cousins to share with.
  unsigned depth =
      std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u;

  if (!m_styleSharingLists[depth])
    m_styleSharingLists[depth] = new StyleSharingList;
  return *m_styleSharingLists[depth];
}

void StyleResolver::clearStyleSharingList() {
  m_styleSharingLists.resize(0);
}

static inline ScopedStyleResolver* scopedResolverFor(const Element& element) {
  // Ideally, returning element->treeScope().scopedStyleResolver() should be
  // enough, but ::cue and custom pseudo elements like ::-webkit-meter-bar
  // pierce through a shadow dom boundary, yet they are not part of
  // m_treeBoundaryCrossingScopes.  The assumption here is that these rules only
  // pierce through one boundary and that the scope of these elements do not
  // have a style resolver due to the fact that VTT scopes and UA shadow trees
  // don't have <style> elements. This is backed up by the ASSERTs below.
  //
  // FIXME: Make ::cue and custom pseudo elements part of boundary crossing
  // rules when moving those rules to ScopedStyleResolver as part of issue
  // 401359.

  TreeScope* treeScope = &element.treeScope();
  if (ScopedStyleResolver* resolver = treeScope->scopedStyleResolver()) {
    ASSERT(element.shadowPseudoId().isEmpty());
    ASSERT(!element.isVTTElement());
    return resolver;
  }

  treeScope = treeScope->parentTreeScope();
  if (!treeScope)
    return nullptr;
  if (element.shadowPseudoId().isEmpty() && !element.isVTTElement())
    return nullptr;
  return treeScope->scopedStyleResolver();
}

static void matchHostRules(const Element& element,
                           ElementRuleCollector& collector) {
  ElementShadow* shadow = element.shadow();
  if (!shadow)
    return;

  for (ShadowRoot* shadowRoot = &shadow->oldestShadowRoot(); shadowRoot;
       shadowRoot = shadowRoot->youngerShadowRoot()) {
    if (!shadowRoot->numberOfStyles())
      continue;
    if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver()) {
      collector.clearMatchedRules();
      resolver->collectMatchingShadowHostRules(collector);
      collector.sortAndTransferMatchedRules();
      collector.finishAddingAuthorRulesForTreeScope();
    }
  }
}

static void matchSlottedRules(const Element& element,
                              ElementRuleCollector& collector) {
  HTMLSlotElement* slot = element.assignedSlot();
  if (!slot)
    return;

  HeapVector<Member<ScopedStyleResolver>> resolvers;
  for (; slot; slot = slot->assignedSlot()) {
    if (ScopedStyleResolver* resolver = slot->treeScope().scopedStyleResolver())
      resolvers.append(resolver);
  }
  for (auto it = resolvers.rbegin(); it != resolvers.rend(); ++it) {
    collector.clearMatchedRules();
    (*it)->collectMatchingTreeBoundaryCrossingRules(collector);
    collector.sortAndTransferMatchedRules();
    collector.finishAddingAuthorRulesForTreeScope();
  }
}

static void matchElementScopeRules(const Element& element,
                                   ScopedStyleResolver* elementScopeResolver,
                                   ElementRuleCollector& collector) {
  if (elementScopeResolver) {
    collector.clearMatchedRules();
    elementScopeResolver->collectMatchingAuthorRules(collector);
    elementScopeResolver->collectMatchingTreeBoundaryCrossingRules(collector);
    collector.sortAndTransferMatchedRules();
  }

  if (element.isStyledElement() && element.inlineStyle() &&
      !collector.isCollectingForPseudoElement()) {
    // Inline style is immutable as long as there is no CSSOM wrapper.
    bool isInlineStyleCacheable = !element.inlineStyle()->isMutable();
    collector.addElementStyleProperties(element.inlineStyle(),
                                        isInlineStyleCacheable);
  }

  collector.finishAddingAuthorRulesForTreeScope();
}

static bool shouldCheckScope(const Element& element,
                             const Node& scopingNode,
                             bool isInnerTreeScope) {
  if (isInnerTreeScope && element.treeScope() != scopingNode.treeScope()) {
    // Check if |element| may be affected by a ::content rule in |scopingNode|'s
    // style.  If |element| is a descendant of a shadow host which is ancestral
    // to |scopingNode|, the |element| should be included for rule collection.
    // Skip otherwise.
    const TreeScope* scope = &scopingNode.treeScope();
    while (scope && scope->parentTreeScope() != &element.treeScope())
      scope = scope->parentTreeScope();
    Element* shadowHost = scope ? scope->rootNode().ownerShadowHost() : nullptr;
    return shadowHost && element.isDescendantOf(shadowHost);
  }

  // When |element| can be distributed to |scopingNode| via <shadow>, ::content
  // rule can match, thus the case should be included.
  if (!isInnerTreeScope &&
      scopingNode.parentOrShadowHostNode() ==
          element.treeScope().rootNode().parentOrShadowHostNode())
    return true;

  // Obviously cases when ancestor scope has /deep/ or ::shadow rule should be
  // included.  Skip otherwise.
  return scopingNode.treeScope()
      .scopedStyleResolver()
      ->hasDeepOrShadowSelector();
}

void StyleResolver::matchScopedRules(const Element& element,
                                     ElementRuleCollector& collector) {
  // Match rules from treeScopes in the reverse tree-of-trees order, since the
  // cascading order for normal rules is such that when comparing rules from
  // different shadow trees, the rule from the tree which comes first in the
  // tree-of-trees order wins. From other treeScopes than the element's own
  // scope, only tree-boundary-crossing rules may match.

  ScopedStyleResolver* elementScopeResolver = scopedResolverFor(element);

  if (!document().mayContainV0Shadow()) {
    matchSlottedRules(element, collector);
    matchElementScopeRules(element, elementScopeResolver, collector);
    return;
  }

  bool matchElementScopeDone = !elementScopeResolver && !element.inlineStyle();

  for (auto it = m_treeBoundaryCrossingScopes.rbegin();
       it != m_treeBoundaryCrossingScopes.rend(); ++it) {
    const TreeScope& scope = (*it)->containingTreeScope();
    ScopedStyleResolver* resolver = scope.scopedStyleResolver();
    ASSERT(resolver);

    bool isInnerTreeScope =
        element.containingTreeScope().isInclusiveAncestorOf(scope);
    if (!shouldCheckScope(element, **it, isInnerTreeScope))
      continue;

    if (!matchElementScopeDone &&
        scope.isInclusiveAncestorOf(element.containingTreeScope())) {
      matchElementScopeDone = true;

      // At this point, the iterator has either encountered the scope for the
      // element itself (if that scope has boundary-crossing rules), or the
      // iterator has moved to a scope which appears before the element's scope
      // in the tree-of-trees order.  Try to match all rules from the element's
      // scope.

      matchElementScopeRules(element, elementScopeResolver, collector);
      if (resolver == elementScopeResolver) {
        // Boundary-crossing rules already collected in matchElementScopeRules.
        continue;
      }
    }

    collector.clearMatchedRules();
    resolver->collectMatchingTreeBoundaryCrossingRules(collector);
    collector.sortAndTransferMatchedRules();
    collector.finishAddingAuthorRulesForTreeScope();
  }

  if (!matchElementScopeDone)
    matchElementScopeRules(element, elementScopeResolver, collector);
}

void StyleResolver::matchAuthorRules(const Element& element,
                                     ElementRuleCollector& collector) {
  if (document().shadowCascadeOrder() != ShadowCascadeOrder::ShadowCascadeV1) {
    matchAuthorRulesV0(element, collector);
    return;
  }

  ASSERT(RuntimeEnabledFeatures::shadowDOMV1Enabled());
  matchHostRules(element, collector);
  matchScopedRules(element, collector);
}

void StyleResolver::matchAuthorRulesV0(const Element& element,
                                       ElementRuleCollector& collector) {
  collector.clearMatchedRules();

  CascadeOrder cascadeOrder = 0;
  HeapVector<Member<ScopedStyleResolver>, 8> resolversInShadowTree;
  collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree);

  // Apply :host and :host-context rules from inner scopes.
  for (int j = resolversInShadowTree.size() - 1; j >= 0; --j)
    resolversInShadowTree.at(j)->collectMatchingShadowHostRules(collector,
                                                                ++cascadeOrder);

  // Apply normal rules from element scope.
  if (ScopedStyleResolver* resolver = scopedResolverFor(element))
    resolver->collectMatchingAuthorRules(collector, ++cascadeOrder);

  // Apply /deep/ and ::shadow rules from outer scopes, and ::content from
  // inner.
  collectTreeBoundaryCrossingRules(element, collector);
  collector.sortAndTransferMatchedRules();
}

void StyleResolver::matchUARules(ElementRuleCollector& collector) {
  collector.setMatchingUARules(true);

  CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
  RuleSet* userAgentStyleSheet = m_printMediaType
                                     ? defaultStyleSheets.defaultPrintStyle()
                                     : defaultStyleSheets.defaultStyle();
  matchRuleSet(collector, userAgentStyleSheet);

  // In quirks mode, we match rules from the quirks user agent sheet.
  if (document().inQuirksMode())
    matchRuleSet(collector, defaultStyleSheets.defaultQuirksStyle());

  // If document uses view source styles (in view source mode or in xml viewer
  // mode), then we match rules from the view source style sheet.
  if (document().isViewSource())
    matchRuleSet(collector, defaultStyleSheets.defaultViewSourceStyle());

  collector.finishAddingUARules();
  collector.setMatchingUARules(false);
}

void StyleResolver::matchRuleSet(ElementRuleCollector& collector,
                                 RuleSet* rules) {
  collector.clearMatchedRules();
  collector.collectMatchingRules(MatchRequest(rules));
  collector.sortAndTransferMatchedRules();
}

void StyleResolver::matchAllRules(StyleResolverState& state,
                                  ElementRuleCollector& collector,
                                  bool includeSMILProperties) {
  matchUARules(collector);

  // Now check author rules, beginning first with presentational attributes
  // mapped from HTML.
  if (state.element()->isStyledElement()) {
    collector.addElementStyleProperties(
        state.element()->presentationAttributeStyle());

    // Now we check additional mapped declarations.
    // Tables and table cells share an additional mapped rule that must be
    // applied after all attributes, since their mapped style depends on the
    // values of multiple attributes.
    collector.addElementStyleProperties(
        state.element()->additionalPresentationAttributeStyle());

    if (state.element()->isHTMLElement()) {
      bool isAuto;
      TextDirection textDirection =
          toHTMLElement(state.element())
              ->directionalityIfhasDirAutoAttribute(isAuto);
      if (isAuto) {
        state.setHasDirAutoAttribute(true);
        collector.addElementStyleProperties(textDirection == LTR
                                                ? leftToRightDeclaration()
                                                : rightToLeftDeclaration());
      }
    }
  }

  matchAuthorRules(*state.element(), collector);

  if (state.element()->isStyledElement()) {
    // For Shadow DOM V1, inline style is already collected in
    // matchScopedRules().
    if (document().shadowCascadeOrder() !=
            ShadowCascadeOrder::ShadowCascadeV1 &&
        state.element()->inlineStyle()) {
      // Inline style is immutable as long as there is no CSSOM wrapper.
      bool isInlineStyleCacheable =
          !state.element()->inlineStyle()->isMutable();
      collector.addElementStyleProperties(state.element()->inlineStyle(),
                                          isInlineStyleCacheable);
    }

    // Now check SMIL animation override style.
    if (includeSMILProperties && state.element()->isSVGElement())
      collector.addElementStyleProperties(
          toSVGElement(state.element())->animatedSMILStyleProperties(),
          false /* isCacheable */);
  }

  collector.finishAddingAuthorRulesForTreeScope();
}

void StyleResolver::collectTreeBoundaryCrossingRules(
    const Element& element,
    ElementRuleCollector& collector) {
  if (m_treeBoundaryCrossingScopes.isEmpty())
    return;

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

  for (const auto& scopingNode : m_treeBoundaryCrossingScopes) {
    // Skip rule collection for element when tree boundary crossing rules of
    // scopingNode's scope can never apply to it.
    bool isInnerTreeScope = element.containingTreeScope().isInclusiveAncestorOf(
        scopingNode->containingTreeScope());
    if (!shouldCheckScope(element, *scopingNode, isInnerTreeScope))
      continue;

    CascadeOrder cascadeOrder =
        isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder;
    scopingNode->treeScope()
        .scopedStyleResolver()
        ->collectMatchingTreeBoundaryCrossingRules(collector, cascadeOrder);

    ++innerCascadeOrder;
    --outerCascadeOrder;
  }
}

PassRefPtr<ComputedStyle> StyleResolver::styleForDocument(Document& document) {
  const LocalFrame* frame = document.frame();

  RefPtr<ComputedStyle> documentStyle = ComputedStyle::create();
  documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder
                                                           : LogicalOrder);
  documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor()
                                                       : 1);
  FontDescription documentFontDescription = documentStyle->getFontDescription();
  documentFontDescription.setLocale(
      LayoutLocale::get(document.contentLanguage()));
  documentStyle->setFontDescription(documentFontDescription);
  documentStyle->setZIndex(0);
  documentStyle->setIsStackingContext(true);
  documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE
                                                       : READ_ONLY);
  // These are designed to match the user-agent stylesheet values for the
  // document element so that the common case doesn't need to create a new
  // ComputedStyle in Document::inheritHtmlAndBodyElementStyles.
  documentStyle->setDisplay(EDisplay::Block);
  documentStyle->setPosition(AbsolutePosition);

  document.setupFontBuilder(*documentStyle);

  return documentStyle.release();
}

void StyleResolver::adjustComputedStyle(StyleResolverState& state,
                                        Element* element) {
  StyleAdjuster::adjustComputedStyle(state.mutableStyleRef(),
                                     *state.parentStyle(), element);
}

// Start loading resources referenced by this style.
void StyleResolver::loadPendingResources(StyleResolverState& state) {
  state.elementStyleResources().loadPendingResources(state.style());
}

PassRefPtr<ComputedStyle> StyleResolver::styleForElement(
    Element* element,
    const ComputedStyle* defaultParent,
    StyleSharingBehavior sharingBehavior,
    RuleMatchingBehavior matchingBehavior) {
  DCHECK(document().frame());
  ASSERT(document().settings());
  ASSERT(!hasPendingAuthorStyleSheets());
  ASSERT(!m_needCollectFeatures);

  // Once an element has a layoutObject, we don't try to destroy it, since
  // otherwise the layoutObject will vanish if a style recalc happens during
  // loading.
  if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() &&
      !element->layoutObject()) {
    if (!s_styleNotYetAvailable) {
      s_styleNotYetAvailable = ComputedStyle::create().leakRef();
      s_styleNotYetAvailable->setDisplay(EDisplay::None);
      s_styleNotYetAvailable->font().update(
          document().styleEngine().fontSelector());
    }

    document().setHasNodesWithPlaceholderStyle();
    return s_styleNotYetAvailable;
  }

  document().styleEngine().incStyleForElementCount();
  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), elementsStyled, 1);

  SelectorFilterParentScope::ensureParentStackIsPushed();

  ElementResolveContext elementContext(*element);

  if (RuntimeEnabledFeatures::styleSharingEnabled() &&
      sharingBehavior == AllowStyleSharing &&
      (defaultParent || elementContext.parentStyle())) {
    SharedStyleFinder styleFinder(elementContext, m_features,
                                  m_siblingRuleSet.get(),
                                  m_uncommonAttributeRuleSet.get(), *this);
    if (RefPtr<ComputedStyle> sharedStyle = styleFinder.findSharedStyle())
      return sharedStyle.release();
  }

  StyleResolverState state(document(), elementContext, defaultParent);

  ElementAnimations* elementAnimations = element->elementAnimations();
  const ComputedStyle* baseComputedStyle =
      elementAnimations ? elementAnimations->baseComputedStyle() : nullptr;

  if (baseComputedStyle) {
    state.setStyle(ComputedStyle::clone(*baseComputedStyle));
    if (!state.parentStyle())
      state.setParentStyle(initialStyleForElement());
  } else {
    if (state.parentStyle()) {
      RefPtr<ComputedStyle> style = ComputedStyle::create();
      style->inheritFrom(*state.parentStyle(),
                         isAtShadowBoundary(element)
                             ? ComputedStyleBase::AtShadowBoundary
                             : ComputedStyleBase::NotAtShadowBoundary);
      state.setStyle(style.release());
    } else {
      state.setStyle(initialStyleForElement());
      state.setParentStyle(ComputedStyle::clone(*state.style()));
    }
  }

  // contenteditable attribute (implemented by -webkit-user-modify) should
  // be propagated from shadow host to distributed node.
  if (state.distributedToInsertionPoint()) {
    if (Element* parent = element->parentElement()) {
      if (ComputedStyle* styleOfShadowHost = parent->mutableComputedStyle())
        state.style()->setUserModify(styleOfShadowHost->userModify());
    }
  }

  if (element->isLink()) {
    state.style()->setIsLink(true);
    EInsideLink linkState = state.elementLinkState();
    if (linkState != NotInsideLink) {
      bool forceVisited = InspectorInstrumentation::forcePseudoState(
          element, CSSSelector::PseudoVisited);
      if (forceVisited)
        linkState = InsideVisitedLink;
    }
    state.style()->setInsideLink(linkState);
  }

  if (!baseComputedStyle) {
    bool needsCollection = false;
    CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(
        *element, needsCollection);
    if (needsCollection)
      collectFeatures();

    ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                   state.style());

    matchAllRules(state, collector,
                  matchingBehavior != MatchAllRulesExcludingSMIL);

    // TODO(dominicc): Remove this counter when Issue 590014 is fixed.
    if (element->hasTagName(HTMLNames::summaryTag)) {
      MatchedPropertiesRange properties =
          collector.matchedResult().authorRules();
      for (auto it = properties.begin(); it != properties.end(); ++it) {
        const CSSValue* value =
            it->properties->getPropertyCSSValue(CSSPropertyDisplay);
        if (value && value->isIdentifierValue() &&
            toCSSIdentifierValue(*value).getValueID() == CSSValueBlock)
          UseCounter::count(
              element->document(),
              UseCounter::SummaryElementWithDisplayBlockAuthorRule);
      }
    }

    if (element->computedStyle() &&
        element->computedStyle()->textAutosizingMultiplier() !=
            state.style()->textAutosizingMultiplier()) {
      // Preserve the text autosizing multiplier on style recalc. Autosizer will
      // update it during layout if needed.
      // NOTE: this must occur before applyMatchedProperties for correct
      // computation of font-relative lengths.
      state.style()->setTextAutosizingMultiplier(
          element->computedStyle()->textAutosizingMultiplier());
      state.style()->setUnique();
    }

    if (state.hasDirAutoAttribute())
      state.style()->setSelfOrAncestorHasDirAutoAttribute(true);

    applyMatchedProperties(state, collector.matchedResult());
    applyCallbackSelectors(state);

    // Cache our original display.
    state.style()->setOriginalDisplay(state.style()->display());

    adjustComputedStyle(state, element);

    if (elementAnimations)
      elementAnimations->updateBaseComputedStyle(state.style());
  } else {
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), baseStylesUsed, 1);
  }

  // FIXME: The CSSWG wants to specify that the effects of animations are
  // applied before important rules, but this currently happens here as we
  // require adjustment to have happened before deciding which properties to
  // transition.
  if (applyAnimatedProperties(state, element)) {
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), stylesAnimated, 1);
    adjustComputedStyle(state, element);
  }

  if (isHTMLBodyElement(*element))
    document().textLinkColors().setTextColor(state.style()->color());

  setAnimationUpdateIfNeeded(state, *element);

  if (state.style()->hasViewportUnits())
    document().setHasViewportUnits();

  if (state.style()->hasRemUnits())
    document().styleEngine().setUsesRemUnit(true);

  // Now return the style.
  return state.takeStyle();
}

// TODO(alancutter): Create compositor keyframe values directly instead of
// intermediate AnimatableValues.
PassRefPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(
    Element& element,
    const ComputedStyle& baseStyle,
    const ComputedStyle* parentStyle,
    CSSPropertyID property,
    const CSSValue* value) {
  // TODO(alancutter): Avoid creating a StyleResolverState just to apply a
  // single value on a ComputedStyle.
  StyleResolverState state(element.document(), &element, parentStyle);
  state.setStyle(ComputedStyle::clone(baseStyle));
  if (value) {
    StyleBuilder::applyProperty(property, state, *value);
    state.fontBuilder().createFont(
        state.document().styleEngine().fontSelector(), state.mutableStyleRef());
  }
  return CSSAnimatableValueFactory::create(property, *state.style());
}

PseudoElement* StyleResolver::createPseudoElement(Element* parent,
                                                  PseudoId pseudoId) {
  if (pseudoId == PseudoIdFirstLetter)
    return FirstLetterPseudoElement::create(parent);
  return PseudoElement::create(parent, pseudoId);
}

PseudoElement* StyleResolver::createPseudoElementIfNeeded(Element& parent,
                                                          PseudoId pseudoId) {
  LayoutObject* parentLayoutObject = parent.layoutObject();
  if (!parentLayoutObject)
    return nullptr;

  // The first letter pseudo element has to look up the tree and see if any
  // of the ancestors are first letter.
  if (pseudoId < FirstInternalPseudoId && pseudoId != PseudoIdFirstLetter &&
      !parentLayoutObject->style()->hasPseudoStyle(pseudoId))
    return nullptr;

  if (pseudoId == PseudoIdBackdrop && !parent.isInTopLayer())
    return nullptr;

  if (pseudoId == PseudoIdFirstLetter &&
      (parent.isSVGElement() ||
       !FirstLetterPseudoElement::firstLetterTextLayoutObject(parent)))
    return nullptr;

  if (!canHaveGeneratedChildren(*parentLayoutObject))
    return nullptr;

  ComputedStyle* parentStyle = parentLayoutObject->mutableStyle();
  if (ComputedStyle* cachedStyle =
          parentStyle->getCachedPseudoStyle(pseudoId)) {
    if (!pseudoElementLayoutObjectIsNeeded(cachedStyle))
      return nullptr;
    return createPseudoElement(&parent, pseudoId);
  }

  StyleResolverState state(document(), &parent, parentStyle);
  if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state))
    return nullptr;
  RefPtr<ComputedStyle> style = state.takeStyle();
  ASSERT(style);
  parentStyle->addCachedPseudoStyle(style);

  if (!pseudoElementLayoutObjectIsNeeded(style.get()))
    return nullptr;

  PseudoElement* pseudo = createPseudoElement(&parent, pseudoId);

  setAnimationUpdateIfNeeded(state, *pseudo);
  if (ElementAnimations* elementAnimations = pseudo->elementAnimations())
    elementAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo);
  return pseudo;
}

bool StyleResolver::pseudoStyleForElementInternal(
    Element& element,
    const PseudoStyleRequest& pseudoStyleRequest,
    const ComputedStyle* parentStyle,
    StyleResolverState& state) {
  ASSERT(document().frame());
  ASSERT(document().settings());
  ASSERT(pseudoStyleRequest.pseudoId != PseudoIdFirstLineInherited);
  ASSERT(state.parentStyle());

  SelectorFilterParentScope::ensureParentStackIsPushed();

  Element* pseudoElement = element.pseudoElement(pseudoStyleRequest.pseudoId);

  ElementAnimations* elementAnimations =
      pseudoElement ? pseudoElement->elementAnimations() : nullptr;
  const ComputedStyle* baseComputedStyle =
      elementAnimations ? elementAnimations->baseComputedStyle() : nullptr;

  if (baseComputedStyle) {
    state.setStyle(ComputedStyle::clone(*baseComputedStyle));
  } else if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
    RefPtr<ComputedStyle> style = ComputedStyle::create();
    style->inheritFrom(*state.parentStyle());
    state.setStyle(style.release());
  } else {
    state.setStyle(initialStyleForElement());
    state.setParentStyle(ComputedStyle::clone(*state.style()));
  }

  state.style()->setStyleType(pseudoStyleRequest.pseudoId);

  // Since we don't use pseudo-elements in any of our quirk/print
  // user agent rules, don't waste time walking those rules.

  if (!baseComputedStyle) {
    // Check UA, user and author rules.
    ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                   state.style());
    collector.setPseudoStyleRequest(pseudoStyleRequest);

    matchUARules(collector);
    matchAuthorRules(*state.element(), collector);
    collector.finishAddingAuthorRulesForTreeScope();

    if (!collector.matchedResult().hasMatchedProperties())
      return false;

    applyMatchedProperties(state, collector.matchedResult());
    applyCallbackSelectors(state);

    // Cache our original display.
    state.style()->setOriginalDisplay(state.style()->display());

    // FIXME: Passing 0 as the Element* introduces a lot of complexity
    // in the adjustComputedStyle code.
    adjustComputedStyle(state, 0);

    if (elementAnimations)
      elementAnimations->updateBaseComputedStyle(state.style());
  }

  // FIXME: The CSSWG wants to specify that the effects of animations are
  // applied before important rules, but this currently happens here as we
  // require adjustment to have happened before deciding which properties to
  // transition.
  if (applyAnimatedProperties(state, pseudoElement))
    adjustComputedStyle(state, 0);

  document().styleEngine().incStyleForElementCount();
  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), pseudoElementsStyled,
                                1);

  if (state.style()->hasViewportUnits())
    document().setHasViewportUnits();

  return true;
}

PassRefPtr<ComputedStyle> StyleResolver::pseudoStyleForElement(
    Element* element,
    const PseudoStyleRequest& pseudoStyleRequest,
    const ComputedStyle* parentStyle) {
  ASSERT(parentStyle);
  if (!element)
    return nullptr;

  StyleResolverState state(document(), element, parentStyle);
  if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle,
                                     state)) {
    if (pseudoStyleRequest.type == PseudoStyleRequest::ForRenderer)
      return nullptr;
    return state.takeStyle();
  }

  if (PseudoElement* pseudoElement =
          element->pseudoElement(pseudoStyleRequest.pseudoId))
    setAnimationUpdateIfNeeded(state, *pseudoElement);

  // Now return the style.
  return state.takeStyle();
}

PassRefPtr<ComputedStyle> StyleResolver::styleForPage(int pageIndex) {
  ASSERT(!hasPendingAuthorStyleSheets());
  // m_rootElementStyle will be set to the document style.
  StyleResolverState state(document(), document().documentElement());

  RefPtr<ComputedStyle> style = ComputedStyle::create();
  const ComputedStyle* rootElementStyle = state.rootElementStyle()
                                              ? state.rootElementStyle()
                                              : document().computedStyle();
  ASSERT(rootElementStyle);
  style->inheritFrom(*rootElementStyle);
  state.setStyle(style.release());

  PageRuleCollector collector(rootElementStyle, pageIndex);

  collector.matchPageRules(
      CSSDefaultStyleSheets::instance().defaultPrintStyle());

  if (ScopedStyleResolver* scopedResolver = document().scopedStyleResolver())
    scopedResolver->matchPageRules(collector);

  bool inheritedOnly = false;

  const MatchResult& result = collector.matchedResult();
  applyMatchedProperties<HighPropertyPriority>(state, result.allRules(), false,
                                               inheritedOnly);

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

  applyMatchedProperties<LowPropertyPriority>(state, result.allRules(), false,
                                              inheritedOnly);

  loadPendingResources(state);

  // Now return the style.
  return state.takeStyle();
}

PassRefPtr<ComputedStyle> StyleResolver::initialStyleForElement() {
  RefPtr<ComputedStyle> style = ComputedStyle::create();
  FontBuilder fontBuilder(document());
  fontBuilder.setInitial(style->effectiveZoom());
  fontBuilder.createFont(document().styleEngine().fontSelector(), *style);
  return style.release();
}

PassRefPtr<ComputedStyle> StyleResolver::styleForText(Text* textNode) {
  ASSERT(textNode);

  Node* parentNode = LayoutTreeBuilderTraversal::parent(*textNode);
  if (!parentNode || !parentNode->computedStyle())
    return initialStyleForElement();
  return parentNode->mutableComputedStyle();
}

void StyleResolver::updateFont(StyleResolverState& state) {
  state.fontBuilder().createFont(document().styleEngine().fontSelector(),
                                 state.mutableStyleRef());
  state.setConversionFontSizes(CSSToLengthConversionData::FontSizes(
      state.style(), state.rootElementStyle()));
  state.setConversionZoom(state.style()->effectiveZoom());
}

StyleRuleList* StyleResolver::styleRulesForElement(Element* element,
                                                   unsigned rulesToInclude) {
  ASSERT(element);
  StyleResolverState state(document(), element);
  ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                 state.style());
  collector.setMode(SelectorChecker::CollectingStyleRules);
  collectPseudoRulesForElement(*element, collector, PseudoIdNone,
                               rulesToInclude);
  return collector.matchedStyleRuleList();
}

CSSRuleList* StyleResolver::pseudoCSSRulesForElement(Element* element,
                                                     PseudoId pseudoId,
                                                     unsigned rulesToInclude) {
  ASSERT(element);
  StyleResolverState state(document(), element);
  ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                 state.style());
  collector.setMode(SelectorChecker::CollectingCSSRules);
  collectPseudoRulesForElement(*element, collector, pseudoId, rulesToInclude);
  return collector.matchedCSSRuleList();
}

CSSRuleList* StyleResolver::cssRulesForElement(Element* element,
                                               unsigned rulesToInclude) {
  return pseudoCSSRulesForElement(element, PseudoIdNone, rulesToInclude);
}

void StyleResolver::collectPseudoRulesForElement(
    const Element& element,
    ElementRuleCollector& collector,
    PseudoId pseudoId,
    unsigned rulesToInclude) {
  collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));

  if (rulesToInclude & UAAndUserCSSRules)
    matchUARules(collector);

  if (rulesToInclude & AuthorCSSRules) {
    collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
    collector.setIncludeEmptyRules(rulesToInclude & EmptyCSSRules);
    matchAuthorRules(element, collector);
  }
}

bool StyleResolver::applyAnimatedProperties(StyleResolverState& state,
                                            const Element* animatingElement) {
  Element* element = state.element();
  ASSERT(element);

  // The animating element may be this element, or its pseudo element. It is
  // null when calculating the style for a potential pseudo element that has
  // yet to be created.
  ASSERT(animatingElement == element || !animatingElement ||
         animatingElement->parentOrShadowHostElement() == element);

  if (!(animatingElement && animatingElement->hasAnimations()) &&
      !state.style()->transitions() && !state.style()->animations())
    return false;

  CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(),
                                 state.parentStyle(), state.animationUpdate(),
                                 this);
  if (state.animationUpdate().isEmpty())
    return false;

  CSSAnimations::snapshotCompositorKeyframes(
      *element, state.animationUpdate(), *state.style(), state.parentStyle());

  if (state.style()->insideLink() != NotInsideLink) {
    ASSERT(state.applyPropertyToRegularStyle());
    state.setApplyPropertyToVisitedLinkStyle(true);
  }

  const ActiveInterpolationsMap& activeInterpolationsMapForAnimations =
      state.animationUpdate().activeInterpolationsForAnimations();
  const ActiveInterpolationsMap& activeInterpolationsMapForTransitions =
      state.animationUpdate().activeInterpolationsForTransitions();
  // TODO(crbug.com/644148): Apply animations on custom properties.
  applyAnimatedProperties<HighPropertyPriority>(
      state, activeInterpolationsMapForAnimations);
  applyAnimatedProperties<HighPropertyPriority>(
      state, activeInterpolationsMapForTransitions);

  updateFont(state);

  applyAnimatedProperties<LowPropertyPriority>(
      state, activeInterpolationsMapForAnimations);
  applyAnimatedProperties<LowPropertyPriority>(
      state, activeInterpolationsMapForTransitions);

  // Start loading resources used by animations.
  loadPendingResources(state);

  ASSERT(!state.fontBuilder().fontDirty());

  state.setApplyPropertyToVisitedLinkStyle(false);

  return true;
}

StyleRuleKeyframes* StyleResolver::findKeyframesRule(
    const Element* element,
    const AtomicString& animationName) {
  HeapVector<Member<ScopedStyleResolver>, 8> resolvers;
  collectScopedResolversForHostedShadowTrees(*element, resolvers);
  if (ScopedStyleResolver* scopedResolver =
          element->treeScope().scopedStyleResolver())
    resolvers.append(scopedResolver);

  for (auto& resolver : resolvers) {
    if (StyleRuleKeyframes* keyframesRule =
            resolver->keyframeStylesForAnimation(animationName.impl()))
      return keyframesRule;
  }

  for (auto& resolver : resolvers)
    resolver->setHasUnresolvedKeyframesRule();
  return nullptr;
}

template <CSSPropertyPriority priority>
void StyleResolver::applyAnimatedProperties(
    StyleResolverState& state,
    const ActiveInterpolationsMap& activeInterpolationsMap) {
  // TODO(alancutter): Don't apply presentation attribute animations here,
  // they should instead apply in
  // SVGElement::collectStyleForPresentationAttribute().
  for (const auto& entry : activeInterpolationsMap) {
    CSSPropertyID property = entry.key.isCSSProperty()
                                 ? entry.key.cssProperty()
                                 : entry.key.presentationAttribute();
    if (!CSSPropertyPriorityData<priority>::propertyHasPriority(property))
      continue;
    const Interpolation& interpolation = *entry.value.first();
    if (interpolation.isInvalidatableInterpolation()) {
      InterpolationEnvironment environment(state);
      InvalidatableInterpolation::applyStack(entry.value, environment);
    } else {
      // TODO(alancutter): Remove this old code path once animations have
      // completely migrated to InterpolationTypes.
      toStyleInterpolation(interpolation).apply(state);
    }
  }
}

static inline bool isValidCueStyleProperty(CSSPropertyID id) {
  switch (id) {
    case CSSPropertyBackground:
    case CSSPropertyBackgroundAttachment:
    case CSSPropertyBackgroundClip:
    case CSSPropertyBackgroundColor:
    case CSSPropertyBackgroundImage:
    case CSSPropertyBackgroundOrigin:
    case CSSPropertyBackgroundPosition:
    case CSSPropertyBackgroundPositionX:
    case CSSPropertyBackgroundPositionY:
    case CSSPropertyBackgroundRepeat:
    case CSSPropertyBackgroundRepeatX:
    case CSSPropertyBackgroundRepeatY:
    case CSSPropertyBackgroundSize:
    case CSSPropertyColor:
    case CSSPropertyFont:
    case CSSPropertyFontFamily:
    case CSSPropertyFontSize:
    case CSSPropertyFontStretch:
    case CSSPropertyFontStyle:
    case CSSPropertyFontVariant:
    case CSSPropertyFontWeight:
    case CSSPropertyLineHeight:
    case CSSPropertyOpacity:
    case CSSPropertyOutline:
    case CSSPropertyOutlineColor:
    case CSSPropertyOutlineOffset:
    case CSSPropertyOutlineStyle:
    case CSSPropertyOutlineWidth:
    case CSSPropertyVisibility:
    case CSSPropertyWhiteSpace:
    // FIXME: 'text-decoration' shorthand to be handled when available.
    // See https://chromiumcodereview.appspot.com/19516002 for details.
    case CSSPropertyTextDecoration:
    case CSSPropertyTextShadow:
    case CSSPropertyBorderStyle:
      return true;
    case CSSPropertyTextDecorationLine:
    case CSSPropertyTextDecorationStyle:
    case CSSPropertyTextDecorationColor:
    case CSSPropertyTextDecorationSkip:
      return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
    default:
      break;
  }
  return false;
}

static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id) {
  switch (id) {
    // Valid ::first-letter properties listed in spec:
    // http://www.w3.org/TR/css3-selectors/#application-in-css
    case CSSPropertyBackgroundAttachment:
    case CSSPropertyBackgroundBlendMode:
    case CSSPropertyBackgroundClip:
    case CSSPropertyBackgroundColor:
    case CSSPropertyBackgroundImage:
    case CSSPropertyBackgroundOrigin:
    case CSSPropertyBackgroundPosition:
    case CSSPropertyBackgroundPositionX:
    case CSSPropertyBackgroundPositionY:
    case CSSPropertyBackgroundRepeat:
    case CSSPropertyBackgroundRepeatX:
    case CSSPropertyBackgroundRepeatY:
    case CSSPropertyBackgroundSize:
    case CSSPropertyBorderBottomColor:
    case CSSPropertyBorderBottomLeftRadius:
    case CSSPropertyBorderBottomRightRadius:
    case CSSPropertyBorderBottomStyle:
    case CSSPropertyBorderBottomWidth:
    case CSSPropertyBorderImageOutset:
    case CSSPropertyBorderImageRepeat:
    case CSSPropertyBorderImageSlice:
    case CSSPropertyBorderImageSource:
    case CSSPropertyBorderImageWidth:
    case CSSPropertyBorderLeftColor:
    case CSSPropertyBorderLeftStyle:
    case CSSPropertyBorderLeftWidth:
    case CSSPropertyBorderRightColor:
    case CSSPropertyBorderRightStyle:
    case CSSPropertyBorderRightWidth:
    case CSSPropertyBorderTopColor:
    case CSSPropertyBorderTopLeftRadius:
    case CSSPropertyBorderTopRightRadius:
    case CSSPropertyBorderTopStyle:
    case CSSPropertyBorderTopWidth:
    case CSSPropertyColor:
    case CSSPropertyFloat:
    case CSSPropertyFont:
    case CSSPropertyFontFamily:
    case CSSPropertyFontKerning:
    case CSSPropertyFontSize:
    case CSSPropertyFontStretch:
    case CSSPropertyFontStyle:
    case CSSPropertyFontVariant:
    case CSSPropertyFontVariantCaps:
    case CSSPropertyFontVariantLigatures:
    case CSSPropertyFontVariantNumeric:
    case CSSPropertyFontWeight:
    case CSSPropertyLetterSpacing:
    case CSSPropertyLineHeight:
    case CSSPropertyMarginBottom:
    case CSSPropertyMarginLeft:
    case CSSPropertyMarginRight:
    case CSSPropertyMarginTop:
    case CSSPropertyPaddingBottom:
    case CSSPropertyPaddingLeft:
    case CSSPropertyPaddingRight:
    case CSSPropertyPaddingTop:
    case CSSPropertyTextTransform:
    case CSSPropertyVerticalAlign:
    case CSSPropertyWebkitBackgroundClip:
    case CSSPropertyWebkitBackgroundOrigin:
    case CSSPropertyWebkitBorderAfter:
    case CSSPropertyWebkitBorderAfterColor:
    case CSSPropertyWebkitBorderAfterStyle:
    case CSSPropertyWebkitBorderAfterWidth:
    case CSSPropertyWebkitBorderBefore:
    case CSSPropertyWebkitBorderBeforeColor:
    case CSSPropertyWebkitBorderBeforeStyle:
    case CSSPropertyWebkitBorderBeforeWidth:
    case CSSPropertyWebkitBorderEnd:
    case CSSPropertyWebkitBorderEndColor:
    case CSSPropertyWebkitBorderEndStyle:
    case CSSPropertyWebkitBorderEndWidth:
    case CSSPropertyWebkitBorderHorizontalSpacing:
    case CSSPropertyWebkitBorderImage:
    case CSSPropertyWebkitBorderStart:
    case CSSPropertyWebkitBorderStartColor:
    case CSSPropertyWebkitBorderStartStyle:
    case CSSPropertyWebkitBorderStartWidth:
    case CSSPropertyWebkitBorderVerticalSpacing:
    case CSSPropertyWebkitFontSmoothing:
    case CSSPropertyWebkitMarginAfter:
    case CSSPropertyWebkitMarginAfterCollapse:
    case CSSPropertyWebkitMarginBefore:
    case CSSPropertyWebkitMarginBeforeCollapse:
    case CSSPropertyWebkitMarginBottomCollapse:
    case CSSPropertyWebkitMarginCollapse:
    case CSSPropertyWebkitMarginEnd:
    case CSSPropertyWebkitMarginStart:
    case CSSPropertyWebkitMarginTopCollapse:
    case CSSPropertyWordSpacing:
      return true;
    case CSSPropertyTextDecoration:
      ASSERT(!RuntimeEnabledFeatures::css3TextDecorationsEnabled());
      return true;
    case CSSPropertyTextDecorationColor:
    case CSSPropertyTextDecorationLine:
    case CSSPropertyTextDecorationStyle:
    case CSSPropertyTextDecorationSkip:
      ASSERT(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
      return true;

    // text-shadow added in text decoration spec:
    // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
    case CSSPropertyTextShadow:
    // box-shadox added in CSS3 backgrounds spec:
    // http://www.w3.org/TR/css3-background/#placement
    case CSSPropertyBoxShadow:
    // Properties that we currently support outside of spec.
    case CSSPropertyVisibility:
      return true;

    default:
      return false;
  }
}

static bool shouldIgnoreTextTrackAuthorStyle(const Document& document) {
  Settings* settings = document.settings();
  if (!settings)
    return false;
  // Ignore author specified settings for text tracks when any of the user
  // settings are present.
  if (!settings->textTrackBackgroundColor().isEmpty() ||
      !settings->textTrackFontFamily().isEmpty() ||
      !settings->textTrackFontStyle().isEmpty() ||
      !settings->textTrackFontVariant().isEmpty() ||
      !settings->textTrackTextColor().isEmpty() ||
      !settings->textTrackTextShadow().isEmpty() ||
      !settings->textTrackTextSize().isEmpty())
    return true;
  return false;
}

static inline bool isPropertyInWhitelist(
    PropertyWhitelistType propertyWhitelistType,
    CSSPropertyID property,
    const Document& document) {
  if (propertyWhitelistType == PropertyWhitelistNone)
    return true;  // Early bail for the by far most common case.

  if (propertyWhitelistType == PropertyWhitelistFirstLetter)
    return isValidFirstLetterStyleProperty(property);

  if (propertyWhitelistType == PropertyWhitelistCue)
    return isValidCueStyleProperty(property) &&
           !shouldIgnoreTextTrackAuthorStyle(document);

  ASSERT_NOT_REACHED();
  return true;
}

// This method expands the 'all' shorthand property to longhand properties
// and applies the expanded longhand properties.
template <CSSPropertyPriority priority>
void StyleResolver::applyAllProperty(
    StyleResolverState& state,
    const CSSValue& allValue,
    bool inheritedOnly,
    PropertyWhitelistType propertyWhitelistType) {
  // The 'all' property doesn't apply to variables:
  // https://drafts.csswg.org/css-variables/#defining-variables
  if (priority == ResolveVariables)
    return;

  unsigned startCSSProperty = CSSPropertyPriorityData<priority>::first();
  unsigned endCSSProperty = CSSPropertyPriorityData<priority>::last();

  for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) {
    CSSPropertyID propertyId = static_cast<CSSPropertyID>(i);

    // StyleBuilder does not allow any expanded shorthands.
    if (isShorthandProperty(propertyId))
      continue;

    // all shorthand spec says:
    // The all property is a shorthand that resets all CSS properties
    // except direction and unicode-bidi.
    // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
    // We skip applyProperty when a given property is unicode-bidi or
    // direction.
    if (!CSSProperty::isAffectedByAllProperty(propertyId))
      continue;

    if (!isPropertyInWhitelist(propertyWhitelistType, propertyId, document()))
      continue;

    // When hitting matched properties' cache, only inherited properties will be
    // applied.
    if (inheritedOnly && !CSSPropertyMetadata::isInheritedProperty(propertyId))
      continue;

    StyleBuilder::applyProperty(propertyId, state, allValue);
  }
}

template <CSSPropertyPriority priority>
void StyleResolver::applyPropertiesForApplyAtRule(
    StyleResolverState& state,
    const CSSValue& value,
    bool isImportant,
    PropertyWhitelistType propertyWhitelistType) {
  state.style()->setHasVariableReferenceFromNonInheritedProperty();
  if (!state.style()->inheritedVariables())
    return;
  const String& name = toCSSCustomIdentValue(value).value();
  const StylePropertySet* propertySet =
      state.customPropertySetForApplyAtRule(name);
  bool inheritedOnly = false;
  if (propertySet)
    applyProperties<priority>(state, propertySet, isImportant, inheritedOnly,
                              propertyWhitelistType);
}

template <CSSPropertyPriority priority>
void StyleResolver::applyProperties(
    StyleResolverState& state,
    const StylePropertySet* properties,
    bool isImportant,
    bool inheritedOnly,
    PropertyWhitelistType propertyWhitelistType) {
  unsigned propertyCount = properties->propertyCount();
  for (unsigned i = 0; i < propertyCount; ++i) {
    StylePropertySet::PropertyReference current = properties->propertyAt(i);
    CSSPropertyID property = current.id();

    if (property == CSSPropertyApplyAtRule) {
      DCHECK(!inheritedOnly);
      applyPropertiesForApplyAtRule<priority>(
          state, current.value(), isImportant, propertyWhitelistType);
      continue;
    }

    if (isImportant != current.isImportant())
      continue;

    if (property == CSSPropertyAll) {
      applyAllProperty<priority>(state, current.value(), inheritedOnly,
                                 propertyWhitelistType);
      continue;
    }

    if (!isPropertyInWhitelist(propertyWhitelistType, property, document()))
      continue;

    if (inheritedOnly && !current.isInherited()) {
      // If the property value is explicitly inherited, we need to apply further
      // non-inherited properties as they might override the value inherited
      // here. For this reason we don't allow declarations with explicitly
      // inherited properties to be cached.
      DCHECK(!current.value().isInheritedValue());
      continue;
    }

    if (!CSSPropertyPriorityData<priority>::propertyHasPriority(property))
      continue;

    StyleBuilder::applyProperty(current.id(), state, current.value());
  }
}

template <CSSPropertyPriority priority>
void StyleResolver::applyMatchedProperties(StyleResolverState& state,
                                           const MatchedPropertiesRange& range,
                                           bool isImportant,
                                           bool inheritedOnly) {
  if (range.isEmpty())
    return;

  if (state.style()->insideLink() != NotInsideLink) {
    for (const auto& matchedProperties : range) {
      unsigned linkMatchType = matchedProperties.m_types.linkMatchType;
      // FIXME: It would be nicer to pass these as arguments but that requires
      // changes in many places.
      state.setApplyPropertyToRegularStyle(linkMatchType &
                                           CSSSelector::MatchLink);
      state.setApplyPropertyToVisitedLinkStyle(linkMatchType &
                                               CSSSelector::MatchVisited);

      applyProperties<priority>(state, matchedProperties.properties.get(),
                                isImportant, inheritedOnly,
                                static_cast<PropertyWhitelistType>(
                                    matchedProperties.m_types.whitelistType));
    }
    state.setApplyPropertyToRegularStyle(true);
    state.setApplyPropertyToVisitedLinkStyle(false);
    return;
  }
  for (const auto& matchedProperties : range)
    applyProperties<priority>(state, matchedProperties.properties.get(),
                              isImportant, inheritedOnly,
                              static_cast<PropertyWhitelistType>(
                                  matchedProperties.m_types.whitelistType));
}

static unsigned computeMatchedPropertiesHash(
    const MatchedProperties* properties,
    unsigned size) {
  return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
}

void StyleResolver::invalidateMatchedPropertiesCache() {
  m_matchedPropertiesCache.clear();
}

void StyleResolver::notifyResizeForViewportUnits() {
  m_viewportStyleResolver->collectViewportRules();
  m_matchedPropertiesCache.clearViewportDependent();
}

void StyleResolver::applyMatchedProperties(StyleResolverState& state,
                                           const MatchResult& matchResult) {
  const Element* element = state.element();
  ASSERT(element);

  INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(), matchedPropertyApply,
                                1);

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

  if (cachedMatchedProperties && MatchedPropertiesCache::isCacheable(state)) {
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
                                  matchedPropertyCacheHit, 1);
    // 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()->copyNonInheritedFromCached(
        *cachedMatchedProperties->computedStyle);
    if (state.parentStyle()->inheritedDataShared(
            *cachedMatchedProperties->parentComputedStyle) &&
        !isAtShadowBoundary(element) &&
        (!state.distributedToInsertionPoint() ||
         state.style()->userModify() == READ_ONLY)) {
      INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
                                    matchedPropertyCacheInheritedHit, 1);

      EInsideLink linkStatus = state.style()->insideLink();
      // 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->computedStyle);

      // Unfortunately the link status is treated like an inherited property. We
      // need to explicitly restore it.
      state.style()->setInsideLink(linkStatus);

      updateFont(state);

      return;
    }
    applyInheritedOnly = true;
  }

  // TODO(leviw): We need the proper bit for tracking whether we need to do this
  // work.
  applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                           false, applyInheritedOnly);
  applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                           true, applyInheritedOnly);
  // TODO(leviw): stop recalculating every time
  CSSVariableResolver::resolveVariableDefinitions(state);

  if (RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) {
    if (cacheCustomPropertiesForApplyAtRules(state,
                                             matchResult.authorRules())) {
      applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                               false, applyInheritedOnly);
      applyMatchedProperties<ResolveVariables>(state, matchResult.authorRules(),
                                               true, applyInheritedOnly);
      CSSVariableResolver::resolveVariableDefinitions(state);
    }
  }

  // Now we have all of the matched rules in the appropriate order. Walk the
  // rules and apply high-priority properties first, i.e., those properties that
  // other properties depend on.  The order is (1) high-priority not important,
  // (2) high-priority important, (3) normal not important and (4) normal
  // important.
  applyMatchedProperties<HighPropertyPriority>(state, matchResult.allRules(),
                                               false, applyInheritedOnly);
  for (auto range : ImportantAuthorRanges(matchResult))
    applyMatchedProperties<HighPropertyPriority>(state, range, true,
                                                 applyInheritedOnly);
  applyMatchedProperties<HighPropertyPriority>(state, matchResult.uaRules(),
                                               true, applyInheritedOnly);

  if (UNLIKELY(isSVGForeignObjectElement(element))) {
    // LayoutSVGRoot handles zooming for the whole SVG subtree, so foreignObject
    // content should not be scaled again.
    //
    // FIXME: The following hijacks the zoom property for foreignObject so that
    // children of foreignObject get the correct font-size in case of zooming.
    // 'zoom' has HighPropertyPriority, along with other font-related properties
    // used as input to the FontBuilder, so resetting it here may cause the
    // FontBuilder to recompute the font used as inheritable font for
    // foreignObject content. If we want to support zoom on foreignObject we'll
    // need to find another way of handling the SVG zoom model.
    state.setEffectiveZoom(ComputedStyle::initialZoom());
  }

  if (cachedMatchedProperties &&
      cachedMatchedProperties->computedStyle->effectiveZoom() !=
          state.style()->effectiveZoom()) {
    state.fontBuilder().didChangeEffectiveZoom();
    applyInheritedOnly = false;
  }

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

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

  // Now do the normal priority UA properties.
  applyMatchedProperties<LowPropertyPriority>(state, matchResult.uaRules(),
                                              false, applyInheritedOnly);

  // Cache the UA properties to pass them to LayoutTheme in adjustComputedStyle.
  state.cacheUserAgentBorderAndBackground();

  // Now do the author and user normal priority properties and all the
  // !important properties.
  applyMatchedProperties<LowPropertyPriority>(state, matchResult.authorRules(),
                                              false, applyInheritedOnly);
  for (auto range : ImportantAuthorRanges(matchResult))
    applyMatchedProperties<LowPropertyPriority>(state, range, true,
                                                applyInheritedOnly);
  applyMatchedProperties<LowPropertyPriority>(state, matchResult.uaRules(),
                                              true, applyInheritedOnly);

  if (state.style()->hasAppearance() && !applyInheritedOnly) {
    // Check whether the final border and background differs from the cached UA
    // ones.  When there is a partial match in the MatchedPropertiesCache, these
    // flags will already be set correctly and the value stored in
    // cacheUserAgentBorderAndBackground is incorrect, so doing this check again
    // would give the wrong answer.
    state.style()->setHasAuthorBackground(hasAuthorBackground(state));
    state.style()->setHasAuthorBorder(hasAuthorBorder(state));
  }

  loadPendingResources(state);

  if (!cachedMatchedProperties && cacheHash &&
      MatchedPropertiesCache::isCacheable(state)) {
    ASSERT(RuntimeEnabledFeatures::styleMatchedPropertiesCacheEnabled());
    INCREMENT_STYLE_STATS_COUNTER(document().styleEngine(),
                                  matchedPropertyCacheAdded, 1);
    m_matchedPropertiesCache.add(*state.style(), *state.parentStyle(),
                                 cacheHash, matchResult.matchedProperties());
  }

  ASSERT(!state.fontBuilder().fontDirty());
}

bool StyleResolver::hasAuthorBackground(const StyleResolverState& state) {
  const CachedUAStyle* cachedUAStyle = state.cachedUAStyle();
  if (!cachedUAStyle)
    return false;

  FillLayer oldFill = cachedUAStyle->backgroundLayers;
  FillLayer newFill = state.style()->backgroundLayers();
  // Exclude background-repeat from comparison by resetting it.
  oldFill.setRepeatX(NoRepeatFill);
  oldFill.setRepeatY(NoRepeatFill);
  newFill.setRepeatX(NoRepeatFill);
  newFill.setRepeatY(NoRepeatFill);

  return (oldFill != newFill ||
          cachedUAStyle->backgroundColor != state.style()->backgroundColor());
}

bool StyleResolver::hasAuthorBorder(const StyleResolverState& state) {
  const CachedUAStyle* cachedUAStyle = state.cachedUAStyle();
  return cachedUAStyle && (cachedUAStyle->border != state.style()->border());
}

void StyleResolver::applyCallbackSelectors(StyleResolverState& state) {
  if (!m_watchedSelectorsRules)
    return;

  ElementRuleCollector collector(state.elementContext(), m_selectorFilter,
                                 state.style());
  collector.setMode(SelectorChecker::CollectingStyleRules);
  collector.setIncludeEmptyRules(true);

  MatchRequest matchRequest(m_watchedSelectorsRules.get());
  collector.collectMatchingRules(matchRequest);
  collector.sortAndTransferMatchedRules();

  StyleRuleList* rules = collector.matchedStyleRuleList();
  if (!rules)
    return;
  for (size_t i = 0; i < rules->size(); i++)
    state.style()->addCallbackSelector(
        rules->at(i)->selectorList().selectorsText());
}

void StyleResolver::computeFont(ComputedStyle* style,
                                const StylePropertySet& propertySet) {
  CSSPropertyID properties[] = {
      CSSPropertyFontSize,   CSSPropertyFontFamily,      CSSPropertyFontStretch,
      CSSPropertyFontStyle,  CSSPropertyFontVariantCaps, CSSPropertyFontWeight,
      CSSPropertyLineHeight,
  };

  // TODO(timloh): This is weird, the style is being used as its own parent
  StyleResolverState state(document(), nullptr, style);
  state.setStyle(style);

  for (CSSPropertyID property : properties) {
    if (property == CSSPropertyLineHeight)
      updateFont(state);
    StyleBuilder::applyProperty(property, state,
                                *propertySet.getPropertyCSSValue(property));
  }
}

void StyleResolver::addViewportDependentMediaQueries(
    const MediaQueryResultList& list) {
  for (size_t i = 0; i < list.size(); ++i)
    m_viewportDependentMediaQueryResults.append(list[i]);
}

void StyleResolver::addDeviceDependentMediaQueries(
    const MediaQueryResultList& list) {
  for (size_t i = 0; i < list.size(); ++i)
    m_deviceDependentMediaQueryResults.append(list[i]);
}

bool StyleResolver::mediaQueryAffectedByViewportChange() const {
  for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) {
    if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) !=
        m_viewportDependentMediaQueryResults[i]->result())
      return true;
  }
  return false;
}

bool StyleResolver::mediaQueryAffectedByDeviceChange() const {
  for (unsigned i = 0; i < m_deviceDependentMediaQueryResults.size(); ++i) {
    if (m_medium->eval(m_deviceDependentMediaQueryResults[i]->expression()) !=
        m_deviceDependentMediaQueryResults[i]->result())
      return true;
  }
  return false;
}

DEFINE_TRACE(StyleResolver) {
  visitor->trace(m_matchedPropertiesCache);
  visitor->trace(m_medium);
  visitor->trace(m_viewportDependentMediaQueryResults);
  visitor->trace(m_deviceDependentMediaQueryResults);
  visitor->trace(m_selectorFilter);
  visitor->trace(m_viewportStyleResolver);
  visitor->trace(m_features);
  visitor->trace(m_siblingRuleSet);
  visitor->trace(m_uncommonAttributeRuleSet);
  visitor->trace(m_watchedSelectorsRules);
  visitor->trace(m_treeBoundaryCrossingScopes);
  visitor->trace(m_styleSharingLists);
  visitor->trace(m_pendingStyleSheets);
  visitor->trace(m_document);
}

}  // namespace blink
