// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/css/parser/css_parser_impl.h"

#include <bitset>
#include <memory>
#include <utility>

#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_at_rule_id.h"
#include "third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h"
#include "third_party/blink/renderer/core/css/parser/css_lazy_property_parser_impl.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_observer.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_selector.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_selector_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_supports_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
#include "third_party/blink/renderer/core/css/parser/media_query_parser.h"
#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/css/style_rule_counter_style.h"
#include "third_party/blink/renderer/core/css/style_rule_import.h"
#include "third_party/blink/renderer/core/css/style_rule_keyframe.h"
#include "third_party/blink/renderer/core/css/style_rule_namespace.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"

namespace blink {

namespace {

// This may still consume tokens if it fails
AtomicString ConsumeStringOrURI(CSSParserTokenStream& stream) {
  const CSSParserToken& token = stream.Peek();

  if (token.GetType() == kStringToken || token.GetType() == kUrlToken)
    return stream.ConsumeIncludingWhitespace().Value().ToAtomicString();

  if (token.GetType() != kFunctionToken ||
      !EqualIgnoringASCIICase(token.Value(), "url"))
    return AtomicString();

  CSSParserTokenStream::BlockGuard guard(stream);
  const CSSParserToken& uri = stream.ConsumeIncludingWhitespace();
  if (uri.GetType() == kBadStringToken || !stream.UncheckedAtEnd())
    return AtomicString();
  DCHECK_EQ(uri.GetType(), kStringToken);
  return uri.Value().ToAtomicString();
}

}  // namespace

CSSParserImpl::CSSParserImpl(const CSSParserContext* context,
                             StyleSheetContents* style_sheet)
    : context_(context),
      style_sheet_(style_sheet),
      observer_(nullptr),
      lazy_state_(nullptr) {}

MutableCSSPropertyValueSet::SetResult CSSParserImpl::ParseValue(
    MutableCSSPropertyValueSet* declaration,
    CSSPropertyID unresolved_property,
    const String& string,
    bool important,
    const CSSParserContext* context) {
  STACK_UNINITIALIZED CSSParserImpl parser(context);
  StyleRule::RuleType rule_type = StyleRule::kStyle;
  if (declaration->CssParserMode() == kCSSViewportRuleMode)
    rule_type = StyleRule::kViewport;
  else if (declaration->CssParserMode() == kCSSFontFaceRuleMode)
    rule_type = StyleRule::kFontFace;
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  CSSTokenizedValue tokenized_value = ConsumeValue(stream);
  parser.ConsumeDeclarationValue(tokenized_value, unresolved_property,
                                 important, rule_type);
  bool did_parse = false;
  bool did_change = false;
  if (!parser.parsed_properties_.IsEmpty()) {
    did_parse = true;
    did_change = declaration->AddParsedProperties(parser.parsed_properties_);
  }
  return MutableCSSPropertyValueSet::SetResult{did_parse, did_change};
}

MutableCSSPropertyValueSet::SetResult CSSParserImpl::ParseVariableValue(
    MutableCSSPropertyValueSet* declaration,
    const AtomicString& property_name,
    const String& value,
    bool important,
    const CSSParserContext* context,
    bool is_animation_tainted) {
  STACK_UNINITIALIZED CSSParserImpl parser(context);
  CSSTokenizer tokenizer(value);
  CSSParserTokenStream stream(tokenizer);
  CSSTokenizedValue tokenized_value = ConsumeValue(stream);
  parser.ConsumeVariableValue(tokenized_value, property_name, important,
                              is_animation_tainted);
  bool did_parse = false;
  bool did_change = false;
  if (!parser.parsed_properties_.IsEmpty()) {
    did_parse = true;
    did_change = declaration->AddParsedProperties(parser.parsed_properties_);
  }
  return MutableCSSPropertyValueSet::SetResult{did_parse, did_change};
}

static inline void FilterProperties(
    bool important,
    const HeapVector<CSSPropertyValue, 256>& input,
    HeapVector<CSSPropertyValue, 256>& output,
    wtf_size_t& unused_entries,
    std::bitset<kNumCSSProperties>& seen_properties,
    HashSet<AtomicString>& seen_custom_properties) {
  // Add properties in reverse order so that highest priority definitions are
  // reached first. Duplicate definitions can then be ignored when found.
  for (wtf_size_t i = input.size(); i--;) {
    const CSSPropertyValue& property = input[i];
    if (property.IsImportant() != important)
      continue;
    if (property.Id() == CSSPropertyID::kVariable) {
      const AtomicString& name =
          To<CSSCustomPropertyDeclaration>(property.Value())->GetName();
      if (seen_custom_properties.Contains(name))
        continue;
      seen_custom_properties.insert(name);
    } else {
      const unsigned property_id_index = GetCSSPropertyIDIndex(property.Id());
      if (seen_properties.test(property_id_index))
        continue;
      seen_properties.set(property_id_index);
    }
    output[--unused_entries] = property;
  }
}

static ImmutableCSSPropertyValueSet* CreateCSSPropertyValueSet(
    HeapVector<CSSPropertyValue, 256>& parsed_properties,
    CSSParserMode mode) {
  std::bitset<kNumCSSProperties> seen_properties;
  wtf_size_t unused_entries = parsed_properties.size();
  HeapVector<CSSPropertyValue, 256> results(unused_entries);
  HashSet<AtomicString> seen_custom_properties;

  FilterProperties(true, parsed_properties, results, unused_entries,
                   seen_properties, seen_custom_properties);
  FilterProperties(false, parsed_properties, results, unused_entries,
                   seen_properties, seen_custom_properties);

  ImmutableCSSPropertyValueSet* result = ImmutableCSSPropertyValueSet::Create(
      results.data() + unused_entries, results.size() - unused_entries, mode);
  parsed_properties.clear();
  return result;
}

ImmutableCSSPropertyValueSet* CSSParserImpl::ParseInlineStyleDeclaration(
    const String& string,
    Element* element) {
  Document& document = element->GetDocument();
  auto* context = MakeGarbageCollected<CSSParserContext>(
      document.ElementSheet().Contents()->ParserContext(), &document);
  CSSParserMode mode = element->IsHTMLElement() && !document.InQuirksMode()
                           ? kHTMLStandardMode
                           : kHTMLQuirksMode;
  context->SetMode(mode);
  CSSParserImpl parser(context, document.ElementSheet().Contents());
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  parser.ConsumeDeclarationList(stream, StyleRule::kStyle);
  return CreateCSSPropertyValueSet(parser.parsed_properties_, mode);
}

ImmutableCSSPropertyValueSet* CSSParserImpl::ParseInlineStyleDeclaration(
    const String& string,
    CSSParserMode parser_mode,
    SecureContextMode secure_context_mode) {
  auto* context =
      MakeGarbageCollected<CSSParserContext>(parser_mode, secure_context_mode);
  CSSParserImpl parser(context);
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  parser.ConsumeDeclarationList(stream, StyleRule::kStyle);
  return CreateCSSPropertyValueSet(parser.parsed_properties_, parser_mode);
}

bool CSSParserImpl::ParseDeclarationList(
    MutableCSSPropertyValueSet* declaration,
    const String& string,
    const CSSParserContext* context) {
  CSSParserImpl parser(context);
  StyleRule::RuleType rule_type = StyleRule::kStyle;
  if (declaration->CssParserMode() == kCSSViewportRuleMode)
    rule_type = StyleRule::kViewport;
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  parser.ConsumeDeclarationList(stream, rule_type);
  if (parser.parsed_properties_.IsEmpty())
    return false;

  std::bitset<kNumCSSProperties> seen_properties;
  wtf_size_t unused_entries = parser.parsed_properties_.size();
  HeapVector<CSSPropertyValue, 256> results(unused_entries);
  HashSet<AtomicString> seen_custom_properties;
  FilterProperties(true, parser.parsed_properties_, results, unused_entries,
                   seen_properties, seen_custom_properties);
  FilterProperties(false, parser.parsed_properties_, results, unused_entries,
                   seen_properties, seen_custom_properties);
  if (unused_entries)
    results.EraseAt(0, unused_entries);
  return declaration->AddParsedProperties(results);
}

StyleRuleBase* CSSParserImpl::ParseRule(const String& string,
                                        const CSSParserContext* context,
                                        StyleSheetContents* style_sheet,
                                        AllowedRulesType allowed_rules) {
  CSSParserImpl parser(context, style_sheet);
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  stream.ConsumeWhitespace();
  if (stream.UncheckedAtEnd())
    return nullptr;  // Parse error, empty rule
  StyleRuleBase* rule;
  if (stream.UncheckedPeek().GetType() == kAtKeywordToken)
    rule = parser.ConsumeAtRule(stream, allowed_rules);
  else
    rule = parser.ConsumeQualifiedRule(stream, allowed_rules);
  if (!rule)
    return nullptr;  // Parse error, failed to consume rule
  stream.ConsumeWhitespace();
  if (!rule || !stream.UncheckedAtEnd())
    return nullptr;  // Parse error, trailing garbage
  return rule;
}

ParseSheetResult CSSParserImpl::ParseStyleSheet(
    const String& string,
    const CSSParserContext* context,
    StyleSheetContents* style_sheet,
    CSSDeferPropertyParsing defer_property_parsing,
    bool allow_import_rules) {
  TRACE_EVENT_BEGIN2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
                     "baseUrl", context->BaseURL().GetString().Utf8(), "mode",
                     context->Mode());

