/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All
 * rights reserved.
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) Research In Motion Limited 2010-2011. 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 "third_party/blink/renderer/core/css/style_engine.h"

#include "base/auto_reset.h"
#include "base/containers/adapters.h"
#include "base/hash/hash.h"
#include "base/ranges/algorithm.h"
#include "third_party/blink/public/mojom/frame/color_scheme.mojom-blink.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink.h"
#include "third_party/blink/renderer/core/css/cascade_layer_map.h"
#include "third_party/blink/renderer/core/css/check_pseudo_has_cache_scope.h"
#include "third_party/blink/renderer/core/css/container_query_data.h"
#include "third_party/blink/renderer/core/css/container_query_evaluator.h"
#include "third_party/blink/renderer/core/css/counter_style_map.h"
#include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
#include "third_party/blink/renderer/core/css/css_font_family_value.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/css_uri_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
#include "third_party/blink/renderer/core/css/document_style_sheet_collection.h"
#include "third_party/blink/renderer/core/css/font_face_cache.h"
#include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h"
#include "third_party/blink/renderer/core/css/media_feature_overrides.h"
#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/out_of_flow_data.h"
#include "third_party/blink/renderer/core/css/property_registration.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.h"
#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_stats.h"
#include "third_party/blink/renderer/core/css/resolver/style_rule_usage_tracker.h"
#include "third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h"
#include "third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css/style_containment_scope_tree.h"
#include "third_party/blink/renderer/core/css/style_environment_variables.h"
#include "third_party/blink/renderer/core/css/style_rule_font_feature_values.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/css/vision_deficiency.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/nth_index_cache.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/frame_owner.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_html_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/render_blocking_resource_manager.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_popup_controller.h"
#include "third_party/blink/renderer/core/preferences/preference_overrides.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/filter_operations.h"
#include "third_party/blink/renderer/core/style/style_initial_data.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h"
#include "third_party/blink/renderer/core/view_transition/view_transition.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_selector.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"

namespace blink {

namespace {

CSSFontSelector* CreateCSSFontSelectorFor(Document& document) {
  DCHECK(document.GetFrame());
  if (UNLIKELY(document.GetFrame()->PagePopupOwner())) {
    return PagePopupController::CreateCSSFontSelector(document);
  }
  return MakeGarbageCollected<CSSFontSelector>(document);
}

enum RuleSetFlags {
  kFontFaceRules = 1 << 0,
  kKeyframesRules = 1 << 1,
  kPropertyRules = 1 << 2,
  kCounterStyleRules = 1 << 3,
  kLayerRules = 1 << 4,
  kFontPaletteValuesRules = 1 << 5,
  kPositionTryRules = 1 << 6,
  kFontFeatureValuesRules = 1 << 7,
  kViewTransitionRules = 1 << 8,
  kFunctionRules = 1 << 9,
};

const unsigned kRuleSetFlagsAll = ~0u;

unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) {
  unsigned flags = 0;
  for (auto& rule_set : rule_sets) {
    if (!rule_set->KeyframesRules().empty()) {
      flags |= kKeyframesRules;
    }
    if (!rule_set->FontFaceRules().empty()) {
      flags |= kFontFaceRules;
    }
    if (!rule_set->FontPaletteValuesRules().empty()) {
      flags |= kFontPaletteValuesRules;
    }
    if (!rule_set->FontFeatureValuesRules().empty()) {
      flags |= kFontFeatureValuesRules;
    }
    if (!rule_set->PropertyRules().empty()) {
      flags |= kPropertyRules;
    }
    if (!rule_set->CounterStyleRules().empty()) {
      flags |= kCounterStyleRules;
    }
    if (rule_set->HasCascadeLayers()) {
      flags |= kLayerRules;
    }
    if (!rule_set->PositionTryRules().empty()) {
      flags |= kPositionTryRules;
    }
    if (!rule_set->ViewTransitionRules().empty()) {
      flags |= kViewTransitionRules;
    }
    if (!rule_set->FunctionRules().empty()) {
      flags |= kFunctionRules;
    }
  }
  return flags;
}

const Vector<AtomicString> ConvertFontFamilyToVector(const CSSValue* value) {
  const CSSValueList* family_list = DynamicTo<CSSValueList>(value);
  if (!family_list) {
    return Vector<AtomicString>();
  }
  wtf_size_t length = family_list->length();
  if (!length) {
    return Vector<AtomicString>();
  }
  Vector<AtomicString> families(length);
  for (wtf_size_t i = 0; i < length; i++) {
    const CSSFontFamilyValue* family_value =
        DynamicTo<CSSFontFamilyValue>(family_list->Item(i));
    if (!family_value) {
      return Vector<AtomicString>();
    }
    families[i] = family_value->Value();
  }
  return families;
}

}  // namespace

StyleEngine::StyleEngine(Document& document)
    : document_(&document),
      style_containment_scope_tree_(
          MakeGarbageCollected<StyleContainmentScopeTree>()),
      document_style_sheet_collection_(
          MakeGarbageCollected<DocumentStyleSheetCollection>(document)),
      resolver_(MakeGarbageCollected<StyleResolver>(document)),
      preferred_color_scheme_(mojom::blink::PreferredColorScheme::kLight),
      owner_color_scheme_(mojom::blink::ColorScheme::kLight) {
  if (document.GetFrame()) {
    global_rule_set_ = MakeGarbageCollected<CSSGlobalRuleSet>();
    font_selector_ = CreateCSSFontSelectorFor(document);
    font_selector_->RegisterForInvalidationCallbacks(this);
    if (const auto* owner = document.GetFrame()->Owner()) {
      owner_color_scheme_ = owner->GetColorScheme();
    }

    // Viewport styles are only processed in the main frame of a page with an
    // active viewport. That is, a pages that their own independently zoomable
    // viewport: the outermost main frame and portals.
    DCHECK(document.GetPage());
    VisualViewport& viewport = document.GetPage()->GetVisualViewport();
    if (document.IsInMainFrame() && viewport.IsActiveViewport()) {
      viewport_resolver_ =
          MakeGarbageCollected<ViewportStyleResolver>(document);
    }

    DCHECK(document.GetSettings());
    preferred_color_scheme_ = document.GetSettings()->GetPreferredColorScheme();
    force_dark_mode_enabled_ =
        document.GetSettings()->GetForceDarkModeEnabled();
    UpdateColorSchemeMetrics();

    forced_colors_ = document.GetSettings()->GetInForcedColors()
                         ? ForcedColors::kActive
                         : ForcedColors::kNone;
    UpdateForcedBackgroundColor();
  }

  UpdateColorScheme();

  // Mostly for the benefit of unit tests.
  UpdateViewportSize();
}

StyleEngine::~StyleEngine() = default;

TreeScopeStyleSheetCollection& StyleEngine::EnsureStyleSheetCollectionFor(
    TreeScope& tree_scope) {
  if (tree_scope == document_) {
    return GetDocumentStyleSheetCollection();
  }

  StyleSheetCollectionMap::AddResult result =
      style_sheet_collection_map_.insert(&tree_scope, nullptr);
  if (result.is_new_entry) {
    result.stored_value->value =
        MakeGarbageCollected<ShadowTreeStyleSheetCollection>(
            To<ShadowRoot>(tree_scope));
  }
  return *result.stored_value->value.Get();
}

TreeScopeStyleSheetCollection* StyleEngine::StyleSheetCollectionFor(
    TreeScope& tree_scope) {
  if (tree_scope == document_) {
    return &GetDocumentStyleSheetCollection();
  }

  StyleSheetCollectionMap::iterator it =
      style_sheet_collection_map_.find(&tree_scope);
  if (it == style_sheet_collection_map_.end()) {
    return nullptr;
  }
  return it->value.Get();
}

const HeapVector<Member<StyleSheet>>& StyleEngine::StyleSheetsForStyleSheetList(
    TreeScope& tree_scope) {
  DCHECK(document_);
  TreeScopeStyleSheetCollection& collection =
      EnsureStyleSheetCollectionFor(tree_scope);
  if (document_->IsActive()) {
    collection.UpdateStyleSheetList();
  }
  return collection.StyleSheetsForStyleSheetList();
}

void StyleEngine::InjectSheet(const StyleSheetKey& key,
                              StyleSheetContents* sheet,
                              WebCssOrigin origin) {
  HeapVector<std::pair<StyleSheetKey, Member<CSSStyleSheet>>>&
      injected_style_sheets =
          origin == WebCssOrigin::kUser ? injected_user_style_sheets_
                                        : injected_author_style_sheets_;
  injected_style_sheets.push_back(std::make_pair(
      key, MakeGarbageCollected<CSSStyleSheet>(sheet, *document_)));
  if (origin == WebCssOrigin::kUser) {
    MarkUserStyleDirty();
  } else {
    MarkDocumentDirty();
  }
}

void StyleEngine::RemoveInjectedSheet(const StyleSheetKey& key,
                                      WebCssOrigin origin) {
  HeapVector<std::pair<StyleSheetKey, Member<CSSStyleSheet>>>&
      injected_style_sheets =
          origin == WebCssOrigin::kUser ? injected_user_style_sheets_
                                        : injected_author_style_sheets_;
  // Remove the last sheet that matches.
  const auto& it = base::ranges::find(
      base::Reversed(injected_style_sheets), key,
      &std::pair<StyleSheetKey, Member<CSSStyleSheet>>::first);
  if (it != injected_style_sheets.rend()) {
    injected_style_sheets.erase(std::next(it).base());
    if (origin == WebCssOrigin::kUser) {
      MarkUserStyleDirty();
    } else {
      MarkDocumentDirty();
    }
  }
}

CSSStyleSheet& StyleEngine::EnsureInspectorStyleSheet() {
  if (inspector_style_sheet_) {
    return *inspector_style_sheet_;
  }

  auto* contents = MakeGarbageCollected<StyleSheetContents>(
      MakeGarbageCollected<CSSParserContext>(*document_));
  inspector_style_sheet_ =
      MakeGarbageCollected<CSSStyleSheet>(contents, *document_);
  MarkDocumentDirty();
  // TODO(futhark@chromium.org): Making the active stylesheets up-to-date here
  // is required by some inspector tests, at least. I theory this should not be
  // necessary. Need to investigate to figure out if/why.
  UpdateActiveStyle();
  return *inspector_style_sheet_;
}

void StyleEngine::AddPendingBlockingSheet(Node& style_sheet_candidate_node,
                                          PendingSheetType type) {
  DCHECK(type == PendingSheetType::kBlocking ||
         type == PendingSheetType::kDynamicRenderBlocking);

  auto* manager = GetDocument().GetRenderBlockingResourceManager();
  bool is_render_blocking =
      manager && manager->AddPendingStylesheet(style_sheet_candidate_node);

  if (type != PendingSheetType::kBlocking) {
    return;
  }

  pending_script_blocking_stylesheets_++;

  if (!is_render_blocking) {
    pending_parser_blocking_stylesheets_++;
    if (GetDocument().body()) {
      GetDocument().CountUse(
          WebFeature::kPendingStylesheetAddedAfterBodyStarted);
    }
    GetDocument().DidAddPendingParserBlockingStylesheet();
  }
}

// This method is called whenever a top-level stylesheet has finished loading.
void StyleEngine::RemovePendingBlockingSheet(Node& style_sheet_candidate_node,
                                             PendingSheetType type) {
  DCHECK(type == PendingSheetType::kBlocking ||
         type == PendingSheetType::kDynamicRenderBlocking);

  if (style_sheet_candidate_node.isConnected()) {
    SetNeedsActiveStyleUpdate(style_sheet_candidate_node.GetTreeScope());
  }

  auto* manager = GetDocument().GetRenderBlockingResourceManager();
  bool is_render_blocking =
      manager && manager->RemovePendingStylesheet(style_sheet_candidate_node);

  if (type != PendingSheetType::kBlocking) {
    return;
  }

  if (!is_render_blocking) {
    DCHECK_GT(pending_parser_blocking_stylesheets_, 0);
    pending_parser_blocking_stylesheets_--;
    if (!pending_parser_blocking_stylesheets_) {
      GetDocument().DidLoadAllPendingParserBlockingStylesheets();
    }
  }

  // Make sure we knew this sheet was pending, and that our count isn't out of
  // sync.
  DCHECK_GT(pending_script_blocking_stylesheets_, 0);

  pending_script_blocking_stylesheets_--;
  if (pending_script_blocking_stylesheets_) {
    return;
  }

  GetDocument().DidRemoveAllPendingStylesheets();
}

void StyleEngine::SetNeedsActiveStyleUpdate(TreeScope& tree_scope) {
  DCHECK(tree_scope.RootNode().isConnected());
  if (GetDocument().IsActive()) {
    MarkTreeScopeDirty(tree_scope);
  }
}

void StyleEngine::AddStyleSheetCandidateNode(Node& node) {
  if (!node.isConnected() || GetDocument().IsDetached()) {
    return;
  }

  DCHECK(!IsXSLStyleSheet(node));
  TreeScope& tree_scope = node.GetTreeScope();
  EnsureStyleSheetCollectionFor(tree_scope).AddStyleSheetCandidateNode(node);

  SetNeedsActiveStyleUpdate(tree_scope);
  if (tree_scope != document_) {
    active_tree_scopes_.insert(&tree_scope);
  }
}

void StyleEngine::RemoveStyleSheetCandidateNode(
    Node& node,
    ContainerNode& insertion_point) {
  DCHECK(!IsXSLStyleSheet(node));
  DCHECK(insertion_point.isConnected());

  ShadowRoot* shadow_root = node.ContainingShadowRoot();
  if (!shadow_root) {
    shadow_root = insertion_point.ContainingShadowRoot();
  }

  static_assert(std::is_base_of<TreeScope, ShadowRoot>::value,
                "The ShadowRoot must be subclass of TreeScope.");
  TreeScope& tree_scope =
      shadow_root ? static_cast<TreeScope&>(*shadow_root) : GetDocument();
  TreeScopeStyleSheetCollection* collection =
      StyleSheetCollectionFor(tree_scope);
  // After detaching document, collection could be null. In the case,
  // we should not update anything. Instead, just return.
  if (!collection) {
    return;
  }
  collection->RemoveStyleSheetCandidateNode(node);

  SetNeedsActiveStyleUpdate(tree_scope);
}

void StyleEngine::ModifiedStyleSheetCandidateNode(Node& node) {
  if (node.isConnected()) {
    SetNeedsActiveStyleUpdate(node.GetTreeScope());
  }
}

void StyleEngine::AdoptedStyleSheetAdded(TreeScope& tree_scope,
                                         CSSStyleSheet* sheet) {
  if (GetDocument().IsDetached()) {
    return;
  }
  sheet->AddedAdoptedToTreeScope(tree_scope);
  if (!tree_scope.RootNode().isConnected()) {
    return;
  }
  EnsureStyleSheetCollectionFor(tree_scope);
  if (tree_scope != document_) {
    active_tree_scopes_.insert(&tree_scope);
  }
  SetNeedsActiveStyleUpdate(tree_scope);
}

void StyleEngine::AdoptedStyleSheetRemoved(TreeScope& tree_scope,
                                           CSSStyleSheet* sheet) {
  if (GetDocument().IsDetached()) {
    return;
  }
  sheet->RemovedAdoptedFromTreeScope(tree_scope);
  if (!tree_scope.RootNode().isConnected()) {
    return;
  }
  if (!StyleSheetCollectionFor(tree_scope)) {
    return;
  }
  SetNeedsActiveStyleUpdate(tree_scope);
}

void StyleEngine::MediaQueryAffectingValueChanged(TreeScope& tree_scope,
                                                  MediaValueChange change) {
  auto* collection = StyleSheetCollectionFor(tree_scope);
  DCHECK(collection);
  if (AffectedByMediaValueChange(collection->ActiveStyleSheets(), change)) {
    SetNeedsActiveStyleUpdate(tree_scope);
  }
}

void StyleEngine::WatchedSelectorsChanged() {
  DCHECK(global_rule_set_);
  global_rule_set_->InitWatchedSelectorsRuleSet(GetDocument());
  // TODO(futhark@chromium.org): Should be able to use RuleSetInvalidation here.
  MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
      style_change_reason::kDeclarativeContent));
}

void StyleEngine::DocumentRulesSelectorsChanged() {
  DCHECK(global_rule_set_);
  Member<RuleSet> old_rule_set =
      global_rule_set_->DocumentRulesSelectorsRuleSet();
  global_rule_set_->UpdateDocumentRulesSelectorsRuleSet(GetDocument());
  Member<RuleSet> new_rule_set =
      global_rule_set_->DocumentRulesSelectorsRuleSet();
  DCHECK_NE(old_rule_set, new_rule_set);

  HeapHashSet<Member<RuleSet>> changed_rule_sets;
  if (old_rule_set) {
    changed_rule_sets.insert(old_rule_set);
  }
  if (new_rule_set) {
    changed_rule_sets.insert(new_rule_set);
  }

  const unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
  InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets,
                              changed_rule_flags, kInvalidateAllScopes);

  // The global rule set must be updated immediately, so that any DOM mutations
  // that happen after this (but before the next style update) can use the
  // updated invalidation sets.
  UpdateActiveStyle();
}

bool StyleEngine::ShouldUpdateDocumentStyleSheetCollection() const {
  return document_scope_dirty_;
}

bool StyleEngine::ShouldUpdateShadowTreeStyleSheetCollection() const {
  return !dirty_tree_scopes_.empty();
}

void StyleEngine::MediaQueryAffectingValueChanged(
    UnorderedTreeScopeSet& tree_scopes,
    MediaValueChange change) {
  for (TreeScope* tree_scope : tree_scopes) {
    DCHECK(tree_scope != document_);
    MediaQueryAffectingValueChanged(*tree_scope, change);
  }
}

void StyleEngine::AddTextTrack(TextTrack* text_track) {
  text_tracks_.insert(text_track);
}

void StyleEngine::RemoveTextTrack(TextTrack* text_track) {
  text_tracks_.erase(text_track);
}

Element* StyleEngine::EnsureVTTOriginatingElement() {
  if (!vtt_originating_element_) {
    vtt_originating_element_ = MakeGarbageCollected<Element>(
        QualifiedName(g_null_atom, g_empty_atom, g_empty_atom), document_);
  }
  return vtt_originating_element_.Get();
}

void StyleEngine::MediaQueryAffectingValueChanged(
    HeapHashSet<Member<TextTrack>>& text_tracks,
    MediaValueChange change) {
  if (text_tracks.empty()) {
    return;
  }

  for (auto text_track : text_tracks) {
    bool style_needs_recalc = false;
    auto style_sheets = text_track->GetCSSStyleSheets();
    for (const auto& sheet : style_sheets) {
      StyleSheetContents* contents = sheet->Contents();
      if (contents->HasMediaQueries()) {
        style_needs_recalc = true;
        contents->ClearRuleSet();
      }
    }

    if (style_needs_recalc && text_track->Owner()) {
      // Use kSubtreeTreeStyleChange instead of RuleSet style invalidation
      // because it won't be expensive for tracks and we won't have dynamic
      // changes.
      text_track->Owner()->SetNeedsStyleRecalc(
          kSubtreeStyleChange,
          StyleChangeReasonForTracing::Create(style_change_reason::kShadow));
    }
  }
}

void StyleEngine::MediaQueryAffectingValueChanged(MediaValueChange change) {
  if (AffectedByMediaValueChange(active_user_style_sheets_, change)) {
    MarkUserStyleDirty();
  }
  MediaQueryAffectingValueChanged(GetDocument(), change);
  MediaQueryAffectingValueChanged(active_tree_scopes_, change);
  MediaQueryAffectingValueChanged(text_tracks_, change);
  if (resolver_) {
    resolver_->UpdateMediaType();
  }
}

