Auto merge of #17687 - upsuper:tree-pseudo, r=heycam

Support parsing ::-moz-tree-* pseudo-elements selector

This is the Servo side change of [bug 1348488](https://bugzilla.mozilla.org/show_bug.cgi?id=1348488).

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17687)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-07-12 03:35:37 -07:00 committed by GitHub
commit ce52c16a8f
11 changed files with 765 additions and 788 deletions

View file

@ -17,6 +17,7 @@ pub enum PseudoClass {
pub enum PseudoElement {
A,
B,
Tree(Box<[String]>),
}
#[derive(Eq, PartialEq, Clone, Debug, Default)]

View file

@ -131,6 +131,12 @@ pub trait Parser<'i> {
type Impl: SelectorImpl;
type Error: 'i;
/// Whether the name is a pseudo-element that can be specified with
/// the single colon syntax in addition to the double-colon syntax.
fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool {
is_css2_pseudo_element(name)
}
/// This function can return an "Err" pseudo-element in order to support CSS2.1
/// pseudo-elements.
fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
@ -153,6 +159,13 @@ pub trait Parser<'i> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn parse_functional_pseudo_element<'t>
(&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>)
-> Result<<Self::Impl as SelectorImpl>::PseudoElement,
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
}
fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
None
}
@ -1471,6 +1484,17 @@ where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
}
/// Returns whether the name corresponds to a CSS2 pseudo-element that
/// can be specified with the single colon syntax (in addition to the
/// double-colon syntax, which can be used for all pseudo-elements).
pub fn is_css2_pseudo_element<'i>(name: &CompactCowStr<'i>) -> bool {
// ** Do not add to this list! **
return name.eq_ignore_ascii_case("before") ||
name.eq_ignore_ascii_case("after") ||
name.eq_ignore_ascii_case("first-line") ||
name.eq_ignore_ascii_case("first-letter");
}
/// Parse a simple selector other than a type selector.
///
/// * `Err(())`: Invalid selector, abort
@ -1490,13 +1514,12 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
Ok(Some(SimpleSelectorParseResult::SimpleSelector(id)))
}
Ok(Token::Delim('.')) => {
match input.next_including_whitespace() {
Ok(Token::Ident(class)) => {
match input.next_including_whitespace()? {
Token::Ident(class) => {
let class = Component::Class(from_cow_str(class.into()));
Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
}
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
}
}
Ok(Token::SquareBracketBlock) => {
@ -1504,39 +1527,35 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
Ok(Some(SimpleSelectorParseResult::SimpleSelector(attr)))
}
Ok(Token::Colon) => {
match input.next_including_whitespace() {
Ok(Token::Ident(name)) => {
// Supported CSS 2.1 pseudo-elements only.
// ** Do not add to this list! **
if name.eq_ignore_ascii_case("before") ||
name.eq_ignore_ascii_case("after") ||
name.eq_ignore_ascii_case("first-line") ||
name.eq_ignore_ascii_case("first-letter") {
let pseudo_element = P::parse_pseudo_element(parser, name)?;
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo_element)))
} else {
let pseudo_class = parse_simple_pseudo_class(parser, name)?;
Ok(Some(SimpleSelectorParseResult::SimpleSelector(pseudo_class)))
}
}
Ok(Token::Function(name)) => {
let pseudo = input.parse_nested_block(|input| {
let (is_single_colon, next_token) = match input.next_including_whitespace()? {
Token::Colon => (false, input.next_including_whitespace()?),
t => (true, t),
};
let (name, is_functional) = match next_token {
Token::Ident(name) => (name, false),
Token::Function(name) => (name, true),
t => return Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
};
let is_pseudo_element = !is_single_colon ||
P::is_pseudo_element_allows_single_colon(&name);
if is_pseudo_element {
let pseudo_element = if is_functional {
input.parse_nested_block(|input| {
P::parse_functional_pseudo_element(parser, name, input)
})?
} else {
P::parse_pseudo_element(parser, name)?
};
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo_element)))
} else {
let pseudo_class = if is_functional {
input.parse_nested_block(|input| {
parse_functional_pseudo_class(parser, input, name, inside_negation)
})?;
Ok(Some(SimpleSelectorParseResult::SimpleSelector(pseudo)))
}
Ok(Token::Colon) => {
match input.next_including_whitespace() {
Ok(Token::Ident(name)) => {
let pseudo = P::parse_pseudo_element(parser, name)?;
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo)))
}
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
}
}
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
Err(e) => Err(ParseError::Basic(e)),
})?
} else {
parse_simple_pseudo_class(parser, name)?
};
Ok(Some(SimpleSelectorParseResult::SimpleSelector(pseudo_class)))
}
}
_ => {

View file

@ -12,7 +12,7 @@ use std::fmt;
use visitor::SelectorVisitor;
size_of_test!(size_of_selector, Selector<Impl>, 8);
size_of_test!(size_of_pseudo_element, gecko_like_types::PseudoElement, 1);
size_of_test!(size_of_pseudo_element, gecko_like_types::PseudoElement, 24);
size_of_test!(size_of_component, Component<Impl>, 32);
size_of_test!(size_of_pseudo_class, PseudoClass, 24);

View file

@ -5114,30 +5114,30 @@ cfg_if! {
pub static nsCSSAnonBoxes_rubyText: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes17rubyTextContainerE"]
pub static nsCSSAnonBoxes_rubyTextContainer: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes13moztreecolumnE"]
pub static nsCSSAnonBoxes_moztreecolumn: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes10moztreerowE"]
pub static nsCSSAnonBoxes_moztreerow: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes16moztreeseparatorE"]
pub static nsCSSAnonBoxes_moztreeseparator: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes11moztreecellE"]
pub static nsCSSAnonBoxes_moztreecell: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes18moztreeindentationE"]
pub static nsCSSAnonBoxes_moztreeindentation: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes11moztreelineE"]
pub static nsCSSAnonBoxes_moztreeline: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes13moztreetwistyE"]
pub static nsCSSAnonBoxes_moztreetwisty: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes12moztreeimageE"]
pub static nsCSSAnonBoxes_moztreeimage: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes15moztreecelltextE"]
pub static nsCSSAnonBoxes_moztreecelltext: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes15moztreecheckboxE"]
pub static nsCSSAnonBoxes_moztreecheckbox: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes20moztreeprogressmeterE"]
pub static nsCSSAnonBoxes_moztreeprogressmeter: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes19moztreedropfeedbackE"]
pub static nsCSSAnonBoxes_moztreedropfeedback: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes13mozTreeColumnE"]
pub static nsCSSAnonBoxes_mozTreeColumn: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes10mozTreeRowE"]
pub static nsCSSAnonBoxes_mozTreeRow: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes16mozTreeSeparatorE"]
pub static nsCSSAnonBoxes_mozTreeSeparator: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes11mozTreeCellE"]
pub static nsCSSAnonBoxes_mozTreeCell: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes18mozTreeIndentationE"]
pub static nsCSSAnonBoxes_mozTreeIndentation: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes11mozTreeLineE"]
pub static nsCSSAnonBoxes_mozTreeLine: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes13mozTreeTwistyE"]
pub static nsCSSAnonBoxes_mozTreeTwisty: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes12mozTreeImageE"]
pub static nsCSSAnonBoxes_mozTreeImage: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes15mozTreeCellTextE"]
pub static nsCSSAnonBoxes_mozTreeCellText: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes15mozTreeCheckboxE"]
pub static nsCSSAnonBoxes_mozTreeCheckbox: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes20mozTreeProgressmeterE"]
pub static nsCSSAnonBoxes_mozTreeProgressmeter: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes19mozTreeDropFeedbackE"]
pub static nsCSSAnonBoxes_mozTreeDropFeedback: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes21mozSVGMarkerAnonChildE"]
pub static nsCSSAnonBoxes_mozSVGMarkerAnonChild: *mut nsICSSAnonBoxPseudo;
#[link_name = "_ZN14nsCSSAnonBoxes23mozSVGOuterSVGAnonChildE"]
@ -10243,30 +10243,30 @@ cfg_if! {
pub static nsCSSAnonBoxes_rubyText: *mut nsICSSAnonBoxPseudo;
#[link_name = "?rubyTextContainer@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_rubyTextContainer: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreecolumn@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreecolumn: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreerow@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreerow: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreeseparator@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreeseparator: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreecell@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreecell: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreeindentation@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreeindentation: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreeline@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreeline: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreetwisty@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreetwisty: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreeimage@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreeimage: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreecelltext@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreecelltext: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreecheckbox@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreecheckbox: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreeprogressmeter@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreeprogressmeter: *mut nsICSSAnonBoxPseudo;
#[link_name = "?moztreedropfeedback@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_moztreedropfeedback: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeColumn@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeColumn: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeRow@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeRow: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeSeparator@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeSeparator: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeCell@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeCell: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeIndentation@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeIndentation: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeLine@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeLine: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeTwisty@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeTwisty: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeImage@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeImage: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeCellText@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeCellText: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeCheckbox@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeCheckbox: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeProgressmeter@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeProgressmeter: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozTreeDropFeedback@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozTreeDropFeedback: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozSVGMarkerAnonChild@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
pub static nsCSSAnonBoxes_mozSVGMarkerAnonChild: *mut nsICSSAnonBoxPseudo;
#[link_name = "?mozSVGOuterSVGAnonChild@nsCSSAnonBoxes@@2PEAVnsICSSAnonBoxPseudo@@EA"]
@ -15372,30 +15372,30 @@ cfg_if! {
pub static nsCSSAnonBoxes_rubyText: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?rubyTextContainer@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_rubyTextContainer: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreecolumn@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreecolumn: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreerow@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreerow: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreeseparator@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreeseparator: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreecell@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreecell: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreeindentation@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreeindentation: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreeline@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreeline: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreetwisty@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreetwisty: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreeimage@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreeimage: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreecelltext@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreecelltext: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreecheckbox@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreecheckbox: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreeprogressmeter@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreeprogressmeter: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?moztreedropfeedback@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_moztreedropfeedback: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeColumn@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeColumn: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeRow@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeRow: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeSeparator@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeSeparator: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeCell@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeCell: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeIndentation@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeIndentation: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeLine@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeLine: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeTwisty@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeTwisty: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeImage@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeImage: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeCellText@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeCellText: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeCheckbox@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeCheckbox: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeProgressmeter@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeProgressmeter: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozTreeDropFeedback@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozTreeDropFeedback: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozSVGMarkerAnonChild@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
pub static nsCSSAnonBoxes_mozSVGMarkerAnonChild: *mut nsICSSAnonBoxPseudo;
#[link_name = "\x01?mozSVGOuterSVGAnonChild@nsCSSAnonBoxes@@2PAVnsICSSAnonBoxPseudo@@A"]
@ -20505,29 +20505,29 @@ macro_rules! atom {
(":-moz-ruby-text-container") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_rubyTextContainer as *mut _) } };
(":-moz-tree-column") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreecolumn as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeColumn as *mut _) } };
(":-moz-tree-row") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreerow as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeRow as *mut _) } };
(":-moz-tree-separator") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreeseparator as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeSeparator as *mut _) } };
(":-moz-tree-cell") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreecell as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeCell as *mut _) } };
(":-moz-tree-indentation") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreeindentation as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeIndentation as *mut _) } };
(":-moz-tree-line") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreeline as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeLine as *mut _) } };
(":-moz-tree-twisty") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreetwisty as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeTwisty as *mut _) } };
(":-moz-tree-image") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreeimage as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeImage as *mut _) } };
(":-moz-tree-cell-text") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreecelltext as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeCellText as *mut _) } };
(":-moz-tree-checkbox") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreecheckbox as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeCheckbox as *mut _) } };
(":-moz-tree-progressmeter") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreeprogressmeter as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeProgressmeter as *mut _) } };
(":-moz-tree-drop-feedback") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_moztreedropfeedback as *mut _) } };
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozTreeDropFeedback as *mut _) } };
(":-moz-svg-marker-anon-child") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsCSSAnonBoxes_mozSVGMarkerAnonChild as *mut _) } };
(":-moz-svg-outer-svg-anon-child") =>

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@
//! `pseudo_element_definition.mako.rs`. If you touch that file, you probably
//! need to update the checked-in files for Servo.
use cssparser::ToCss;
use cssparser::{ToCss, serialize_identifier};
use gecko_bindings::structs::{self, CSSPseudoElementType};
use selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl};
use std::fmt;
@ -91,10 +91,6 @@ impl PseudoElement {
/// Whether this pseudo-element is web-exposed.
pub fn exposed_in_non_ua_sheets(&self) -> bool {
if self.is_anon_box() {
return false;
}
(self.flags() & structs::CSS_PSEUDO_ELEMENT_UA_SHEET_ONLY) == 0
}
@ -118,10 +114,3 @@ impl PseudoElement {
}
}
}
impl ToCss for PseudoElement {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
dest.write_char(':')?;
dest.write_str(self.as_str())
}
}

