mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Add more enum types to avoid unreachable!() for selector case-sensitivity
This commit is contained in:
parent
7149a6a29d
commit
76166bce58
6 changed files with 57 additions and 48 deletions
|
@ -12,7 +12,7 @@ pub struct AttrSelectorWithNamespace<Impl: SelectorImpl> {
|
||||||
pub namespace: NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>,
|
pub namespace: NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>,
|
||||||
pub local_name: Impl::LocalName,
|
pub local_name: Impl::LocalName,
|
||||||
pub local_name_lower: Impl::LocalName,
|
pub local_name_lower: Impl::LocalName,
|
||||||
pub operation: AttrSelectorOperation<Impl::AttrValue>,
|
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
|
||||||
pub never_matches: bool,
|
pub never_matches: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,16 @@ pub enum NamespaceConstraint<NamespaceUrl> {
|
||||||
Specific(NamespaceUrl),
|
Specific(NamespaceUrl),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone)]
|
||||||
|
pub enum ParsedAttrSelectorOperation<AttrValue> {
|
||||||
|
Exists,
|
||||||
|
WithValue {
|
||||||
|
operator: AttrSelectorOperator,
|
||||||
|
case_sensitivity: ParsedCaseSensitivity,
|
||||||
|
expected_value: AttrValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone)]
|
#[derive(Eq, PartialEq, Clone)]
|
||||||
pub enum AttrSelectorOperation<AttrValue> {
|
pub enum AttrSelectorOperation<AttrValue> {
|
||||||
Exists,
|
Exists,
|
||||||
|
@ -116,32 +126,39 @@ impl AttrSelectorOperator {
|
||||||
pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C'];
|
pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C'];
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
|
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
|
||||||
pub enum CaseSensitivity {
|
pub enum ParsedCaseSensitivity {
|
||||||
CaseSensitive, // Selectors spec says language-defined, but HTML says sensitive.
|
CaseSensitive, // Selectors spec says language-defined, but HTML says sensitive.
|
||||||
AsciiCaseInsensitive,
|
AsciiCaseInsensitive,
|
||||||
AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument,
|
AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CaseSensitivity {
|
impl ParsedCaseSensitivity {
|
||||||
pub fn to_definite(self, is_html_element_in_html_document: bool) -> Self {
|
pub fn to_unconditional(self, is_html_element_in_html_document: bool) -> CaseSensitivity {
|
||||||
if let CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument = self {
|
match self {
|
||||||
if is_html_element_in_html_document {
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
|
||||||
|
if is_html_element_in_html_document => {
|
||||||
CaseSensitivity::AsciiCaseInsensitive
|
CaseSensitivity::AsciiCaseInsensitive
|
||||||
} else {
|
}
|
||||||
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
||||||
CaseSensitivity::CaseSensitive
|
CaseSensitivity::CaseSensitive
|
||||||
}
|
}
|
||||||
} else {
|
ParsedCaseSensitivity::CaseSensitive => CaseSensitivity::CaseSensitive,
|
||||||
self
|
ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
|
||||||
|
pub enum CaseSensitivity {
|
||||||
|
CaseSensitive, // Selectors spec says language-defined, but HTML says sensitive.
|
||||||
|
AsciiCaseInsensitive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CaseSensitivity {
|
||||||
pub fn eq(self, a: &[u8], b: &[u8]) -> bool {
|
pub fn eq(self, a: &[u8], b: &[u8]) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CaseSensitivity::CaseSensitive => a == b,
|
CaseSensitivity::CaseSensitive => a == b,
|
||||||
CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
|
CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
|
||||||
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
|
||||||
unreachable!("matching.rs should have called case_sensitivity.to_definite()");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,9 +185,6 @@ impl CaseSensitivity {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
|
||||||
unreachable!("matching.rs should have called case_sensitivity.to_definite()");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use attr::{AttrSelectorOperation, NamespaceConstraint};
|
use attr::{ParsedAttrSelectorOperation, AttrSelectorOperation, NamespaceConstraint};
|
||||||
use bloom::BloomFilter;
|
use bloom::BloomFilter;
|
||||||
use parser::{Combinator, ComplexSelector, Component, LocalName};
|
use parser::{Combinator, ComplexSelector, Component, LocalName};
|
||||||
use parser::{Selector, SelectorInner, SelectorIter};
|
use parser::{Selector, SelectorInner, SelectorIter};
|
||||||
|
@ -435,7 +435,7 @@ fn matches_simple_selector<E, F>(
|
||||||
select_name(is_html, local_name, local_name_lower),
|
select_name(is_html, local_name, local_name_lower),
|
||||||
&AttrSelectorOperation::WithValue {
|
&AttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity.to_definite(is_html),
|
case_sensitivity: case_sensitivity.to_unconditional(is_html),
|
||||||
expected_value: value,
|
expected_value: value,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -450,15 +450,15 @@ fn matches_simple_selector<E, F>(
|
||||||
&attr_sel.namespace(),
|
&attr_sel.namespace(),
|
||||||
select_name(is_html, &attr_sel.local_name, &attr_sel.local_name_lower),
|
select_name(is_html, &attr_sel.local_name, &attr_sel.local_name_lower),
|
||||||
&match attr_sel.operation {
|
&match attr_sel.operation {
|
||||||
AttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
||||||
AttrSelectorOperation::WithValue {
|
ParsedAttrSelectorOperation::WithValue {
|
||||||
operator,
|
operator,
|
||||||
case_sensitivity,
|
case_sensitivity,
|
||||||
ref expected_value,
|
ref expected_value,
|
||||||
} => {
|
} => {
|
||||||
AttrSelectorOperation::WithValue {
|
AttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity.to_definite(is_html),
|
case_sensitivity: case_sensitivity.to_unconditional(is_html),
|
||||||
expected_value: expected_value,
|
expected_value: expected_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use arcslice::ArcSlice;
|
use arcslice::ArcSlice;
|
||||||
use attr::{AttrSelectorWithNamespace, AttrSelectorOperation, AttrSelectorOperator};
|
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
|
||||||
use attr::{CaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
||||||
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
||||||
use precomputed_hash::PrecomputedHash;
|
use precomputed_hash::PrecomputedHash;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -548,7 +548,7 @@ pub enum Component<Impl: SelectorImpl> {
|
||||||
local_name_lower: Impl::LocalName,
|
local_name_lower: Impl::LocalName,
|
||||||
operator: AttrSelectorOperator,
|
operator: AttrSelectorOperator,
|
||||||
value: Impl::AttrValue,
|
value: Impl::AttrValue,
|
||||||
case_sensitivity: CaseSensitivity,
|
case_sensitivity: ParsedCaseSensitivity,
|
||||||
never_matches: bool,
|
never_matches: bool,
|
||||||
},
|
},
|
||||||
// Use a Box in the less common cases with more data to keep size_of::<Component>() small.
|
// Use a Box in the less common cases with more data to keep size_of::<Component>() small.
|
||||||
|
@ -735,9 +735,9 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
|
||||||
write!(CssStringWriter::new(dest), "{}", value)?;
|
write!(CssStringWriter::new(dest), "{}", value)?;
|
||||||
dest.write_char('"')?;
|
dest.write_char('"')?;
|
||||||
match case_sensitivity {
|
match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive |
|
ParsedCaseSensitivity::CaseSensitive |
|
||||||
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
||||||
CaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
||||||
}
|
}
|
||||||
dest.write_char(']')
|
dest.write_char(']')
|
||||||
}
|
}
|
||||||
|
@ -784,16 +784,18 @@ impl<Impl: SelectorImpl> ToCss for AttrSelectorWithNamespace<Impl> {
|
||||||
}
|
}
|
||||||
display_to_css_identifier(&self.local_name, dest)?;
|
display_to_css_identifier(&self.local_name, dest)?;
|
||||||
match self.operation {
|
match self.operation {
|
||||||
AttrSelectorOperation::Exists => {},
|
ParsedAttrSelectorOperation::Exists => {},
|
||||||
AttrSelectorOperation::WithValue { operator, case_sensitivity, ref expected_value } => {
|
ParsedAttrSelectorOperation::WithValue {
|
||||||
|
operator, case_sensitivity, ref expected_value
|
||||||
|
} => {
|
||||||
operator.to_css(dest)?;
|
operator.to_css(dest)?;
|
||||||
dest.write_char('"')?;
|
dest.write_char('"')?;
|
||||||
write!(CssStringWriter::new(dest), "{}", expected_value)?;
|
write!(CssStringWriter::new(dest), "{}", expected_value)?;
|
||||||
dest.write_char('"')?;
|
dest.write_char('"')?;
|
||||||
match case_sensitivity {
|
match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive |
|
ParsedCaseSensitivity::CaseSensitive |
|
||||||
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
||||||
CaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1229,7 +1231,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
local_name: local_name,
|
local_name: local_name,
|
||||||
local_name_lower: local_name_lower,
|
local_name_lower: local_name_lower,
|
||||||
operation: AttrSelectorOperation::Exists,
|
operation: ParsedAttrSelectorOperation::Exists,
|
||||||
never_matches: false,
|
never_matches: false,
|
||||||
})))
|
})))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1285,12 +1287,13 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
let local_name_lower;
|
let local_name_lower;
|
||||||
{
|
{
|
||||||
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
||||||
if let CaseSensitivity::CaseSensitive = case_sensitivity {
|
if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity {
|
||||||
if namespace.is_none() &&
|
if namespace.is_none() &&
|
||||||
include!(concat!(env!("OUT_DIR"), "/ascii_case_insensitive_html_attributes.rs"))
|
include!(concat!(env!("OUT_DIR"), "/ascii_case_insensitive_html_attributes.rs"))
|
||||||
.contains(&*local_name_lower_cow)
|
.contains(&*local_name_lower_cow)
|
||||||
{
|
{
|
||||||
case_sensitivity = CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
|
case_sensitivity =
|
||||||
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_name_lower = from_cow_str(local_name_lower_cow);
|
local_name_lower = from_cow_str(local_name_lower_cow);
|
||||||
|
@ -1302,7 +1305,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
local_name: local_name,
|
local_name: local_name,
|
||||||
local_name_lower: local_name_lower,
|
local_name_lower: local_name_lower,
|
||||||
never_matches: never_matches,
|
never_matches: never_matches,
|
||||||
operation: AttrSelectorOperation::WithValue {
|
operation: ParsedAttrSelectorOperation::WithValue {
|
||||||
operator: operator,
|
operator: operator,
|
||||||
case_sensitivity: case_sensitivity,
|
case_sensitivity: case_sensitivity,
|
||||||
expected_value: value,
|
expected_value: value,
|
||||||
|
@ -1321,11 +1324,11 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_attribute_flags(input: &mut CssParser) -> Result<CaseSensitivity, ()> {
|
fn parse_attribute_flags(input: &mut CssParser) -> Result<ParsedCaseSensitivity, ()> {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Err(()) => Ok(CaseSensitivity::CaseSensitive),
|
Err(()) => Ok(ParsedCaseSensitivity::CaseSensitive),
|
||||||
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
|
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
|
||||||
Ok(CaseSensitivity::AsciiCaseInsensitive)
|
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
|
@ -1971,7 +1974,7 @@ pub mod tests {
|
||||||
operator: AttrSelectorOperator::DashMatch,
|
operator: AttrSelectorOperator::DashMatch,
|
||||||
value: DummyAtom::from("foo"),
|
value: DummyAtom::from("foo"),
|
||||||
never_matches: false,
|
never_matches: false,
|
||||||
case_sensitivity: CaseSensitivity::CaseSensitive,
|
case_sensitivity: ParsedCaseSensitivity::CaseSensitive,
|
||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
specificity_and_flags: specificity(0, 1, 0),
|
specificity_and_flags: specificity(0, 1, 0),
|
||||||
|
|
|
@ -72,10 +72,6 @@ impl GeckoElementSnapshot {
|
||||||
let ignore_case = match case_sensitivity {
|
let ignore_case = match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive => false,
|
CaseSensitivity::CaseSensitive => false,
|
||||||
CaseSensitivity::AsciiCaseInsensitive => true,
|
CaseSensitivity::AsciiCaseInsensitive => true,
|
||||||
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
|
||||||
unreachable!("selectors/matching.rs should have \
|
|
||||||
called case_sensitivity.to_definite()");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// FIXME: case sensitivity for operators other than Equal
|
// FIXME: case sensitivity for operators other than Equal
|
||||||
match operator {
|
match operator {
|
||||||
|
|
|
@ -1162,10 +1162,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
let ignore_case = match case_sensitivity {
|
let ignore_case = match case_sensitivity {
|
||||||
CaseSensitivity::CaseSensitive => false,
|
CaseSensitivity::CaseSensitive => false,
|
||||||
CaseSensitivity::AsciiCaseInsensitive => true,
|
CaseSensitivity::AsciiCaseInsensitive => true,
|
||||||
CaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
|
||||||
unreachable!("selectors/matching.rs should have \
|
|
||||||
called case_sensitivity.to_definite()");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// FIXME: case sensitivity for operators other than Equal
|
// FIXME: case sensitivity for operators other than Equal
|
||||||
match operator {
|
match operator {
|
||||||
|
|
|
@ -103,7 +103,7 @@ fn test_parse_stylesheet() {
|
||||||
local_name_lower: local_name!("type"),
|
local_name_lower: local_name!("type"),
|
||||||
operator: AttrSelectorOperator::Equal,
|
operator: AttrSelectorOperator::Equal,
|
||||||
value: "hidden".to_owned(),
|
value: "hidden".to_owned(),
|
||||||
case_sensitivity: CaseSensitivity::AsciiCaseInsensitive,
|
case_sensitivity: ParsedCaseSensitivity::AsciiCaseInsensitive,
|
||||||
never_matches: false,
|
never_matches: false,
|
||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue