summaryrefslogtreecommitdiffstats
path: root/servo/components/selectors/parser.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /servo/components/selectors/parser.rs
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--servo/components/selectors/parser.rs257
1 files changed, 134 insertions, 123 deletions
diff --git a/servo/components/selectors/parser.rs b/servo/components/selectors/parser.rs
index 9b0acb0671..37b2b00ca5 100644
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -438,10 +438,20 @@ pub enum ParseRelative {
/// Allow selectors to start with a combinator, prepending a parent selector if so. Do nothing
/// otherwise
ForNesting,
+ /// Allow selectors to start with a combinator, prepending a scope selector if so. Do nothing
+ /// otherwise
+ ForScope,
/// Treat as parse error if any selector begins with a combinator.
No,
}
+impl ParseRelative {
+ #[inline]
+ pub(crate) fn needs_implicit_parent_selector(self) -> bool {
+ matches!(self, Self::ForNesting)
+ }
+}
+
impl<Impl: SelectorImpl> SelectorList<Impl> {
/// Returns a selector list with a single `&`
pub fn ampersand() -> Self {
@@ -469,6 +479,23 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
)
}
+ pub fn parse_forgiving<'i, 't, P>(
+ parser: &P,
+ input: &mut CssParser<'i, 't>,
+ parse_relative: ParseRelative,
+ ) -> Result<Self, ParseError<'i, P::Error>>
+ where
+ P: Parser<'i, Impl = Impl>,
+ {
+ Self::parse_with_state(
+ parser,
+ input,
+ SelectorParsingState::empty(),
+ ForgivingParsing::Yes,
+ parse_relative,
+ )
+ }
+
#[inline]
fn parse_with_state<'i, 't, P>(
parser: &P,
@@ -932,7 +959,7 @@ impl<Impl: SelectorImpl> Selector<Impl> {
}
}
let spec = SpecificityAndFlags { specificity, flags };
- Selector(builder.build_with_specificity_and_flags(spec))
+ Selector(builder.build_with_specificity_and_flags(spec, ParseRelative::No))
}
#[inline]
@@ -960,9 +987,6 @@ impl<Impl: SelectorImpl> Selector<Impl> {
}
let result = SelectorList::from_iter(orig.iter().map(|s| {
- if !s.has_parent_selector() {
- return s.clone();
- }
s.replace_parent_selector(parent)
}));
@@ -1030,82 +1054,53 @@ impl<Impl: SelectorImpl> Selector<Impl> {
flags: &mut SelectorFlags,
flags_to_propagate: SelectorFlags,
) -> Selector<Impl> {
- if !orig.has_parent_selector() {
- return orig.clone();
- }
let new_selector = orig.replace_parent_selector(parent);
*specificity += Specificity::from(new_selector.specificity() - orig.specificity());
flags.insert(new_selector.flags().intersection(flags_to_propagate));
new_selector
}
- let mut items = if !self.has_parent_selector() {
- // Implicit `&` plus descendant combinator.
- let iter = self.iter_raw_match_order();
- let len = iter.len() + 2;
- specificity += Specificity::from(parent_specificity_and_flags.specificity);
- flags.insert(
- parent_specificity_and_flags
- .flags
- .intersection(SelectorFlags::for_nesting()),
- );
- let iter = iter
- .cloned()
- .chain(std::iter::once(Component::Combinator(
- Combinator::Descendant,
- )))
- .chain(std::iter::once(Component::Is(parent.clone())));
- UniqueArc::from_header_and_iter_with_size(Default::default(), iter, len)
- } else {
- let iter = self.iter_raw_match_order().map(|component| {
- use self::Component::*;
- match *component {
- LocalName(..) |
- ID(..) |
- Class(..) |
- AttributeInNoNamespaceExists { .. } |
- AttributeInNoNamespace { .. } |
- AttributeOther(..) |
- ExplicitUniversalType |
- ExplicitAnyNamespace |
- ExplicitNoNamespace |
- DefaultNamespace(..) |
- Namespace(..) |
- Root |
- Empty |
- Scope |
- Nth(..) |
- NonTSPseudoClass(..) |
- PseudoElement(..) |
- Combinator(..) |
- Host(None) |
- Part(..) |
- Invalid(..) |
- RelativeSelectorAnchor => component.clone(),
- ParentSelector => {
- specificity += Specificity::from(parent_specificity_and_flags.specificity);
- flags.insert(
- parent_specificity_and_flags
- .flags
- .intersection(SelectorFlags::for_nesting()),
- );
- Is(parent.clone())
- },
- Negation(ref selectors) => {
- Negation(
- replace_parent_on_selector_list(
- selectors.slice(),
- parent,
- &mut specificity,
- &mut flags,
- /* propagate_specificity = */ true,
- SelectorFlags::for_nesting(),
- )
- .unwrap_or_else(|| selectors.clone()),
- )
- },
- Is(ref selectors) => {
- Is(replace_parent_on_selector_list(
+ if !self.has_parent_selector() {
+ return self.clone();
+ }
+
+ let iter = self.iter_raw_match_order().map(|component| {
+ use self::Component::*;
+ match *component {
+ LocalName(..) |
+ ID(..) |
+ Class(..) |
+ AttributeInNoNamespaceExists { .. } |
+ AttributeInNoNamespace { .. } |
+ AttributeOther(..) |
+ ExplicitUniversalType |
+ ExplicitAnyNamespace |
+ ExplicitNoNamespace |
+ DefaultNamespace(..) |
+ Namespace(..) |
+ Root |
+ Empty |
+ Scope |
+ Nth(..) |
+ NonTSPseudoClass(..) |
+ PseudoElement(..) |
+ Combinator(..) |
+ Host(None) |
+ Part(..) |
+ Invalid(..) |
+ RelativeSelectorAnchor => component.clone(),
+ ParentSelector => {
+ specificity += Specificity::from(parent_specificity_and_flags.specificity);
+ flags.insert(
+ parent_specificity_and_flags
+ .flags
+ .intersection(SelectorFlags::for_nesting()),
+ );
+ Is(parent.clone())
+ },
+ Negation(ref selectors) => {
+ Negation(
+ replace_parent_on_selector_list(
selectors.slice(),
parent,
&mut specificity,
@@ -1113,64 +1108,75 @@ impl<Impl: SelectorImpl> Selector<Impl> {
/* propagate_specificity = */ true,
SelectorFlags::for_nesting(),
)
- .unwrap_or_else(|| selectors.clone()))
- },
- Where(ref selectors) => {
- Where(
- replace_parent_on_selector_list(
- selectors.slice(),
- parent,
- &mut specificity,
- &mut flags,
- /* propagate_specificity = */ false,
- SelectorFlags::for_nesting(),
- )
- .unwrap_or_else(|| selectors.clone()),
- )
- },
- Has(ref selectors) => Has(replace_parent_on_relative_selector_list(
- selectors,
+ .unwrap_or_else(|| selectors.clone()),
+ )
+ },
+ Is(ref selectors) => {
+ Is(replace_parent_on_selector_list(
+ selectors.slice(),
parent,
&mut specificity,
&mut flags,
+ /* propagate_specificity = */ true,
SelectorFlags::for_nesting(),
)
- .into_boxed_slice()),
-
- Host(Some(ref selector)) => Host(Some(replace_parent_on_selector(
- selector,
- parent,
- &mut specificity,
- &mut flags,
- SelectorFlags::for_nesting() - SelectorFlags::HAS_NON_FEATURELESS_COMPONENT,
- ))),
- NthOf(ref data) => {
- let selectors = replace_parent_on_selector_list(
- data.selectors(),
+ .unwrap_or_else(|| selectors.clone()))
+ },
+ Where(ref selectors) => {
+ Where(
+ replace_parent_on_selector_list(
+ selectors.slice(),
parent,
&mut specificity,
&mut flags,
- /* propagate_specificity = */ true,
+ /* propagate_specificity = */ false,
SelectorFlags::for_nesting(),
- );
- NthOf(match selectors {
- Some(s) => {
- NthOfSelectorData::new(data.nth_data(), s.slice().iter().cloned())
- },
- None => data.clone(),
- })
- },
- Slotted(ref selector) => Slotted(replace_parent_on_selector(
- selector,
+ )
+ .unwrap_or_else(|| selectors.clone()),
+ )
+ },
+ Has(ref selectors) => Has(replace_parent_on_relative_selector_list(
+ selectors,
+ parent,
+ &mut specificity,
+ &mut flags,
+ SelectorFlags::for_nesting(),
+ )
+ .into_boxed_slice()),
+
+ Host(Some(ref selector)) => Host(Some(replace_parent_on_selector(
+ selector,
+ parent,
+ &mut specificity,
+ &mut flags,
+ SelectorFlags::for_nesting() - SelectorFlags::HAS_NON_FEATURELESS_COMPONENT,
+ ))),
+ NthOf(ref data) => {
+ let selectors = replace_parent_on_selector_list(
+ data.selectors(),
parent,
&mut specificity,
&mut flags,
+ /* propagate_specificity = */ true,
SelectorFlags::for_nesting(),
- )),
- }
- });
- UniqueArc::from_header_and_iter(Default::default(), iter)
- };
+ );
+ NthOf(match selectors {
+ Some(s) => {
+ NthOfSelectorData::new(data.nth_data(), s.slice().iter().cloned())
+ },
+ None => data.clone(),
+ })
+ },
+ Slotted(ref selector) => Slotted(replace_parent_on_selector(
+ selector,
+ parent,
+ &mut specificity,
+ &mut flags,
+ SelectorFlags::for_nesting(),
+ )),
+ }
+ });
+ let mut items = UniqueArc::from_header_and_iter(Default::default(), iter);
*items.header_mut() = SpecificityAndFlags {
specificity: specificity.into(),
flags,
@@ -2602,9 +2608,14 @@ where
// combinator.
builder.push_combinator(combinator.unwrap_or(Combinator::Descendant));
},
- ParseRelative::ForNesting => {
+ ParseRelative::ForNesting | ParseRelative::ForScope => {
if let Ok(combinator) = combinator {
- builder.push_simple_selector(Component::ParentSelector);
+ let selector = match parse_relative {
+ ParseRelative::ForHas | ParseRelative::No => unreachable!(),
+ ParseRelative::ForNesting => Component::ParentSelector,
+ ParseRelative::ForScope => Component::Scope,
+ };
+ builder.push_simple_selector(selector);
builder.push_combinator(combinator);
}
},
@@ -2643,7 +2654,7 @@ where
builder.push_combinator(combinator);
}
- return Ok(Selector(builder.build()));
+ return Ok(Selector(builder.build(parse_relative)));
}
fn try_parse_combinator<'i, 't, P, Impl>(input: &mut CssParser<'i, 't>) -> Result<Combinator, ()> {
@@ -4375,7 +4386,7 @@ pub mod tests {
parse("#foo:has(:is(.bar, div .baz).bar)").unwrap()
);
- let child = parse("#foo").unwrap();
+ let child = parse_relative_expected("#foo", ParseRelative::ForNesting, Some("& #foo")).unwrap();
assert_eq!(
child.replace_parent_selector(&parent),
parse(":is(.bar, div .baz) #foo").unwrap()