void StyleEngine::UpdateActiveStyleSheetsInShadow(
    TreeScope* tree_scope,
    UnorderedTreeScopeSet& tree_scopes_removed) {
  DCHECK_NE(tree_scope, document_);
  auto* collection =
      To<ShadowTreeStyleSheetCollection>(StyleSheetCollectionFor(*tree_scope));
  DCHECK(collection);
  collection->UpdateActiveStyleSheets(*this);
  if (!collection->HasStyleSheetCandidateNodes() &&
      !tree_scope->HasAdoptedStyleSheets()) {
    tree_scopes_removed.insert(tree_scope);
    // When removing TreeScope from ActiveTreeScopes,
    // its resolver should be destroyed by invoking resetAuthorStyle.
    DCHECK(!tree_scope->GetScopedStyleResolver());
  }
}

void StyleEngine::UpdateActiveUserStyleSheets() {
  DCHECK(user_style_dirty_);

  ActiveStyleSheetVector new_active_sheets;
  for (auto& sheet : injected_user_style_sheets_) {
    if (RuleSet* rule_set = RuleSetForSheet(*sheet.second)) {
      new_active_sheets.push_back(std::make_pair(sheet.second, rule_set));
    }
  }

  ApplyUserRuleSetChanges(active_user_style_sheets_, new_active_sheets);
  new_active_sheets.swap(active_user_style_sheets_);
}

void StyleEngine::UpdateActiveStyleSheets() {
  if (!NeedsActiveStyleSheetUpdate()) {
    return;
  }

  DCHECK(!GetDocument().InStyleRecalc());
  DCHECK(GetDocument().IsActive());

  TRACE_EVENT0("blink,blink_style", "StyleEngine::updateActiveStyleSheets");

  if (user_style_dirty_) {
    UpdateActiveUserStyleSheets();
  }

  if (ShouldUpdateDocumentStyleSheetCollection()) {
    GetDocumentStyleSheetCollection().UpdateActiveStyleSheets(*this);
  }

  if (ShouldUpdateShadowTreeStyleSheetCollection()) {
    UnorderedTreeScopeSet tree_scopes_removed;
    for (TreeScope* tree_scope : dirty_tree_scopes_) {
      UpdateActiveStyleSheetsInShadow(tree_scope, tree_scopes_removed);
    }
    for (TreeScope* tree_scope : tree_scopes_removed) {
      active_tree_scopes_.erase(tree_scope);
    }
  }

  probe::ActiveStyleSheetsUpdated(document_);

  dirty_tree_scopes_.clear();
  document_scope_dirty_ = false;
  tree_scopes_removed_ = false;
  user_style_dirty_ = false;
}

void StyleEngine::UpdateCounterStyles() {
  if (!counter_styles_need_update_) {
    return;
  }
  CounterStyleMap::MarkAllDirtyCounterStyles(GetDocument(),
                                             active_tree_scopes_);
  CounterStyleMap::ResolveAllReferences(GetDocument(), active_tree_scopes_);
  counter_styles_need_update_ = false;
}