  TRACE_EVENT_BEGIN0("blink,blink_style",
                     "CSSParserImpl::parseStyleSheet.parse");
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  CSSParserImpl parser(context, style_sheet);
  if (defer_property_parsing == CSSDeferPropertyParsing::kYes) {
    parser.lazy_state_ = MakeGarbageCollected<CSSLazyParsingState>(
        context, string, parser.style_sheet_);
  }
  ParseSheetResult result = ParseSheetResult::kSucceeded;
  bool first_rule_valid = parser.ConsumeRuleList(
      stream, kTopLevelRuleList,
      [&style_sheet, &result, allow_import_rules,
       context](StyleRuleBase* rule) {
        if (rule->IsCharsetRule())
          return;
        if (rule->IsImportRule()) {
          if (!allow_import_rules || context->IsForMarkupSanitization()) {
            result = ParseSheetResult::kHasUnallowedImportRule;
            return;
          }
        }
        style_sheet->ParserAppendRule(rule);
      });
  style_sheet->SetHasSyntacticallyValidCSSHeader(first_rule_valid);
  TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");

  TRACE_EVENT_END2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
                   "tokenCount", tokenizer.TokenCount(), "length",
                   string.length());
  return result;
}

CSSSelectorList CSSParserImpl::ParsePageSelector(
    CSSParserTokenRange range,
    StyleSheetContents* style_sheet) {
  // We only support a small subset of the css-page spec.
  range.ConsumeWhitespace();
  AtomicString type_selector;
  if (range.Peek().GetType() == kIdentToken)
    type_selector = range.Consume().Value().ToAtomicString();

  AtomicString pseudo;
  if (range.Peek().GetType() == kColonToken) {
    range.Consume();
    if (range.Peek().GetType() != kIdentToken)
      return CSSSelectorList();
    pseudo = range.Consume().Value().ToAtomicString();
  }

  range.ConsumeWhitespace();
  if (!range.AtEnd())
    return CSSSelectorList();  // Parse error; extra tokens in @page selector

  std::unique_ptr<CSSParserSelector> selector;
  if (!type_selector.IsNull() && pseudo.IsNull()) {
    selector = std::make_unique<CSSParserSelector>(
        QualifiedName(g_null_atom, type_selector, g_star_atom));
  } else {
    selector = std::make_unique<CSSParserSelector>();
    if (!pseudo.IsNull()) {
      selector->SetMatch(CSSSelector::kPagePseudoClass);
      selector->UpdatePseudoPage(pseudo.LowerASCII());
      if (selector->GetPseudoType() == CSSSelector::kPseudoUnknown)
        return CSSSelectorList();
    }
    if (!type_selector.IsNull()) {
      selector->PrependTagSelector(
          QualifiedName(g_null_atom, type_selector, g_star_atom));
    }
  }

  selector->SetForPage();
  Vector<std::unique_ptr<CSSParserSelector>> selector_vector;
  selector_vector.push_back(std::move(selector));
  CSSSelectorList selector_list =
      CSSSelectorList::AdoptSelectorVector(selector_vector);
  return selector_list;
}

std::unique_ptr<Vector<double>> CSSParserImpl::ParseKeyframeKeyList(
    const String& key_list) {
  CSSTokenizer tokenizer(key_list);
  // TODO(crbug.com/661854): Use streams instead of ranges
  return ConsumeKeyframeKeyList(CSSParserTokenRange(tokenizer.TokenizeToEOF()));
}

bool CSSParserImpl::ConsumeSupportsDeclaration(CSSParserTokenStream& stream) {
  DCHECK(parsed_properties_.IsEmpty());
  // Even though we might use an observer here, this is just to test if we
  // successfully parse the range, so we can temporarily remove the observer.
  CSSParserObserver* observer_copy = observer_;
  observer_ = nullptr;
  CSSParserTokenStream::RangeBoundary range_boundary(
      stream, CSSParserTokenType::kRightParenthesisToken);
  ConsumeDeclaration(stream, StyleRule::kStyle);
  observer_ = observer_copy;

  bool result = !parsed_properties_.IsEmpty();
  parsed_properties_.clear();
  return result;
}

void CSSParserImpl::ParseDeclarationListForInspector(
    const String& declaration,
    const CSSParserContext* context,
    CSSParserObserver& observer) {
  CSSParserImpl parser(context);
  parser.observer_ = &observer;
  CSSTokenizer tokenizer(declaration);
  observer.StartRuleHeader(StyleRule::kStyle, 0);
  observer.EndRuleHeader(1);
  CSSParserTokenStream stream(tokenizer);
  parser.ConsumeDeclarationList(stream, StyleRule::kStyle);
}

void CSSParserImpl::ParseStyleSheetForInspector(const String& string,
                                                const CSSParserContext* context,
                                                StyleSheetContents* style_sheet,
                                                CSSParserObserver& observer) {
  CSSParserImpl parser(context, style_sheet);
  parser.observer_ = &observer;
  CSSTokenizer tokenizer(string);
  CSSParserTokenStream stream(tokenizer);
  bool first_rule_valid = parser.ConsumeRuleList(
      stream, kTopLevelRuleList, [&style_sheet](StyleRuleBase* rule) {
        if (rule->IsCharsetRule())
          return;
        style_sheet->ParserAppendRule(rule);
      });
  style_sheet->SetHasSyntacticallyValidCSSHeader(first_rule_valid);
}

CSSPropertyValueSet* CSSParserImpl::ParseDeclarationListForLazyStyle(
    const String& string,
    wtf_size_t offset,
    const CSSParserContext* context) {
  CSSTokenizer tokenizer(string, offset);
  CSSParserTokenStream stream(tokenizer);
  CSSParserTokenStream::BlockGuard guard(stream);
  CSSParserImpl parser(context);
  parser.ConsumeDeclarationList(stream, StyleRule::kStyle);
  return CreateCSSPropertyValueSet(parser.parsed_properties_, context->Mode());
}

static CSSParserImpl::AllowedRulesType ComputeNewAllowedRules(
    CSSParserImpl::AllowedRulesType allowed_rules,
    StyleRuleBase* rule) {
  if (!rule || allowed_rules == CSSParserImpl::kKeyframeRules ||
      allowed_rules == CSSParserImpl::kFontFeatureRules ||
      allowed_rules == CSSParserImpl::kNoRules)
    return allowed_rules;
  DCHECK_LE(allowed_rules, CSSParserImpl::kRegularRules);
  if (rule->IsCharsetRule() || rule->IsImportRule())
    return CSSParserImpl::kAllowImportRules;
  if (rule->IsNamespaceRule())
    return CSSParserImpl::kAllowNamespaceRules;
  return CSSParserImpl::kRegularRules;
}

template <typename T>
bool CSSParserImpl::ConsumeRuleList(CSSParserTokenStream& stream,
                                    RuleListType rule_list_type,
                                    const T callback) {
  AllowedRulesType allowed_rules = kRegularRules;
  switch (rule_list_type) {
    case kTopLevelRuleList:
      allowed_rules = kAllowCharsetRules;
      break;
    case kRegularRuleList:
      allowed_rules = kRegularRules;
      break;
    case kKeyframesRuleList:
      allowed_rules = kKeyframeRules;
      break;
    case kFontFeatureRuleList:
      allowed_rules = kFontFeatureRules;
      break;
    default:
      NOTREACHED();
  }

  bool seen_rule = false;
  bool first_rule_valid = false;
  while (!stream.AtEnd()) {
    StyleRuleBase* rule;
    switch (stream.UncheckedPeek().GetType()) {
      case kWhitespaceToken:
        stream.UncheckedConsume();
        continue;
      case kAtKeywordToken:
        rule = ConsumeAtRule(stream, allowed_rules);
        break;
      case kCDOToken:
      case kCDCToken:
        if (rule_list_type == kTopLevelRuleList) {
          stream.UncheckedConsume();
          continue;
        }
        FALLTHROUGH;
      default:
        rule = ConsumeQualifiedRule(stream, allowed_rules);
        break;
    }
    if (!seen_rule) {
      seen_rule = true;
      first_rule_valid = rule;
    }
    if (rule) {
      allowed_rules = ComputeNewAllowedRules(allowed_rules, rule);
      callback(rule);
    }
  }

  return first_rule_valid;
}

