blob: 87f205545d9c7d40b31b49aee3c88a371c2f02b2 [file] [log] [blame]
// 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.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_SELECTOR_PARSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_SELECTOR_PARSER_H_
#include <memory>
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_selector.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
namespace blink {
class CSSParserContext;
class CSSParserTokenStream;
class CSSParserObserver;
class CSSSelectorList;
class StyleSheetContents;
// FIXME: We should consider building CSSSelectors directly instead of using
// the intermediate CSSParserSelector.
class CORE_EXPORT CSSSelectorParser {
STACK_ALLOCATED();
public:
static CSSSelectorList ParseSelector(CSSParserTokenRange,
const CSSParserContext*,
StyleSheetContents*);
static CSSSelectorList ConsumeSelector(CSSParserTokenStream&,
const CSSParserContext*,
StyleSheetContents*,
CSSParserObserver*);
static bool ConsumeANPlusB(CSSParserTokenRange&, std::pair<int, int>&);
static bool SupportsComplexSelector(CSSParserTokenRange,
const CSSParserContext*);
private:
CSSSelectorParser(const CSSParserContext*, StyleSheetContents*);
// These will all consume trailing comments if successful
CSSSelectorList ConsumeComplexSelectorList(CSSParserTokenRange&);
CSSSelectorList ConsumeComplexSelectorList(CSSParserTokenStream&,
CSSParserObserver*);
CSSSelectorList ConsumeCompoundSelectorList(CSSParserTokenRange&);
// Consumes a complex selector list if inside_compound_pseudo_ is false,
// otherwise consumes a compound selector list.
CSSSelectorList ConsumeNestedSelectorList(CSSParserTokenRange&);
CSSSelectorList ConsumeForgivingNestedSelectorList(CSSParserTokenRange&);
// https://drafts.csswg.org/selectors/#typedef-forgiving-selector-list
CSSSelectorList ConsumeForgivingComplexSelectorList(CSSParserTokenRange&);
CSSSelectorList ConsumeForgivingCompoundSelectorList(CSSParserTokenRange&);
std::unique_ptr<CSSParserSelector> ConsumeComplexSelector(
CSSParserTokenRange&);
std::unique_ptr<CSSParserSelector> ConsumeCompoundSelector(
CSSParserTokenRange&);
// This doesn't include element names, since they're handled specially
std::unique_ptr<CSSParserSelector> ConsumeSimpleSelector(
CSSParserTokenRange&);
bool ConsumeName(CSSParserTokenRange&,
AtomicString& name,
AtomicString& namespace_prefix);
// These will return nullptr when the selector is invalid
std::unique_ptr<CSSParserSelector> ConsumeId(CSSParserTokenRange&);
std::unique_ptr<CSSParserSelector> ConsumeClass(CSSParserTokenRange&);
std::unique_ptr<CSSParserSelector> ConsumePseudo(CSSParserTokenRange&);
std::unique_ptr<CSSParserSelector> ConsumeAttribute(CSSParserTokenRange&);
CSSSelector::RelationType ConsumeCombinator(CSSParserTokenRange&);
CSSSelector::MatchType ConsumeAttributeMatch(CSSParserTokenRange&);
CSSSelector::AttributeMatchType ConsumeAttributeFlags(CSSParserTokenRange&);
const AtomicString& DefaultNamespace() const;
const AtomicString& DetermineNamespace(const AtomicString& prefix);
void PrependTypeSelectorIfNeeded(const AtomicString& namespace_prefix,
bool has_element_name,
const AtomicString& element_name,
CSSParserSelector*);
static std::unique_ptr<CSSParserSelector> AddSimpleSelectorToCompound(
std::unique_ptr<CSSParserSelector> compound_selector,
std::unique_ptr<CSSParserSelector> simple_selector);
static std::unique_ptr<CSSParserSelector>
SplitCompoundAtImplicitShadowCrossingCombinator(
std::unique_ptr<CSSParserSelector> compound_selector);
void RecordUsageAndDeprecations(const CSSSelectorList&);
static bool ContainsUnknownWebkitPseudoElements(
const CSSSelector& complex_selector);
const CSSParserContext* context_;
const StyleSheetContents* style_sheet_;
bool failed_parsing_ = false;
bool disallow_pseudo_elements_ = false;
// If we're inside a pseudo class that only accepts compound selectors,
// for example :host, inner :is()/:where() pseudo classes are also only
// allowed to contain compound selectors.
bool inside_compound_pseudo_ = false;
// When parsing a compound which includes a pseudo-element, the simple
// selectors permitted to follow that pseudo-element may be restricted.
// If this is the case, then restricting_pseudo_element_ will be set to the
// PseudoType of the pseudo-element causing the restriction.
CSSSelector::PseudoType restricting_pseudo_element_ =
CSSSelector::kPseudoUnknown;
// If we're _resisting_ the default namespace, it means that we are inside
// a nested selector (:is(), :where(), etc) where we should _consider_
// ignoring the default namespace (depending on circumstance). See the
// relevant spec text [1] regarding default namespaces for information about
// those circumstances.
//
// [1] https://drafts.csswg.org/selectors/#matches
bool resist_default_namespace_ = false;
// While this flag is true, the default namespace is ignored. In other words,
// the default namespace is '*' while this flag is true.
bool ignore_default_namespace_ = false;
class DisallowPseudoElementsScope {
STACK_ALLOCATED();
public:
DisallowPseudoElementsScope(CSSSelectorParser* parser)
: parser_(parser), was_disallowed_(parser_->disallow_pseudo_elements_) {
parser_->disallow_pseudo_elements_ = true;
}
DisallowPseudoElementsScope(const DisallowPseudoElementsScope&) = delete;
DisallowPseudoElementsScope& operator=(const DisallowPseudoElementsScope&) =
delete;
~DisallowPseudoElementsScope() {
parser_->disallow_pseudo_elements_ = was_disallowed_;
}
private:
CSSSelectorParser* parser_;
bool was_disallowed_;
};
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_CSS_SELECTOR_PARSER_H_