void StyleEngine::MarkPositionTryStylesDirty() {
  // TODO(crbug.com/1381623): Currently invalidating all elements in the
  // document with position-options, regardless of where the @position-try rules
  // are added. In order to make invalidation more targeted we would need to add
  // per tree-scope dirtiness, but also adding at-rules in one tree-scope may
  // affect multiple other tree scopes through :host, ::slotted, ::part,
  // exportparts, and inheritance. Doing that is going to be a lot more
  // complicated.
  position_try_styles_dirty_ = true;
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void StyleEngine::InvalidatePositionTryStyles() {
  if (!position_try_styles_dirty_) {
    return;
  }
  position_try_styles_dirty_ = false;
  const bool mark_style_dirty = true;
  GetDocument().GetLayoutView()->InvalidateSubtreePositionTry(mark_style_dirty);
}

void StyleEngine::UpdateViewport() {
  if (viewport_resolver_) {
    viewport_resolver_->UpdateViewport();
  }
}

bool StyleEngine::NeedsActiveStyleUpdate() const {
  return (viewport_resolver_ && viewport_resolver_->NeedsUpdate()) ||
         NeedsActiveStyleSheetUpdate() ||
         (global_rule_set_ && global_rule_set_->IsDirty());
}

void StyleEngine::UpdateActiveStyle() {
  DCHECK(GetDocument().IsActive());
  DCHECK(IsMainThread());
  TRACE_EVENT0("blink", "Document::updateActiveStyle");
  UpdateViewport();
  UpdateActiveStyleSheets();
  UpdateGlobalRuleSet();
}

const ActiveStyleSheetVector StyleEngine::ActiveStyleSheetsForInspector() {
  if (GetDocument().IsActive()) {
    UpdateActiveStyle();
  }

  if (active_tree_scopes_.empty()) {
    return GetDocumentStyleSheetCollection().ActiveStyleSheets();
  }

  ActiveStyleSheetVector active_style_sheets;

  active_style_sheets.AppendVector(
      GetDocumentStyleSheetCollection().ActiveStyleSheets());
  for (TreeScope* tree_scope : active_tree_scopes_) {
    if (TreeScopeStyleSheetCollection* collection =
            style_sheet_collection_map_.at(tree_scope)) {
      active_style_sheets.AppendVector(collection->ActiveStyleSheets());
    }
  }

  // FIXME: Inspector needs a vector which has all active stylesheets.
  // However, creating such a large vector might cause performance regression.
  // Need to implement some smarter solution.
  return active_style_sheets;
}

void StyleEngine::ShadowRootInsertedToDocument(ShadowRoot& shadow_root) {
  DCHECK(shadow_root.isConnected());
  if (GetDocument().IsDetached() || !shadow_root.HasAdoptedStyleSheets()) {
    return;
  }
  EnsureStyleSheetCollectionFor(shadow_root);
  SetNeedsActiveStyleUpdate(shadow_root);
  active_tree_scopes_.insert(&shadow_root);
}

void StyleEngine::ShadowRootRemovedFromDocument(ShadowRoot* shadow_root) {
  style_sheet_collection_map_.erase(shadow_root);
  active_tree_scopes_.erase(shadow_root);
  dirty_tree_scopes_.erase(shadow_root);
  tree_scopes_removed_ = true;
  ResetAuthorStyle(*shadow_root);
}

void StyleEngine::ResetAuthorStyle(TreeScope& tree_scope) {
  ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver();
  if (!scoped_resolver) {
    return;
  }

  if (global_rule_set_) {
    global_rule_set_->MarkDirty();
  }
  if (tree_scope.RootNode().IsDocumentNode()) {
    scoped_resolver->ResetStyle();
    return;
  }

  tree_scope.ClearScopedStyleResolver();
}

StyleContainmentScopeTree& StyleEngine::EnsureStyleContainmentScopeTree() {
  if (!style_containment_scope_tree_) {
    style_containment_scope_tree_ =
        MakeGarbageCollected<StyleContainmentScopeTree>();
  }
  return *style_containment_scope_tree_;
}

void StyleEngine::SetRuleUsageTracker(StyleRuleUsageTracker* tracker) {
  tracker_ = tracker;

  if (resolver_) {
    resolver_->SetRuleUsageTracker(tracker_);
  }
}

Font StyleEngine::ComputeFont(Element& element,
                              const ComputedStyle& font_style,
                              const CSSPropertyValueSet& font_properties) {
  UpdateActiveStyle();
  return GetStyleResolver().ComputeFont(element, font_style, font_properties);
}

RuleSet* StyleEngine::RuleSetForSheet(CSSStyleSheet& sheet) {
  if (!sheet.MatchesMediaQueries(EnsureMediaQueryEvaluator())) {
    return nullptr;
  }
  return &sheet.Contents()->EnsureRuleSet(*media_query_evaluator_);
}

RuleSet* StyleEngine::RuleSetScope::RuleSetForSheet(StyleEngine& engine,
                                                    CSSStyleSheet* css_sheet) {
  RuleSet* rule_set = engine.RuleSetForSheet(*css_sheet);
  if (rule_set && rule_set->HasCascadeLayers() &&
      !css_sheet->Contents()->HasSingleOwnerNode() &&
      !layer_rule_sets_.insert(rule_set).is_new_entry) {
    // The condition above is met for a stylesheet with cascade layers which
    // shares StyleSheetContents with another stylesheet in this TreeScope.
    // WillMutateRules() creates a unique StyleSheetContents for this sheet to
    // avoid incorrectly identifying two separate anonymous layers as the same
    // layer.
    css_sheet->WillMutateRules();
    rule_set = engine.RuleSetForSheet(*css_sheet);
  }
  return rule_set;
}

void StyleEngine::ClearResolvers() {
  DCHECK(!GetDocument().InStyleRecalc());

  GetDocument().ClearScopedStyleResolver();
  for (TreeScope* tree_scope : active_tree_scopes_) {
    tree_scope->ClearScopedStyleResolver();
  }

  if (resolver_) {
    TRACE_EVENT1("blink", "StyleEngine::clearResolver", "frame",
                 GetFrameIdForTracing(GetDocument().GetFrame()));
    resolver_->Dispose();
    resolver_.Clear();
  }
}

void StyleEngine::DidDetach() {
  ClearResolvers();
  if (global_rule_set_) {
    global_rule_set_->Dispose();
  }
  global_rule_set_ = nullptr;
  dirty_tree_scopes_.clear();
  active_tree_scopes_.clear();
  viewport_resolver_ = nullptr;
  media_query_evaluator_ = nullptr;
  style_invalidation_root_.Clear();
  style_recalc_root_.Clear();
  layout_tree_rebuild_root_.Clear();
  if (font_selector_) {
    font_selector_->GetFontFaceCache()->ClearAll();
  }
  font_selector_ = nullptr;
  if (environment_variables_) {
    environment_variables_->DetachFromParent();
  }
  environment_variables_ = nullptr;
  style_containment_scope_tree_ = nullptr;
}

bool StyleEngine::ClearFontFaceCacheAndAddUserFonts(
    const ActiveStyleSheetVector& user_sheets) {
  bool fonts_changed = false;

  if (font_selector_ &&
      font_selector_->GetFontFaceCache()->ClearCSSConnected()) {
    fonts_changed = true;
    if (resolver_) {
      resolver_->InvalidateMatchedPropertiesCache();
    }
  }

  // Rebuild the font cache with @font-face rules from user style sheets.
  for (unsigned i = 0; i < user_sheets.size(); ++i) {
    DCHECK(user_sheets[i].second);
    if (AddUserFontFaceRules(*user_sheets[i].second)) {
      fonts_changed = true;
    }
  }

  return fonts_changed;
}

void StyleEngine::UpdateGenericFontFamilySettings() {
  // FIXME: we should not update generic font family settings when
  // document is inactive.
  DCHECK(GetDocument().IsActive());

  if (!font_selector_) {
    return;
  }

  font_selector_->UpdateGenericFontFamilySettings(*document_);
  if (resolver_) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
  FontCache::Get().InvalidateShapeCache();
}

void StyleEngine::RemoveFontFaceRules(
    const HeapVector<Member<const StyleRuleFontFace>>& font_face_rules) {
  if (!font_selector_) {
    return;
  }

  FontFaceCache* cache = font_selector_->GetFontFaceCache();
  for (const auto& rule : font_face_rules) {
    cache->Remove(rule);
  }
  if (resolver_) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
}

void StyleEngine::MarkTreeScopeDirty(TreeScope& scope) {
  if (scope == document_) {
    MarkDocumentDirty();
    return;
  }

  TreeScopeStyleSheetCollection* collection = StyleSheetCollectionFor(scope);
  DCHECK(collection);
  collection->MarkSheetListDirty();
  dirty_tree_scopes_.insert(&scope);
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void StyleEngine::MarkDocumentDirty() {
  document_scope_dirty_ = true;
  document_style_sheet_collection_->MarkSheetListDirty();
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void StyleEngine::MarkUserStyleDirty() {
  user_style_dirty_ = true;
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void StyleEngine::MarkViewportStyleDirty() {
  viewport_style_dirty_ = true;
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

CSSStyleSheet* StyleEngine::CreateSheet(
    Element& element,
    const String& text,
    TextPosition start_position,
    PendingSheetType type,
    RenderBlockingBehavior render_blocking_behavior) {
  DCHECK(element.GetDocument() == GetDocument());
  CSSStyleSheet* style_sheet = nullptr;

  if (type != PendingSheetType::kNonBlocking) {
    AddPendingBlockingSheet(element, type);
  }

  // The style sheet text can be long; hundreds of kilobytes. In order not to
  // insert such a huge string into the AtomicString table, we take its hash
  // instead and use that. (This is not a cryptographic hash, so a page could
  // cause collisions if it wanted to, but only within its own renderer.)
  // Note that in many cases, we won't actually be able to free the
  // memory used by the string, since it may e.g. be already stuck in
  // the DOM (as text contents of the <style> tag), but it may eventually
  // be parked (compressed, or stored to disk) if there's memory pressure,
  // or otherwise dropped, so this keeps us from being the only thing
  // that keeps it alive.
  AtomicString key;
  if (text.length() >= 1024) {
    size_t digest = FastHash(base::span<const uint8_t>(
        reinterpret_cast<const uint8_t*>(text.Bytes()),
        text.CharactersSizeInBytes()));
    LChar digest_as_char[sizeof(digest)];
    memcpy(digest_as_char, &digest, sizeof(digest));
    key = AtomicString(digest_as_char, sizeof(digest));
  } else {
    key = AtomicString(text);
  }

  auto result = text_to_sheet_cache_.insert(key, nullptr);
  StyleSheetContents* contents = result.stored_value->value;
  if (result.is_new_entry || !contents ||
      !contents->IsCacheableForStyleElement()) {
    result.stored_value->value = nullptr;
    style_sheet =
        ParseSheet(element, text, start_position, render_blocking_behavior);
    if (style_sheet->Contents()->IsCacheableForStyleElement()) {
      result.stored_value->value = style_sheet->Contents();
    }
  } else {
    DCHECK(contents);
    DCHECK(contents->IsCacheableForStyleElement());
    DCHECK(contents->HasSingleOwnerDocument());
    contents->SetIsUsedFromTextCache();
    style_sheet =
        CSSStyleSheet::CreateInline(contents, element, start_position);
  }

  DCHECK(style_sheet);
  if (!element.IsInShadowTree()) {
    String title = element.title();
    if (!title.empty()) {
      style_sheet->SetTitle(title);
      SetPreferredStylesheetSetNameIfNotSet(title);
    }
  }
  return style_sheet;
}

CSSStyleSheet* StyleEngine::ParseSheet(
    Element& element,
    const String& text,
    TextPosition start_position,
    RenderBlockingBehavior render_blocking_behavior) {
  CSSStyleSheet* style_sheet = nullptr;
  style_sheet = CSSStyleSheet::CreateInline(element, NullURL(), start_position,
                                            GetDocument().Encoding());
  style_sheet->Contents()->SetRenderBlocking(render_blocking_behavior);
  style_sheet->Contents()->ParseString(text);
  return style_sheet;
}

void StyleEngine::CollectUserStyleFeaturesTo(RuleFeatureSet& features) const {
  for (unsigned i = 0; i < active_user_style_sheets_.size(); ++i) {
    CSSStyleSheet* sheet = active_user_style_sheets_[i].first;
    features.MutableMediaQueryResultFlags().Add(
        sheet->GetMediaQueryResultFlags());
    DCHECK(sheet->Contents()->HasRuleSet());
    features.Merge(sheet->Contents()->GetRuleSet().Features());
  }
}

void StyleEngine::CollectScopedStyleFeaturesTo(RuleFeatureSet& features) const {
  HeapHashSet<Member<const StyleSheetContents>>
      visited_shared_style_sheet_contents;
  if (GetDocument().GetScopedStyleResolver()) {
    GetDocument().GetScopedStyleResolver()->CollectFeaturesTo(
        features, visited_shared_style_sheet_contents);
  }
  for (TreeScope* tree_scope : active_tree_scopes_) {
    if (ScopedStyleResolver* resolver = tree_scope->GetScopedStyleResolver()) {
      resolver->CollectFeaturesTo(features,
                                  visited_shared_style_sheet_contents);
    }
  }
}

void StyleEngine::MarkViewportUnitDirty(ViewportUnitFlag flag) {
  if (viewport_unit_dirty_flags_ & static_cast<unsigned>(flag)) {
    return;
  }

  viewport_unit_dirty_flags_ |= static_cast<unsigned>(flag);
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

namespace {

void SetNeedsStyleRecalcForViewportUnits(TreeScope& tree_scope,
                                         unsigned dirty_flags) {
  for (Element* element = ElementTraversal::FirstWithin(tree_scope.RootNode());
       element; element = ElementTraversal::NextIncludingPseudo(*element)) {
    if (ShadowRoot* root = element->GetShadowRoot()) {
      SetNeedsStyleRecalcForViewportUnits(*root, dirty_flags);
    }
    const ComputedStyle* style = element->GetComputedStyle();
    if (style && ((style->ViewportUnitFlags() & dirty_flags) ||
                  style->HighlightPseudoElementStylesDependOnViewportUnits())) {
      element->SetNeedsStyleRecalc(kLocalStyleChange,
                                   StyleChangeReasonForTracing::Create(
                                       style_change_reason::kViewportUnits));
    }
  }
}

}  // namespace

void StyleEngine::InvalidateViewportUnitStylesIfNeeded() {
  if (!viewport_unit_dirty_flags_) {
    return;
  }
  unsigned dirty_flags = 0;
  std::swap(viewport_unit_dirty_flags_, dirty_flags);

  // If there are registered custom properties which depend on the invalidated
  // viewport units, it can potentially affect every element.
  if (initial_data_ && (initial_data_->GetViewportUnitFlags() & dirty_flags)) {
    InvalidateInitialData();
    MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
        style_change_reason::kViewportUnits));
    return;
  }

  SetNeedsStyleRecalcForViewportUnits(GetDocument(), dirty_flags);
}

void StyleEngine::InvalidateStyleAndLayoutForFontUpdates() {
  if (!fonts_need_update_) {
    return;
  }

  TRACE_EVENT0("blink", "StyleEngine::InvalidateStyleAndLayoutForFontUpdates");

  fonts_need_update_ = false;

  if (Element* root = GetDocument().documentElement()) {
    TRACE_EVENT0("blink", "Node::MarkSubtreeNeedsStyleRecalcForFontUpdates");
    root->MarkSubtreeNeedsStyleRecalcForFontUpdates();
  }

  // TODO(xiaochengh): Move layout invalidation after style update.
  if (LayoutView* layout_view = GetDocument().GetLayoutView()) {
    TRACE_EVENT0("blink", "LayoutObject::InvalidateSubtreeForFontUpdates");
    layout_view->InvalidateSubtreeLayoutForFontUpdates();
  }
}

void StyleEngine::MarkFontsNeedUpdate() {
  fonts_need_update_ = true;
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void StyleEngine::MarkCounterStylesNeedUpdate() {
  counter_styles_need_update_ = true;
  if (LayoutView* layout_view = GetDocument().GetLayoutView()) {
    layout_view->SetNeedsMarkerOrCounterUpdate();
  }
  GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}

void StyleEngine::FontsNeedUpdate(FontSelector*, FontInvalidationReason) {
  if (!GetDocument().IsActive()) {
    return;
  }

  if (resolver_) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
  MarkViewportStyleDirty();
  MarkFontsNeedUpdate();

  probe::FontsUpdated(document_->GetExecutionContext(), nullptr, String(),
                      nullptr);
}

void StyleEngine::PlatformColorsChanged() {
  UpdateForcedBackgroundColor();
  UpdateColorSchemeBackground(/* color_scheme_changed */ true);
  if (resolver_) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
  MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
      style_change_reason::kPlatformColorChange));

  // Invalidate paint so that SVG images can update the preferred color scheme
  // of their document.
  if (auto* view = GetDocument().GetLayoutView()) {
    view->InvalidatePaintForViewAndDescendants();
  }
}

bool StyleEngine::ShouldSkipInvalidationFor(const Element& element) const {
  DCHECK(element.GetDocument() == &GetDocument())
      << "Only schedule invalidations using the StyleEngine of the Document "
         "which owns the element.";
  if (!element.InActiveDocument()) {
    return true;
  }
  if (!global_rule_set_) {
    // TODO(crbug.com/1175902): This is a speculative fix for a crash.
    NOTREACHED()
        << "global_rule_set_ should only be null for inactive documents.";
    return true;
  }
  if (GetDocument().InStyleRecalc()) {
#if DCHECK_IS_ON()
    // TODO(futhark): The InStyleRecalc() if-guard above should have been a
    // DCHECK(!InStyleRecalc()), but there are a couple of cases where we try to
    // invalidate style from style recalc:
    //
    // 1. We may animate the class attribute of an SVG element and change it
    //    during style recalc when applying the animation effect.
    // 2. We may call SetInlineStyle on elements in a UA shadow tree as part of
    //    style recalc. For instance from HTMLImageFallbackHelper.
    //
    // If there are more cases, we need to adjust the DCHECKs below, but ideally
    // The origin of these invalidations should be fixed.
    if (!element.IsSVGElement()) {
      DCHECK(element.ContainingShadowRoot());
      DCHECK(element.ContainingShadowRoot()->IsUserAgent());
    }
#endif  // DCHECK_IS_ON()
    return true;
  }
  return false;
}

bool StyleEngine::IsSubtreeAndSiblingsStyleDirty(const Element& element) const {
  if (GetDocument().GetStyleChangeType() == kSubtreeStyleChange) {
    return true;
  }
  Element* root = GetDocument().documentElement();
  if (!root || root->GetStyleChangeType() == kSubtreeStyleChange) {
    return true;
  }
  if (!element.parentNode()) {
    return true;
  }
  return element.parentNode()->GetStyleChangeType() == kSubtreeStyleChange;
}

namespace {

bool PossiblyAffectingHasState(Element& element) {
  return element.AncestorsOrAncestorSiblingsAffectedByHas() ||
         element.GetSiblingsAffectedByHasFlags() ||
         element.AffectedByLogicalCombinationsInHas();
}

bool InsertionOrRemovalPossiblyAffectHasStateOfAncestorsOrAncestorSiblings(
    Element* parent) {
  // Only if the parent of the inserted element or subtree has the
  // AncestorsOrAncestorSiblingsAffectedByHas or
  // SiblingsAffectedByHasForSiblingDescendantRelationship flag set, the
  // inserted element or subtree possibly affect the :has() state on its (or the
  // subtree root's) ancestors.
  return parent && (parent->AncestorsOrAncestorSiblingsAffectedByHas() ||
                    parent->HasSiblingsAffectedByHasFlags(
                        SiblingsAffectedByHasFlags::
                            kFlagForSiblingDescendantRelationship));
}

bool InsertionOrRemovalPossiblyAffectHasStateOfPreviousSiblings(
    Element* previous_sibling) {
  // Only if the previous sibling of the inserted element or subtree has the
  // SiblingsAffectedByHas flag set, the inserted element or subtree possibly
  // affect the :has() state on its (or the subtree root's) previous siblings.
  return previous_sibling && previous_sibling->GetSiblingsAffectedByHasFlags();
}

inline Element* SelfOrPreviousSibling(Node* node) {
  if (!node) {
    return nullptr;
  }
  if (Element* element = DynamicTo<Element>(node)) {
    return element;
  }
  return ElementTraversal::PreviousSibling(*node);
}

}  // namespace

void PossiblyScheduleNthPseudoInvalidations(Node& node) {
  if (!node.IsElementNode()) {
    return;
  }
  ContainerNode* parent = node.parentNode();
  if (parent == nullptr) {
    return;
  }

  if ((parent->ChildrenAffectedByForwardPositionalRules() &&
       node.nextSibling()) ||
      (parent->ChildrenAffectedByBackwardPositionalRules() &&
       node.previousSibling())) {
    node.GetDocument().GetStyleEngine().ScheduleNthPseudoInvalidations(*parent);
  }
}

void StyleEngine::InvalidateElementAffectedByHas(
    Element& element,
    bool for_element_affected_by_pseudo_in_has) {
  if (for_element_affected_by_pseudo_in_has &&
      !element.AffectedByPseudoInHas()) {
    return;
  }

  if (element.AffectedBySubjectHas()) {
    // TODO(blee@igalia.com) Need filtering for irrelevant elements.
    // e.g. When we have '.a:has(.b) {}', '.c:has(.d) {}', mutation of class
    // value 'd' can invalidate ancestor with class value 'a' because we
    // don't have any filtering for this case.
    element.SetNeedsStyleRecalc(
        StyleChangeType::kLocalStyleChange,
        StyleChangeReasonForTracing::Create(
            blink::style_change_reason::kStyleInvalidator));

    if (GetRuleFeatureSet().UsesHasInsideNth()) {
      PossiblyScheduleNthPseudoInvalidations(element);
    }
  }

  if (element.AffectedByNonSubjectHas()) {
    InvalidationLists invalidation_lists;
    GetRuleFeatureSet().CollectInvalidationSetsForPseudoClass(
        invalidation_lists, element, CSSSelector::kPseudoHas);
    pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                           element);
  }
}

// Context class to provide :has() invalidation traversal information.
//
// This class provides this information to the :has() invalidation traversal:
// - first element of the traversal.
// - flag to indicate whether the traversal moves to the parent of the first
//   element.
// - flag to indicate whether the :has() invalidation invalidates the elements
//   with AffectedByPseudoInHas flag set.
class StyleEngine::PseudoHasInvalidationTraversalContext {
  STACK_ALLOCATED();

 public:
  Element* FirstElement() const { return first_element_; }

  bool TraverseToParentOfFirstElement() const {
    return traverse_to_parent_of_first_element_;
  }

  bool ForElementAffectedByPseudoInHas() const {
    return for_element_affected_by_pseudo_in_has_;
  }

  PseudoHasInvalidationTraversalContext& SetForElementAffectedByPseudoInHas() {
    for_element_affected_by_pseudo_in_has_ = true;
    return *this;
  }

  // Create :has() invalidation traversal context for attribute change or
  // pseudo state change without structural DOM changes.
  static PseudoHasInvalidationTraversalContext ForAttributeOrPseudoStateChange(
      Element& changed_element) {
    bool traverse_ancestors =
        changed_element.AncestorsOrAncestorSiblingsAffectedByHas();

    Element* parent =
        traverse_ancestors ? changed_element.parentElement() : nullptr;
    Element* previous_sibling =
        changed_element.GetSiblingsAffectedByHasFlags()
            ? ElementTraversal::PreviousSibling(changed_element)
            : nullptr;

    return PseudoHasInvalidationTraversalContext(
        previous_sibling ? previous_sibling : parent, traverse_ancestors);
  }

  // Create :has() invalidation traversal context for element or subtree
  // insertion.
  static PseudoHasInvalidationTraversalContext ForInsertion(
      Element* parent,
      Element* previous_sibling) {
    bool traverse_ancestors =
        parent ? parent->AncestorsOrAncestorSiblingsAffectedByHas() : false;

    return PseudoHasInvalidationTraversalContext(
        previous_sibling ? previous_sibling : parent, traverse_ancestors);
  }

  // Create :has() invalidation traversal context for element or subtree
  // removal. In case of subtree removal, the subtree root element will be
  // passed through the 'removed_element'.
  static PseudoHasInvalidationTraversalContext ForRemoval(
      Element* parent,
      Element* previous_sibling,
      Element& removed_element) {
    bool traverse_ancestors =
        removed_element.AncestorsOrAncestorSiblingsAffectedByHas();

    if (!traverse_ancestors) {
      parent = nullptr;
    }

    if (!removed_element.GetSiblingsAffectedByHasFlags()) {
      previous_sibling = nullptr;
    }

    return PseudoHasInvalidationTraversalContext(
        previous_sibling ? previous_sibling : parent, traverse_ancestors);
  }

  // Create :has() invalidation traversal context for removing all children of
  // a parent.
  static PseudoHasInvalidationTraversalContext ForAllChildrenRemoved(
      Element& parent) {
    return PseudoHasInvalidationTraversalContext(
        &parent, parent.AncestorsOrAncestorSiblingsAffectedByHas());
  }

 private:
  PseudoHasInvalidationTraversalContext(
      Element* first_element,
      bool traverse_to_parent_of_first_element)
      : first_element_(first_element),
        traverse_to_parent_of_first_element_(
            traverse_to_parent_of_first_element) {}

  // The first element of the :has() invalidation traversal.
  Element* first_element_;

  // This flag indicates whether the :has() invalidation traversal moves to the
  // parent of the first element or not.
  bool traverse_to_parent_of_first_element_;

  // This flag indicates that the :has() invalidation invalidates a element
  // only when the element has the AffectedByPseudoInHas flag set. If this flag
  // is true, the :has() invalidation skips the elements that doesn't have the
  // AffectedByPseudoInHas flag set even if the elements have the
  // AffectedBy[Subject|NonSubject]Has flag set.
  //
  // FYI. The AffectedByPseudoInHas flag indicates that the element can be
  // affected by any pseudo state change. (e.g. :hover state change by moving
  // mouse pointer) If an element doesn't have the flag set, it means the
  // element is not affected by any pseudo state change.
  bool for_element_affected_by_pseudo_in_has_{false};
};

void StyleEngine::InvalidateAncestorsOrSiblingsAffectedByHas(
    const PseudoHasInvalidationTraversalContext& traversal_context) {
  bool traverse_to_parent = traversal_context.TraverseToParentOfFirstElement();
  bool traverse_to_previous_sibling = false;
  Element* element = traversal_context.FirstElement();
  bool for_element_affected_by_pseudo_in_has =
      traversal_context.ForElementAffectedByPseudoInHas();

  while (element) {
    traverse_to_parent |= element->AncestorsOrAncestorSiblingsAffectedByHas();
    traverse_to_previous_sibling = element->GetSiblingsAffectedByHasFlags();

    InvalidateElementAffectedByHas(*element,
                                   for_element_affected_by_pseudo_in_has);

    if (traverse_to_previous_sibling) {
      if (Element* previous = ElementTraversal::PreviousSibling(*element)) {
        element = previous;
        continue;
      }
    }

    if (!traverse_to_parent) {
      return;
    }

    element = element->parentElement();
    traverse_to_parent = false;
  }
}

void StyleEngine::InvalidateChangedElementAffectedByLogicalCombinationsInHas(
    Element& changed_element,
    bool for_element_affected_by_pseudo_in_has) {
  if (!changed_element.AffectedByLogicalCombinationsInHas()) {
    return;
  }
  InvalidateElementAffectedByHas(changed_element,
                                 for_element_affected_by_pseudo_in_has);
}

void StyleEngine::ClassChangedForElement(
    const SpaceSplitString& changed_classes,
    Element& element) {
  if (ShouldSkipInvalidationFor(element)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();

  if (features.NeedsHasInvalidationForClassChange() &&
      PossiblyAffectingHasState(element)) {
    unsigned changed_size = changed_classes.size();
    for (unsigned i = 0; i < changed_size; ++i) {
      if (features.NeedsHasInvalidationForClass(changed_classes[i])) {
        InvalidateChangedElementAffectedByLogicalCombinationsInHas(
            element, /* for_element_affected_by_pseudo_in_has */ false);
        InvalidateAncestorsOrSiblingsAffectedByHas(
            PseudoHasInvalidationTraversalContext::
                ForAttributeOrPseudoStateChange(element));
        break;
      }
    }
  }

  if (IsSubtreeAndSiblingsStyleDirty(element)) {
    return;
  }

  InvalidationLists invalidation_lists;
  unsigned changed_size = changed_classes.size();
  for (unsigned i = 0; i < changed_size; ++i) {
    features.CollectInvalidationSetsForClass(invalidation_lists, element,
                                             changed_classes[i]);
  }
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         element);
}

void StyleEngine::ClassChangedForElement(const SpaceSplitString& old_classes,
                                         const SpaceSplitString& new_classes,
                                         Element& element) {
  if (ShouldSkipInvalidationFor(element)) {
    return;
  }

  if (!old_classes.size()) {
    ClassChangedForElement(new_classes, element);
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();

  bool needs_schedule_invalidation = !IsSubtreeAndSiblingsStyleDirty(element);
  bool possibly_affecting_has_state =
      features.NeedsHasInvalidationForClassChange() &&
      PossiblyAffectingHasState(element);
  if (!needs_schedule_invalidation && !possibly_affecting_has_state) {
    return;
  }

  // Class vectors tend to be very short. This is faster than using a hash
  // table.
  WTF::Vector<bool> remaining_class_bits(old_classes.size());

  InvalidationLists invalidation_lists;
  bool affecting_has_state = false;

  for (unsigned i = 0; i < new_classes.size(); ++i) {
    bool found = false;
    for (unsigned j = 0; j < old_classes.size(); ++j) {
      if (new_classes[i] == old_classes[j]) {
        // Mark each class that is still in the newClasses so we can skip doing
        // an n^2 search below when looking for removals. We can't break from
        // this loop early since a class can appear more than once.
        remaining_class_bits[j] = true;
        found = true;
      }
    }
    // Class was added.
    if (!found) {
      if (LIKELY(needs_schedule_invalidation)) {
        features.CollectInvalidationSetsForClass(invalidation_lists, element,
                                                 new_classes[i]);
      }
      if (UNLIKELY(possibly_affecting_has_state)) {
        if (features.NeedsHasInvalidationForClass(new_classes[i])) {
          affecting_has_state = true;
          possibly_affecting_has_state = false;  // Clear to skip check
        }
      }
    }
  }

  for (unsigned i = 0; i < old_classes.size(); ++i) {
    if (remaining_class_bits[i]) {
      continue;
    }
    // Class was removed.
    if (LIKELY(needs_schedule_invalidation)) {
      features.CollectInvalidationSetsForClass(invalidation_lists, element,
                                               old_classes[i]);
    }
    if (UNLIKELY(possibly_affecting_has_state)) {
      if (features.NeedsHasInvalidationForClass(old_classes[i])) {
        affecting_has_state = true;
        possibly_affecting_has_state = false;  // Clear to skip check
      }
    }
  }
  if (needs_schedule_invalidation) {
    pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                           element);
  }

  if (affecting_has_state) {
    InvalidateChangedElementAffectedByLogicalCombinationsInHas(
        element, /* for_element_affected_by_pseudo_in_has */ false);
    InvalidateAncestorsOrSiblingsAffectedByHas(
        PseudoHasInvalidationTraversalContext::ForAttributeOrPseudoStateChange(
            element));
  }
}

namespace {

bool HasAttributeDependentGeneratedContent(const Element& element) {
  if (PseudoElement* before = element.GetPseudoElement(kPseudoIdBefore)) {
    const ComputedStyle* style = before->GetComputedStyle();
    if (style && style->HasAttrContent()) {
      return true;
    }
  }
  if (PseudoElement* after = element.GetPseudoElement(kPseudoIdAfter)) {
    const ComputedStyle* style = after->GetComputedStyle();
    if (style && style->HasAttrContent()) {
      return true;
    }
  }
  return false;
}

}  // namespace

void StyleEngine::AttributeChangedForElement(
    const QualifiedName& attribute_name,
    Element& element) {
  if (ShouldSkipInvalidationFor(element)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();

  if (features.NeedsHasInvalidationForAttributeChange() &&
      PossiblyAffectingHasState(element)) {
    if (features.NeedsHasInvalidationForAttribute(attribute_name)) {
      InvalidateChangedElementAffectedByLogicalCombinationsInHas(
          element, /* for_element_affected_by_pseudo_in_has */ false);
      InvalidateAncestorsOrSiblingsAffectedByHas(
          PseudoHasInvalidationTraversalContext::
              ForAttributeOrPseudoStateChange(element));
    }
  }

  if (IsSubtreeAndSiblingsStyleDirty(element)) {
    return;
  }

  InvalidationLists invalidation_lists;
  features.CollectInvalidationSetsForAttribute(invalidation_lists, element,
                                               attribute_name);
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         element);

  if (!element.NeedsStyleRecalc() &&
      HasAttributeDependentGeneratedContent(element)) {
    element.SetNeedsStyleRecalc(
        kLocalStyleChange,
        StyleChangeReasonForTracing::FromAttribute(attribute_name));
  }
}

void StyleEngine::IdChangedForElement(const AtomicString& old_id,
                                      const AtomicString& new_id,
                                      Element& element) {
  if (ShouldSkipInvalidationFor(element)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();

  if (features.NeedsHasInvalidationForIdChange() &&
      PossiblyAffectingHasState(element)) {
    if ((!old_id.empty() && features.NeedsHasInvalidationForId(old_id)) ||
        (!new_id.empty() && features.NeedsHasInvalidationForId(new_id))) {
      InvalidateChangedElementAffectedByLogicalCombinationsInHas(
          element, /* for_element_affected_by_pseudo_in_has */ false);
      InvalidateAncestorsOrSiblingsAffectedByHas(
          PseudoHasInvalidationTraversalContext::
              ForAttributeOrPseudoStateChange(element));
    }
  }

  if (IsSubtreeAndSiblingsStyleDirty(element)) {
    return;
  }

  InvalidationLists invalidation_lists;
  if (!old_id.empty()) {
    features.CollectInvalidationSetsForId(invalidation_lists, element, old_id);
  }
  if (!new_id.empty()) {
    features.CollectInvalidationSetsForId(invalidation_lists, element, new_id);
  }
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         element);
}

void StyleEngine::PseudoStateChangedForElement(
    CSSSelector::PseudoType pseudo_type,
    Element& element,
    bool invalidate_descendants_or_siblings,
    bool invalidate_ancestors_or_siblings) {
  DCHECK(invalidate_descendants_or_siblings ||
         invalidate_ancestors_or_siblings);

  if (ShouldSkipInvalidationFor(element)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();

  if (invalidate_ancestors_or_siblings &&
      features.NeedsHasInvalidationForPseudoStateChange() &&
      PossiblyAffectingHasState(element)) {
    if (features.NeedsHasInvalidationForPseudoClass(pseudo_type)) {
      InvalidateChangedElementAffectedByLogicalCombinationsInHas(
          element, /* for_element_affected_by_pseudo_in_has */ true);
      InvalidateAncestorsOrSiblingsAffectedByHas(
          PseudoHasInvalidationTraversalContext::
              ForAttributeOrPseudoStateChange(element)
                  .SetForElementAffectedByPseudoInHas());
    }
  }

  if (!invalidate_descendants_or_siblings ||
      IsSubtreeAndSiblingsStyleDirty(element)) {
    return;
  }

  InvalidationLists invalidation_lists;
  features.CollectInvalidationSetsForPseudoClass(invalidation_lists, element,
                                                 pseudo_type);
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         element);
}

void StyleEngine::PartChangedForElement(Element& element) {
  if (ShouldSkipInvalidationFor(element)) {
    return;
  }
  if (IsSubtreeAndSiblingsStyleDirty(element)) {
    return;
  }
  if (element.GetTreeScope() == document_) {
    return;
  }
  if (!GetRuleFeatureSet().InvalidatesParts()) {
    return;
  }
  element.SetNeedsStyleRecalc(
      kLocalStyleChange,
      StyleChangeReasonForTracing::FromAttribute(html_names::kPartAttr));
}

void StyleEngine::ExportpartsChangedForElement(Element& element) {
  if (ShouldSkipInvalidationFor(element)) {
    return;
  }
  if (IsSubtreeAndSiblingsStyleDirty(element)) {
    return;
  }
  if (!element.GetShadowRoot()) {
    return;
  }

  InvalidationLists invalidation_lists;
  GetRuleFeatureSet().CollectPartInvalidationSet(invalidation_lists);
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         element);
}

void StyleEngine::ScheduleSiblingInvalidationsForElement(
    Element& element,
    ContainerNode& scheduling_parent,
    unsigned min_direct_adjacent) {
  DCHECK(min_direct_adjacent);

  InvalidationLists invalidation_lists;

  const RuleFeatureSet& features = GetRuleFeatureSet();

  if (element.HasID()) {
    features.CollectSiblingInvalidationSetForId(invalidation_lists, element,
                                                element.IdForStyleResolution(),
                                                min_direct_adjacent);
  }

  if (element.HasClass()) {
    const SpaceSplitString& class_names = element.ClassNames();
    for (wtf_size_t i = 0; i < class_names.size(); i++) {
      features.CollectSiblingInvalidationSetForClass(
          invalidation_lists, element, class_names[i], min_direct_adjacent);
    }
  }

  for (const Attribute& attribute : element.Attributes()) {
    features.CollectSiblingInvalidationSetForAttribute(
        invalidation_lists, element, attribute.GetName(), min_direct_adjacent);
  }

  features.CollectUniversalSiblingInvalidationSet(invalidation_lists,
                                                  min_direct_adjacent);

  pending_invalidations_.ScheduleSiblingInvalidationsAsDescendants(
      invalidation_lists, scheduling_parent);
}

void StyleEngine::ScheduleInvalidationsForInsertedSibling(
    Element* before_element,
    Element& inserted_element) {
  unsigned affected_siblings =
      inserted_element.parentNode()->ChildrenAffectedByIndirectAdjacentRules()
          ? SiblingInvalidationSet::kDirectAdjacentMax
          : MaxDirectAdjacentSelectors();

  ContainerNode* scheduling_parent =
      inserted_element.ParentElementOrShadowRoot();
  if (!scheduling_parent) {
    return;
  }

  ScheduleSiblingInvalidationsForElement(inserted_element, *scheduling_parent,
                                         1);

  for (unsigned i = 1; before_element && i <= affected_siblings;
       i++, before_element =
                ElementTraversal::PreviousSibling(*before_element)) {
    ScheduleSiblingInvalidationsForElement(*before_element, *scheduling_parent,
                                           i);
  }
}

void StyleEngine::ScheduleInvalidationsForRemovedSibling(
    Element* before_element,
    Element& removed_element,
    Element& after_element) {
  unsigned affected_siblings =
      after_element.parentNode()->ChildrenAffectedByIndirectAdjacentRules()
          ? SiblingInvalidationSet::kDirectAdjacentMax
          : MaxDirectAdjacentSelectors();

  ContainerNode* scheduling_parent = after_element.ParentElementOrShadowRoot();
  if (!scheduling_parent) {
    return;
  }

  ScheduleSiblingInvalidationsForElement(removed_element, *scheduling_parent,
                                         1);

  for (unsigned i = 1; before_element && i <= affected_siblings;
       i++, before_element =
                ElementTraversal::PreviousSibling(*before_element)) {
    ScheduleSiblingInvalidationsForElement(*before_element, *scheduling_parent,
                                           i);
  }
}

void StyleEngine::ScheduleNthPseudoInvalidations(ContainerNode& nth_parent) {
  InvalidationLists invalidation_lists;
  GetRuleFeatureSet().CollectNthInvalidationSet(invalidation_lists);
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         nth_parent);
}