View file

@ -7,7 +7,11 @@
pub enum PseudoElement {
% for pseudo in PSEUDOS:
/// ${pseudo.value}
% if pseudo.is_tree_pseudo_element():
${pseudo.capitalized()}(Box<[String]>),
% else:
${pseudo.capitalized()},
% endif
% endfor
}
@ -23,13 +27,21 @@ pub const EAGER_PSEUDOS: [PseudoElement; EAGER_PSEUDO_COUNT] = [
% endfor
];
<% TREE_PSEUDOS = [pseudo for pseudo in PSEUDOS if pseudo.is_tree_pseudo_element()] %>
<% SIMPLE_PSEUDOS = [pseudo for pseudo in PSEUDOS if not pseudo.is_tree_pseudo_element()] %>
<%def name="pseudo_element_variant(pseudo, tree_arg='..')">\
PseudoElement::${pseudo.capitalized()}${"({})".format(tree_arg) if pseudo.is_tree_pseudo_element() else ""}\
</%def>
impl PseudoElement {
/// Executes a closure with each pseudo-element as an argument.
pub fn each<F>(mut fun: F)
/// Executes a closure with each simple (not functional)
/// pseudo-element as an argument.
pub fn each_simple<F>(mut fun: F)
where F: FnMut(Self),
{
% for pseudo in PSEUDOS:
fun(PseudoElement::${pseudo.capitalized()});
% for pseudo in SIMPLE_PSEUDOS:
fun(${pseudo_element_variant(pseudo)});
% endfor
}
@ -38,7 +50,7 @@ impl PseudoElement {
pub fn atom(&self) -> Atom {
match *self {
% for pseudo in PSEUDOS:
PseudoElement::${pseudo.capitalized()} => atom!("${pseudo.value}"),
${pseudo_element_variant(pseudo)} => atom!("${pseudo.value}"),
% endfor
}
}
@ -48,8 +60,11 @@ impl PseudoElement {
fn is_anon_box(&self) -> bool {
match *self {
% for pseudo in PSEUDOS:
PseudoElement::${pseudo.capitalized()} => ${str(pseudo.is_anon_box()).lower()},
% if pseudo.is_anon_box():
${pseudo_element_variant(pseudo)} => true,
% endif
% endfor
_ => false,
}
}
@ -65,13 +80,14 @@ impl PseudoElement {
pub fn flags(&self) -> u32 {
match *self {
% for pseudo in PSEUDOS:
PseudoElement::${pseudo.capitalized()} => {
% if pseudo.is_anon_box():
0
% else:
structs::SERVO_CSS_PSEUDO_ELEMENT_FLAGS_${pseudo.original_ident}
% endif
}
${pseudo_element_variant(pseudo)} =>
% if pseudo.is_tree_pseudo_element():
0,
% elif pseudo.is_anon_box():
structs::CSS_PSEUDO_ELEMENT_UA_SHEET_ONLY,
% else:
structs::SERVO_CSS_PSEUDO_ELEMENT_FLAGS_${pseudo.original_ident},
% endif
% endfor
}
}
@ -83,7 +99,7 @@ impl PseudoElement {
% for pseudo in PSEUDOS:
% if not pseudo.is_anon_box():
CSSPseudoElementType::${pseudo.original_ident} => {
Some(PseudoElement::${pseudo.capitalized()})
Some(${pseudo_element_variant(pseudo)})
},
% endif
% endfor
@ -95,9 +111,11 @@ impl PseudoElement {
#[inline]
pub fn from_anon_box_atom(atom: &Atom) -> Option<Self> {
% for pseudo in PSEUDOS:
% if pseudo.is_anon_box():
% if pseudo.is_tree_pseudo_element():
// We cannot generate ${pseudo_element_variant(pseudo)} from just an atom.
% elif pseudo.is_anon_box():
if atom == &atom!("${pseudo.value}") {
return Some(PseudoElement::${pseudo.capitalized()});
return Some(${pseudo_element_variant(pseudo)});
}
% endif
% endfor
@ -115,10 +133,13 @@ impl PseudoElement {
pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> {
use std::ascii::AsciiExt;
% for pseudo in PSEUDOS:
if in_ua_stylesheet || PseudoElement::${pseudo.capitalized()}.exposed_in_non_ua_sheets() {
// We don't need to support tree pseudos because functional
// pseudo-elements needs arguments, and thus should be created
// via other methods.
% for pseudo in SIMPLE_PSEUDOS:
if in_ua_stylesheet || ${pseudo_element_variant(pseudo)}.exposed_in_non_ua_sheets() {
if s.eq_ignore_ascii_case("${pseudo.value[1:]}") {
return Some(PseudoElement::${pseudo.capitalized()})
return Some(${pseudo_element_variant(pseudo)});
}
}
% endfor
@ -126,13 +147,47 @@ impl PseudoElement {
None
}
/// Returns the pseudo-element's definition as a string, with only one colon
/// before it.
pub fn as_str(&self) -> &'static str {
match *self {
% for pseudo in PSEUDOS:
PseudoElement::${pseudo.capitalized()} => "${pseudo.value}",
/// Constructs a tree pseudo-element from the given name and arguments.
/// "name" must start with "-moz-tree-".
///
/// Returns `None` if the pseudo-element is not recognized.
#[inline]
pub fn tree_pseudo_element(name: &str, args: Box<[String]>) -> Option<Self> {
use std::ascii::AsciiExt;
debug_assert!(name.starts_with("-moz-tree-"));
let tree_part = &name[10..];
% for pseudo in TREE_PSEUDOS:
if tree_part.eq_ignore_ascii_case("${pseudo.value[11:]}") {
return Some(${pseudo_element_variant(pseudo, "args")});
}
% endfor
None
}
}
impl ToCss for PseudoElement {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
dest.write_char(':')?;
match *self {
% for pseudo in PSEUDOS:
${pseudo_element_variant(pseudo)} => dest.write_str("${pseudo.value}")?,
% endfor
}
match *self {
${" |\n ".join("PseudoElement::{}(ref args)".format(pseudo.capitalized())
for pseudo in TREE_PSEUDOS)} => {
dest.write_char('(')?;
let mut iter = args.iter();
if let Some(first) = iter.next() {
serialize_identifier(first, dest)?;
for item in iter {
dest.write_str(", ")?;
serialize_identifier(item, dest)?;
}
}
dest.write_char(')')
}
_ => Ok(()),
}
}
}

View file

@ -103,6 +103,9 @@ class Atom:
def is_anon_box(self):
return self.type() == "nsICSSAnonBoxPseudo"
def is_tree_pseudo_element(self):
return self.value.startswith(":-moz-tree-")
def collect_atoms(objdir):
atoms = []

View file

@ -4,7 +4,7 @@
//! Gecko-specific bits for selector-parsing.
use cssparser::{Parser, ToCss, CompactCowStr};
use cssparser::{BasicParseError, Parser, ToCss, Token, CompactCowStr};
use element_state::ElementState;
use gecko_bindings::structs::CSSPseudoClassType;
use selector_parser::{SelectorParser, PseudoElementCascadeType};
@ -267,6 +267,11 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
type Impl = SelectorImpl;
type Error = StyleParseError<'i>;
fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool {
::selectors::parser::is_css2_pseudo_element(name) ||
name.starts_with("-moz-tree-") // tree pseudo-elements
}
fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>)
-> Result<NonTSPseudoClass, ParseError<'i>> {
macro_rules! pseudo_class_parse {
@ -338,6 +343,30 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
.ok_or(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
fn parse_functional_pseudo_element<'t>(&self, name: CompactCowStr<'i>,
parser: &mut Parser<'i, 't>)
-> Result<PseudoElement, ParseError<'i>> {
if name.starts_with("-moz-tree-") {
// Tree pseudo-elements can have zero or more arguments,
// separated by either comma or space.
let mut args = Vec::new();
loop {
match parser.next() {
Ok(Token::Ident(ident)) => args.push(ident.into_owned()),
Ok(Token::Comma) => {},
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
Err(BasicParseError::EndOfInput) => break,
_ => unreachable!("Parser::next() shouldn't return any other error"),
}
}
let args = args.into_boxed_slice();
if let Some(pseudo) = PseudoElement::tree_pseudo_element(&name, args) {
return Ok(pseudo);
}
}
Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
}
fn default_namespace(&self) -> Option<Namespace> {
self.namespaces.default.clone().as_ref().map(|&(ref ns, _)| ns.clone())
}
@ -367,11 +396,11 @@ impl SelectorImpl {
#[inline]
/// Executes a function for each pseudo-element.
pub fn each_pseudo_element<F>(fun: F)
/// Executes a function for each simple (not functional) pseudo-element.
pub fn each_simple_pseudo_element<F>(fun: F)
where F: FnMut(PseudoElement),
{
PseudoElement::each(fun)
PseudoElement::each_simple(fun)
}
#[inline]

View file

@ -121,7 +121,7 @@ impl SelectorImpl {
pub fn each_precomputed_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement),
{
Self::each_pseudo_element(|pseudo| {
Self::each_simple_pseudo_element(|pseudo| {
if pseudo.is_precomputed() {
fun(pseudo)
}

View file

@ -28,7 +28,7 @@ use style_traits::{ParseError, StyleParseError};
/// A pseudo-element, both public and private.
///
/// NB: If you add to this list, be sure to update `each_pseudo_element` too.
/// NB: If you add to this list, be sure to update `each_simple_pseudo_element` too.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
@ -485,7 +485,7 @@ impl SelectorImpl {
/// Executes `fun` for each pseudo-element.
#[inline]
pub fn each_pseudo_element<F>(mut fun: F)
pub fn each_simple_pseudo_element<F>(mut fun: F)
where F: FnMut(PseudoElement),
{
fun(PseudoElement::Before);