aboutsummaryrefslogtreecommitdiffstats
path: root/components/selectors/tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/selectors/tree.rs')
-rw-r--r--components/selectors/tree.rs139
1 files changed, 17 insertions, 122 deletions
diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs
index e5a4539e3cc..276c788d05b 100644
--- a/components/selectors/tree.rs
+++ b/components/selectors/tree.rs
@@ -5,122 +5,13 @@
//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between layout and
//! style.
+use attr::{AttrSelectorOperation, NamespaceConstraint};
use matching::{ElementSelectorFlags, MatchingContext};
-use parser::{AttrSelector, SelectorImpl};
-use std::ascii::AsciiExt;
+use parser::SelectorImpl;
-/// The definition of whitespace per CSS Selectors Level 3 § 4.
-pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C'];
-
-// Attribute matching routines. Consumers with simple implementations can implement
-// MatchAttrGeneric instead.
-pub trait MatchAttr {
- type Impl: SelectorImpl;
-
- fn match_attr_has(
- &self,
- attr: &AttrSelector<Self::Impl>) -> bool;
-
- fn match_attr_equals(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-
- fn match_attr_equals_ignore_ascii_case(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-
- fn match_attr_includes(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-
- fn match_attr_dash(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-
- fn match_attr_prefix(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-
- fn match_attr_substring(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-
- fn match_attr_suffix(
- &self,
- attr: &AttrSelector<Self::Impl>,
- value: &<Self::Impl as SelectorImpl>::AttrValue) -> bool;
-}
-
-pub trait MatchAttrGeneric {
+pub trait Element: Sized {
type Impl: SelectorImpl;
- fn match_attr<F>(&self, attr: &AttrSelector<Self::Impl>, test: F) -> bool where F: Fn(&str) -> bool;
-}
-
-impl<T> MatchAttr for T where T: MatchAttrGeneric, T::Impl: SelectorImpl<AttrValue = String> {
- type Impl = T::Impl;
-
- fn match_attr_has(&self, attr: &AttrSelector<Self::Impl>) -> bool {
- self.match_attr(attr, |_| true)
- }
-
- fn match_attr_equals(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
- self.match_attr(attr, |v| v == value)
- }
-
- fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector<Self::Impl>,
- value: &String) -> bool {
- self.match_attr(attr, |v| v.eq_ignore_ascii_case(value))
- }
-
- fn match_attr_includes(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
- self.match_attr(attr, |attr_value| {
- attr_value.split(SELECTOR_WHITESPACE).any(|v| v == value)
- })
- }
- fn match_attr_dash(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
- self.match_attr(attr, |attr_value| {
- // The attribute must start with the pattern.
- if !attr_value.starts_with(value) {
- return false
- }
-
- // If the strings are the same, we're done.
- if attr_value.len() == value.len() {
- return true
- }
-
- // The attribute is long than the pattern, so the next character must be '-'.
- attr_value.as_bytes()[value.len()] == '-' as u8
- })
- }
-
- fn match_attr_prefix(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
- self.match_attr(attr, |attr_value| {
- attr_value.starts_with(value)
- })
- }
-
- fn match_attr_substring(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
- self.match_attr(attr, |attr_value| {
- attr_value.contains(value)
- })
- }
-
- fn match_attr_suffix(&self, attr: &AttrSelector<Self::Impl>, value: &String) -> bool {
- self.match_attr(attr, |attr_value| {
- attr_value.ends_with(value)
- })
- }
-}
-
-pub trait Element: MatchAttr + Sized {
fn parent_element(&self) -> Option<Self>;
/// The parent of a given pseudo-element, after matching a pseudo-element
@@ -131,22 +22,31 @@ pub trait Element: MatchAttr + Sized {
self.parent_element()
}
- // Skips non-element nodes
+ /// Skips non-element nodes
fn first_child_element(&self) -> Option<Self>;
- // Skips non-element nodes
+ /// Skips non-element nodes
fn last_child_element(&self) -> Option<Self>;
- // Skips non-element nodes
+ /// Skips non-element nodes
fn prev_sibling_element(&self) -> Option<Self>;
- // Skips non-element nodes
+ /// Skips non-element nodes
fn next_sibling_element(&self) -> Option<Self>;
fn is_html_element_in_html_document(&self) -> bool;
+
fn get_local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName;
+
+ /// Empty string for no namespace
fn get_namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl;
+ fn attr_matches(&self,
+ ns: &NamespaceConstraint<&<Self::Impl as SelectorImpl>::NamespaceUrl>,
+ local_name: &<Self::Impl as SelectorImpl>::LocalName,
+ operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>)
+ -> bool;
+
fn match_non_ts_pseudo_class<F>(&self,
pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
context: &mut MatchingContext,
@@ -159,6 +59,7 @@ pub trait Element: MatchAttr + Sized {
-> bool;
fn get_id(&self) -> Option<<Self::Impl as SelectorImpl>::Identifier>;
+
fn has_class(&self, name: &<Self::Impl as SelectorImpl>::ClassName) -> bool;
/// Returns whether this element matches `:empty`.
@@ -173,10 +74,4 @@ pub trait Element: MatchAttr + Sized {
/// Note: this can be false even if `.parent_element()` is `None`
/// if the parent node is a `DocumentFragment`.
fn is_root(&self) -> bool;
-
- // Ordinarily I wouldn't use callbacks like this, but the alternative is
- // really messy, since there is a `JSRef` and a `RefCell` involved. Maybe
- // in the future when we have associated types and/or a more convenient
- // JS GC story... --pcwalton
- fn each_class<F>(&self, callback: F) where F: FnMut(&<Self::Impl as SelectorImpl>::ClassName);
}