// Inserting/changing some types of rules cause invalidation even if they don't
// match, because the very act of evaluating them has side effects for the
// ComputedStyle. For instance, evaluating a rule with :hover will set the
// AffectedByHover() flag on ComputedStyle even if it matches (for
// invalidation). So we need to test for that here, and invalidate the element
// so that such rules are properly evaluated.
//
// We don't need to care specifically about @starting-style, but all other flags
// should probably be covered here.
static bool FlagsCauseInvalidation(const MatchResult& result) {
  return result.HasFlag(MatchFlag::kAffectedByDrag) ||
         result.HasFlag(MatchFlag::kAffectedByFocusWithin) ||
         result.HasFlag(MatchFlag::kAffectedByHover) ||
         result.HasFlag(MatchFlag::kAffectedByActive);
}

static bool AnyRuleCausesInvalidation(const MatchRequest& match_request,
                                      ElementRuleCollector& collector,
                                      bool is_shadow_host) {
  if (collector.CheckIfAnyRuleMatches(match_request) ||
      FlagsCauseInvalidation(collector.MatchedResult())) {
    return true;
  }
  if (is_shadow_host) {
    if (collector.CheckIfAnyShadowHostRuleMatches(match_request) ||
        FlagsCauseInvalidation(collector.MatchedResult())) {
      return true;
    }
  }
  return false;
}

namespace {

bool CanRejectRuleSet(ElementRuleCollector& collector,
                      const RuleSet& rule_set) {
  const StyleScope* scope = rule_set.SingleScope();
  return scope && collector.CanRejectScope(*scope);
}

}  // namespace

// See if a given element needs to be recalculated after RuleSet changes
// (see ApplyRuleSetInvalidation()).
void StyleEngine::ApplyRuleSetInvalidationForElement(
    const TreeScope& tree_scope,
    Element& element,
    SelectorFilter& selector_filter,
    StyleScopeFrame& style_scope_frame,
    const HeapHashSet<Member<RuleSet>>& rule_sets,
    unsigned changed_rule_flags,
    bool is_shadow_host) {
  if ((changed_rule_flags & kFunctionRules) && element.GetComputedStyle() &&
      element.GetComputedStyle()->AffectedByCSSFunction()) {
    // If @function rules have changed, and the style is (was) using a function,
    // we invalidate it unconditionally. We currently do not attempt
    // finer-grained invalidation, since it would also require tracking which
    // functions call other functions on some level.
    element.SetNeedsStyleRecalc(kLocalStyleChange,
                                StyleChangeReasonForTracing::Create(
                                    style_change_reason::kStyleInvalidator));
    return;
  }
  ElementResolveContext element_resolve_context(element);
  MatchResult match_result;
  EInsideLink inside_link =
      EInsideLink::kNotInsideLink;  // Only used for MatchedProperties, so does
                                    // not matter for us.
  StyleRecalcContext style_recalc_context =
      StyleRecalcContext::FromAncestors(element);
  style_recalc_context.style_scope_frame = &style_scope_frame;
  ElementRuleCollector collector(element_resolve_context, style_recalc_context,
                                 selector_filter, match_result, inside_link);

  MatchRequest match_request{&tree_scope.RootNode()};
  bool matched_any = false;
  for (const Member<RuleSet>& rule_set : rule_sets) {
    if (CanRejectRuleSet(collector, *rule_set)) {
      continue;
    }
    match_request.AddRuleset(rule_set.Get());
    if (match_request.IsFull()) {
      if (AnyRuleCausesInvalidation(match_request, collector, is_shadow_host)) {
        matched_any = true;
        break;
      }
      match_request.ClearAfterMatching();
    }
  }
  if (!match_request.IsEmpty() && !matched_any) {
    matched_any =
        AnyRuleCausesInvalidation(match_request, collector, is_shadow_host);
  }
  if (matched_any) {
    element.SetNeedsStyleRecalc(kLocalStyleChange,
                                StyleChangeReasonForTracing::Create(
                                    style_change_reason::kStyleInvalidator));
  }
}

void StyleEngine::ScheduleCustomElementInvalidations(
    HashSet<AtomicString> tag_names) {
  scoped_refptr<DescendantInvalidationSet> invalidation_set =
      DescendantInvalidationSet::Create();
  for (auto& tag_name : tag_names) {
    invalidation_set->AddTagName(tag_name);
  }
  invalidation_set->SetTreeBoundaryCrossing();
  InvalidationLists invalidation_lists;
  invalidation_lists.descendants.push_back(invalidation_set);
  pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
                                                         *document_);
}

void StyleEngine::ScheduleInvalidationsForHasPseudoAffectedByInsertion(
    Element* parent,
    Node* node_before_change,
    Element& inserted_element) {
  if (!parent) {
    return;
  }

  if (ShouldSkipInvalidationFor(*parent)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();
  if (!features.NeedsHasInvalidationForInsertionOrRemoval()) {
    return;
  }

  Element* previous_sibling = SelfOrPreviousSibling(node_before_change);

  bool possibly_affecting_has_state = false;
  bool descendants_possibly_affecting_has_state = false;

  if (InsertionOrRemovalPossiblyAffectHasStateOfPreviousSiblings(
          previous_sibling)) {
    inserted_element.SetSiblingsAffectedByHasFlags(
        previous_sibling->GetSiblingsAffectedByHasFlags());
    possibly_affecting_has_state = true;
    descendants_possibly_affecting_has_state =
        inserted_element.HasSiblingsAffectedByHasFlags(
            SiblingsAffectedByHasFlags::kFlagForSiblingDescendantRelationship);
  }
  if (InsertionOrRemovalPossiblyAffectHasStateOfAncestorsOrAncestorSiblings(
          parent)) {
    inserted_element.SetAncestorsOrAncestorSiblingsAffectedByHas();
    possibly_affecting_has_state = true;
    descendants_possibly_affecting_has_state = true;
  }

  if (!possibly_affecting_has_state) {
    return;  // Inserted subtree will not affect :has() state
  }

  // Always schedule :has() invalidation if the inserted element may affect
  // a match result of a compound after direct adjacent combinator by changing
  // sibling order. (e.g. When we have a style rule '.a:has(+ .b) {}', we always
  // need :has() invalidation if any element is inserted before '.b')
  bool needs_has_invalidation_for_inserted_subtree =
      parent->ChildrenAffectedByDirectAdjacentRules();

  if (!needs_has_invalidation_for_inserted_subtree &&
      features.NeedsHasInvalidationForInsertedOrRemovedElement(
          inserted_element)) {
    needs_has_invalidation_for_inserted_subtree = true;
  }

  if (descendants_possibly_affecting_has_state) {
    // Do not stop subtree traversal early so that all the descendants have the
    // AncestorsOrAncestorSiblingsAffectedByHas flag set.
    for (Element& element : ElementTraversal::DescendantsOf(inserted_element)) {
      element.SetAncestorsOrAncestorSiblingsAffectedByHas();
      if (!needs_has_invalidation_for_inserted_subtree &&
          features.NeedsHasInvalidationForInsertedOrRemovedElement(element)) {
        needs_has_invalidation_for_inserted_subtree = true;
      }
    }
  }

  if (needs_has_invalidation_for_inserted_subtree) {
    InvalidateAncestorsOrSiblingsAffectedByHas(
        PseudoHasInvalidationTraversalContext::ForInsertion(parent,
                                                            previous_sibling));
    return;
  }

  if (features.NeedsHasInvalidationForPseudoStateChange()) {
    InvalidateAncestorsOrSiblingsAffectedByHas(
        PseudoHasInvalidationTraversalContext::ForInsertion(parent,
                                                            previous_sibling)
            .SetForElementAffectedByPseudoInHas());
  }
}

void StyleEngine::ScheduleInvalidationsForHasPseudoAffectedByRemoval(
    Element* parent,
    Node* node_before_change,
    Element& removed_element) {
  if (!parent) {
    return;
  }

  if (ShouldSkipInvalidationFor(*parent)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();
  if (!features.NeedsHasInvalidationForInsertionOrRemoval()) {
    return;
  }

  Element* previous_sibling = SelfOrPreviousSibling(node_before_change);

  if (!InsertionOrRemovalPossiblyAffectHasStateOfAncestorsOrAncestorSiblings(
          parent) &&
      !InsertionOrRemovalPossiblyAffectHasStateOfPreviousSiblings(
          previous_sibling)) {
    // Removed element will not affect :has() state
    return;
  }

  // Always schedule :has() invalidation if the removed element may affect
  // a match result of a compound after direct adjacent combinator by changing
  // sibling order. (e.g. When we have a style rule '.a:has(+ .b) {}', we always
  // need :has() invalidation if the preceding element of '.b' is removed)
  if (parent->ChildrenAffectedByDirectAdjacentRules()) {
    InvalidateAncestorsOrSiblingsAffectedByHas(
        PseudoHasInvalidationTraversalContext::ForRemoval(
            parent, previous_sibling, removed_element));
    return;
  }

  for (Element& element :
       ElementTraversal::InclusiveDescendantsOf(removed_element)) {
    if (features.NeedsHasInvalidationForInsertedOrRemovedElement(element)) {
      InvalidateAncestorsOrSiblingsAffectedByHas(
          PseudoHasInvalidationTraversalContext::ForRemoval(
              parent, previous_sibling, removed_element));
      return;
    }
  }

  if (features.NeedsHasInvalidationForPseudoStateChange()) {
    InvalidateAncestorsOrSiblingsAffectedByHas(
        PseudoHasInvalidationTraversalContext::ForRemoval(
            parent, previous_sibling, removed_element)
            .SetForElementAffectedByPseudoInHas());
  }
}

void StyleEngine::ScheduleInvalidationsForHasPseudoWhenAllChildrenRemoved(
    Element& parent) {
  if (ShouldSkipInvalidationFor(parent)) {
    return;
  }

  const RuleFeatureSet& features = GetRuleFeatureSet();
  if (!features.NeedsHasInvalidationForInsertionOrRemoval()) {
    return;
  }

  if (!InsertionOrRemovalPossiblyAffectHasStateOfAncestorsOrAncestorSiblings(
          &parent)) {
    // Removed children will not affect :has() state
    return;
  }

  // Always invalidate elements possibly affected by the removed children.
  InvalidateAncestorsOrSiblingsAffectedByHas(
      PseudoHasInvalidationTraversalContext::ForAllChildrenRemoved(parent));
}

void StyleEngine::InvalidateStyle() {
  StyleInvalidator style_invalidator(
      pending_invalidations_.GetPendingInvalidationMap());
  style_invalidator.Invalidate(GetDocument(),
                               style_invalidation_root_.RootElement());
  style_invalidation_root_.Clear();
}

void StyleEngine::InvalidateSlottedElements(HTMLSlotElement& slot) {
  for (auto& node : slot.FlattenedAssignedNodes()) {
    if (node->IsElementNode()) {
      node->SetNeedsStyleRecalc(kLocalStyleChange,
                                StyleChangeReasonForTracing::Create(
                                    style_change_reason::kStyleSheetChange));
    }
  }
}

bool StyleEngine::HasViewportDependentPropertyRegistrations() {
  UpdateActiveStyle();
  const PropertyRegistry* registry = GetDocument().GetPropertyRegistry();
  return registry && registry->GetViewportUnitFlags();
}

// Given a list of RuleSets that have changed (both old and new), see what
// elements in the given TreeScope that could be affected by them and need
// style recalculation.
//
// This generally works by our regular selector matching; if any selector
// in any of the given RuleSets match, it means we need to mark the element
// for style recalc. This could either be because the element is affected
// by a rule where it wasn't before, or because the element used to be
// affected by some rule and isn't anymore, or even that the rule itself
// changed. (It could also be a false positive, e.g. because someone added
// a single new rule to a style sheet, causing a new RuleSet to be created
// that also contains all the old rules, and the element matches one of them.)
//
// There are some twists to this; e.g., for a rule like a:hover, we will need
// to invalidate all <a> elements whether they are currently matching :hover
// or not (see FlagsCauseInvalidation()).
//
// In general, we check all elements in this TreeScope and nothing else.
// There are some exceptions (in both directions); in particular, if an element
// is already marked for subtree recalc, we don't need to go below it. Also,
// if invalidation_scope says so, or if we have rules pertaining to UA shadows,
// we may need to descend into child TreeScopes.
void StyleEngine::ApplyRuleSetInvalidationForTreeScope(
    TreeScope& tree_scope,
    ContainerNode& node,
    SelectorFilter& selector_filter,
    StyleScopeFrame& style_scope_frame,
    const HeapHashSet<Member<RuleSet>>& rule_sets,
    unsigned changed_rule_flags,
    InvalidationScope invalidation_scope) {
  TRACE_EVENT0("blink,blink_style",
               "StyleEngine::scheduleInvalidationsForRuleSets");

  bool invalidate_slotted = false;
  bool invalidate_part = false;
  if (auto* shadow_root = DynamicTo<ShadowRoot>(&node)) {
    Element& host = shadow_root->host();
    // The SelectorFilter stack is set up for invalidating the tree
    // under the host, which includes the host. When invalidating the
    // host itself, we need to take it out so that the stack is consistent.
    selector_filter.PopParent(host);
    ApplyRuleSetInvalidationForElement(tree_scope, host, selector_filter,
                                       style_scope_frame, rule_sets,
                                       changed_rule_flags,
                                       /*is_shadow_host=*/true);
    selector_filter.PushParent(host);
    if (host.GetStyleChangeType() == kSubtreeStyleChange) {
      return;
    }
    for (auto rule_set : rule_sets) {
      if (rule_set->HasSlottedRules()) {
        invalidate_slotted = true;
        break;
      }
      if (rule_set->HasPartPseudoRules()) {
        invalidate_part = true;
        break;
      }
    }
  }

  // If there are any rules that cover UA pseudos, we need to descend into
  // UA shadows so that we can invalidate them. This is pretty crude
  // (it descends into all shadows), but such rules are fairly rare anyway.
  //
  // We do a similar thing for :part(), descending into all shadows.
  if (invalidation_scope != kInvalidateAllScopes) {
    for (auto rule_set : rule_sets) {
      if (rule_set->HasUAShadowPseudoElementRules() ||
          rule_set->HasPartPseudoRules()) {
        invalidation_scope = kInvalidateAllScopes;
        break;
      }
    }
  }

  // Note that there is no need to meddle with the SelectorFilter
  // or StyleScopeFrame here: the caller should already have set up
  // the required state for `node` in both cases.
  for (Element& child : ElementTraversal::ChildrenOf(node)) {
    ApplyRuleSetInvalidationForSubtree(
        tree_scope, child, selector_filter,
        /* parent_style_scope_frame */ style_scope_frame, rule_sets,
        changed_rule_flags, invalidation_scope, invalidate_slotted,
        invalidate_part);
  }
}

void StyleEngine::ApplyRuleSetInvalidationForSubtree(
    TreeScope& tree_scope,
    Element& element,
    SelectorFilter& selector_filter,
    StyleScopeFrame& parent_style_scope_frame,
    const HeapHashSet<Member<RuleSet>>& rule_sets,
    unsigned changed_rule_flags,
    InvalidationScope invalidation_scope,
    bool invalidate_slotted,
    bool invalidate_part) {
  StyleScopeFrame style_scope_frame(element, &parent_style_scope_frame);

  if (invalidate_part && element.hasAttribute(html_names::kPartAttr)) {
    // It's too complicated to try to handle ::part() precisely.
    // If we have any ::part() rules, and the element has a [part]
    // attribute, just invalidate it.
    element.SetNeedsStyleRecalc(kLocalStyleChange,
                                StyleChangeReasonForTracing::Create(
                                    style_change_reason::kStyleInvalidator));
  } else {
    ApplyRuleSetInvalidationForElement(tree_scope, element, selector_filter,
                                       style_scope_frame, rule_sets,
                                       changed_rule_flags,
                                       /*is_shadow_host=*/false);
  }

  auto* html_slot_element = DynamicTo<HTMLSlotElement>(element);
  if (html_slot_element && invalidate_slotted) {
    InvalidateSlottedElements(*html_slot_element);
  }

  if (invalidation_scope == kInvalidateAllScopes) {
    if (ShadowRoot* shadow_root = element.GetShadowRoot()) {
      selector_filter.PushParent(element);
      ApplyRuleSetInvalidationForTreeScope(tree_scope, shadow_root->RootNode(),
                                           selector_filter, style_scope_frame,
                                           rule_sets, kInvalidateAllScopes);
      selector_filter.PopParent(element);
    }
  }

  // Skip traversal of the subtree if we're going to update the entire subtree
  // anyway.
  const bool traverse_children =
      (element.GetStyleChangeType() < kSubtreeStyleChange &&
       element.GetComputedStyle());

  if (traverse_children) {
    selector_filter.PushParent(element);

    for (Element& child : ElementTraversal::ChildrenOf(element)) {
      ApplyRuleSetInvalidationForSubtree(
          tree_scope, child, selector_filter,
          /* parent_style_scope_frame */ style_scope_frame, rule_sets,
          changed_rule_flags, invalidation_scope, invalidate_slotted,
          invalidate_part);
    }

    selector_filter.PopParent(element);
  }
}

void StyleEngine::SetStatsEnabled(bool enabled) {
  if (!enabled) {
    style_resolver_stats_ = nullptr;
    return;
  }
  if (!style_resolver_stats_) {
    style_resolver_stats_ = std::make_unique<StyleResolverStats>();
  } else {
    style_resolver_stats_->Reset();
  }
}

void StyleEngine::SetPreferredStylesheetSetNameIfNotSet(const String& name) {
  DCHECK(!name.empty());
  if (!preferred_stylesheet_set_name_.empty()) {
    return;
  }
  preferred_stylesheet_set_name_ = name;
  MarkDocumentDirty();
}

void StyleEngine::SetHttpDefaultStyle(const String& content) {
  if (!content.empty()) {
    SetPreferredStylesheetSetNameIfNotSet(content);
  }
}

void StyleEngine::CollectFeaturesTo(RuleFeatureSet& features) {
  CollectUserStyleFeaturesTo(features);
  CollectScopedStyleFeaturesTo(features);
}

void StyleEngine::EnsureUAStyleForFullscreen(const Element& element) {
  DCHECK(global_rule_set_);
  if (global_rule_set_->HasFullscreenUAStyle()) {
    return;
  }
  CSSDefaultStyleSheets::Instance().EnsureDefaultStyleSheetForFullscreen(
      element);
  global_rule_set_->MarkDirty();
  UpdateActiveStyle();
}

void StyleEngine::EnsureUAStyleForElement(const Element& element) {
  DCHECK(global_rule_set_);
  if (CSSDefaultStyleSheets::Instance().EnsureDefaultStyleSheetsForElement(
          element)) {
    global_rule_set_->MarkDirty();
    UpdateActiveStyle();
  }
}

void StyleEngine::EnsureUAStyleForPseudoElement(PseudoId pseudo_id) {
  DCHECK(global_rule_set_);

  if (CSSDefaultStyleSheets::Instance()
          .EnsureDefaultStyleSheetsForPseudoElement(pseudo_id)) {
    global_rule_set_->MarkDirty();
    UpdateActiveStyle();
  }
}

void StyleEngine::EnsureUAStyleForForcedColors() {
  DCHECK(global_rule_set_);
  if (CSSDefaultStyleSheets::Instance()
          .EnsureDefaultStyleSheetForForcedColors()) {
    global_rule_set_->MarkDirty();
    if (GetDocument().IsActive()) {
      UpdateActiveStyle();
    }
  }
}

RuleSet* StyleEngine::DefaultViewTransitionStyle() const {
  auto* transition = ViewTransitionUtils::GetTransition(GetDocument());
  if (!transition) {
    return nullptr;
  }

  auto* css_style_sheet = transition->UAStyleSheet();
  return &css_style_sheet->Contents()->EnsureRuleSet(
      CSSDefaultStyleSheets::ScreenEval());
}

void StyleEngine::UpdateViewTransitionOptIn() {
  bool cross_document_enabled = false;

  // TODO(https://crbug.com/1463966): This will likely need to change to a
  // CSSValueList if we want to support multiple tokens as a trigger.
  Vector<String> types;
  if (view_transition_rule_) {
    types = view_transition_rule_->GetTypes();
    if (const CSSValue* value = view_transition_rule_->GetNavigation()) {
      cross_document_enabled =
          To<CSSIdentifierValue>(value)->GetValueID() == CSSValueID::kAuto;
    }
  }

  ViewTransitionSupplement::From(GetDocument())
      ->OnViewTransitionsStyleUpdated(cross_document_enabled, types);
}

bool StyleEngine::HasRulesForId(const AtomicString& id) const {
  DCHECK(global_rule_set_);
  return global_rule_set_->GetRuleFeatureSet().HasSelectorForId(id);
}

void StyleEngine::InitialStyleChanged() {
  MarkViewportStyleDirty();
  // We need to update the viewport style immediately because media queries
  // evaluated in MediaQueryAffectingValueChanged() below may rely on the
  // initial font size relative lengths which may have changed.
  UpdateViewportStyle();
  MediaQueryAffectingValueChanged(MediaValueChange::kOther);
  MarkAllElementsForStyleRecalc(
      StyleChangeReasonForTracing::Create(style_change_reason::kSettings));
}

void StyleEngine::ViewportStyleSettingChanged() {
  if (viewport_resolver_) {
    viewport_resolver_->SetNeedsUpdate();
  }

  // When we remove an import link and re-insert it into the document, the
  // import Document and CSSStyleSheet pointers are persisted. That means the
  // comparison of active stylesheets is not able to figure out that the order
  // of the stylesheets have changed after insertion.
  //
  // This is also the case when we import the same document twice where the
  // last inserted document is inserted before the first one in dom order where
  // the last would take precedence.
  //
  // Fall back to re-add all sheets to the scoped resolver and recalculate style
  // for the whole document when we remove or insert an import document.
  if (ScopedStyleResolver* resolver = GetDocument().GetScopedStyleResolver()) {
    MarkDocumentDirty();
    resolver->SetNeedsAppendAllSheets();
    MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
        style_change_reason::kActiveStylesheetsUpdate));
  }
}

