Commit b8c55dc8 authored by Anders Hartvoll Ruud's avatar Anders Hartvoll Ruud Committed by Commit Bot

[:is/:where] Ignore default namespace when appropriate

Bug: 568705
Change-Id: I60d908398869162c664760da5d638d7bac2dae2f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2489891Reviewed-by: default avatarEmilio Cobos Álvarez <emilio@chromium.org>
Reviewed-by: default avatarRune Lillesveen <futhark@chromium.org>
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820500}
parent ff8494b5
...@@ -34,6 +34,11 @@ CSSParserTokenRange ConsumeNestedArgument(CSSParserTokenRange& range) { ...@@ -34,6 +34,11 @@ CSSParserTokenRange ConsumeNestedArgument(CSSParserTokenRange& range) {
return range.MakeSubRange(&first, &range.Peek()); return range.MakeSubRange(&first, &range.Peek());
} }
bool AtEndIgnoringWhitepace(CSSParserTokenRange range) {
range.ConsumeWhitespace();
return range.AtEnd();
}
} // namespace } // namespace
// static // static
...@@ -420,6 +425,18 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumeCompoundSelector( ...@@ -420,6 +425,18 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumeCompoundSelector(
compound_selector = std::move(simple_selector); compound_selector = std::move(simple_selector);
} }
// While inside a nested selector like :is(), the default namespace shall
// be ignored when [1]:
//
// - The compound selector represents the subject [2], and
// - The compound selector does not contain a type/universal selector.
//
// [1] https://drafts.csswg.org/selectors/#matches
// [2] https://drafts.csswg.org/selectors/#selector-subject
base::AutoReset<bool> ignore_namespace(
&ignore_default_namespace_, resist_default_namespace_ && !has_q_name &&
AtEndIgnoringWhitepace(range));
if (!compound_selector) { if (!compound_selector) {
AtomicString namespace_uri = DetermineNamespace(namespace_prefix); AtomicString namespace_uri = DetermineNamespace(namespace_prefix);
if (namespace_uri.IsNull()) { if (namespace_uri.IsNull()) {
...@@ -670,6 +687,7 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumePseudo( ...@@ -670,6 +687,7 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumePseudo(
disallow_shadow_dom_v0_ = true; disallow_shadow_dom_v0_ = true;
DisallowPseudoElementsScope scope(this); DisallowPseudoElementsScope scope(this);
base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
std::unique_ptr<CSSSelectorList> selector_list = std::unique_ptr<CSSSelectorList> selector_list =
std::make_unique<CSSSelectorList>(); std::make_unique<CSSSelectorList>();
...@@ -687,6 +705,7 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumePseudo( ...@@ -687,6 +705,7 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumePseudo(
disallow_shadow_dom_v0_ = true; disallow_shadow_dom_v0_ = true;
DisallowPseudoElementsScope scope(this); DisallowPseudoElementsScope scope(this);
base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
std::unique_ptr<CSSSelectorList> selector_list = std::unique_ptr<CSSSelectorList> selector_list =
std::make_unique<CSSSelectorList>(); std::make_unique<CSSSelectorList>();
...@@ -953,7 +972,7 @@ bool CSSSelectorParser::ConsumeANPlusB(CSSParserTokenRange& range, ...@@ -953,7 +972,7 @@ bool CSSSelectorParser::ConsumeANPlusB(CSSParserTokenRange& range,
} }
const AtomicString& CSSSelectorParser::DefaultNamespace() const { const AtomicString& CSSSelectorParser::DefaultNamespace() const {
if (!style_sheet_) if (!style_sheet_ || ignore_default_namespace_)
return g_star_atom; return g_star_atom;
return style_sheet_->DefaultNamespace(); return style_sheet_->DefaultNamespace();
} }
......
...@@ -112,6 +112,17 @@ class CORE_EXPORT CSSSelectorParser { ...@@ -112,6 +112,17 @@ class CORE_EXPORT CSSSelectorParser {
// PseudoType of the pseudo-element causing the restriction. // PseudoType of the pseudo-element causing the restriction.
CSSSelector::PseudoType restricting_pseudo_element_ = CSSSelector::PseudoType restricting_pseudo_element_ =
CSSSelector::kPseudoUnknown; 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 { class DisallowPseudoElementsScope {
STACK_ALLOCATED(); STACK_ALLOCATED();
......
<!DOCTYPE html>
<title>Default namespace respected inside :is() for non-subject compounds</title>
<link rel="help" href="https://drafts.csswg.org/selectors-4/#matches">
<link rel="match" href="/css/reference/blank.html">
<!--
Default namespace declarations do not affect the compound selector
representing the *subject* of any selector within a :is() pseudo-class, unless
that compound selector contains an explicit universal selector or type
selector.
-->
<style>
@namespace "http://www.w3.org/1999/xhtml";
*|*.a {
display:none;
}
/* This should not apply, since the '.container' compound is affected by the
default namespace (even though the '.a' compound is not). */
*|*:is(.container .a) {
display:initial;
}
</style>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100">
<g class=container>
<text class="a" y="1em">FAIL if this text is visible</text>
</g>
</svg>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment