chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

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

#include <algorithm>
#include <memory>

#include "base/auto_reset.h"
#include "base/containers/span.h"
#include "base/numerics/safe_conversions.h"
#include "third_party/blink/renderer/core/css/css_selector.h"
#include "third_party/blink/renderer/core/css/css_selector_list.h"
#include "third_party/blink/renderer/core/css/parser/css_nesting_type.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_observer.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_save_point.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.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/pseudo_element.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/frame/deprecation/deprecation.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"

namespace blink {

static void RecordUsageAndDeprecationsOneSelector(
    const CSSSelector* selector,
    const CSSParserContext* context);

namespace {

bool AtEndIgnoringWhitespace(CSSParserTokenStream& stream) {}

bool IsHostPseudoSelector(const CSSSelector& selector) {}

// Some pseudo elements behave as if they have an implicit combinator to their
// left even though they are written without one. This method returns the
// correct implicit combinator. If no new combinator should be used,
// it returns RelationType::kSubSelector.
CSSSelector::RelationType GetImplicitShadowCombinatorForMatching(
    CSSSelector::PseudoType pseudo_type) {}

bool NeedsImplicitShadowCombinatorForMatching(const CSSSelector& selector) {}

// Marks the end of parsing a complex selector. (In many cases, there may
// be more complex selectors after this, since we are often dealing with
// lists of complex selectors. Those are marked using SetLastInSelectorList(),
// which happens in CSSSelectorList::AdoptSelectorVector.)
void MarkAsEntireComplexSelector(base::span<CSSSelector> selectors) {}

}  // namespace

// static
base::span<CSSSelector> CSSSelectorParser::ParseSelector(
    CSSParserTokenStream& stream,
    const CSSParserContext* context,
    CSSNestingType nesting_type,
    const StyleRule* parent_rule_for_nesting,
    bool is_within_scope,
    bool semicolon_aborts_nested_selector,
    StyleSheetContents* style_sheet,
    HeapVector<CSSSelector>& arena) {}

// static
base::span<CSSSelector> CSSSelectorParser::ConsumeSelector(
    CSSParserTokenStream& stream,
    const CSSParserContext* context,
    CSSNestingType nesting_type,
    const StyleRule* parent_rule_for_nesting,
    bool is_within_scope,
    bool semicolon_aborts_nested_selector,
    StyleSheetContents* style_sheet,
    CSSParserObserver* observer,
    HeapVector<CSSSelector>& arena) {}

// static
std::optional<base::span<CSSSelector>> CSSSelectorParser::ParseScopeBoundary(
    CSSParserTokenStream& stream,
    const CSSParserContext* context,
    CSSNestingType nesting_type,
    const StyleRule* parent_rule_for_nesting,
    bool is_within_scope,
    StyleSheetContents* style_sheet,
    HeapVector<CSSSelector>& arena) {}

// static
bool CSSSelectorParser::SupportsComplexSelector(
    CSSParserTokenStream& stream,
    const CSSParserContext* context) {}

CSSSelectorParser::CSSSelectorParser(const CSSParserContext* context,
                                     const StyleRule* parent_rule_for_nesting,
                                     bool is_within_scope,
                                     bool semicolon_aborts_nested_selector,
                                     StyleSheetContents* style_sheet,
                                     HeapVector<CSSSelector>& output)
    :{}

base::span<CSSSelector> CSSSelectorParser::ConsumeComplexSelectorList(
    CSSParserTokenStream& stream,
    CSSNestingType nesting_type) {}

static bool AtEndOfComplexSelector(CSSParserTokenStream& stream) {}

base::span<CSSSelector> CSSSelectorParser::ConsumeComplexSelectorList(
    CSSParserTokenStream& stream,
    CSSParserObserver* observer,
    CSSNestingType nesting_type) {}

CSSSelectorList* CSSSelectorParser::ConsumeCompoundSelectorList(
    CSSParserTokenStream& stream) {}

CSSSelectorList* CSSSelectorParser::ConsumeNestedSelectorList(
    CSSParserTokenStream& stream) {}

CSSSelectorList* CSSSelectorParser::ConsumeForgivingNestedSelectorList(
    CSSParserTokenStream& stream) {}

std::optional<base::span<CSSSelector>>
CSSSelectorParser::ConsumeForgivingComplexSelectorList(
    CSSParserTokenStream& stream,
    CSSNestingType nesting_type) {}

static CSSNestingType ConsumeUntilCommaAndFindNestingType(
    CSSParserTokenStream& stream) {}

// If the argument was unparsable but contained a parent-referencing selector
// (& or :scope), we need to keep it so that we still consider the :is()
// as containing that selector; furthermore, we need to keep it on serialization
// so that a round-trip doesn't lose this information.
// We do not preserve comments fully.
//
// Note that this forwards the stream to the end of the argument (either to the
// next comma on the same nesting level, or the end of block).
void CSSSelectorParser::AddPlaceholderSelectorIfNeeded(
    CSSParserTokenStream& stream) {}

CSSSelectorList* CSSSelectorParser::ConsumeForgivingCompoundSelectorList(
    CSSParserTokenStream& stream) {}

CSSSelectorList* CSSSelectorParser::ConsumeForgivingRelativeSelectorList(
    CSSParserTokenStream& stream) {}

CSSSelectorList* CSSSelectorParser::ConsumeRelativeSelectorList(
    CSSParserTokenStream& stream) {}

namespace {

enum CompoundSelectorFlags {};

unsigned ExtractCompoundFlags(const CSSSelector& simple_selector,
                              CSSParserMode parser_mode) {}

unsigned ExtractCompoundFlags(const base::span<CSSSelector> compound_selector,
                              CSSParserMode parser_mode) {}

}  // namespace

base::span<CSSSelector> CSSSelectorParser::ConsumeRelativeSelector(
    CSSParserTokenStream& stream) {}

// This acts like CSSSelector::GetNestingType, except across a whole
// selector list.
//
// A return value of CSSNestingType::kNesting means that the list
// "contains the nesting selector".
// https://drafts.csswg.org/css-nesting-1/#contain-the-nesting-selector
//
// A return value of CSSNestingType::kScope means that the list
// contains the :scope selector.
static CSSNestingType GetNestingTypeForSelectorList(
    const CSSSelector* selector) {}

// https://drafts.csswg.org/selectors/#relative-selector-anchor-elements
static CSSSelector CreateImplicitAnchor(
    CSSNestingType nesting_type,
    const StyleRule* parent_rule_for_nesting) {}

// Within @scope, each compound that contains either :scope or '&' is prepended
// with an implicit :true + relation=kScopeActivation. This makes it possible
// for SelectorChecker to (re)try the selector's NextSimpleSelector with
// different :scope nodes.
static CSSSelector CreateImplicitScopeActivation() {}

static std::optional<CSSSelector> MaybeCreateImplicitDescendantAnchor(
    CSSNestingType nesting_type,
    const StyleRule* parent_rule_for_nesting,
    const CSSSelector* selector) {}

// A nested rule that starts with a combinator; very similar to
// ConsumeRelativeSelector() (but we don't use the kRelative* relations,
// as they have different matching semantics). There's an implicit anchor
// compound in front, which for CSSNestingType::kNesting is the nesting
// selector (&) and for CSSNestingType::kScope is the :scope pseudo class.
// E.g. given CSSNestingType::kNesting, “> .a” is parsed as “& > .a” ().
base::span<CSSSelector> CSSSelectorParser::ConsumeNestedRelativeSelector(
    CSSParserTokenStream& stream,
    CSSNestingType nesting_type) {}

base::span<CSSSelector> CSSSelectorParser::ConsumeComplexSelector(
    CSSParserTokenStream& stream,
    CSSNestingType nesting_type,
    bool first_in_complex_selector_list) {}

bool CSSSelectorParser::ConsumePartialComplexSelector(
    CSSParserTokenStream& stream,
    CSSSelector::RelationType& combinator,
    unsigned previous_compound_flags,
    CSSNestingType nesting_type) {}

// static
CSSSelector::PseudoType CSSSelectorParser::ParsePseudoType(
    const AtomicString& name,
    bool has_arguments,
    const Document* document) {}

namespace {
PseudoId ParsePseudoElementLegacy(const String& selector_string,
                                  const Node* parent) {}

AtomicString ParsePseudoElementArgument(const String& selector_string) {}
}  // namespace

// static
PseudoId CSSSelectorParser::ParsePseudoElement(const String& selector_string,
                                               const Node* parent,
                                               AtomicString& argument) {}

namespace {

bool IsScrollbarPseudoClass(CSSSelector::PseudoType pseudo) {}

bool IsUserActionPseudoClass(CSSSelector::PseudoType pseudo) {}

bool IsPseudoClassValidAfterPseudoElement(
    CSSSelector::PseudoType pseudo_class,
    CSSSelector::PseudoType compound_pseudo_element) {}

bool IsSimpleSelectorValidAfterPseudoElement(
    const CSSSelector& simple_selector,
    CSSSelector::PseudoType compound_pseudo_element) {}

bool IsPseudoClassValidWithinHasArgument(CSSSelector& selector) {}

// Checks if an implicit scope activation (see CreateImplicitScopeActivation())
// must be prepended to a given compound selector.
static bool SelectorListRequiresScopeActivation(const CSSSelectorList& list);

static bool SimpleSelectorRequiresScopeActivation(const CSSSelector& selector) {}

static bool SelectorListRequiresScopeActivation(const CSSSelectorList& list) {}

}  // namespace

base::span<CSSSelector> CSSSelectorParser::ConsumeCompoundSelector(
    CSSParserTokenStream& stream,
    CSSNestingType nesting_type) {}

bool CSSSelectorParser::ConsumeSimpleSelector(CSSParserTokenStream& stream) {}

bool CSSSelectorParser::ConsumeName(CSSParserTokenStream& stream,
                                    AtomicString& name,
                                    AtomicString& namespace_prefix) {}

bool CSSSelectorParser::ConsumeId(CSSParserTokenStream& stream) {}

bool CSSSelectorParser::ConsumeClass(CSSParserTokenStream& stream) {}

bool CSSSelectorParser::ConsumeAttribute(CSSParserTokenStream& stream) {}

bool CSSSelectorParser::ConsumePseudo(CSSParserTokenStream& stream) {}

bool CSSSelectorParser::ConsumeNestingParent(CSSParserTokenStream& stream) {}

bool CSSSelectorParser::PeekIsCombinator(CSSParserTokenStream& stream) {}

CSSSelector::RelationType CSSSelectorParser::ConsumeCombinator(
    CSSParserTokenStream& stream) {}

CSSSelector::MatchType CSSSelectorParser::ConsumeAttributeMatch(
    CSSParserTokenStream& stream) {}

CSSSelector::AttributeMatchType CSSSelectorParser::ConsumeAttributeFlags(
    CSSParserTokenStream& stream) {}

bool CSSSelectorParser::ConsumeANPlusB(CSSParserTokenStream& stream,
                                       std::pair<int, int>& result) {}

// Consumes the “of ...” part of :nth_child(An+B of ...).
// Returns nullptr on failure.
CSSSelectorList* CSSSelectorParser::ConsumeNthChildOfSelectors(
    CSSParserTokenStream& stream) {}

const AtomicString& CSSSelectorParser::DefaultNamespace() const {}

const AtomicString& CSSSelectorParser::DetermineNamespace(
    const AtomicString& prefix) {}

void CSSSelectorParser::PrependTypeSelectorIfNeeded(
    const AtomicString& namespace_prefix,
    bool has_q_name,
    const AtomicString& element_name,
    wtf_size_t start_index_of_compound_selector) {}

// If we have a compound that implicitly crosses a shadow root, rewrite it to
// have a shadow-crossing combinator (kUAShadow, which has no symbol, but let's
// call it >> for the same of the argument) instead of kSubSelector. E.g.:
//
//   video::-webkit-video-controls => video >> ::webkit-video-controls
//
// This is required because the element matching ::-webkit-video-controls is
// not the video element itself, but an element somewhere down in <video>'s
// shadow DOM tree. Note that since we store compounds right-to-left, this may
// require rearranging elements in memory (see the comment below).
void CSSSelectorParser::SplitCompoundAtImplicitShadowCrossingCombinator(
    base::span<CSSSelector> selectors) {}

namespace {

struct PseudoElementFeatureMapEntry {};

WebFeature FeatureForWebKitCustomPseudoElement(const AtomicString& name) {}

}  // namespace

static void RecordUsageAndDeprecationsOneSelector(
    const CSSSelector* selector,
    const CSSParserContext* context) {}

void CSSSelectorParser::RecordUsageAndDeprecations(
    const base::span<CSSSelector> selector_vector) {}

bool CSSSelectorParser::ContainsUnknownWebkitPseudoElements(
    base::span<CSSSelector> selectors) {}

}  // namespace blink