void StyleEngine::InvalidateForRuleSetChanges(
    TreeScope& tree_scope,
    const HeapHashSet<Member<RuleSet>>& changed_rule_sets,
    unsigned changed_rule_flags,
    InvalidationScope invalidation_scope) {
  if (tree_scope.GetDocument().HasPendingForcedStyleRecalc()) {
    return;
  }
  if (!tree_scope.GetDocument().documentElement()) {
    return;
  }
  if (changed_rule_sets.empty()) {
    return;
  }

  Element& invalidation_root =
      ScopedStyleResolver::InvalidationRootForTreeScope(tree_scope);
  if (invalidation_root.GetStyleChangeType() == kSubtreeStyleChange) {
    return;
  }

  SelectorFilter selector_filter;
  selector_filter.PushAllParentsOf(tree_scope);

  // Note that unlike the SelectorFilter, there is no need to explicitly
  // handle the ancestor chain. It's OK to have a "root" StyleScopeFrame
  // (i.e. a StyleScopeFrame without a parent frame) in the middle of the
  // tree.
  //
  // Note also in the below call to ApplyRuleSetInvalidationForTreeScope,
  // when `tree_scope` is a ShadowRoot, we have special behavior inside
  // which invalidates "up" to the shadow *host*. This is why we use the
  // host (if applicable) as the StyleScopeFrame element here.
  StyleScopeFrame style_scope_frame(
      IsA<ShadowRoot>(tree_scope)
          ? To<ShadowRoot>(tree_scope).host()
          : *tree_scope.GetDocument().documentElement());

  ApplyRuleSetInvalidationForTreeScope(
      tree_scope, tree_scope.RootNode(), selector_filter, style_scope_frame,
      changed_rule_sets, changed_rule_flags, invalidation_scope);
}

void StyleEngine::InvalidateInitialData() {
  initial_data_ = nullptr;
}

// A miniature CascadeMap for cascading @property at-rules according to their
// origin, cascade layer order and position.
class StyleEngine::AtRuleCascadeMap {
  STACK_ALLOCATED();

 public:
  explicit AtRuleCascadeMap(Document& document) : document_(document) {}

  // No need to use the full CascadePriority class, since we are not handling UA
  // style, shadow DOM or importance, and rules are inserted in source ordering.
  struct Priority {
    DISALLOW_NEW();
    bool is_user_style;
    unsigned layer_order;

    bool operator<(const Priority& other) const {
      if (is_user_style != other.is_user_style) {
        return is_user_style;
      }
      return layer_order < other.layer_order;
    }
  };

  Priority GetPriority(bool is_user_style, const CascadeLayer* layer) {
    return Priority{is_user_style, GetLayerOrder(is_user_style, layer)};
  }

  // Returns true if this is the first rule with the name, or if this has a
  // higher priority than all the previously added rules with the same name.
  bool AddAndCascade(const AtomicString& name, Priority priority) {
    auto add_result = map_.insert(name, priority);
    if (add_result.is_new_entry) {
      return true;
    }
    if (priority < add_result.stored_value->value) {
      return false;
    }
    add_result.stored_value->value = priority;
    return true;
  }

 private:
  unsigned GetLayerOrder(bool is_user_style, const CascadeLayer* layer) {
    if (!layer) {
      return CascadeLayerMap::kImplicitOuterLayerOrder;
    }
    const CascadeLayerMap* layer_map = nullptr;
    if (is_user_style) {
      layer_map = document_.GetStyleEngine().GetUserCascadeLayerMap();
    } else if (document_.GetScopedStyleResolver()) {
      layer_map = document_.GetScopedStyleResolver()->GetCascadeLayerMap();
    }
    if (!layer_map) {
      return CascadeLayerMap::kImplicitOuterLayerOrder;
    }
    return layer_map->GetLayerOrder(*layer);
  }

  Document& document_;
  HashMap<AtomicString, Priority> map_;
};

void StyleEngine::ApplyUserRuleSetChanges(
    const ActiveStyleSheetVector& old_style_sheets,
    const ActiveStyleSheetVector& new_style_sheets) {
  DCHECK(global_rule_set_);
  HeapHashSet<Member<RuleSet>> changed_rule_sets;

  ActiveSheetsChange change = CompareActiveStyleSheets(
      old_style_sheets, new_style_sheets, /*diffs=*/{}, changed_rule_sets);

  if (change == kNoActiveSheetsChanged) {
    return;
  }

  // With rules added or removed, we need to re-aggregate rule meta data.
  global_rule_set_->MarkDirty();

  unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);

  // Cascade layer map must be built before adding other at-rules, because other
  // at-rules rely on layer order to resolve name conflicts.
  if (changed_rule_flags & kLayerRules) {
    // Rebuild cascade layer map in all cases, because a newly inserted
    // sub-layer can precede an original layer in the final ordering.
    user_cascade_layer_map_ =
        MakeGarbageCollected<CascadeLayerMap>(new_style_sheets);

    if (resolver_) {
      resolver_->InvalidateMatchedPropertiesCache();
    }

    // When we have layer changes other than appended, existing layer ordering
    // may be changed, which requires rebuilding all at-rule registries and
    // full document style recalc.
    if (change == kActiveSheetsChanged) {
      changed_rule_flags = kRuleSetFlagsAll;
    }
  }

  if (changed_rule_flags & kFontFaceRules) {
    if (ScopedStyleResolver* scoped_resolver =
            GetDocument().GetScopedStyleResolver()) {
      // User style and document scope author style shares the font cache. If
      // @font-face rules are added/removed from user stylesheets, we need to
      // reconstruct the font cache because @font-face rules from author style
      // need to be added to the cache after user rules.
      scoped_resolver->SetNeedsAppendAllSheets();
      MarkDocumentDirty();
    } else {
      bool has_rebuilt_font_face_cache =
          ClearFontFaceCacheAndAddUserFonts(new_style_sheets);
      if (has_rebuilt_font_face_cache) {
        GetFontSelector()->FontFaceInvalidated(
            FontInvalidationReason::kGeneralInvalidation);
      }
    }
  }

  if (changed_rule_flags & kKeyframesRules) {
    if (change == kActiveSheetsChanged) {
      ClearKeyframeRules();
    }

    for (auto* it = new_style_sheets.begin(); it != new_style_sheets.end();
         it++) {
      DCHECK(it->second);
      AddUserKeyframeRules(*it->second);
    }
    ScopedStyleResolver::KeyframesRulesAdded(GetDocument());
  }

  if (changed_rule_flags & kCounterStyleRules) {
    if (change == kActiveSheetsChanged && user_counter_style_map_) {
      user_counter_style_map_->Dispose();
    }

    for (auto* it = new_style_sheets.begin(); it != new_style_sheets.end();
         it++) {
      DCHECK(it->second);
      if (!it->second->CounterStyleRules().empty()) {
        EnsureUserCounterStyleMap().AddCounterStyles(*it->second);
      }
    }

    MarkCounterStylesNeedUpdate();
  }

  if (changed_rule_flags &
      (kPropertyRules | kFontPaletteValuesRules | kFontFeatureValuesRules)) {
    if (changed_rule_flags & kPropertyRules) {
      ClearPropertyRules();
      AtRuleCascadeMap cascade_map(GetDocument());
      AddPropertyRulesFromSheets(cascade_map, new_style_sheets,
                                 true /* is_user_style */);
    }

    if (changed_rule_flags & kFontPaletteValuesRules) {
      font_palette_values_rule_map_.clear();
      AddFontPaletteValuesRulesFromSheets(new_style_sheets);
      MarkFontsNeedUpdate();
    }

    // TODO(https://crbug.com/1402199): kFontFeatureValuesRules changes not
    // handled in user sheets.

    // We just cleared all the rules, which includes any author rules. They
    // must be forcibly re-added.
    if (ScopedStyleResolver* scoped_resolver =
            GetDocument().GetScopedStyleResolver()) {
      scoped_resolver->SetNeedsAppendAllSheets();
      MarkDocumentDirty();
    }
  }

  if (changed_rule_flags & kPositionTryRules) {
    // TODO(crbug.com/1383907): @position-try rules are not yet collected from
    // user stylesheets.
    MarkPositionTryStylesDirty();
  }

  InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets,
                              changed_rule_flags, kInvalidateAllScopes);
}

void StyleEngine::ApplyRuleSetChanges(
    TreeScope& tree_scope,
    const ActiveStyleSheetVector& old_style_sheets,
    const ActiveStyleSheetVector& new_style_sheets,
    const HeapVector<Member<RuleSetDiff>>& diffs) {
  DCHECK(global_rule_set_);
  HeapHashSet<Member<RuleSet>> changed_rule_sets;

  ActiveSheetsChange change = CompareActiveStyleSheets(
      old_style_sheets, new_style_sheets, diffs, changed_rule_sets);

  unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);

  bool rebuild_font_face_cache = change == kActiveSheetsChanged &&
                                 (changed_rule_flags & kFontFaceRules) &&
                                 tree_scope.RootNode().IsDocumentNode();
  bool rebuild_at_property_registry = false;
  bool rebuild_at_font_palette_values_map = false;
  ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver();
  if (scoped_resolver && scoped_resolver->NeedsAppendAllSheets()) {
    rebuild_font_face_cache = true;
    rebuild_at_property_registry = true;
    rebuild_at_font_palette_values_map = true;
    change = kActiveSheetsChanged;
  }

  if (change == kNoActiveSheetsChanged) {
    return;
  }

  // With rules added or removed, we need to re-aggregate rule meta data.
  global_rule_set_->MarkDirty();

  if (changed_rule_flags & kKeyframesRules) {
    ScopedStyleResolver::KeyframesRulesAdded(tree_scope);
  }

  if (changed_rule_flags & kCounterStyleRules) {
    MarkCounterStylesNeedUpdate();
  }

  unsigned append_start_index = 0;
  bool rebuild_cascade_layer_map = changed_rule_flags & kLayerRules;
  if (scoped_resolver) {
    // - If all sheets were removed, we remove the ScopedStyleResolver
    // - If new sheets were appended to existing ones, start appending after the
    //   common prefix, and rebuild CascadeLayerMap only if layers are changed.
    // - For other diffs, reset author style and re-add all sheets for the
    //   TreeScope. If new sheets need a CascadeLayerMap, rebuild it.
    if (new_style_sheets.empty()) {
      rebuild_cascade_layer_map = false;
      ResetAuthorStyle(tree_scope);
    } else if (change == kActiveSheetsAppended) {
      append_start_index = old_style_sheets.size();
    } else {
      rebuild_cascade_layer_map = (changed_rule_flags & kLayerRules) ||
                                  scoped_resolver->HasCascadeLayerMap();
      scoped_resolver->ResetStyle();
    }
  }

  if (rebuild_cascade_layer_map) {
    tree_scope.EnsureScopedStyleResolver().RebuildCascadeLayerMap(
        new_style_sheets);
  }

  if (changed_rule_flags & kLayerRules) {
    if (resolver_) {
      resolver_->InvalidateMatchedPropertiesCache();
    }

    // When we have layer changes other than appended, existing layer ordering
    // may be changed, which requires rebuilding all at-rule registries and
    // full document style recalc.
    if (change == kActiveSheetsChanged) {
      changed_rule_flags = kRuleSetFlagsAll;
      if (tree_scope.RootNode().IsDocumentNode()) {
        rebuild_font_face_cache = true;
      }
    }
  }

  if ((changed_rule_flags & kPropertyRules) || rebuild_at_property_registry) {
    // @property rules are (for now) ignored in shadow trees, per spec.
    // https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule
    if (tree_scope.RootNode().IsDocumentNode()) {
      ClearPropertyRules();
      AtRuleCascadeMap cascade_map(GetDocument());
      AddPropertyRulesFromSheets(cascade_map, active_user_style_sheets_,
                                 true /* is_user_style */);
      AddPropertyRulesFromSheets(cascade_map, new_style_sheets,
                                 false /* is_user_style */);
    }
  }

  if ((changed_rule_flags & kFontPaletteValuesRules) ||
      rebuild_at_font_palette_values_map) {
    // TODO(crbug.com/1296114): Support @font-palette-values in shadow trees and
    // support scoping correctly.
    if (tree_scope.RootNode().IsDocumentNode()) {
      font_palette_values_rule_map_.clear();
      AddFontPaletteValuesRulesFromSheets(active_user_style_sheets_);
      AddFontPaletteValuesRulesFromSheets(new_style_sheets);
    }
  }

  // The kFontFeatureValuesRules case is handled in
  // tree_scope.EnsureScopedStyleResolver().AppendActiveStyleSheets below.

  if (tree_scope.RootNode().IsDocumentNode()) {
    bool has_rebuilt_font_face_cache = false;
    if (rebuild_font_face_cache) {
      has_rebuilt_font_face_cache =
          ClearFontFaceCacheAndAddUserFonts(active_user_style_sheets_);
    }
    if ((changed_rule_flags & kFontFaceRules) ||
        (changed_rule_flags & kFontPaletteValuesRules) ||
        (changed_rule_flags & kFontFeatureValuesRules) ||
        has_rebuilt_font_face_cache) {
      GetFontSelector()->FontFaceInvalidated(
          FontInvalidationReason::kGeneralInvalidation);
    }
  }

  if (changed_rule_flags & kPositionTryRules) {
    MarkPositionTryStylesDirty();
  }

  if (changed_rule_flags & kViewTransitionRules) {
    // Since a shadow-tree isn't an independent navigable, @view-transition
    // doesn't apply within one.
    if (tree_scope.RootNode().IsDocumentNode()) {
      AddViewTransitionRules(new_style_sheets);
    }
  }

  if (changed_rule_flags & kFunctionRules) {
    // Changes in function can affect function-using declarations
    // in arbitrary ways.
    if (resolver_) {
      resolver_->InvalidateMatchedPropertiesCache();
    }
  }

  if (!new_style_sheets.empty()) {
    tree_scope.EnsureScopedStyleResolver().AppendActiveStyleSheets(
        append_start_index, new_style_sheets);
  }

  InvalidateForRuleSetChanges(tree_scope, changed_rule_sets, changed_rule_flags,
                              kInvalidateCurrentScope);
}