CSSParserTokenRange ConsumeAtRulePrelude(CSSParserTokenStream& stream) {
  return stream.ConsumeUntilPeekedTypeIs<kLeftBraceToken, kSemicolonToken>();
}

bool ConsumeEndOfPreludeForAtRuleWithoutBlock(CSSParserTokenStream& stream) {
  if (stream.AtEnd() || stream.UncheckedPeek().GetType() == kSemicolonToken) {
    if (!stream.UncheckedAtEnd())
      stream.UncheckedConsume();  // kSemicolonToken
    return true;
  }

  // Consume the erroneous block.
  CSSParserTokenStream::BlockGuard guard(stream);
  return false;  // Parse error, we expected no block.
}

bool ConsumeEndOfPreludeForAtRuleWithBlock(CSSParserTokenStream& stream) {
  if (stream.AtEnd() || stream.UncheckedPeek().GetType() == kSemicolonToken) {
    if (!stream.UncheckedAtEnd())
      stream.UncheckedConsume();  // kSemicolonToken
    return false;                 // Parse error, we expected a block.
  }

  return true;
}

void ConsumeErroneousAtRule(CSSParserTokenStream& stream) {
  // Consume the prelude and block if present.
  ConsumeAtRulePrelude(stream);
  if (!stream.AtEnd()) {
    if (stream.UncheckedPeek().GetType() == kLeftBraceToken)
      CSSParserTokenStream::BlockGuard guard(stream);
    else
      stream.UncheckedConsume();  // kSemicolonToken
  }
}

StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenStream& stream,
                                            AllowedRulesType allowed_rules) {
  DCHECK_EQ(stream.Peek().GetType(), kAtKeywordToken);
  const StringView name = stream.ConsumeIncludingWhitespace().Value();
  const CSSAtRuleID id = CssAtRuleID(name);

  // @import rules have a URI component that is not technically part of the
  // prelude.
  AtomicString import_prelude_uri;
  if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport)
    import_prelude_uri = ConsumeStringOrURI(stream);

  if (id != kCSSAtRuleInvalid && context_->IsUseCounterRecordingEnabled())
    CountAtRule(context_, id);

  if (allowed_rules == kKeyframeRules || allowed_rules == kFontFeatureRules ||
      allowed_rules == kNoRules) {
    // Parse error, no at-rules supported inside @keyframes,
    // @font-feature-values, or blocks supported inside declaration lists.
    ConsumeErroneousAtRule(stream);
    return nullptr;
  }

  stream.EnsureLookAhead();
  if (allowed_rules == kAllowCharsetRules && id == kCSSAtRuleCharset) {
    return ConsumeCharsetRule(stream);
  } else if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport) {
    return ConsumeImportRule(std::move(import_prelude_uri), stream);
  } else if (allowed_rules <= kAllowNamespaceRules &&
             id == kCSSAtRuleNamespace) {
    return ConsumeNamespaceRule(stream);
  } else {
    DCHECK_LE(allowed_rules, kRegularRules);

    switch (id) {
      case kCSSAtRuleContainer:
        return ConsumeContainerRule(stream);
      case kCSSAtRuleMedia:
        return ConsumeMediaRule(stream);
      case kCSSAtRuleSupports:
        return ConsumeSupportsRule(stream);
      case kCSSAtRuleViewport:
        return ConsumeViewportRule(stream);
      case kCSSAtRuleFontFace:
        return ConsumeFontFaceRule(stream);
      case kCSSAtRuleWebkitKeyframes:
        return ConsumeKeyframesRule(true, stream);
      case kCSSAtRuleKeyframes:
        return ConsumeKeyframesRule(false, stream);
      case kCSSAtRulePage:
        return ConsumePageRule(stream);
      case kCSSAtRuleProperty:
        return ConsumePropertyRule(stream);
      case kCSSAtRuleScrollTimeline:
        return ConsumeScrollTimelineRule(stream);
      case kCSSAtRuleCounterStyle:
        return ConsumeCounterStyleRule(stream);
      default:
        ConsumeErroneousAtRule(stream);
        return nullptr;  // Parse error, unrecognised or not-allowed at-rule
    }
  }
}

