Shrink selectors::Component, add case-insensitive for other attr selectors

* https://bugzilla.mozilla.org/show_bug.cgi?id=1364148
* https://bugzilla.mozilla.org/show_bug.cgi?id=1364162
This commit is contained in:
Simon Sapin 2017-05-17 22:21:00 +02:00
parent 83c7824fda
commit 9376abdd2c
15 changed files with 377 additions and 357 deletions

View file

@ -2,10 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use attr::{AttrSelectorOperation, AttrSelectorOperator, CaseSensitivity};
use attr::{AttrSelectorOperation, NamespaceConstraint};
use bloom::BloomFilter;
use parser::{Combinator, ComplexSelector, Component, LocalName, NamespaceConstraint};
use parser::{Selector, SelectorInner, SelectorIter, SelectorImpl, AttrSelector};
use parser::{Combinator, ComplexSelector, Component, LocalName};
use parser::{Selector, SelectorInner, SelectorIter, SelectorImpl};
use std::borrow::Borrow;
use tree::Element;
@ -387,8 +387,7 @@ fn matches_simple_selector<E, F>(
element.match_pseudo_element(pseudo, context)
}
Component::LocalName(LocalName { ref name, ref lower_name }) => {
let name = if element.is_html_element_in_html_document() { lower_name } else { name };
element.get_local_name() == name.borrow()
element.get_local_name() == select_name(element, name, lower_name).borrow()
}
Component::ExplicitUniversalType |
Component::ExplicitAnyNamespace => {
@ -399,9 +398,8 @@ fn matches_simple_selector<E, F>(
element.get_namespace() == url.borrow()
}
Component::ExplicitNoNamespace => {
// Rust types default, not default namespace
let empty_string = <E::Impl as SelectorImpl>::NamespaceUrl::default();
element.get_namespace() == empty_string.borrow()
let ns = ::parser::namespace_empty_string::<E::Impl>();
element.get_namespace() == ns.borrow()
}
// TODO: case-sensitivity depends on the document type and quirks mode
Component::ID(ref id) => {
@ -411,63 +409,58 @@ fn matches_simple_selector<E, F>(
Component::Class(ref class) => {
element.has_class(class)
}
Component::AttrExists(ref attr) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::Exists)
Component::AttributeInNoNamespaceExists { ref local_name, ref local_name_lower } => {
element.attr_matches(
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
select_name(element, local_name, local_name_lower),
&AttrSelectorOperation::Exists
)
}
Component::AttrEqual(ref attr, ref value, case_sensitivity) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::WithValue {
operator: AttrSelectorOperator::Equal,
case_sensitivity: case_sensitivity,
expected_value: value
})
Component::AttributeInNoNamespace {
ref local_name,
ref local_name_lower,
ref value,
operator,
case_sensitivity,
never_matches,
} => {
if never_matches {
false
} else {
element.attr_matches(
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
select_name(element, local_name, local_name_lower),
&AttrSelectorOperation::WithValue {
operator: operator,
case_sensitivity: case_sensitivity,
expected_value: value,
}
)
}
}
Component::AttrIncludes(ref attr, ref value) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::WithValue {
operator: AttrSelectorOperator::Includes,
case_sensitivity: CaseSensitivity::CaseSensitive,
expected_value: value
})
}
Component::AttrDashMatch(ref attr, ref value) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::WithValue {
operator: AttrSelectorOperator::DashMatch,
case_sensitivity: CaseSensitivity::CaseSensitive,
expected_value: value
})
}
Component::AttrPrefixMatch(ref attr, ref value) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::WithValue {
operator: AttrSelectorOperator::Prefix,
case_sensitivity: CaseSensitivity::CaseSensitive,
expected_value: value
})
}
Component::AttrSubstringMatch(ref attr, ref value) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::WithValue {
operator: AttrSelectorOperator::Substring,
case_sensitivity: CaseSensitivity::CaseSensitive,
expected_value: value
})
}
Component::AttrSuffixMatch(ref attr, ref value) => {
let (ns, n) = unpack_attr_selector(element, attr);
element.attr_matches(ns, n, &AttrSelectorOperation::WithValue {
operator: AttrSelectorOperator::Suffix,
case_sensitivity: CaseSensitivity::CaseSensitive,
expected_value: value
})
}
Component::AttrIncludesNeverMatch(..) |
Component::AttrPrefixNeverMatch(..) |
Component::AttrSubstringNeverMatch(..) |
Component::AttrSuffixNeverMatch(..) => {
false
Component::AttributeOther(ref attr_sel) => {
if attr_sel.never_matches {
return false
} else {
element.attr_matches(
&attr_sel.namespace(),
select_name(element, &attr_sel.local_name, &attr_sel.local_name_lower),
&match attr_sel.operation {
AttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
AttrSelectorOperation::WithValue {
operator,
case_sensitivity,
ref expected_value,
} => {
AttrSelectorOperation::WithValue {
operator: operator,
case_sensitivity: case_sensitivity,
expected_value: expected_value,
}
}
}
)
}
}
Component::NonTSPseudoClass(ref pc) => {
element.match_non_ts_pseudo_class(pc, context, flags_setter)
@ -519,16 +512,15 @@ fn matches_simple_selector<E, F>(
}
}
fn unpack_attr_selector<'a, E>(element: &E, attr: &'a AttrSelector<E::Impl>)
-> (&'a NamespaceConstraint<E::Impl>,
&'a <E::Impl as SelectorImpl>::LocalName)
fn select_name<'a, E>(element: &E, local_name: &'a <E::Impl as SelectorImpl>::LocalName,
local_name_lower: &'a <E::Impl as SelectorImpl>::LocalName)
-> &'a <E::Impl as SelectorImpl>::LocalName
where E: Element {
let name = if element.is_html_element_in_html_document() {
&attr.lower_name
if element.is_html_element_in_html_document() {
local_name_lower
} else {
&attr.name
};
(&attr.namespace, name)
local_name
}
}
#[inline]