void StyleEngine::LoadVisionDeficiencyFilter() {
  VisionDeficiency old_vision_deficiency = vision_deficiency_;
  vision_deficiency_ = GetDocument().GetPage()->GetVisionDeficiency();
  if (vision_deficiency_ == old_vision_deficiency) {
    return;
  }

  if (vision_deficiency_ == VisionDeficiency::kNoVisionDeficiency) {
    vision_deficiency_filter_ = nullptr;
  } else {
    AtomicString url = CreateVisionDeficiencyFilterUrl(vision_deficiency_);
    cssvalue::CSSURIValue css_uri_value{CSSUrlData(url)};
    SVGResource* svg_resource = css_uri_value.EnsureResourceReference();
    // Note: The fact that we're using data: URLs here is an
    // implementation detail. Emulating vision deficiencies should still
    // work even if the Document's Content-Security-Policy disallows
    // data: URLs.
    svg_resource->LoadWithoutCSP(GetDocument());
    vision_deficiency_filter_ =
        MakeGarbageCollected<ReferenceFilterOperation>(url, svg_resource);
  }
}

void StyleEngine::VisionDeficiencyChanged() {
  MarkViewportStyleDirty();
}

void StyleEngine::ApplyVisionDeficiencyStyle(
    ComputedStyleBuilder& layout_view_style_builder) {
  LoadVisionDeficiencyFilter();
  if (vision_deficiency_filter_) {
    FilterOperations ops;
    ops.Operations().push_back(vision_deficiency_filter_);
    layout_view_style_builder.SetFilter(ops);
  }
}

const MediaQueryEvaluator& StyleEngine::EnsureMediaQueryEvaluator() {
  if (!media_query_evaluator_) {
    if (GetDocument().GetFrame()) {
      media_query_evaluator_ =
          MakeGarbageCollected<MediaQueryEvaluator>(GetDocument().GetFrame());
    } else {
      media_query_evaluator_ = MakeGarbageCollected<MediaQueryEvaluator>("all");
    }
  }
  return *media_query_evaluator_;
}

bool StyleEngine::StyleMaybeAffectedByLayout(const Node& node) {
  // Note that the StyleAffectedByLayout flag is set based on which
  // ComputedStyles we've resolved previously. Since style resolution may never
  // reach elements in display:none, we defensively treat any null-or-ensured
  // ComputedStyle as affected by layout.
  return StyleAffectedByLayout() ||
         ComputedStyle::IsNullOrEnsured(node.GetComputedStyle());
}

bool StyleEngine::UpdateRootFontRelativeUnits(
    const ComputedStyle* old_root_style,
    const ComputedStyle* new_root_style) {
  if (!new_root_style || !UsesRootFontRelativeUnits()) {
    return false;
  }
  bool rem_changed = !old_root_style || old_root_style->SpecifiedFontSize() !=
                                            new_root_style->SpecifiedFontSize();
  bool root_font_glyphs_changed =
      !old_root_style ||
      (UsesGlyphRelativeUnits() &&
       old_root_style->GetFont() != new_root_style->GetFont());
  bool root_line_height_changed =
      !old_root_style ||
      (UsesLineHeightUnits() &&
       old_root_style->LineHeight() != new_root_style->LineHeight());
  bool root_font_changed =
      rem_changed || root_font_glyphs_changed || root_line_height_changed;
  if (root_font_changed) {
    // Resolved root font relative units are stored in the matched properties
    // cache so we need to make sure to invalidate the cache if the
    // documentElement font size changes.
    GetStyleResolver().InvalidateMatchedPropertiesCache();
    return true;
  }
  return false;
}

void StyleEngine::PropertyRegistryChanged() {
  // TODO(timloh): Invalidate only elements with this custom property set
  MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
      style_change_reason::kPropertyRegistration));
  if (resolver_) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
  InvalidateInitialData();
}

void StyleEngine::EnvironmentVariableChanged() {
  MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
      style_change_reason::kPropertyRegistration));
  if (resolver_) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
}

void StyleEngine::NodeWillBeRemoved(Node& node) {
  if (auto* element = DynamicTo<Element>(node)) {
    if (StyleContainmentScopeTree* tree = GetStyleContainmentScopeTree()) {
      if (element->GetComputedStyle() &&
          element->ComputedStyleRef().ContainsStyle()) {
        tree->RemoveScopeForElement(*element);
      }
    }
    pending_invalidations_.RescheduleSiblingInvalidationsAsDescendants(
        *element);
  }
}

void StyleEngine::ChildrenRemoved(ContainerNode& parent) {
  if (!parent.isConnected()) {
    return;
  }
  DCHECK(!layout_tree_rebuild_root_.GetRootNode());
  if (InDOMRemoval()) {
    // This is necessary for nested removals. There are elements which
    // removes parts of its UA shadow DOM as part of being removed which means
    // we do a removal from within another removal where isConnected() is not
    // completely up to date which would confuse this code. Also, the removal
    // doesn't have to be in the same subtree as the outer removal. For instance
    // for the ListAttributeTargetChanged mentioned below.
    //
    // Instead we fall back to use the document root as the traversal root for
    // all traversal roots.
    //
    // TODO(crbug.com/882869): MediaControlLoadingPanelElement
    // TODO(crbug.com/888448): TextFieldInputType::ListAttributeTargetChanged
    if (style_invalidation_root_.GetRootNode()) {
      UpdateStyleInvalidationRoot(nullptr, nullptr);
    }
    if (style_recalc_root_.GetRootNode()) {
      UpdateStyleRecalcRoot(nullptr, nullptr);
    }
    return;
  }
  style_invalidation_root_.SubtreeModified(parent);
  style_recalc_root_.SubtreeModified(parent);
}

void StyleEngine::CollectMatchingUserRules(
    ElementRuleCollector& collector) const {
  MatchRequest match_request;
  for (const ActiveStyleSheet& style_sheet : active_user_style_sheets_) {
    match_request.AddRuleset(style_sheet.second);
    if (match_request.IsFull()) {
      collector.CollectMatchingRules(match_request);
      match_request.ClearAfterMatching();
    }
  }
  if (!match_request.IsEmpty()) {
    collector.CollectMatchingRules(match_request);
  }
}

void StyleEngine::ClearKeyframeRules() {
  keyframes_rule_map_.clear();
}

void StyleEngine::ClearPropertyRules() {
  PropertyRegistration::RemoveDeclaredProperties(GetDocument());
}

void StyleEngine::AddPropertyRulesFromSheets(
    AtRuleCascadeMap& cascade_map,
    const ActiveStyleSheetVector& sheets,
    bool is_user_style) {
  for (const ActiveStyleSheet& active_sheet : sheets) {
    if (RuleSet* rule_set = active_sheet.second) {
      AddPropertyRules(cascade_map, *rule_set, is_user_style);
    }
  }
}

void StyleEngine::AddFontPaletteValuesRulesFromSheets(
    const ActiveStyleSheetVector& sheets) {
  for (const ActiveStyleSheet& active_sheet : sheets) {
    if (RuleSet* rule_set = active_sheet.second) {
      AddFontPaletteValuesRules(*rule_set);
    }
  }
}

bool StyleEngine::AddUserFontFaceRules(const RuleSet& rule_set) {
  if (!font_selector_) {
    return false;
  }

  const HeapVector<Member<StyleRuleFontFace>> font_face_rules =
      rule_set.FontFaceRules();
  for (auto& font_face_rule : font_face_rules) {
    if (FontFace* font_face = FontFace::Create(document_, font_face_rule,
                                               true /* is_user_style */)) {
      font_selector_->GetFontFaceCache()->Add(font_face_rule, font_face);
    }
  }
  if (resolver_ && font_face_rules.size()) {
    resolver_->InvalidateMatchedPropertiesCache();
  }
  return font_face_rules.size();
}

void StyleEngine::AddUserKeyframeRules(const RuleSet& rule_set) {
  const HeapVector<Member<StyleRuleKeyframes>> keyframes_rules =
      rule_set.KeyframesRules();
  for (unsigned i = 0; i < keyframes_rules.size(); ++i) {
    AddUserKeyframeStyle(keyframes_rules[i]);
  }
}

void StyleEngine::AddUserKeyframeStyle(StyleRuleKeyframes* rule) {
  AtomicString animation_name(rule->GetName());

  KeyframesRuleMap::iterator it = keyframes_rule_map_.find(animation_name);
  if (it == keyframes_rule_map_.end() ||
      UserKeyframeStyleShouldOverride(rule, it->value)) {
    keyframes_rule_map_.Set(animation_name, rule);
  }
}

bool StyleEngine::UserKeyframeStyleShouldOverride(
    const StyleRuleKeyframes* new_rule,
    const StyleRuleKeyframes* existing_rule) const {
  if (new_rule->IsVendorPrefixed() != existing_rule->IsVendorPrefixed()) {
    return existing_rule->IsVendorPrefixed();
  }
  return !user_cascade_layer_map_ || user_cascade_layer_map_->CompareLayerOrder(
                                         existing_rule->GetCascadeLayer(),
                                         new_rule->GetCascadeLayer()) <= 0;
}

void StyleEngine::AddViewTransitionRules(const ActiveStyleSheetVector& sheets) {
  if (!RuntimeEnabledFeatures::ViewTransitionOnNavigationEnabled()) {
    return;
  }
  view_transition_rule_.Clear();

  for (const ActiveStyleSheet& active_sheet : sheets) {
    RuleSet* rule_set = active_sheet.second;
    if (!rule_set || rule_set->ViewTransitionRules().empty()) {
      continue;
    }

    const CascadeLayerMap* layer_map =
        document_->GetScopedStyleResolver()
            ? document_->GetScopedStyleResolver()->GetCascadeLayerMap()
            : nullptr;
    for (auto& rule : rule_set->ViewTransitionRules()) {
      if (!view_transition_rule_ || !layer_map ||
          layer_map->CompareLayerOrder(view_transition_rule_->GetCascadeLayer(),
                                       rule->GetCascadeLayer()) <= 0) {
        view_transition_rule_ = rule;
      }
    }
  }

  UpdateViewTransitionOptIn();
}

void StyleEngine::AddFontPaletteValuesRules(const RuleSet& rule_set) {
  const HeapVector<Member<StyleRuleFontPaletteValues>>
      font_palette_values_rules = rule_set.FontPaletteValuesRules();
  for (auto& rule : font_palette_values_rules) {
    // TODO(https://crbug.com/1170794): Handle cascade layer reordering here.
    for (auto& family : ConvertFontFamilyToVector(rule->GetFontFamily())) {
      font_palette_values_rule_map_.Set(
          std::make_pair(rule->GetName(), String(family).FoldCase()), rule);
    }
  }
}

void StyleEngine::AddPropertyRules(AtRuleCascadeMap& cascade_map,
                                   const RuleSet& rule_set,
                                   bool is_user_style) {
  const HeapVector<Member<StyleRuleProperty>> property_rules =
      rule_set.PropertyRules();
  for (unsigned i = 0; i < property_rules.size(); ++i) {
    StyleRuleProperty* rule = property_rules[i];
    AtomicString name(rule->GetName());

    PropertyRegistration* registration =
        PropertyRegistration::MaybeCreateForDeclaredProperty(GetDocument(),
                                                             name, *rule);
    if (!registration) {
      continue;
    }

    auto priority =
        cascade_map.GetPriority(is_user_style, rule->GetCascadeLayer());
    if (!cascade_map.AddAndCascade(name, priority)) {
      continue;
    }

    GetDocument().EnsurePropertyRegistry().DeclareProperty(name, *registration);
    PropertyRegistryChanged();
  }
}

StyleRuleKeyframes* StyleEngine::KeyframeStylesForAnimation(
    const AtomicString& animation_name) {
  if (keyframes_rule_map_.empty()) {
    return nullptr;
  }

  KeyframesRuleMap::iterator it = keyframes_rule_map_.find(animation_name);
  if (it == keyframes_rule_map_.end()) {
    return nullptr;
  }

  return it->value.Get();
}

StyleRuleFontPaletteValues* StyleEngine::FontPaletteValuesForNameAndFamily(
    AtomicString palette_name,
    AtomicString family_name) {
  if (font_palette_values_rule_map_.empty() || palette_name.empty()) {
    return nullptr;
  }

  auto it = font_palette_values_rule_map_.find(
      std::make_pair(palette_name, String(family_name).FoldCase()));
  if (it == font_palette_values_rule_map_.end()) {
    return nullptr;
  }

  return it->value.Get();
}

DocumentStyleEnvironmentVariables& StyleEngine::EnsureEnvironmentVariables() {
  if (!environment_variables_) {
    environment_variables_ = DocumentStyleEnvironmentVariables::Create(
        StyleEnvironmentVariables::GetRootInstance(), *document_);
  }
  return *environment_variables_.get();
}

scoped_refptr<StyleInitialData> StyleEngine::MaybeCreateAndGetInitialData() {
  if (initial_data_) {
    return initial_data_;
  }
  if (const PropertyRegistry* registry = document_->GetPropertyRegistry()) {
    if (!registry->IsEmpty()) {
      initial_data_ = StyleInitialData::Create(GetDocument(), *registry);
    }
  }
  return initial_data_;
}

bool StyleEngine::RecalcHighlightStylesForContainer(Element& container) {
  const ComputedStyle& style = container.ComputedStyleRef();
  // If we depend on container queries we need to update styles, and also
  // the styles for dependents. Hence we return this value, which is used
  // in RecalcStyleForContainer to set the flag for child recalc.
  bool depends_on_container_queries =
      style.HighlightData().DependsOnSizeContainerQueries() ||
      style.HighlightsDependOnSizeContainerQueries();
  if (!style.HasAnyHighlightPseudoElementStyles() ||
      !style.HasNonUaHighlightPseudoStyles() || !depends_on_container_queries) {
    return false;
  }

  // We are recalculating styles for a size container whose highlight pseudo
  // styles depend on size container queries. Make sure we update those styles
  // based on the changed container size.
  StyleRecalcContext recalc_context;
  recalc_context.container = &container;
  if (const ComputedStyle* new_style = container.RecalcHighlightStyles(
          recalc_context, nullptr /* old_style */, style,
          container.ParentComputedStyle());
      new_style != &style) {
    container.SetComputedStyle(new_style);
    container.GetLayoutObject()->SetStyle(new_style,
                                          LayoutObject::ApplyStyleChanges::kNo);
  }

  return depends_on_container_queries;
}

#if DCHECK_IS_ON()
namespace {
bool ContainerStyleChangesAllowed(Element& container,
                                  const ComputedStyle* old_element_style,
                                  const ComputedStyle* old_layout_style) {
  // Generally, the size container element style is not allowed to change during
  // layout, but for highlight pseudo elements depending on queries against
  // their originating element, we need to update the style during layout since
  // the highlight styles hangs off the originating element's ComputedStyle.
  const ComputedStyle* new_element_style = container.GetComputedStyle();
  const ComputedStyle* new_layout_style =
      container.GetLayoutObject() ? container.GetLayoutObject()->Style()
                                  : nullptr;

  if (!new_element_style || !old_element_style) {
    // The container should always have a ComputedStyle.
    return false;
  }
  if (new_element_style != old_element_style) {
    Vector<ComputedStyleBase::DebugDiff> diff =
        old_element_style->DebugDiffFields(*new_element_style);
    // Allow highlight styles to change, but only highlight styles.
    if (diff.size() > 1 ||
        (diff.size() == 1 &&
         diff[0].field != ComputedStyleBase::DebugField::highlight_data_)) {
      return false;
    }
  }
  if (new_layout_style == old_layout_style) {
    return true;
  }
  if (!new_layout_style || !old_element_style) {
    // Container may not have a LayoutObject when called from
    // UpdateStyleForNonEligibleContainer(), but then make sure the style is
    // null for both cases.
    return new_layout_style == old_element_style;
  }
  Vector<ComputedStyleBase::DebugDiff> diff =
      old_layout_style->DebugDiffFields(*new_layout_style);
  // Allow highlight styles to change, but only highlight styles.
  return diff.size() == 0 ||
         (diff.size() == 1 &&
          diff[0].field == ComputedStyleBase::DebugField::highlight_data_);
}
}  // namespace
#endif  // DCHECK_IS_ON()

void StyleEngine::RecalcStyleForContainer(Element& container,
                                          StyleRecalcChange change) {
  // The container node must not need recalc at this point.
  DCHECK(!StyleRecalcChange().ShouldRecalcStyleFor(container));

#if DCHECK_IS_ON()
  const ComputedStyle* old_element_style = container.GetComputedStyle();
  const ComputedStyle* old_layout_style =
      container.GetLayoutObject() ? container.GetLayoutObject()->Style()
                                  : nullptr;
#endif  // DCHECK_IS_ON()

  // If the container itself depends on an outer container, then its
  // DependsOnSizeContainerQueries flag will be set, and we would recalc its
  // style (due to ForceRecalcContainer/ForceRecalcDescendantSizeContainers).
  // This is not necessary, hence we suppress recalc for this element.
  change = change.SuppressRecalc();

  // The StyleRecalcRoot invariants requires the root to be dirty/child-dirty
  container.SetChildNeedsStyleRecalc();
  style_recalc_root_.Update(nullptr, &container);

  if (RecalcHighlightStylesForContainer(container)) {
    change = change.ForceRecalcDescendantSizeContainers();
  }

  // TODO(crbug.com/1145970): Consider use a caching mechanism for FromAncestors
  // as we typically will call it for all containers on the first style/layout
  // pass.
  RecalcStyle(change, StyleRecalcContext::FromAncestors(container));

#if DCHECK_IS_ON()
  DCHECK(ContainerStyleChangesAllowed(container, old_element_style,
                                      old_layout_style));
#endif  // DCHECK_IS_ON()
}

