aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/gecko/media_queries.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/gecko/media_queries.rs')
-rw-r--r--components/style/gecko/media_queries.rs190
1 files changed, 108 insertions, 82 deletions
diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs
index 067375bef40..c1637b3c283 100644
--- a/components/style/gecko/media_queries.rs
+++ b/components/style/gecko/media_queries.rs
@@ -23,7 +23,6 @@ use media_queries::MediaType;
use parser::ParserContext;
use properties::{ComputedValues, StyleBuilder};
use properties::longhands::font_size;
-use selectors::parser::SelectorParseError;
use servo_arc::Arc;
use std::fmt::{self, Write};
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
@@ -469,6 +468,89 @@ unsafe fn find_in_table<F>(mut current_entry: *const nsCSSProps_KTableEntry,
}
}
+fn parse_feature_value<'i, 't>(feature: &nsMediaFeature,
+ feature_value_type: nsMediaFeature_ValueType,
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>)
+ -> Result<MediaExpressionValue, ParseError<'i>> {
+ let value = match feature_value_type {
+ nsMediaFeature_ValueType::eLength => {
+ let length = Length::parse_non_negative(context, input)?;
+ // FIXME(canaltinova): See bug 1396057. Gecko doesn't support calc
+ // inside media queries. This check is for temporarily remove it
+ // for parity with gecko. We should remove this check when we want
+ // to support it.
+ if let Length::Calc(_) = length {
+ return Err(StyleParseError::UnspecifiedError.into())
+ }
+ MediaExpressionValue::Length(length)
+ },
+ nsMediaFeature_ValueType::eInteger => {
+ // FIXME(emilio): We should use `Integer::parse` to handle `calc`
+ // properly in integer expressions. Note that calc is still not
+ // supported in media queries per FIXME above.
+ let i = input.expect_integer()?;
+ if i < 0 {
+ return Err(StyleParseError::UnspecifiedError.into())
+ }
+ MediaExpressionValue::Integer(i as u32)
+ }
+ nsMediaFeature_ValueType::eBoolInteger => {
+ let i = input.expect_integer()?;
+ if i < 0 || i > 1 {
+ return Err(StyleParseError::UnspecifiedError.into())
+ }
+ MediaExpressionValue::BoolInteger(i == 1)
+ }
+ nsMediaFeature_ValueType::eFloat => {
+ MediaExpressionValue::Float(input.expect_number()?)
+ }
+ nsMediaFeature_ValueType::eIntRatio => {
+ let a = input.expect_integer()?;
+ if a <= 0 {
+ return Err(StyleParseError::UnspecifiedError.into())
+ }
+
+ input.expect_delim('/')?;
+
+ let b = input.expect_integer()?;
+ if b <= 0 {
+ return Err(StyleParseError::UnspecifiedError.into())
+ }
+ MediaExpressionValue::IntRatio(a as u32, b as u32)
+ }
+ nsMediaFeature_ValueType::eResolution => {
+ MediaExpressionValue::Resolution(Resolution::parse(input)?)
+ }
+ nsMediaFeature_ValueType::eEnumerated => {
+ let keyword = input.expect_ident()?;
+ let keyword = unsafe {
+ bindings::Gecko_LookupCSSKeyword(keyword.as_bytes().as_ptr(),
+ keyword.len() as u32)
+ };
+
+ let first_table_entry: *const nsCSSProps_KTableEntry = unsafe {
+ *feature.mData.mKeywordTable.as_ref()
+ };
+
+ let value =
+ match unsafe { find_in_table(first_table_entry, |kw, _| kw == keyword) } {
+ Some((_kw, value)) => {
+ value
+ }
+ None => return Err(StyleParseError::UnspecifiedError.into()),
+ };
+
+ MediaExpressionValue::Enumerated(value)
+ }
+ nsMediaFeature_ValueType::eIdent => {
+ MediaExpressionValue::Ident(input.expect_ident()?.as_ref().to_owned())
+ }
+ };
+
+ Ok(value)
+}
+
impl Expression {
/// Trivially construct a new expression.
fn new(feature: &'static nsMediaFeature,
@@ -488,13 +570,24 @@ impl Expression {
/// ```
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
- input.expect_parenthesis_block()?;
+ input.expect_parenthesis_block().map_err(|err|
+ match err {
+ BasicParseError::UnexpectedToken(t) => StyleParseError::ExpectedIdentifier(t),
+ _ => StyleParseError::UnspecifiedError,
+ }
+ )?;
+
input.parse_nested_block(|input| {
// FIXME: remove extra indented block when lifetimes are non-lexical
let feature;
let range;
{
- let ident = input.expect_ident()?;
+ let ident = input.expect_ident().map_err(|err|
+ match err {
+ BasicParseError::UnexpectedToken(t) => StyleParseError::ExpectedIdentifier(t),
+ _ => StyleParseError::UnspecifiedError,
+ }
+ )?;
let mut flags = 0;
let result = {
@@ -530,17 +623,19 @@ impl Expression {
Ok((f, r)) => {
feature = f;
range = r;
- }
- Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
+ },
+ Err(()) => {
+ return Err(StyleParseError::MediaQueryExpectedFeatureName(ident.clone()).into())
+ },
}
if (feature.mReqFlags & !flags) != 0 {
- return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into());
+ return Err(StyleParseError::MediaQueryExpectedFeatureName(ident.clone()).into());
}
if range != nsMediaExpression_Range::eEqual &&
- feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
- return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into());
+ feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
+ return Err(StyleParseError::MediaQueryExpectedFeatureName(ident.clone()).into());
}
}
@@ -556,80 +651,11 @@ impl Expression {
return Ok(Expression::new(feature, None, range));
}
- let value = match feature.mValueType {
- nsMediaFeature_ValueType::eLength => {
- let length = Length::parse_non_negative(context, input)?;
- // FIXME(canaltinova): See bug 1396057. Gecko doesn't support calc
- // inside media queries. This check is for temporarily remove it
- // for parity with gecko. We should remove this check when we want
- // to support it.
- if let Length::Calc(_) = length {
- return Err(StyleParseError::UnspecifiedError.into())
- }
- MediaExpressionValue::Length(length)
- },
- nsMediaFeature_ValueType::eInteger => {
- // FIXME(emilio): We should use `Integer::parse` to handle `calc`
- // properly in integer expressions. Note that calc is still not
- // supported in media queries per FIXME above.
- let i = input.expect_integer()?;
- if i < 0 {
- return Err(StyleParseError::UnspecifiedError.into())
- }
- MediaExpressionValue::Integer(i as u32)
- }
- nsMediaFeature_ValueType::eBoolInteger => {
- let i = input.expect_integer()?;
- if i < 0 || i > 1 {
- return Err(StyleParseError::UnspecifiedError.into())
- }
- MediaExpressionValue::BoolInteger(i == 1)
- }
- nsMediaFeature_ValueType::eFloat => {
- MediaExpressionValue::Float(input.expect_number()?)
- }
- nsMediaFeature_ValueType::eIntRatio => {
- let a = input.expect_integer()?;
- if a <= 0 {
- return Err(StyleParseError::UnspecifiedError.into())
- }
-
- input.expect_delim('/')?;
-
- let b = input.expect_integer()?;
- if b <= 0 {
- return Err(StyleParseError::UnspecifiedError.into())
- }
- MediaExpressionValue::IntRatio(a as u32, b as u32)
- }
- nsMediaFeature_ValueType::eResolution => {
- MediaExpressionValue::Resolution(Resolution::parse(input)?)
- }
- nsMediaFeature_ValueType::eEnumerated => {
- let keyword = input.expect_ident()?;
- let keyword = unsafe {
- bindings::Gecko_LookupCSSKeyword(keyword.as_bytes().as_ptr(),
- keyword.len() as u32)
- };
-
- let first_table_entry: *const nsCSSProps_KTableEntry = unsafe {
- *feature.mData.mKeywordTable.as_ref()
- };
-
- let value =
- match unsafe { find_in_table(first_table_entry, |kw, _| kw == keyword) } {
- Some((_kw, value)) => {
- value
- }
- None => return Err(StyleParseError::UnspecifiedError.into()),
- };
-
- MediaExpressionValue::Enumerated(value)
- }
- nsMediaFeature_ValueType::eIdent => {
- MediaExpressionValue::Ident(input.expect_ident()?.as_ref().to_owned())
- }
- };
+ let value = parse_feature_value(feature,
+ feature.mValueType,
+ context, input).map_err(|_|
+ StyleParseError::MediaQueryExpectedFeatureValue
+ )?;
Ok(Expression::new(feature, Some(value), range))
})