StyleRuleBase* CSSParserImpl::ConsumeQualifiedRule(
    CSSParserTokenStream& stream,
    AllowedRulesType allowed_rules) {
  if (allowed_rules <= kRegularRules) {
    return ConsumeStyleRule(stream);
  }

  if (allowed_rules == kKeyframeRules) {
    stream.EnsureLookAhead();
    const wtf_size_t prelude_offset_start = stream.LookAheadOffset();
    const CSSParserTokenRange prelude =
        stream.ConsumeUntilPeekedTypeIs<kLeftBraceToken>();
    const RangeOffset prelude_offset(prelude_offset_start,
                                     stream.LookAheadOffset());

    if (stream.AtEnd())
      return nullptr;  // Parse error, EOF instead of qualified rule block

    CSSParserTokenStream::BlockGuard guard(stream);
    StyleRuleKeyframe* keyframe_style_rule =
        ConsumeKeyframeStyleRule(prelude, prelude_offset, stream);
    if (keyframe_style_rule)
      context_->ReportLayoutAnimationsViolationIfNeeded(*keyframe_style_rule);
    return keyframe_style_rule;
  }
  if (allowed_rules == kFontFeatureRules) {
    stream.ConsumeWhitespace();
    if (stream.AtEnd())
      return nullptr;  // Parse error, EOF instead of qualified rule block
    bool prelude_invalid = false;
    stream.EnsureLookAhead();
    if (stream.UncheckedPeek().GetType() != kLeftBraceToken) {
      prelude_invalid = true;
      while (!stream.AtEnd() &&
             stream.UncheckedPeek().GetType() != kLeftBraceToken)
        stream.UncheckedConsumeComponentValue();
      if (stream.AtEnd())
        return nullptr;
    }

    CSSParserTokenStream::BlockGuard guard(stream);
    if (prelude_invalid)
      return nullptr;
    ConsumeDeclarationList(stream, StyleRule::kFontFace);
    return MakeGarbageCollected<StyleRuleFontFace>(
        CreateCSSPropertyValueSet(parsed_properties_, kCSSFontFaceRuleMode));
  }

  NOTREACHED();
  return nullptr;
}

// This may still consume tokens if it fails
static AtomicString ConsumeStringOrURI(CSSParserTokenRange& range) {
  const CSSParserToken& token = range.Peek();

  if (token.GetType() == kStringToken || token.GetType() == kUrlToken)
    return range.ConsumeIncludingWhitespace().Value().ToAtomicString();

  if (token.GetType() != kFunctionToken ||
      !EqualIgnoringASCIICase(token.Value(), "url"))
    return AtomicString();

  CSSParserTokenRange contents = range.ConsumeBlock();
  const CSSParserToken& uri = contents.ConsumeIncludingWhitespace();
  if (uri.GetType() == kBadStringToken || !contents.AtEnd())
    return AtomicString();
  DCHECK_EQ(uri.GetType(), kStringToken);
  return uri.Value().ToAtomicString();
}

StyleRuleCharset* CSSParserImpl::ConsumeCharsetRule(
    CSSParserTokenStream& stream) {
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  if (!ConsumeEndOfPreludeForAtRuleWithoutBlock(stream))
    return nullptr;

  const CSSParserToken& string = prelude.ConsumeIncludingWhitespace();
  if (string.GetType() != kStringToken || !prelude.AtEnd())
    return nullptr;  // Parse error, expected a single string
  return MakeGarbageCollected<StyleRuleCharset>();
}

StyleRuleImport* CSSParserImpl::ConsumeImportRule(
    AtomicString uri,
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithoutBlock(stream))
    return nullptr;

  if (uri.IsNull())
    return nullptr;  // Parse error, expected string or URI

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kImport, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(prelude_offset_end);
    observer_->EndRuleBody(prelude_offset_end);
  }

  return MakeGarbageCollected<StyleRuleImport>(
      uri,
      MediaQueryParser::ParseMediaQuerySet(prelude,
                                           context_->GetExecutionContext()),
      context_->IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse);
}

StyleRuleNamespace* CSSParserImpl::ConsumeNamespaceRule(
    CSSParserTokenStream& stream) {
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  if (!ConsumeEndOfPreludeForAtRuleWithoutBlock(stream))
    return nullptr;

  AtomicString namespace_prefix;
  if (prelude.Peek().GetType() == kIdentToken)
    namespace_prefix =
        prelude.ConsumeIncludingWhitespace().Value().ToAtomicString();

  AtomicString uri(ConsumeStringOrURI(prelude));
  if (uri.IsNull() || !prelude.AtEnd())
    return nullptr;  // Parse error, expected string or URI

  return MakeGarbageCollected<StyleRuleNamespace>(namespace_prefix, uri);
}

StyleRuleMedia* CSSParserImpl::ConsumeMediaRule(CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  HeapVector<Member<StyleRuleBase>> rules;

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kMedia, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(stream.Offset());
  }

  if (style_sheet_)
    style_sheet_->SetHasMediaQueries();

  const auto media = MediaQueryParser::ParseMediaQuerySet(
      prelude, context_->GetExecutionContext());

  ConsumeRuleList(stream, kRegularRuleList,
                  [&rules](StyleRuleBase* rule) { rules.push_back(rule); });

  if (observer_)
    observer_->EndRuleBody(stream.Offset());

  return MakeGarbageCollected<StyleRuleMedia>(media, rules);
}

StyleRuleSupports* CSSParserImpl::ConsumeSupportsRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSSupportsParser::Result supported =
      CSSSupportsParser::ConsumeSupportsCondition(stream, *this);
  // Check whether the entire prelude was consumed. If it wasn't, ensure we
  // consume any leftovers plus the block before returning a parse error.
  stream.ConsumeWhitespace();
  CSSParserTokenRange prelude_remainder = ConsumeAtRulePrelude(stream);
  if (!prelude_remainder.AtEnd())
    supported = CSSSupportsParser::Result::kParseFailure;
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  if (supported == CSSSupportsParser::Result::kParseFailure)
    return nullptr;  // Parse error, invalid @supports condition

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kSupports, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(stream.Offset());
  }

  const auto prelude_serialized =
      stream
          .StringRangeAt(prelude_offset_start,
                         prelude_offset_end - prelude_offset_start)
          .ToString()
          .SimplifyWhiteSpace();

  HeapVector<Member<StyleRuleBase>> rules;
  ConsumeRuleList(stream, kRegularRuleList,
                  [&rules](StyleRuleBase* rule) { rules.push_back(rule); });

  if (observer_)
    observer_->EndRuleBody(stream.Offset());

  return MakeGarbageCollected<StyleRuleSupports>(
      prelude_serialized, supported == CSSSupportsParser::Result::kSupported,
      rules);
}