void StyleEngine::UpdateStyleForNonEligibleContainer(Element& container) {
  DCHECK(InRebuildLayoutTree());
  // This method is called from AttachLayoutTree() when we skipped style recalc
  // for descendants of a size query container but figured that the LayoutObject
  // we created is not going to be reached for layout in block_node.cc where
  // we would otherwise resume style recalc.
  //
  // This may be due to legacy layout fallback, inline box, table box, etc.
  // Also, if we could not predict that the LayoutObject would not be created,
  // like if the parent LayoutObject returns false for IsChildAllowed.
  ContainerQueryData* cq_data = container.GetContainerQueryData();
  if (!cq_data) {
    return;
  }

  StyleRecalcChange change;
  ContainerQueryEvaluator& evaluator =
      container.EnsureContainerQueryEvaluator();
  ContainerQueryEvaluator::Change query_change =
      evaluator.SizeContainerChanged(PhysicalSize(), kPhysicalAxesNone);
  switch (query_change) {
    case ContainerQueryEvaluator::Change::kNone:
      DCHECK(cq_data->SkippedStyleRecalc());
      break;
    case ContainerQueryEvaluator::Change::kNearestContainer:
      if (!IsShadowHost(container)) {
        change = change.ForceRecalcSizeContainer();
        break;
      }
      // Since the nearest container is found in shadow-including ancestors
      // and not in flat tree ancestors, and style recalc traversal happens in
      // flat tree order, we need to invalidate inside flat tree descendant
      // containers if such containers are inside shadow trees.
      //
      // See also StyleRecalcChange::FlagsForChildren where we turn
      // kRecalcContainer into kRecalcDescendantContainers when traversing
      // past a shadow host.
      [[fallthrough]];
    case ContainerQueryEvaluator::Change::kDescendantContainers:
      change = change.ForceRecalcDescendantSizeContainers();
      break;
  }
  if (query_change != ContainerQueryEvaluator::Change::kNone) {
    container.ComputedStyleRef().ClearCachedPseudoElementStyles();
  }

  DecrementSkippedContainerRecalc();
  AllowMarkForReattachFromRebuildLayoutTreeScope allow_reattach(*this);
  base::AutoReset<bool> cq_recalc(&in_container_query_style_recalc_, true);
  RecalcStyleForContainer(container, change);
}

void StyleEngine::UpdateStyleAndLayoutTreeForContainer(
    Element& container,
    const LogicalSize& logical_size,
    LogicalAxes contained_axes) {
  DCHECK(!style_recalc_root_.GetRootNode());
  DCHECK(!container.NeedsStyleRecalc());
  DCHECK(!in_container_query_style_recalc_);

  base::AutoReset<bool> cq_recalc(&in_container_query_style_recalc_, true);

  DCHECK(container.GetLayoutObject()) << "Containers must have a LayoutObject";
  const ComputedStyle& style = container.GetLayoutObject()->StyleRef();
  DCHECK(style.IsContainerForSizeContainerQueries());
  WritingMode writing_mode = style.GetWritingMode();
  PhysicalSize physical_size = AdjustForAbsoluteZoom::AdjustPhysicalSize(
      ToPhysicalSize(logical_size, writing_mode), style);
  PhysicalAxes physical_axes = ToPhysicalAxes(contained_axes, writing_mode);

  StyleRecalcChange change;

  ContainerQueryEvaluator::Change query_change =
      container.EnsureContainerQueryEvaluator().SizeContainerChanged(
          physical_size, physical_axes);

  ContainerQueryData* cq_data = container.GetContainerQueryData();
  CHECK(cq_data);

  switch (query_change) {
    case ContainerQueryEvaluator::Change::kNone:
      if (!cq_data->SkippedStyleRecalc()) {
        return;
      }
      break;
    case ContainerQueryEvaluator::Change::kNearestContainer:
      if (!IsShadowHost(container)) {
        change = change.ForceRecalcSizeContainer();
        break;
      }
      // Since the nearest container is found in shadow-including ancestors and
      // not in flat tree ancestors, and style recalc traversal happens in flat
      // tree order, we need to invalidate inside flat tree descendant
      // containers if such containers are inside shadow trees.
      //
      // See also StyleRecalcChange::FlagsForChildren where we turn
      // kRecalcContainer into kRecalcDescendantContainers when traversing past
      // a shadow host.
      [[fallthrough]];
    case ContainerQueryEvaluator::Change::kDescendantContainers:
      change = change.ForceRecalcDescendantSizeContainers();
      break;
  }

  if (query_change != ContainerQueryEvaluator::Change::kNone) {
    style.ClearCachedPseudoElementStyles();
    // When the container query changes, the ::first-line matching the container
    // itself is not detected as changed. Firstly, because the style for the
    // container is computed before the layout causing the ::first-line styles
    // to change. Also, we mark the ComputedStyle with HasPseudoElementStyle()
    // for kPseudoIdFirstLine, even when the container query for the
    // ::first-line rules doesn't match, which means a diff for that flag would
    // not detect a change. Instead, if a container has ::first-line rules which
    // depends on size container queries, fall back to re-attaching its box tree
    // when any of the size queries change the evaluation result.
    if (style.HasPseudoElementStyle(kPseudoIdFirstLine) &&
        style.FirstLineDependsOnSizeContainerQueries()) {
      change = change.ForceMarkReattachLayoutTree().ForceReattachLayoutTree();
    }
  }

  NthIndexCache nth_index_cache(GetDocument());

  if (cq_data->SkippedStyleRecalc()) {
    DecrementSkippedContainerRecalc();
  }
  UpdateViewportSize();
  RecalcStyleForContainer(container, change);

  if (container.NeedsReattachLayoutTree()) {
    ReattachContainerSubtree(container);
  } else if (NeedsLayoutTreeRebuild()) {
    if (layout_tree_rebuild_root_.GetRootNode()->IsDocumentNode()) {
      // Avoid traversing from outside the container root. We know none of the
      // elements outside the subtree should be marked dirty in this pass, but
      // we may have fallen back to the document root.
      layout_tree_rebuild_root_.Clear();
      layout_tree_rebuild_root_.Update(nullptr, &container);
    } else {
      DCHECK(FlatTreeTraversal::ContainsIncludingPseudoElement(
          container, *layout_tree_rebuild_root_.GetRootNode()));
    }
    RebuildLayoutTree(&container);
  }

  // Update quotes only if there are any scopes marked dirty.
  if (StyleContainmentScopeTree* tree = GetStyleContainmentScopeTree()) {
    tree->UpdateQuotes();
  }
  if (container == GetDocument().documentElement()) {
    // If the container is the root element, there may be body styles which have
    // changed as a result of the new container query evaluation, and if
    // properties propagated from body changed, we need to update the viewport
    // styles.
    GetStyleResolver().PropagateStyleToViewport();
  }
  GetDocument().GetLayoutView()->UpdateMarkersAndCountersAfterStyleChange(
      container.GetLayoutObject());
}

void StyleEngine::UpdateStyleForOutOfFlow(Element& element,
                                          const CSSPropertyValueSet* try_set,
                                          const TryTacticList& tactic_list,
                                          AnchorEvaluator* anchor_evaluator) {
  // Note that we enter this function for any OOF element, not just those that
  // use position-try-options. Therefore, it's important to return without
  // doing style recalc when anchor positioning features are not in use.

  const CSSPropertyValueSet* try_tactics_set =
      try_value_flips_.FlipSet(tactic_list);

  bool needs_update = try_set || try_tactics_set;

  if (element.ComputedStyleRef().PositionAnchor() ||
      element.ImplicitAnchorElement()) {
    // anchor-center offsets may need to be updated since the layout of the
    // anchor may have changed. anchor-center offsets are computed when a
    // default anchor is present.
    needs_update = true;
  }
  if (element.ComputedStyleRef().HasAnchorFunctions()) {
    needs_update = true;
  }

  if (!needs_update) {
    CHECK(!try_set);
    CHECK(!try_tactics_set);
    return;
  }

  base::AutoReset<bool> pt_recalc(&in_position_try_style_recalc_, true);

  UpdateViewportSize();

  StyleRecalcContext style_recalc_context =
      StyleRecalcContext::FromAncestors(element);
  style_recalc_context.is_interleaved_oof = true;
  style_recalc_context.anchor_evaluator = anchor_evaluator;
  style_recalc_context.try_set = try_set;
  style_recalc_context.try_tactics_set = try_tactics_set;

  StyleRecalcChange change = StyleRecalcChange().ForceRecalcChildren();

  if (auto* pseudo_element = DynamicTo<PseudoElement>(element)) {
    RecalcPositionTryStyleForPseudoElement(*pseudo_element, change,
                                           style_recalc_context);
  } else {
    element.SetChildNeedsStyleRecalc();
    style_recalc_root_.Update(nullptr, &element);
    RecalcStyle(change, style_recalc_context);
  }
}

StyleRulePositionTry* StyleEngine::GetPositionTryRule(
    const ScopedCSSName& scoped_name) {
  const TreeScope* tree_scope = scoped_name.GetTreeScope();
  if (!tree_scope) {
    tree_scope = &GetDocument();
  }
  return GetStyleResolver().ResolvePositionTryRule(tree_scope,
                                                   scoped_name.GetName());
}

void StyleEngine::RecalcStyle(StyleRecalcChange change,
                              const StyleRecalcContext& style_recalc_context) {
  DCHECK(GetDocument().documentElement());
  ScriptForbiddenScope forbid_script;
  SkipStyleRecalcScope skip_scope(*this);
  CheckPseudoHasCacheScope check_pseudo_has_cache_scope(
      &GetDocument(), /*within_selector_checking=*/false);
  Element& root_element = style_recalc_root_.RootElement();
  Element* parent = FlatTreeTraversal::ParentElement(root_element);

  SelectorFilterRootScope filter_scope(parent);
  root_element.RecalcStyle(change, style_recalc_context);

  for (ContainerNode* ancestor = root_element.GetStyleRecalcParent(); ancestor;
       ancestor = ancestor->GetStyleRecalcParent()) {
    if (auto* ancestor_element = DynamicTo<Element>(ancestor)) {
      ancestor_element->RecalcStyleForTraversalRootAncestor();
    }
    ancestor->ClearChildNeedsStyleRecalc();
  }
  style_recalc_root_.Clear();
  if (!parent || IsA<HTMLBodyElement>(root_element)) {
    PropagateWritingModeAndDirectionToHTMLRoot();
  }
}

void StyleEngine::RecalcPositionTryStyleForPseudoElement(
    PseudoElement& pseudo_element,
    const StyleRecalcChange style_recalc_change,
    const StyleRecalcContext& style_recalc_context) {
  ScriptForbiddenScope forbid_script;
  SkipStyleRecalcScope skip_scope(*this);
  CheckPseudoHasCacheScope check_pseudo_has_cache_scope(
      &GetDocument(), /*within-selector_checking=*/false);
  SelectorFilterRootScope filter_scope(
      FlatTreeTraversal::ParentElement(*pseudo_element.OriginatingElement()));
  pseudo_element.RecalcStyle(style_recalc_change, style_recalc_context);
}

void StyleEngine::RecalcTransitionPseudoStyle() {
  // TODO(khushalsagar) : This forces a style recalc and layout tree rebuild
  // for the pseudo element tree each time we do a style recalc phase. See if
  // we can optimize this to only when the pseudo element tree is dirtied.
  SelectorFilterRootScope filter_scope(nullptr);
  document_->documentElement()->RecalcTransitionPseudoTreeStyle(
      view_transition_names_);
}

void StyleEngine::RecalcStyle() {
  RecalcStyle(
      {}, StyleRecalcContext::FromAncestors(style_recalc_root_.RootElement()));
  RecalcTransitionPseudoStyle();
}

void StyleEngine::ClearEnsuredDescendantStyles(Element& root) {
  Node* current = &root;
  while (current) {
    if (auto* element = DynamicTo<Element>(current)) {
      if (const auto* style = element->GetComputedStyle()) {
        DCHECK(style->IsEnsuredOutsideFlatTree());
        element->SetComputedStyle(nullptr);
        element->ClearNeedsStyleRecalc();
        element->ClearChildNeedsStyleRecalc();
        current = FlatTreeTraversal::Next(*current, &root);
        continue;
      }
    }
    current = FlatTreeTraversal::NextSkippingChildren(*current, &root);
  }
}

void StyleEngine::RebuildLayoutTreeForTraversalRootAncestors(
    Element* parent,
    Element* container_parent) {
  bool is_container_ancestor = false;

  for (auto* ancestor = parent; ancestor;
       ancestor = ancestor->GetReattachParent()) {
    if (ancestor == container_parent) {
      is_container_ancestor = true;
    }
    if (is_container_ancestor) {
      ancestor->RebuildLayoutTreeForSizeContainerAncestor();
    } else {
      ancestor->RebuildLayoutTreeForTraversalRootAncestor();
    }
    ancestor->ClearChildNeedsStyleRecalc();
    ancestor->ClearChildNeedsReattachLayoutTree();
  }
}

void StyleEngine::RebuildLayoutTree(Element* size_container) {
  bool propagate_to_root = false;
  {
    DCHECK(GetDocument().documentElement());
    DCHECK(!InRebuildLayoutTree());
    base::AutoReset<bool> rebuild_scope(&in_layout_tree_rebuild_, true);

    // We need a root scope here in case we recalc style for ::first-letter
    // elements as part of UpdateFirstLetterPseudoElement.
    SelectorFilterRootScope filter_scope(nullptr);

    Element& root_element = layout_tree_rebuild_root_.RootElement();
    {
      WhitespaceAttacher whitespace_attacher;
      root_element.RebuildLayoutTree(whitespace_attacher);
    }

    Element* container_parent =
        size_container ? size_container->GetReattachParent() : nullptr;
    RebuildLayoutTreeForTraversalRootAncestors(root_element.GetReattachParent(),
                                               container_parent);
    if (size_container == nullptr) {
      document_->documentElement()->RebuildTransitionPseudoLayoutTree(
          view_transition_names_);
    }
    layout_tree_rebuild_root_.Clear();
    propagate_to_root = IsA<HTMLHtmlElement>(root_element) ||
                        IsA<HTMLBodyElement>(root_element);
  }
  if (propagate_to_root) {
    PropagateWritingModeAndDirectionToHTMLRoot();
    if (NeedsLayoutTreeRebuild()) {
      RebuildLayoutTree(size_container);
    }
  }
}

void StyleEngine::ReattachContainerSubtree(Element& container) {
  // Generally, the container itself should not be marked for re-attachment. In
  // the case where we have a fieldset as a container, the fieldset itself is
  // marked for re-attachment in HTMLFieldSetElement::DidRecalcStyle to make
  // sure the rendered legend is appropriately placed in the layout tree. We
  // cannot re-attach the fieldset itself in this case since we are in the
  // process of laying it out. Instead we re-attach all children, which should
  // be sufficient.

  DCHECK(container.NeedsReattachLayoutTree());
  DCHECK(DynamicTo<HTMLFieldSetElement>(container));

  base::AutoReset<bool> rebuild_scope(&in_layout_tree_rebuild_, true);
  container.ReattachLayoutTreeChildren(base::PassKey<StyleEngine>());
  RebuildLayoutTreeForTraversalRootAncestors(&container,
                                             container.GetReattachParent());
  layout_tree_rebuild_root_.Clear();
}

void StyleEngine::UpdateStyleAndLayoutTree() {
  // All of layout tree dirtiness and rebuilding needs to happen on a stable
  // flat tree. We have an invariant that all of that happens in this method
  // as a result of style recalc and the following layout tree rebuild.
  //
  // NeedsReattachLayoutTree() marks dirty up the flat tree ancestors. Re-
  // slotting on a dirty tree could break ancestor chains and fail to update the
  // tree properly.
  DCHECK(!NeedsLayoutTreeRebuild());

  UpdateViewportStyle();

  if (GetDocument().documentElement()) {
    UpdateViewportSize();
    NthIndexCache nth_index_cache(GetDocument());
    if (NeedsStyleRecalc()) {
      TRACE_EVENT0("blink,blink_style", "Document::recalcStyle");
      SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RecalcTime");
      Element* viewport_defining = GetDocument().ViewportDefiningElement();
      RecalcStyle();
      if (viewport_defining != GetDocument().ViewportDefiningElement()) {
        ViewportDefiningElementDidChange();
      }
    }
    if (NeedsLayoutTreeRebuild()) {
      TRACE_EVENT0("blink,blink_style", "Document::rebuildLayoutTree");
      SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RebuildLayoutTreeTime");
      RebuildLayoutTree();
    }
    // Update quotes only if there are any scopes marked dirty.
    if (StyleContainmentScopeTree* tree = GetStyleContainmentScopeTree()) {
      tree->UpdateQuotes();
    }
  } else {
    style_recalc_root_.Clear();
  }
  UpdateColorSchemeBackground();
  GetStyleResolver().PropagateStyleToViewport();
}

void StyleEngine::ViewportDefiningElementDidChange() {
  // Guarded by if-test in UpdateStyleAndLayoutTree().
  DCHECK(GetDocument().documentElement());

  // No need to update a layout object which will be destroyed.
  if (GetDocument().documentElement()->NeedsReattachLayoutTree()) {
    return;
  }
  HTMLBodyElement* body = GetDocument().FirstBodyElement();
  if (!body || body->NeedsReattachLayoutTree()) {
    return;
  }

  LayoutObject* layout_object = body->GetLayoutObject();
  if (layout_object && layout_object->IsLayoutBlock()) {
    // When the overflow style for documentElement changes to or from visible,
    // it changes whether the body element's box should have scrollable overflow
    // on its own box or propagated to the viewport. If the body style did not
    // need a recalc, this will not be updated as its done as part of setting
    // ComputedStyle on the LayoutObject. Force a SetStyle for body when the
    // ViewportDefiningElement changes in order to trigger an update of
    // IsScrollContainer() and the PaintLayer in StyleDidChange().
    //
    // This update is also necessary if the first body element changes because
    // another body element is inserted or removed.
    layout_object->SetStyle(
        ComputedStyleBuilder(*layout_object->Style()).TakeStyle());
  }
}

void StyleEngine::FirstBodyElementChanged(HTMLBodyElement* body) {
  // If a body element changed status as being the first body element or not,
  // it might have changed its needs for scrollbars even if the style didn't
  // change. Marking it for recalc here will make sure a new ComputedStyle is
  // set on the layout object for the next style recalc, and the scrollbars will
  // be updated in LayoutObject::SetStyle(). SetStyle cannot be called here
  // directly because SetStyle() relies on style information to be up-to-date,
  // otherwise scrollbar style update might crash.
  //
  // If the body parameter is null, it means the last body is removed. Removing
  // an element does not cause a style recalc on its own, which means we need
  // to force an update of the documentElement to remove used writing-mode and
  // direction which was previously propagated from the removed body element.
  Element* dirty_element = body ? body : GetDocument().documentElement();
  DCHECK(dirty_element);
  if (body) {
    LayoutObject* layout_object = body->GetLayoutObject();
    if (!layout_object || !layout_object->IsLayoutBlock()) {
      return;
    }
  }
  dirty_element->SetNeedsStyleRecalc(
      kLocalStyleChange, StyleChangeReasonForTracing::Create(
                             style_change_reason::kViewportDefiningElement));
}

void StyleEngine::UpdateStyleInvalidationRoot(ContainerNode* ancestor,
                                              Node* dirty_node) {
  if (GetDocument().IsActive()) {
    if (InDOMRemoval()) {
      ancestor = nullptr;
      dirty_node = document_;
    }
    style_invalidation_root_.Update(ancestor, dirty_node);
  }
}

void StyleEngine::UpdateStyleRecalcRoot(ContainerNode* ancestor,
                                        Node* dirty_node) {
  if (!GetDocument().IsActive()) {
    return;
  }
  // We have at least one instance where we mark style dirty from style recalc
  // (from LayoutTextControl::StyleDidChange()). That means we are in the
  // process of traversing down the tree from the recalc root. Any updates to
  // the style recalc root will be cleared after the style recalc traversal
  // finishes and updating it may just trigger sanity DCHECKs in
  // StyleTraversalRoot. Just return here instead.
  if (GetDocument().InStyleRecalc()) {
    DCHECK(allow_mark_style_dirty_from_recalc_);
    return;
  }
  DCHECK(!InRebuildLayoutTree());
  if (InDOMRemoval()) {
    ancestor = nullptr;
    dirty_node = document_;
  }
#if DCHECK_IS_ON()
  DCHECK(!dirty_node || DisplayLockUtilities::AssertStyleAllowed(*dirty_node));
#endif
  style_recalc_root_.Update(ancestor, dirty_node);
}

