Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: Don't support a list of selectors in ::slotted yet. #19610

Merged
merged 1 commit into from Dec 20, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

style: Don't support a list of selectors in ::slotted yet.

Bug: 1425757
Reviewed-by: xidorn
MozReview-Commit-ID: G0I0gM2sWTh
  • Loading branch information
emilio committed Dec 20, 2017
commit b556ddbf559aef6da9f0356a9585b1dc0590e35e
@@ -555,18 +555,16 @@ where
{
match *selector {
Component::Combinator(_) => unreachable!(),
Component::Slotted(ref selectors) => {
Component::Slotted(ref selector) => {
context.shared.nesting_level += 1;
let result =
element.assigned_slot().is_some() &&
selectors.iter().any(|s| {
matches_complex_selector(
s.iter(),
element,
context.shared,
flags_setter,
)
});
matches_complex_selector(
selector.iter(),
element,
context.shared,
flags_setter,
);
context.shared.nesting_level -= 1;
result
}
@@ -215,31 +215,39 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
}
}

/// Parse a comma separated list of compound selectors.
pub fn parse_compound_selector_list<'i, 't, P, Impl>(
/// Parses one compound selector suitable for nested stuff like ::-moz-any, etc.
fn parse_inner_compound_selector<'i, 't, P, Impl>(
parser: &P,
input: &mut CssParser<'i, 't>,
) -> Result<Box<[Selector<Impl>]>, ParseError<'i, P::Error>>
) -> Result<Selector<Impl>, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl=Impl>,
Impl: SelectorImpl,
{
let location = input.current_source_location();
let selectors = input.parse_comma_separated(|input| {
Selector::parse(parser, input)
})?;

let selector = Selector::parse(parser, input)?;
// Ensure they're actually all compound selectors.
if selectors
.iter()
.flat_map(|x| x.iter_raw_match_order())
.any(|s| s.is_combinator()) {
if selector.iter_raw_match_order().any(|s| s.is_combinator()) {
return Err(location.new_custom_error(
SelectorParseErrorKind::NonCompoundSelector
))
}

Ok(selectors.into_boxed_slice())
Ok(selector)
}

/// Parse a comma separated list of compound selectors.
pub fn parse_compound_selector_list<'i, 't, P, Impl>(
parser: &P,
input: &mut CssParser<'i, 't>,
) -> Result<Box<[Selector<Impl>]>, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl=Impl>,
Impl: SelectorImpl,
{
input.parse_comma_separated(|input| {
parse_inner_compound_selector(parser, input)
}).map(|selectors| selectors.into_boxed_slice())
}

/// Ancestor hashes for the bloom filter. We precompute these and store them
@@ -761,8 +769,12 @@ pub enum Component<Impl: SelectorImpl> {
///
/// https://drafts.csswg.org/css-scoping/#slotted-pseudo
///
/// The selectors here are compound selectors, that is, no combinators.
Slotted(Box<[Selector<Impl>]>),
/// The selector here is a compound selector, that is, no combinators.
///
/// NOTE(emilio): This should support a list of selectors, but as of this
/// writing no other browser does, and that allows them to put ::slotted()
/// in the rule hash, so we do that too.
Slotted(Selector<Impl>),
PseudoElement(Impl::PseudoElement),
}

@@ -997,14 +1009,9 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
Combinator(ref c) => {
c.to_css(dest)
}
Slotted(ref selectors) => {
Slotted(ref selector) => {
dest.write_str("::slotted(")?;
let mut iter = selectors.iter();
iter.next().expect("At least one selector").to_css(dest)?;
for other in iter {
dest.write_str(", ")?;
other.to_css(dest)?;
}
selector.to_css(dest)?;
dest.write_char(')')
}
PseudoElement(ref p) => {
@@ -1305,7 +1312,7 @@ where
enum SimpleSelectorParseResult<Impl: SelectorImpl> {
SimpleSelector(Component<Impl>),
PseudoElement(Impl::PseudoElement),
SlottedPseudo(Box<[Selector<Impl>]>),
SlottedPseudo(Selector<Impl>),
}

#[derive(Debug)]
@@ -1724,13 +1731,13 @@ where
empty = false;
break
}
SimpleSelectorParseResult::SlottedPseudo(selectors) => {
SimpleSelectorParseResult::SlottedPseudo(selector) => {
empty = false;
slot = true;
if !builder.is_empty() {
builder.push_combinator(Combinator::SlotAssignment);
}
builder.push_simple_selector(Component::Slotted(selectors));
builder.push_simple_selector(Component::Slotted(selector));
// FIXME(emilio): ::slotted() should support ::before and
// ::after after it, so we shouldn't break, but we shouldn't
// push more type selectors either.
@@ -1857,7 +1864,7 @@ where
if P::parse_slotted(parser) && name.eq_ignore_ascii_case("slotted") {
SimpleSelectorParseResult::SlottedPseudo(
input.parse_nested_block(|input| {
parse_compound_selector_list(
parse_inner_compound_selector(
parser,
input,
)
@@ -2489,7 +2496,10 @@ pub mod tests {
assert!(parse("div ::slotted(div)").is_ok());
assert!(parse("div + slot::slotted(div)").is_ok());
assert!(parse("div + slot::slotted(div.foo)").is_ok());
assert!(parse("div + slot::slotted(.foo, bar, .baz)").is_ok());
assert!(parse("slot::slotted(div,foo)::first-line").is_err());
// TODO
assert!(parse("::slotted(div)::before").is_err());
assert!(parse("slot::slotted(div,foo)").is_err());
}

#[test]
@@ -415,6 +415,25 @@ fn specific_bucket_for<'a>(
lower_name: &selector.lower_name,
}
}
// ::slotted(..) isn't a normal pseudo-element, so we can insert it on
// the rule hash normally without much problem. For example, in a
// selector like:
//
// div::slotted(span)::before
//
// It looks like:
//
// [
// LocalName(div),
// Combinator(SlotAssignment),
// Slotted(span),
// Combinator::PseudoElement,
// PseudoElement(::before),
// ]
//
// So inserting `span` in the rule hash makes sense since we want to
// match the slotted <span>.
Component::Slotted(ref selector) => find_bucket(selector.iter()),
_ => Bucket::Universal
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.