StyleRuleViewport* CSSParserImpl::ConsumeViewportRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  const CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  // Allow @viewport rules from UA stylesheets only.
  if (!IsUASheetBehavior(context_->Mode()))
    return nullptr;

  if (!prelude.AtEnd())
    return nullptr;  // Parser error; @viewport prelude should be empty

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kViewport, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(prelude_offset_end);
    observer_->EndRuleBody(prelude_offset_end);
  }

  if (style_sheet_)
    style_sheet_->SetHasViewportRule();

  ConsumeDeclarationList(stream, StyleRule::kViewport);
  return MakeGarbageCollected<StyleRuleViewport>(
      CreateCSSPropertyValueSet(parsed_properties_, kCSSViewportRuleMode));
}

StyleRuleFontFace* CSSParserImpl::ConsumeFontFaceRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  if (!prelude.AtEnd())
    return nullptr;  // Parse error; @font-face prelude should be empty

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kFontFace, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(prelude_offset_end);
    observer_->EndRuleBody(prelude_offset_end);
  }

  if (style_sheet_)
    style_sheet_->SetHasFontFaceRule();

  ConsumeDeclarationList(stream, StyleRule::kFontFace);
  return MakeGarbageCollected<StyleRuleFontFace>(
      CreateCSSPropertyValueSet(parsed_properties_, kCSSFontFaceRuleMode));
}

StyleRuleKeyframes* CSSParserImpl::ConsumeKeyframesRule(
    bool webkit_prefixed,
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  const CSSParserToken& name_token = prelude.ConsumeIncludingWhitespace();
  if (!prelude.AtEnd())
    return nullptr;  // Parse error; expected single non-whitespace token in
                     // @keyframes header

  String name;
  if (name_token.GetType() == kIdentToken) {
    name = name_token.Value().ToString();
  } else if (name_token.GetType() == kStringToken && webkit_prefixed) {
    context_->Count(WebFeature::kQuotedKeyframesRule);
    name = name_token.Value().ToString();
  } else {
    return nullptr;  // Parse error; expected ident token in @keyframes header
  }

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kKeyframes, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(stream.Offset());
  }

  auto* keyframe_rule = MakeGarbageCollected<StyleRuleKeyframes>();
  ConsumeRuleList(
      stream, kKeyframesRuleList, [keyframe_rule](StyleRuleBase* keyframe) {
        keyframe_rule->ParserAppendKeyframe(To<StyleRuleKeyframe>(keyframe));
      });
  keyframe_rule->SetName(name);
  keyframe_rule->SetVendorPrefixed(webkit_prefixed);

  if (observer_)
    observer_->EndRuleBody(stream.Offset());

  return keyframe_rule;
}

StyleRulePage* CSSParserImpl::ConsumePageRule(CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  CSSSelectorList selector_list = ParsePageSelector(prelude, style_sheet_);
  if (!selector_list.IsValid())
    return nullptr;  // Parse error, invalid @page selector

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kPage, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
  }

  ConsumeDeclarationList(stream, StyleRule::kStyle);

  return MakeGarbageCollected<StyleRulePage>(
      std::move(selector_list),
      CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
}

StyleRuleProperty* CSSParserImpl::ConsumePropertyRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  if (!RuntimeEnabledFeatures::CSSVariables2AtPropertyEnabled())
    return nullptr;

  const CSSParserToken& name_token = prelude.ConsumeIncludingWhitespace();
  if (!prelude.AtEnd())
    return nullptr;
  if (!CSSVariableParser::IsValidVariableName(name_token))
    return nullptr;
  String name = name_token.Value().ToString();

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kProperty, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
  }

  ConsumeDeclarationList(stream, StyleRule::kProperty);
  return MakeGarbageCollected<StyleRuleProperty>(
      name, CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
}

StyleRuleCounterStyle* CSSParserImpl::ConsumeCounterStyleRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  AtomicString name = css_parsing_utils::ConsumeCounterStyleNameInPrelude(
      prelude, *GetContext());
  if (!name)
    return nullptr;

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kCounterStyle, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
  }

  ConsumeDeclarationList(stream, StyleRule::kCounterStyle);
  return MakeGarbageCollected<StyleRuleCounterStyle>(
      name, CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
}

StyleRuleScrollTimeline* CSSParserImpl::ConsumeScrollTimelineRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  if (!RuntimeEnabledFeatures::CSSScrollTimelineEnabled())
    return nullptr;

  const CSSParserToken& name_token = prelude.ConsumeIncludingWhitespace();
  if (!prelude.AtEnd())
    return nullptr;
  if (!css_parsing_utils::IsTimelineName(name_token))
    return nullptr;
  String name = name_token.Value().ToString();

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kScrollTimeline,
                               prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
  }

  ConsumeDeclarationList(stream, StyleRule::kScrollTimeline);
  return MakeGarbageCollected<StyleRuleScrollTimeline>(
      name, CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
}

StyleRuleContainer* CSSParserImpl::ConsumeContainerRule(
    CSSParserTokenStream& stream) {
  wtf_size_t prelude_offset_start = stream.LookAheadOffset();
  CSSParserTokenRange prelude = ConsumeAtRulePrelude(stream);
  wtf_size_t prelude_offset_end = stream.LookAheadOffset();
  if (!ConsumeEndOfPreludeForAtRuleWithBlock(stream))
    return nullptr;
  CSSParserTokenStream::BlockGuard guard(stream);

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kContainer, prelude_offset_start);
    observer_->EndRuleHeader(prelude_offset_end);
    observer_->StartRuleBody(stream.Offset());
  }

  // TODO(crbug.com/1145970): Restrict what is allowed by @container.
  scoped_refptr<MediaQuerySet> media_queries =
      MediaQueryParser::ParseMediaQuerySet(prelude,
                                           context_->GetExecutionContext());
  if (!media_queries)
    return nullptr;
  ContainerQuery* container_query =
      MakeGarbageCollected<ContainerQuery>(media_queries);

  HeapVector<Member<StyleRuleBase>> rules;
  ConsumeRuleList(stream, kRegularRuleList,
                  [&rules](StyleRuleBase* rule) { rules.push_back(rule); });

  if (observer_)
    observer_->EndRuleBody(stream.Offset());

  return MakeGarbageCollected<StyleRuleContainer>(*container_query, rules);
}