void StyleEngine::UpdateLayoutTreeRebuildRoot(ContainerNode* ancestor,
                                              Node* dirty_node) {
  DCHECK(!InDOMRemoval());
  if (!GetDocument().IsActive()) {
    return;
  }
  if (InRebuildLayoutTree()) {
    DCHECK(allow_mark_for_reattach_from_rebuild_layout_tree_);
    return;
  }
#if DCHECK_IS_ON()
  DCHECK(GetDocument().InStyleRecalc());
  DCHECK(dirty_node);
  DCHECK(DisplayLockUtilities::AssertStyleAllowed(*dirty_node));
#endif
  layout_tree_rebuild_root_.Update(ancestor, dirty_node);
}

namespace {

Node* AnalysisParent(const Node& node) {
  return IsA<ShadowRoot>(node) ? node.ParentOrShadowHostElement()
                               : LayoutTreeBuilderTraversal::Parent(node);
}

bool IsRootOrSibling(const Node* root, const Node& node) {
  if (!root) {
    return false;
  }
  if (root == &node) {
    return true;
  }
  if (Node* root_parent = AnalysisParent(*root)) {
    return root_parent == AnalysisParent(node);
  }
  return false;
}

}  // namespace

StyleEngine::AncestorAnalysis StyleEngine::AnalyzeInclusiveAncestor(
    const Node& node) {
  if (IsRootOrSibling(style_recalc_root_.GetRootNode(), node)) {
    return AncestorAnalysis::kStyleRoot;
  }
  if (IsRootOrSibling(style_invalidation_root_.GetRootNode(), node)) {
    return AncestorAnalysis::kStyleRoot;
  }
  if (ComputedStyle::IsInterleavingRoot(node.GetComputedStyle())) {
    return AncestorAnalysis::kInterleavingRoot;
  }
  return AncestorAnalysis::kNone;
}

StyleEngine::AncestorAnalysis StyleEngine::AnalyzeExclusiveAncestor(
    const Node& node) {
  if (DisplayLockUtilities::IsPotentialStyleRecalcRoot(node)) {
    return AncestorAnalysis::kStyleRoot;
  }
  return AnalyzeInclusiveAncestor(node);
}

StyleEngine::AncestorAnalysis StyleEngine::AnalyzeAncestors(const Node& node) {
  AncestorAnalysis analysis = AnalyzeInclusiveAncestor(node);

  for (const Node* ancestor = LayoutTreeBuilderTraversal::Parent(node);
       ancestor; ancestor = LayoutTreeBuilderTraversal::Parent(*ancestor)) {
    // Already at maximum severity, no need to proceed.
    if (analysis == AncestorAnalysis::kStyleRoot) {
      return analysis;
    }

    // LayoutTreeBuilderTraversal::Parent skips ShadowRoots, so we check it
    // explicitly here.
    if (ShadowRoot* root = ancestor->GetShadowRoot()) {
      analysis = std::max(analysis, AnalyzeExclusiveAncestor(*root));
    }

    analysis = std::max(analysis, AnalyzeExclusiveAncestor(*ancestor));
  }

  return analysis;
}

bool StyleEngine::MarkReattachAllowed() const {
  return !InRebuildLayoutTree() ||
         allow_mark_for_reattach_from_rebuild_layout_tree_;
}

bool StyleEngine::MarkStyleDirtyAllowed() const {
  if (GetDocument().InStyleRecalc() || InContainerQueryStyleRecalc()) {
    return allow_mark_style_dirty_from_recalc_;
  }
  return !InRebuildLayoutTree();
}

bool StyleEngine::SupportsDarkColorScheme() {
  return (page_color_schemes_ &
          static_cast<ColorSchemeFlags>(ColorSchemeFlag::kDark)) &&
         (!(page_color_schemes_ &
            static_cast<ColorSchemeFlags>(ColorSchemeFlag::kLight)) ||
          preferred_color_scheme_ == mojom::blink::PreferredColorScheme::kDark);
}

void StyleEngine::UpdateColorScheme() {
  auto* settings = GetDocument().GetSettings();
  if (!settings) {
    return;
  }

  ForcedColors old_forced_colors = forced_colors_;
  forced_colors_ = settings->GetInForcedColors() ? ForcedColors::kActive
                                                 : ForcedColors::kNone;

  mojom::blink::PreferredColorScheme old_preferred_color_scheme =
      preferred_color_scheme_;
  preferred_color_scheme_ = settings->GetPreferredColorScheme();
  bool old_force_dark_mode_enabled = force_dark_mode_enabled_;
  force_dark_mode_enabled_ = settings->GetForceDarkModeEnabled();
  bool media_feature_override_color_scheme = false;

  // TODO(1479201): Should DevTools emulation use the WebPreferences API
  // overrides?
  if (const MediaFeatureOverrides* overrides =
          GetDocument().GetPage()->GetMediaFeatureOverrides()) {
    if (std::optional<ForcedColors> forced_color_override =
            overrides->GetForcedColors()) {
      forced_colors_ = forced_color_override.value();
    }
    if (std::optional<mojom::blink::PreferredColorScheme>
            preferred_color_scheme_override =
                overrides->GetPreferredColorScheme()) {
      preferred_color_scheme_ = preferred_color_scheme_override.value();
      media_feature_override_color_scheme = true;
    }
  }

  const PreferenceOverrides* preference_overrides =
      GetDocument().GetPage()->GetPreferenceOverrides();
  if (preference_overrides && !media_feature_override_color_scheme) {
    std::optional<mojom::blink::PreferredColorScheme>
        preferred_color_scheme_override =
            preference_overrides->GetPreferredColorScheme();
    if (preferred_color_scheme_override.has_value()) {
      preferred_color_scheme_ = preferred_color_scheme_override.value();
    }
  }

  if (GetDocument().Printing()) {
    preferred_color_scheme_ = mojom::blink::PreferredColorScheme::kLight;
    force_dark_mode_enabled_ = false;
  }

  if (forced_colors_ != old_forced_colors ||
      preferred_color_scheme_ != old_preferred_color_scheme ||
      force_dark_mode_enabled_ != old_force_dark_mode_enabled) {
    PlatformColorsChanged();
  }

  UpdateColorSchemeMetrics();
}

void StyleEngine::UpdateColorSchemeMetrics() {
  auto* settings = GetDocument().GetSettings();
  if (settings->GetForceDarkModeEnabled()) {
    UseCounter::Count(GetDocument(), WebFeature::kForcedDarkMode);
  }

  // True if the preferred color scheme will match dark.
  if (preferred_color_scheme_ == mojom::blink::PreferredColorScheme::kDark) {
    UseCounter::Count(GetDocument(), WebFeature::kPreferredColorSchemeDark);
  }

  // This is equal to kPreferredColorSchemeDark in most cases, but can differ
  // with forced dark mode. With the system in dark mode and forced dark mode
  // enabled, the preferred color scheme can be light while the setting is dark.
  if (settings->GetPreferredColorScheme() ==
      mojom::blink::PreferredColorScheme::kDark) {
    UseCounter::Count(GetDocument(),
                      WebFeature::kPreferredColorSchemeDarkSetting);
  }

  // Record kColorSchemeDarkSupportedOnRoot if the meta color-scheme contains
  // dark (though dark may not be used). This metric is also recorded in
  // longhands_custom.cc (see: ColorScheme::ApplyValue) if the root style
  // color-scheme contains dark.
  if (page_color_schemes_ &
      static_cast<ColorSchemeFlags>(ColorSchemeFlag::kDark)) {
    UseCounter::Count(GetDocument(),
                      WebFeature::kColorSchemeDarkSupportedOnRoot);
  }
}

void StyleEngine::ColorSchemeChanged() {
  UpdateColorScheme();
}

void StyleEngine::SetPageColorSchemes(const CSSValue* color_scheme) {
  if (!GetDocument().IsActive()) {
    return;
  }

  if (auto* value_list = DynamicTo<CSSValueList>(color_scheme)) {
    page_color_schemes_ = StyleBuilderConverter::ExtractColorSchemes(
        GetDocument(), *value_list, nullptr /* color_schemes */);
  } else {
    page_color_schemes_ =
        static_cast<ColorSchemeFlags>(ColorSchemeFlag::kNormal);
  }
  DCHECK(GetDocument().documentElement());
  // kSubtreeStyleChange is necessary since the page color schemes may affect
  // used values of any element in the document with a specified color-scheme of
  // 'normal'. A more targeted invalidation would need to traverse the whole
  // document tree for specified values.
  GetDocument().documentElement()->SetNeedsStyleRecalc(
      kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
                               style_change_reason::kPlatformColorChange));
  UpdateColorScheme();
  UpdateColorSchemeBackground();
}

void StyleEngine::UpdateColorSchemeBackground(bool color_scheme_changed) {
  LocalFrameView* view = GetDocument().View();
  if (!view) {
    return;
  }

  LocalFrameView::UseColorAdjustBackground use_color_adjust_background =
      LocalFrameView::UseColorAdjustBackground::kNo;

  if (forced_colors_ != ForcedColors::kNone) {
    if (GetDocument().IsInMainFrame()) {
      use_color_adjust_background =
          LocalFrameView::UseColorAdjustBackground::kIfBaseNotTransparent;
    }
  } else {
    // Find out if we should use a canvas color that is different from the
    // view's base background color in order to match the root element color-
    // scheme. See spec:
    // https://drafts.csswg.org/css-color-adjust/#color-scheme-effect
    mojom::blink::ColorScheme root_color_scheme =
        mojom::blink::ColorScheme::kLight;
    if (auto* root_element = GetDocument().documentElement()) {
      if (const ComputedStyle* style = root_element->GetComputedStyle()) {
        root_color_scheme = style->UsedColorScheme();
      } else if (SupportsDarkColorScheme()) {
        root_color_scheme = mojom::blink::ColorScheme::kDark;
      }
    }
    color_scheme_background_ =
        root_color_scheme == mojom::blink::ColorScheme::kLight
            ? Color::kWhite
            : Color(0x12, 0x12, 0x12);
    if (GetDocument().IsInMainFrame()) {
      if (root_color_scheme == mojom::blink::ColorScheme::kDark) {
        use_color_adjust_background =
            LocalFrameView::UseColorAdjustBackground::kIfBaseNotTransparent;
      }
    } else if (
        root_color_scheme != owner_color_scheme_ &&
        // https://html.spec.whatwg.org/C#is-initial-about:blank
        !view->GetFrame().Loader().IsOnInitialEmptyDocument()) {
      // Iframes should paint a solid background if the embedding iframe has a
      // used color-scheme different from the used color-scheme of the embedded
      // root element. Normally, iframes as transparent by default.
      use_color_adjust_background =
          LocalFrameView::UseColorAdjustBackground::kYes;
    }
  }

  view->SetUseColorAdjustBackground(use_color_adjust_background,
                                    color_scheme_changed);
}

void StyleEngine::SetOwnerColorScheme(mojom::blink::ColorScheme color_scheme) {
  DCHECK(!GetDocument().IsInMainFrame());
  if (owner_color_scheme_ == color_scheme) {
    return;
  }
  owner_color_scheme_ = color_scheme;
  UpdateColorSchemeBackground(true);
}

mojom::blink::PreferredColorScheme StyleEngine::ResolveColorSchemeForEmbedding(
    const ComputedStyle* embedder_style) const {
  const bool embedder_color_scheme_is_normal =
      !embedder_style || embedder_style->ColorScheme().empty();
  // ...if 'color-scheme' is 'normal' and there's no 'color-scheme' meta tag,
  // the propagated scheme is the preferred color-scheme of the embedder
  // document.
  if (embedder_color_scheme_is_normal &&
      GetPageColorSchemes() ==
          static_cast<ColorSchemeFlags>(ColorSchemeFlag::kNormal)) {
    return GetPreferredColorScheme();
  }
  return embedder_style && embedder_style->UsedColorScheme() ==
                               mojom::blink::ColorScheme::kDark
             ? mojom::blink::PreferredColorScheme::kDark
             : mojom::blink::PreferredColorScheme::kLight;
}

void StyleEngine::UpdateForcedBackgroundColor() {
  CHECK(GetDocument().GetPage());
  mojom::blink::ColorScheme color_scheme = mojom::blink::ColorScheme::kLight;
  forced_background_color_ = LayoutTheme::GetTheme().SystemColor(
      CSSValueID::kCanvas, color_scheme,
      GetDocument().GetPage()->GetColorProviderForPainting(
          color_scheme, forced_colors_ != ForcedColors::kNone));
}

Color StyleEngine::ColorAdjustBackgroundColor() const {
  if (forced_colors_ != ForcedColors::kNone) {
    return ForcedBackgroundColor();
  }
  return color_scheme_background_;
}

void StyleEngine::MarkAllElementsForStyleRecalc(
    const StyleChangeReasonForTracing& reason) {
  if (Element* root = GetDocument().documentElement()) {
    root->SetNeedsStyleRecalc(kSubtreeStyleChange, reason);
  }
}

void StyleEngine::UpdateViewportStyle() {
  if (!viewport_style_dirty_) {
    return;
  }

  viewport_style_dirty_ = false;

  if (!resolver_) {
    return;
  }

  const ComputedStyle* viewport_style = resolver_->StyleForViewport();
  if (ComputedStyle::ComputeDifference(
          viewport_style, GetDocument().GetLayoutView()->Style()) !=
      ComputedStyle::Difference::kEqual) {
    GetDocument().GetLayoutView()->SetStyle(viewport_style);
  }
}

bool StyleEngine::NeedsFullStyleUpdate() const {
  return NeedsActiveStyleUpdate() || IsViewportStyleDirty() ||
         viewport_unit_dirty_flags_;
}

void StyleEngine::PropagateWritingModeAndDirectionToHTMLRoot() {
  if (HTMLHtmlElement* root_element =
          DynamicTo<HTMLHtmlElement>(GetDocument().documentElement())) {
    root_element->PropagateWritingModeAndDirectionFromBody();
  }
}

CounterStyleMap& StyleEngine::EnsureUserCounterStyleMap() {
  if (!user_counter_style_map_) {
    user_counter_style_map_ =
        CounterStyleMap::CreateUserCounterStyleMap(GetDocument());
  }
  return *user_counter_style_map_;
}

const CounterStyle& StyleEngine::FindCounterStyleAcrossScopes(
    const AtomicString& name,
    const TreeScope* scope) const {
  CounterStyleMap* target_map = nullptr;
  while (scope) {
    if (CounterStyleMap* map =
            CounterStyleMap::GetAuthorCounterStyleMap(*scope)) {
      target_map = map;
      break;
    }
    scope = scope->ParentTreeScope();
  }
  if (!target_map && user_counter_style_map_) {
    target_map = user_counter_style_map_;
  }
  if (!target_map) {
    target_map = CounterStyleMap::GetUACounterStyleMap();
  }
  if (CounterStyle* result = target_map->FindCounterStyleAcrossScopes(name)) {
    return *result;
  }
  return CounterStyle::GetDecimal();
}

void StyleEngine::Trace(Visitor* visitor) const {
  visitor->Trace(document_);
  visitor->Trace(injected_user_style_sheets_);
  visitor->Trace(injected_author_style_sheets_);
  visitor->Trace(active_user_style_sheets_);
  visitor->Trace(keyframes_rule_map_);
  visitor->Trace(font_palette_values_rule_map_);
  visitor->Trace(user_counter_style_map_);
  visitor->Trace(user_cascade_layer_map_);
  visitor->Trace(inspector_style_sheet_);
  visitor->Trace(document_style_sheet_collection_);
  visitor->Trace(style_sheet_collection_map_);
  visitor->Trace(dirty_tree_scopes_);
  visitor->Trace(active_tree_scopes_);
  visitor->Trace(resolver_);
  visitor->Trace(vision_deficiency_filter_);
  visitor->Trace(viewport_resolver_);
  visitor->Trace(media_query_evaluator_);
  visitor->Trace(global_rule_set_);
  visitor->Trace(pending_invalidations_);
  visitor->Trace(style_invalidation_root_);
  visitor->Trace(style_recalc_root_);
  visitor->Trace(layout_tree_rebuild_root_);
  visitor->Trace(font_selector_);
  visitor->Trace(text_to_sheet_cache_);
  visitor->Trace(tracker_);
  visitor->Trace(text_tracks_);
  visitor->Trace(vtt_originating_element_);
  visitor->Trace(parent_for_detached_subtree_);
  visitor->Trace(view_transition_rule_);
  visitor->Trace(style_image_cache_);
  visitor->Trace(fill_or_clip_path_uri_value_cache_);
  visitor->Trace(style_containment_scope_tree_);
  visitor->Trace(try_value_flips_);
  FontSelectorClient::Trace(visitor);
}

namespace {

inline bool MayHaveFlatTreeChildren(const Element& element) {
  return element.firstChild() || IsShadowHost(element) ||
         element.IsActiveSlot();
}

}  // namespace

void StyleEngine::MarkForLayoutTreeChangesAfterDetach() {
  if (!parent_for_detached_subtree_) {
    return;
  }
  auto* layout_object = parent_for_detached_subtree_.Get();
  if (auto* layout_object_element =
          DynamicTo<Element>(layout_object->GetNode())) {
    DCHECK_EQ(layout_object, layout_object_element->GetLayoutObject());

    // Mark the parent of a detached subtree for doing a whitespace or list item
    // update. These flags will be cause the element to be marked for layout
    // tree rebuild traversal during style recalc to make sure we revisit
    // whitespace text nodes and list items.

    bool mark_ancestors = false;

    // If there are no children left, no whitespace children may need
    // reattachment.
    if (MayHaveFlatTreeChildren(*layout_object_element)) {
      if (!layout_object->WhitespaceChildrenMayChange()) {
        layout_object->SetWhitespaceChildrenMayChange(true);
        mark_ancestors = true;
      }
    }
    if (!layout_object->WasNotifiedOfSubtreeChange()) {
      if (layout_object->NotifyOfSubtreeChange()) {
        mark_ancestors = true;
      }
    }
    if (mark_ancestors) {
      layout_object_element->MarkAncestorsWithChildNeedsStyleRecalc();
    }
  }
  parent_for_detached_subtree_ = nullptr;
}

void StyleEngine::InvalidateSVGResourcesAfterDetach() {
  GetDocument().InvalidatePendingSVGResources();
}

bool StyleEngine::AllowSkipStyleRecalcForScope() const {
  if (InContainerQueryStyleRecalc()) {
    return true;
  }
  if (LocalFrameView* view = GetDocument().View()) {
    // Existing layout roots before starting style recalc may end up being
    // inside skipped subtrees if we allowed skipping. If we start out with an
    // empty list, any added ones will be a result of an element style recalc,
    // which means the will not be inside a skipped subtree.
    return !view->IsSubtreeLayout();
  }
  return true;
}

void StyleEngine::AddCachedFillOrClipPathURIValue(const AtomicString& string,
                                                  const CSSValue& value) {
  fill_or_clip_path_uri_value_cache_.insert(string, &value);
}

const CSSValue* StyleEngine::GetCachedFillOrClipPathURIValue(
    const AtomicString& string) {
  auto it = fill_or_clip_path_uri_value_cache_.find(string);
  if (it == fill_or_clip_path_uri_value_cache_.end()) {
    return nullptr;
  }
  return it->value;
}

void StyleEngine::BaseURLChanged() {
  fill_or_clip_path_uri_value_cache_.clear();
}

void StyleEngine::UpdateViewportSize() {
  viewport_size_ =
      CSSToLengthConversionData::ViewportSize(GetDocument().GetLayoutView());
}

}  // namespace blink
