lazily compute normalized name of psuedo selector

This commit is contained in:
Connor Skees 2020-07-07 14:48:02 -04:00
parent 1ae9cdbb23
commit 4379e1e3b7
4 changed files with 14 additions and 15 deletions

View File

@ -600,7 +600,7 @@ fn first_if_root(queue: &mut VecDeque<ComplexSelectorComponent>) -> Option<Compo
fn has_root(compound: &CompoundSelector) -> bool { fn has_root(compound: &CompoundSelector) -> bool {
compound.components.iter().any(|simple| { compound.components.iter().any(|simple| {
if let SimpleSelector::Pseudo(pseudo) = simple { if let SimpleSelector::Pseudo(pseudo) = simple {
pseudo.is_class && &*pseudo.normalized_name == "root" pseudo.is_class && pseudo.normalized_name() == "root"
} else { } else {
false false
} }

View File

@ -598,7 +598,7 @@ impl Extender {
// writing. We can keep them if either the original selector had a complex // writing. We can keep them if either the original selector had a complex
// selector, or the result of extending has only complex selectors, because // selector, or the result of extending has only complex selectors, because
// either way we aren't breaking anything that isn't already broken. // either way we aren't breaking anything that isn't already broken.
let mut complexes = if &*pseudo.normalized_name == "not" let mut complexes = if pseudo.normalized_name() == "not"
&& !pseudo && !pseudo
.selector .selector
.clone() .clone()
@ -644,7 +644,7 @@ impl Extender {
return vec![complex]; return vec![complex];
} }
match &*pseudo.normalized_name { match pseudo.normalized_name() {
"not" => { "not" => {
// In theory, if there's a `:not` nested within another `:not`, the // In theory, if there's a `:not` nested within another `:not`, the
// inner `:not`'s contents should be unified with the return value. // inner `:not`'s contents should be unified with the return value.
@ -652,7 +652,7 @@ impl Extender {
// become `.foo:not(.bar)`. However, this is a narrow edge case and // become `.foo:not(.bar)`. However, this is a narrow edge case and
// supporting it properly would make this code and the code calling it // supporting it properly would make this code and the code calling it
// a lot more complicated, so it's not supported for now. // a lot more complicated, so it's not supported for now.
if &*inner_pseudo.normalized_name == "matches" { if inner_pseudo.normalized_name() == "matches" {
inner_pseudo.selector.clone().unwrap().components inner_pseudo.selector.clone().unwrap().components
} else { } else {
Vec::new() Vec::new()
@ -684,7 +684,7 @@ impl Extender {
// Older browsers support `:not`, but only with a single complex selector. // Older browsers support `:not`, but only with a single complex selector.
// In order to support those browsers, we break up the contents of a `:not` // In order to support those browsers, we break up the contents of a `:not`
// unless it originally contained a selector list. // unless it originally contained a selector list.
if &*pseudo.normalized_name == "not" if pseudo.normalized_name() == "not"
&& pseudo.selector.clone().unwrap().components.len() == 1 && pseudo.selector.clone().unwrap().components.len() == 1
{ {
let result = complexes let result = complexes

View File

@ -295,8 +295,6 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
Some(Token { kind: '(', .. }) => self.parser.toks.next(), Some(Token { kind: '(', .. }) => self.parser.toks.next(),
_ => { _ => {
return Ok(SimpleSelector::Pseudo(Pseudo { return Ok(SimpleSelector::Pseudo(Pseudo {
// todo: we can store the reference to this
normalized_name: unvendor(&name.node).to_string().into_boxed_str(),
is_class: !element && !is_fake_pseudo_element(&name), is_class: !element && !is_fake_pseudo_element(&name),
name: name.node, name: name.node,
selector: None, selector: None,
@ -353,7 +351,6 @@ impl<'a, 'b> SelectorParser<'a, 'b> {
} }
Ok(SimpleSelector::Pseudo(Pseudo { Ok(SimpleSelector::Pseudo(Pseudo {
normalized_name: unvendor(&name.node).to_string().into_boxed_str(),
is_class: !element && !is_fake_pseudo_element(&name), is_class: !element && !is_fake_pseudo_element(&name),
name: name.node, name: name.node,
selector, selector,

View File

@ -5,7 +5,7 @@ use std::{
use codemap::Span; use codemap::Span;
use crate::error::SassResult; use crate::{common::unvendor, error::SassResult};
use super::{ use super::{
Attribute, ComplexSelector, ComplexSelectorComponent, CompoundSelector, Namespace, Attribute, ComplexSelector, ComplexSelectorComponent, CompoundSelector, Namespace,
@ -353,11 +353,11 @@ impl SimpleSelector {
} }
if let SimpleSelector::Pseudo(Pseudo { if let SimpleSelector::Pseudo(Pseudo {
selector: Some(sel), selector: Some(sel),
normalized_name, name,
.. ..
}) = their_simple }) = their_simple
{ {
if SUBSELECTOR_PSEUDOS.contains(&&**normalized_name) { if SUBSELECTOR_PSEUDOS.contains(&unvendor(&name)) {
return sel.components.iter().all(|complex| { return sel.components.iter().all(|complex| {
if complex.components.len() != 1 { if complex.components.len() != 1 {
return false; return false;
@ -384,9 +384,6 @@ pub(crate) struct Pseudo {
/// The name of this selector. /// The name of this selector.
pub name: String, pub name: String,
/// Like `name`, but without any vendor prefixes.
pub normalized_name: Box<str>,
/// Whether this is a pseudo-class selector. /// Whether this is a pseudo-class selector.
/// ///
/// If this is false, this is a pseudo-element selector /// If this is false, this is a pseudo-element selector
@ -489,7 +486,7 @@ impl Pseudo {
parents: Option<Vec<ComplexSelectorComponent>>, parents: Option<Vec<ComplexSelectorComponent>>,
) -> bool { ) -> bool {
debug_assert!(self.selector.is_some()); debug_assert!(self.selector.is_some());
match &*self.normalized_name { match self.normalized_name() {
"matches" | "any" => { "matches" | "any" => {
let pseudos = selector_pseudos_named(compound.clone(), &self.name, true); let pseudos = selector_pseudos_named(compound.clone(), &self.name, true);
pseudos.iter().any(move |pseudo2| { pseudos.iter().any(move |pseudo2| {
@ -647,6 +644,11 @@ impl Pseudo {
Specificity { min, max } Specificity { min, max }
} }
} }
/// Like `name`, but without any vendor prefixes.
pub fn normalized_name(&self) -> &str {
unvendor(&self.name)
}
} }
/// Returns all pseudo selectors in `compound` that have a selector argument, /// Returns all pseudo selectors in `compound` that have a selector argument,