StyleRuleKeyframe* CSSParserImpl::ConsumeKeyframeStyleRule(
    const CSSParserTokenRange prelude,
    const RangeOffset& prelude_offset,
    CSSParserTokenStream& block) {
  std::unique_ptr<Vector<double>> key_list = ConsumeKeyframeKeyList(prelude);
  if (!key_list)
    return nullptr;

  if (observer_) {
    observer_->StartRuleHeader(StyleRule::kKeyframe, prelude_offset.start);
    observer_->EndRuleHeader(prelude_offset.end);
  }

  ConsumeDeclarationList(block, StyleRule::kKeyframe);

  return MakeGarbageCollected<StyleRuleKeyframe>(
      std::move(key_list),
      CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
}

StyleRule* CSSParserImpl::ConsumeStyleRule(CSSParserTokenStream& stream) {
  if (observer_)
    observer_->StartRuleHeader(StyleRule::kStyle, stream.LookAheadOffset());

  // Parse the prelude of the style rule
  CSSSelectorList selector_list = CSSSelectorParser::ConsumeSelector(
      stream, context_, style_sheet_, observer_);

  if (!selector_list.IsValid()) {
    // Read the rest of the prelude if there was an error
    stream.EnsureLookAhead();
    while (!stream.UncheckedAtEnd() &&
           stream.UncheckedPeek().GetType() != kLeftBraceToken)
      stream.UncheckedConsumeComponentValue();
  }

  if (observer_)
    observer_->EndRuleHeader(stream.LookAheadOffset());

  if (stream.AtEnd())
    return nullptr;  // Parse error, EOF instead of qualified rule block

  DCHECK_EQ(stream.Peek().GetType(), kLeftBraceToken);
  CSSParserTokenStream::BlockGuard guard(stream);

  if (!selector_list.IsValid())
    return nullptr;  // Parse error, invalid selector list

  // TODO(csharrison): How should we lazily parse css that needs the observer?
  if (!observer_ && lazy_state_) {
    DCHECK(style_sheet_);
    return MakeGarbageCollected<StyleRule>(
        std::move(selector_list),
        MakeGarbageCollected<CSSLazyPropertyParserImpl>(stream.Offset() - 1,
                                                        lazy_state_));
  }
  ConsumeDeclarationList(stream, StyleRule::kStyle);

  return MakeGarbageCollected<StyleRule>(
      std::move(selector_list),
      CreateCSSPropertyValueSet(parsed_properties_, context_->Mode()));
}

void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenStream& stream,
                                           StyleRule::RuleType rule_type) {
  DCHECK(parsed_properties_.IsEmpty());

  bool use_observer = observer_ && (rule_type == StyleRule::kStyle ||
                                    rule_type == StyleRule::kProperty ||
                                    rule_type == StyleRule::kContainer ||
                                    rule_type == StyleRule::kCounterStyle ||
                                    rule_type == StyleRule::kScrollTimeline ||
                                    rule_type == StyleRule::kKeyframe);
  if (use_observer) {
    observer_->StartRuleBody(stream.Offset());
  }

  while (true) {
    // Having a lookahead may skip comments, which are used by the observer.
    DCHECK(!stream.HasLookAhead() || stream.AtEnd());

    if (use_observer && !stream.HasLookAhead()) {
      while (true) {
        wtf_size_t start_offset = stream.Offset();
        if (!stream.ConsumeCommentOrNothing())
          break;
        observer_->ObserveComment(start_offset, stream.Offset());
      }
    }

    if (stream.AtEnd())
      break;

    switch (stream.UncheckedPeek().GetType()) {
      case kWhitespaceToken:
      case kSemicolonToken:
        stream.UncheckedConsume();
        break;
      case kIdentToken: {
        CSSParserTokenStream::RangeBoundary range_boundary(stream,
                                                           kSemicolonToken);
        ConsumeDeclaration(stream, rule_type);

        if (!stream.AtEnd())
          stream.UncheckedConsume();  // kSemicolonToken

        break;
      }
      default:
        while (!stream.UncheckedAtEnd() &&
               stream.UncheckedPeek().GetType() != kSemicolonToken) {
          stream.UncheckedConsumeComponentValue();
        }

        if (!stream.UncheckedAtEnd())
          stream.UncheckedConsume();  // kSemicolonToken

        break;
    }
  }

  if (use_observer)
    observer_->EndRuleBody(stream.LookAheadOffset());
}

void CSSParserImpl::ConsumeDeclaration(CSSParserTokenStream& stream,
                                       StyleRule::RuleType rule_type) {
  const wtf_size_t decl_offset_start = stream.Offset();

  DCHECK_EQ(stream.Peek().GetType(), kIdentToken);
  const CSSParserToken& lhs = stream.ConsumeIncludingWhitespace();
  if (stream.Peek().GetType() != kColonToken) {
    // Parse error.
    // Consume the remainder of the declaration for recovery before returning.
    stream.ConsumeUntilPeekedBoundary();
    return;
  }
  stream.UncheckedConsume();  // kColonToken

  CSSTokenizedValue tokenized_value = ConsumeValue(stream);

  bool important = RemoveImportantAnnotationIfPresent(tokenized_value);

  size_t properties_count = parsed_properties_.size();

  CSSPropertyID unresolved_property = CSSPropertyID::kInvalid;
  AtRuleDescriptorID atrule_id = AtRuleDescriptorID::Invalid;
  if (rule_type == StyleRule::kFontFace || rule_type == StyleRule::kProperty ||
      rule_type == StyleRule::kCounterStyle ||
      rule_type == StyleRule::kScrollTimeline) {
    if (important)  // Invalid
      return;
    atrule_id = lhs.ParseAsAtRuleDescriptorID();
    AtRuleDescriptorParser::ParseAtRule(rule_type, atrule_id, tokenized_value,
                                        *context_, parsed_properties_);
  } else {
    unresolved_property = lhs.ParseAsUnresolvedCSSPropertyID(
        context_->GetExecutionContext(), context_->Mode());
  }

  // @rules other than FontFace still handled with legacy code.
  if (important && rule_type == StyleRule::kKeyframe)
    return;

  if (unresolved_property == CSSPropertyID::kVariable) {
    if (rule_type != StyleRule::kStyle && rule_type != StyleRule::kKeyframe)
      return;
    AtomicString variable_name = lhs.Value().ToAtomicString();
    bool is_animation_tainted = rule_type == StyleRule::kKeyframe;
    ConsumeVariableValue(tokenized_value, variable_name, important,
                         is_animation_tainted);
  } else if (unresolved_property != CSSPropertyID::kInvalid) {
    if (style_sheet_ && style_sheet_->SingleOwnerDocument())
      Deprecation::WarnOnDeprecatedProperties(
          style_sheet_->SingleOwnerDocument()->GetFrame(), unresolved_property);
    ConsumeDeclarationValue(tokenized_value, unresolved_property, important,
                            rule_type);
  }

  if (observer_ &&
      (rule_type == StyleRule::kStyle || rule_type == StyleRule::kKeyframe)) {
    // The end offset is the offset of the terminating token, which is peeked
    // but not yet consumed.
    observer_->ObserveProperty(decl_offset_start, stream.LookAheadOffset(),
                               important,
                               parsed_properties_.size() != properties_count);
  }
}

void CSSParserImpl::ConsumeVariableValue(
    const CSSTokenizedValue& tokenized_value,
    const AtomicString& variable_name,
    bool important,
    bool is_animation_tainted) {
  if (CSSCustomPropertyDeclaration* value =
          CSSVariableParser::ParseDeclarationValue(
              variable_name, tokenized_value, is_animation_tainted,
              *context_)) {
    parsed_properties_.push_back(
        CSSPropertyValue(CSSPropertyName(variable_name), *value, important));
    context_->Count(context_->Mode(), CSSPropertyID::kVariable);
  }
}

void CSSParserImpl::ConsumeDeclarationValue(
    const CSSTokenizedValue& tokenized_value,
    CSSPropertyID unresolved_property,
    bool important,
    StyleRule::RuleType rule_type) {
  CSSPropertyParser::ParseValue(unresolved_property, important,
                                tokenized_value.range, context_,
                                parsed_properties_, rule_type);
}

CSSTokenizedValue CSSParserImpl::ConsumeValue(CSSParserTokenStream& stream) {
  stream.EnsureLookAhead();
  wtf_size_t value_start_offset = stream.LookAheadOffset();
  CSSParserTokenRange range = stream.ConsumeUntilPeekedBoundary();
  wtf_size_t value_end_offset = stream.LookAheadOffset();

  return {range, stream.StringRangeAt(value_start_offset,
                                      value_end_offset - value_start_offset)};
}

bool CSSParserImpl::RemoveImportantAnnotationIfPresent(
    CSSTokenizedValue& tokenized_value) {
  const CSSParserToken* first = tokenized_value.range.begin();
  const CSSParserToken* last = tokenized_value.range.end() - 1;
  while (last >= first && last->GetType() == kWhitespaceToken)
    --last;
  if (last >= first && last->GetType() == kIdentToken &&
      EqualIgnoringASCIICase(last->Value(), "important")) {
    --last;
    while (last >= first && last->GetType() == kWhitespaceToken)
      --last;
    if (last >= first && last->GetType() == kDelimiterToken &&
        last->Delimiter() == '!') {
      tokenized_value.range = tokenized_value.range.MakeSubRange(first, last);

      // Truncate the text to remove the delimiter and everything after it.
      DCHECK_NE(tokenized_value.text.ToString().find('!'), kNotFound);
      unsigned truncated_length = tokenized_value.text.length() - 1;
      while (tokenized_value.text[truncated_length] != '!')
        --truncated_length;
      tokenized_value.text =
          StringView(tokenized_value.text, 0, truncated_length);

      return true;
    }
  }

  return false;
}

std::unique_ptr<Vector<double>> CSSParserImpl::ConsumeKeyframeKeyList(
    CSSParserTokenRange range) {
  std::unique_ptr<Vector<double>> result = std::make_unique<Vector<double>>();
  while (true) {
    range.ConsumeWhitespace();
    const CSSParserToken& token = range.ConsumeIncludingWhitespace();
    if (token.GetType() == kPercentageToken && token.NumericValue() >= 0 &&
        token.NumericValue() <= 100)
      result->push_back(token.NumericValue() / 100);
    else if (token.GetType() == kIdentToken &&
             EqualIgnoringASCIICase(token.Value(), "from"))
      result->push_back(0);
    else if (token.GetType() == kIdentToken &&
             EqualIgnoringASCIICase(token.Value(), "to"))
      result->push_back(1);
    else
      return nullptr;  // Parser error, invalid value in keyframe selector
    if (range.AtEnd())
      return result;
    if (range.Consume().GetType() != kCommaToken)
      return nullptr;  // Parser error
  }
}

}  // namespace blink
