diff --git a/servo/Cargo.lock b/servo/Cargo.lock index 852654956254..07cc363059ab 100644 --- a/servo/Cargo.lock +++ b/servo/Cargo.lock @@ -2972,6 +2972,7 @@ name = "style_traits" version = "0.0.1" dependencies = [ "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/servo/components/script/dom/css.rs b/servo/components/script/dom/css.rs index 66f522b23711..31ca219093e3 100644 --- a/servo/components/script/dom/css.rs +++ b/servo/components/script/dom/css.rs @@ -10,9 +10,10 @@ use dom::bindings::str::DOMString; use dom::window::Window; use dom_struct::dom_struct; use style::context::QuirksMode; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::stylesheets::CssRuleType; use style::stylesheets::supports_rule::{Declaration, parse_condition_or_declaration}; +use style_traits::PARSING_MODE_DEFAULT; #[dom_struct] pub struct CSS { diff --git a/servo/components/script/dom/cssmediarule.rs b/servo/components/script/dom/cssmediarule.rs index 1f5535f1b3ea..3c27127ecf4c 100644 --- a/servo/components/script/dom/cssmediarule.rs +++ b/servo/components/script/dom/cssmediarule.rs @@ -16,11 +16,11 @@ use dom::medialist::MediaList; use dom::window::Window; use dom_struct::dom_struct; use style::media_queries::parse_media_query_list; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::shared_lock::{Locked, ToCssWithGuard}; use style::stylearc::Arc; use style::stylesheets::{CssRuleType, MediaRule}; -use style_traits::ToCss; +use style_traits::{PARSING_MODE_DEFAULT, ToCss}; #[dom_struct] pub struct CSSMediaRule { diff --git a/servo/components/script/dom/cssstyledeclaration.rs b/servo/components/script/dom/cssstyledeclaration.rs index 5def880aa7d9..2ef448720d67 100644 --- a/servo/components/script/dom/cssstyledeclaration.rs +++ b/servo/components/script/dom/cssstyledeclaration.rs @@ -17,13 +17,12 @@ use dom_struct::dom_struct; use servo_url::ServoUrl; use std::ascii::AsciiExt; use style::attr::AttrValue; -use style::parser::PARSING_MODE_DEFAULT; use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId}; use style::properties::{parse_one_declaration_into, parse_style_attribute, SourcePropertyDeclaration}; use style::selector_parser::PseudoElement; use style::shared_lock::Locked; use style::stylearc::Arc; -use style_traits::ToCss; +use style_traits::{PARSING_MODE_DEFAULT, ToCss}; // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface #[dom_struct] diff --git a/servo/components/script/dom/csssupportsrule.rs b/servo/components/script/dom/csssupportsrule.rs index 2897b47b35f1..73503d0dfa6a 100644 --- a/servo/components/script/dom/csssupportsrule.rs +++ b/servo/components/script/dom/csssupportsrule.rs @@ -13,12 +13,12 @@ use dom::cssrule::SpecificCSSRule; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::shared_lock::{Locked, ToCssWithGuard}; use style::stylearc::Arc; use style::stylesheets::{CssRuleType, SupportsRule}; use style::stylesheets::supports_rule::SupportsCondition; -use style_traits::ToCss; +use style_traits::{PARSING_MODE_DEFAULT, ToCss}; #[dom_struct] pub struct CSSSupportsRule { diff --git a/servo/components/script/dom/htmllinkelement.rs b/servo/components/script/dom/htmllinkelement.rs index da004317179d..ff004261db5d 100644 --- a/servo/components/script/dom/htmllinkelement.rs +++ b/servo/components/script/dom/htmllinkelement.rs @@ -32,10 +32,11 @@ use std::cell::Cell; use std::default::Default; use style::attr::AttrValue; use style::media_queries::parse_media_query_list; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext as CssParserContext}; +use style::parser::ParserContext as CssParserContext; use style::str::HTML_SPACE_CHARACTERS; use style::stylearc::Arc; use style::stylesheets::{CssRuleType, Stylesheet}; +use style_traits::PARSING_MODE_DEFAULT; use stylesheet_loader::{StylesheetLoader, StylesheetContextSource, StylesheetOwner}; unsafe_no_jsmanaged_fields!(Stylesheet); diff --git a/servo/components/script/dom/htmlstyleelement.rs b/servo/components/script/dom/htmlstyleelement.rs index 4067cb7439d4..bf4266e18750 100644 --- a/servo/components/script/dom/htmlstyleelement.rs +++ b/servo/components/script/dom/htmlstyleelement.rs @@ -23,9 +23,10 @@ use net_traits::ReferrerPolicy; use script_layout_interface::message::Msg; use std::cell::Cell; use style::media_queries::parse_media_query_list; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext as CssParserContext}; +use style::parser::ParserContext as CssParserContext; use style::stylearc::Arc; use style::stylesheets::{CssRuleType, Stylesheet, Origin}; +use style_traits::PARSING_MODE_DEFAULT; use stylesheet_loader::{StylesheetLoader, StylesheetOwner}; #[dom_struct] diff --git a/servo/components/script/dom/medialist.rs b/servo/components/script/dom/medialist.rs index d77af9dc1b95..55ca57cb4fdb 100644 --- a/servo/components/script/dom/medialist.rs +++ b/servo/components/script/dom/medialist.rs @@ -14,11 +14,11 @@ use dom::window::Window; use dom_struct::dom_struct; use style::media_queries::{MediaQuery, parse_media_query_list}; use style::media_queries::MediaList as StyleMediaList; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::shared_lock::{SharedRwLock, Locked}; use style::stylearc::Arc; use style::stylesheets::CssRuleType; -use style_traits::ToCss; +use style_traits::{PARSING_MODE_DEFAULT, ToCss}; #[dom_struct] pub struct MediaList { diff --git a/servo/components/script/dom/window.rs b/servo/components/script/dom/window.rs index 6e89024887ab..c4ec3c07248f 100644 --- a/servo/components/script/dom/window.rs +++ b/servo/components/script/dom/window.rs @@ -107,12 +107,13 @@ use std::sync::mpsc::TryRecvError::{Disconnected, Empty}; use style::context::ReflowGoal; use style::error_reporting::ParseErrorReporter; use style::media_queries; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext as CssParserContext}; +use style::parser::ParserContext as CssParserContext; use style::properties::PropertyId; use style::properties::longhands::overflow_x; use style::selector_parser::PseudoElement; use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::CssRuleType; +use style_traits::PARSING_MODE_DEFAULT; use task_source::dom_manipulation::DOMManipulationTaskSource; use task_source::file_reading::FileReadingTaskSource; use task_source::history_traversal::HistoryTraversalTaskSource; diff --git a/servo/components/style/parser.rs b/servo/components/style/parser.rs index 420572042da6..0145c128eca3 100644 --- a/servo/components/style/parser.rs +++ b/servo/components/style/parser.rs @@ -7,37 +7,11 @@ use context::QuirksMode; use cssparser::{Parser, SourcePosition, UnicodeRange}; use error_reporting::{ParseErrorReporter, ContextualParseError}; -use style_traits::{OneOrMoreCommaSeparated, ParseError}; +use style_traits::{OneOrMoreCommaSeparated, ParseError, ParsingMode}; +#[cfg(feature = "gecko")] +use style_traits::{PARSING_MODE_DEFAULT, PARSING_MODE_ALLOW_UNITLESS_LENGTH, PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES}; use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces}; -bitflags! { - /// The mode to use when parsing values. - pub flags ParsingMode: u8 { - /// In CSS, lengths must have units, except for zero values, where the unit can be omitted. - /// https://www.w3.org/TR/css3-values/#lengths - const PARSING_MODE_DEFAULT = 0x00, - /// In SVG, a coordinate or length value without a unit identifier (e.g., "25") is assumed - /// to be in user units (px). - /// https://www.w3.org/TR/SVG/coords.html#Units - const PARSING_MODE_ALLOW_UNITLESS_LENGTH = 0x01, - /// In SVG, out-of-range values are not treated as an error in parsing. - /// https://www.w3.org/TR/SVG/implnote.html#RangeClamping - const PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES = 0x02, - } -} - -impl ParsingMode { - /// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px. - pub fn allows_unitless_lengths(&self) -> bool { - self.intersects(PARSING_MODE_ALLOW_UNITLESS_LENGTH) - } - - /// Whether the parsing mode allows all numeric values. - pub fn allows_all_numeric_values(&self) -> bool { - self.intersects(PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES) - } -} - /// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko. #[cfg(feature = "gecko")] #[inline] diff --git a/servo/components/style/properties/declaration_block.rs b/servo/components/style/properties/declaration_block.rs index 3c36521ba615..0cc0aeca2fc3 100644 --- a/servo/components/style/properties/declaration_block.rs +++ b/servo/components/style/properties/declaration_block.rs @@ -10,13 +10,13 @@ use context::QuirksMode; use cssparser::{DeclarationListParser, parse_important, ParserInput}; use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter}; use error_reporting::{ParseErrorReporter, ContextualParseError}; -use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error}; +use parser::{ParserContext, log_css_error}; use properties::animated_properties::AnimationValue; use selectors::parser::SelectorParseError; use shared_lock::Locked; use std::fmt; use std::slice::Iter; -use style_traits::{ToCss, ParseError, StyleParseError}; +use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, ParsingMode, StyleParseError}; use stylesheets::{CssRuleType, Origin, UrlExtraData}; use stylesheets::{MallocSizeOf, MallocSizeOfFn}; use super::*; diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index 8bd5ec4680d9..44d0d55a1c3d 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -31,13 +31,13 @@ use font_metrics::FontMetricsProvider; #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide}; use logical_geometry::WritingMode; use media_queries::Device; -use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext}; +use parser::{Parse, ParserContext}; use properties::animated_properties::TransitionProperty; #[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont; use selectors::parser::SelectorParseError; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; use shared_lock::StylesheetGuards; -use style_traits::{HasViewportPercentage, ToCss, ParseError, PropertyDeclarationParseError}; +use style_traits::{PARSING_MODE_DEFAULT, HasViewportPercentage, ToCss, ParseError, PropertyDeclarationParseError}; use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData}; #[cfg(feature = "servo")] use values::Either; use values::generics::text::LineHeight; diff --git a/servo/components/style/stylesheets/keyframes_rule.rs b/servo/components/style/stylesheets/keyframes_rule.rs index c87477a617bf..c03240ecafc0 100644 --- a/servo/components/style/stylesheets/keyframes_rule.rs +++ b/servo/components/style/stylesheets/keyframes_rule.rs @@ -7,7 +7,7 @@ use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput}; use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation}; use error_reporting::{NullReporter, ContextualParseError}; -use parser::{PARSING_MODE_DEFAULT, ParserContext, log_css_error}; +use parser::{ParserContext, log_css_error}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId}; use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration}; use properties::LonghandIdSet; @@ -17,7 +17,7 @@ use selectors::parser::SelectorParseError; use shared_lock::{DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard}; use std::borrow::Cow; use std::fmt; -use style_traits::{ToCss, ParseError, StyleParseError}; +use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError}; use stylearc::Arc; use stylesheets::{CssRuleType, Stylesheet}; use stylesheets::rule_parser::VendorPrefix; diff --git a/servo/components/style/stylesheets/mod.rs b/servo/components/style/stylesheets/mod.rs index 67354889b933..e5e6aa521f9f 100644 --- a/servo/components/style/stylesheets/mod.rs +++ b/servo/components/style/stylesheets/mod.rs @@ -24,9 +24,10 @@ pub mod viewport_rule; use cssparser::{parse_one_rule, Parser, ParserInput}; use error_reporting::NullReporter; -use parser::{ParserContext, PARSING_MODE_DEFAULT}; +use parser::ParserContext; use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; +use style_traits::PARSING_MODE_DEFAULT; use stylearc::Arc; pub use self::counter_style_rule::CounterStyleRule; diff --git a/servo/components/style/stylesheets/stylesheet.rs b/servo/components/style/stylesheets/stylesheet.rs index db49e109687d..477c35f8e641 100644 --- a/servo/components/style/stylesheets/stylesheet.rs +++ b/servo/components/style/stylesheets/stylesheet.rs @@ -9,10 +9,11 @@ use error_reporting::{ParseErrorReporter, ContextualParseError}; use fnv::FnvHashMap; use media_queries::{MediaList, Device}; use parking_lot::RwLock; -use parser::{PARSING_MODE_DEFAULT, ParserContext, log_css_error}; +use parser::{ParserContext, log_css_error}; use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard}; use std::mem; use std::sync::atomic::{AtomicBool, Ordering}; +use style_traits::PARSING_MODE_DEFAULT; use stylearc::Arc; use stylesheets::{CssRule, CssRules, Origin, UrlExtraData}; use stylesheets::loader::StylesheetLoader; diff --git a/servo/components/style/values/specified/length.rs b/servo/components/style/values/specified/length.rs index d2e6e45d4071..a2662247d6f7 100644 --- a/servo/components/style/values/specified/length.rs +++ b/servo/components/style/values/specified/length.rs @@ -611,9 +611,9 @@ impl Length { -> Result> { let token = try!(input.next()); match token { - Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) => + Token::Dimension(ref value, ref unit) if num_context.is_ok(context.parsing_mode, value.value) => Length::parse_dimension(context, value.value, unit), - Token::Number(ref value) if num_context.is_ok(value.value) => { + Token::Number(ref value) if num_context.is_ok(context.parsing_mode, value.value) => { if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { @@ -715,11 +715,12 @@ impl ToCss for Percentage { impl Percentage { /// Parse a specific kind of percentage. - pub fn parse_with_clamping_mode<'i, 't>(input: &mut Parser<'i, 't>, - context: AllowedNumericType) + pub fn parse_with_clamping_mode<'i, 't>(context: &ParserContext, + input: &mut Parser<'i, 't>, + num_context: AllowedNumericType) -> Result> { match try!(input.next()) { - Token::Percentage(ref value) if context.is_ok(value.unit_value) => { + Token::Percentage(ref value) if num_context.is_ok(context.parsing_mode, value.unit_value) => { Ok(Percentage(value.unit_value)) } t => Err(BasicParseError::UnexpectedToken(t).into()) @@ -727,8 +728,10 @@ impl Percentage { } /// Parses a percentage token, but rejects it if it's negative. - pub fn parse_non_negative<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - Self::parse_with_clamping_mode(input, AllowedNumericType::NonNegative) + pub fn parse_non_negative<'i, 't>(context: &ParserContext, + input: &mut Parser<'i, 't>) + -> Result> { + Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative) } /// 0% @@ -746,8 +749,8 @@ impl Percentage { impl Parse for Percentage { #[inline] - fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - Self::parse_with_clamping_mode(input, AllowedNumericType::All) + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + Self::parse_with_clamping_mode(context, input, AllowedNumericType::All) } } @@ -801,11 +804,11 @@ impl LengthOrPercentage { { let token = try!(input.next()); match token { - Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) => + Token::Dimension(ref value, ref unit) if num_context.is_ok(context.parsing_mode, value.value) => NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length), - Token::Percentage(ref value) if num_context.is_ok(value.unit_value) => + Token::Percentage(ref value) if num_context.is_ok(context.parsing_mode, value.unit_value) => return Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))), - Token::Number(value) if num_context.is_ok(value.value) => { + Token::Number(value) if num_context.is_ok(context.parsing_mode, value.value) => { if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { @@ -935,11 +938,11 @@ impl LengthOrPercentageOrAuto { -> Result> { let token = try!(input.next()); match token { - Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) => + Token::Dimension(ref value, ref unit) if num_context.is_ok(context.parsing_mode, value.value) => NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrAuto::Length), - Token::Percentage(ref value) if num_context.is_ok(value.unit_value) => + Token::Percentage(ref value) if num_context.is_ok(context.parsing_mode, value.unit_value) => Ok(LengthOrPercentageOrAuto::Percentage(Percentage(value.unit_value))), - Token::Number(ref value) if num_context.is_ok(value.value) => { + Token::Number(ref value) if num_context.is_ok(context.parsing_mode, value.value) => { if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { @@ -1031,11 +1034,11 @@ impl LengthOrPercentageOrNone { { let token = try!(input.next()); match token { - Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) => + Token::Dimension(ref value, ref unit) if num_context.is_ok(context.parsing_mode, value.value) => NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrNone::Length), - Token::Percentage(ref value) if num_context.is_ok(value.unit_value) => + Token::Percentage(ref value) if num_context.is_ok(context.parsing_mode, value.unit_value) => Ok(LengthOrPercentageOrNone::Percentage(Percentage(value.unit_value))), - Token::Number(value) if num_context.is_ok(value.value) => { + Token::Number(value) if num_context.is_ok(context.parsing_mode, value.value) => { if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { return Err(StyleParseError::UnspecifiedError.into()) @@ -1113,10 +1116,10 @@ impl LengthOrPercentageOrAutoOrContent { let num_context = AllowedLengthType::NonNegative; let token = try!(input.next()); match token { - Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) => + Token::Dimension(ref value, ref unit) if num_context.is_ok(context.parsing_mode, value.value) => NoCalcLength::parse_dimension(context, value.value, unit) .map(LengthOrPercentageOrAutoOrContent::Length), - Token::Percentage(ref value) if num_context.is_ok(value.unit_value) => + Token::Percentage(ref value) if num_context.is_ok(context.parsing_mode, value.unit_value) => Ok(LengthOrPercentageOrAutoOrContent::Percentage(Percentage(value.unit_value))), Token::Number(ref value) if value.value == 0. => Ok(Self::zero()), diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index 80ce0db08d05..112a3c38bc65 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -120,7 +120,7 @@ pub fn parse_number_with_clamping_mode<'i, 't>(context: &ParserContext, clamping_mode: AllowedNumericType) -> Result> { match try!(input.next()) { - Token::Number(ref value) if clamping_mode.is_ok(value.value) => { + Token::Number(ref value) if clamping_mode.is_ok(context.parsing_mode, value.value) => { Ok(Number { value: value.value.min(f32::MAX).max(f32::MIN), calc_clamping_mode: None, @@ -364,14 +364,21 @@ impl Time { input: &mut Parser<'i, 't>, clamping_mode: AllowedNumericType) -> Result> { + use style_traits::PARSING_MODE_DEFAULT; + match input.next() { - Ok(Token::Dimension(ref value, ref unit)) if clamping_mode.is_ok(value.value) => { + // Note that we generally pass ParserContext to is_ok() to check + // that the ParserMode of the ParserContext allows all numeric + // values for SMIL regardless of clamping_mode, but in this Time + // value case, the value does not animate for SMIL at all, so we use + // PARSING_MODE_DEFAULT directly. + Ok(Token::Dimension(ref value, ref unit)) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, value.value) => { Time::parse_dimension(value.value, &unit, /* from_calc = */ false) .map_err(|()| StyleParseError::UnspecifiedError.into()) } Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => { match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) { - Ok(time) if clamping_mode.is_ok(time.seconds) => Ok(time), + Ok(time) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, time.seconds) => Ok(time), _ => Err(StyleParseError::UnspecifiedError.into()), } } @@ -457,21 +464,13 @@ impl Number { #[allow(missing_docs)] pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - if context.parsing_mode.allows_all_numeric_values() { - parse_number(context, input) - } else { - parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative) - } + parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative) } #[allow(missing_docs)] pub fn parse_at_least_one<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - if context.parsing_mode.allows_all_numeric_values() { - parse_number(context, input) - } else { - parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne) - } + parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne) } } @@ -522,7 +521,7 @@ impl NumberOrPercentage { input: &mut Parser<'i, 't>, type_: AllowedNumericType) -> Result> { - if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(i, type_)) { + if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(context, i, type_)) { return Ok(NumberOrPercentage::Percentage(per)); } diff --git a/servo/components/style_traits/Cargo.toml b/servo/components/style_traits/Cargo.toml index e298fe530534..d668bc8984f6 100644 --- a/servo/components/style_traits/Cargo.toml +++ b/servo/components/style_traits/Cargo.toml @@ -16,6 +16,7 @@ gecko = [] [dependencies] app_units = "0.4.1" +bitflags = "0.7" cssparser = "0.14.0" euclid = "0.13" heapsize = {version = "0.4", optional = true} diff --git a/servo/components/style_traits/lib.rs b/servo/components/style_traits/lib.rs index 87aa6b330fb9..ed085a12993c 100644 --- a/servo/components/style_traits/lib.rs +++ b/servo/components/style_traits/lib.rs @@ -14,6 +14,7 @@ #![cfg_attr(feature = "servo", feature(plugin))] extern crate app_units; +#[macro_use] extern crate bitflags; #[macro_use] extern crate cssparser; extern crate euclid; #[cfg(feature = "servo")] extern crate heapsize; @@ -140,3 +141,32 @@ impl<'a> From for ParseError<'a> { cssparser::ParseError::Custom(SelectorParseError::Custom(StyleParseError::PropertyDeclaration(this))) } } + +bitflags! { + /// The mode to use when parsing values. + pub flags ParsingMode: u8 { + /// In CSS, lengths must have units, except for zero values, where the unit can be omitted. + /// https://www.w3.org/TR/css3-values/#lengths + const PARSING_MODE_DEFAULT = 0x00, + /// In SVG, a coordinate or length value without a unit identifier (e.g., "25") is assumed + /// to be in user units (px). + /// https://www.w3.org/TR/SVG/coords.html#Units + const PARSING_MODE_ALLOW_UNITLESS_LENGTH = 0x01, + /// In SVG, out-of-range values are not treated as an error in parsing. + /// https://www.w3.org/TR/SVG/implnote.html#RangeClamping + const PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES = 0x02, + } +} + +impl ParsingMode { + /// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px. + pub fn allows_unitless_lengths(&self) -> bool { + self.intersects(PARSING_MODE_ALLOW_UNITLESS_LENGTH) + } + + /// Whether the parsing mode allows all numeric values. + pub fn allows_all_numeric_values(&self) -> bool { + self.intersects(PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES) + } +} + diff --git a/servo/components/style_traits/values.rs b/servo/components/style_traits/values.rs index 6c31da166641..3a587ac81f93 100644 --- a/servo/components/style_traits/values.rs +++ b/servo/components/style_traits/values.rs @@ -204,6 +204,7 @@ macro_rules! __define_css_keyword_enum__actual { /// Helper types for the handling of specified values. pub mod specified { + use ParsingMode; use app_units::Au; use std::cmp; @@ -228,7 +229,10 @@ pub mod specified { impl AllowedLengthType { /// Whether value is valid for this allowed length type. #[inline] - pub fn is_ok(&self, value: f32) -> bool { + pub fn is_ok(&self, parsing_mode: ParsingMode, value: f32) -> bool { + if parsing_mode.allows_all_numeric_values() { + return true; + } match *self { AllowedLengthType::All => true, AllowedLengthType::NonNegative => value >= 0., @@ -261,7 +265,10 @@ pub mod specified { impl AllowedNumericType { /// Whether the value fits the rules of this numeric type. #[inline] - pub fn is_ok(&self, val: f32) -> bool { + pub fn is_ok(&self, parsing_mode: ParsingMode, val: f32) -> bool { + if parsing_mode.allows_all_numeric_values() { + return true; + } match *self { AllowedNumericType::All => true, AllowedNumericType::NonNegative => val >= 0.0, diff --git a/servo/components/style_traits/viewport.rs b/servo/components/style_traits/viewport.rs index 9a77a554f295..4bfaef849acd 100644 --- a/servo/components/style_traits/viewport.rs +++ b/servo/components/style_traits/viewport.rs @@ -9,7 +9,6 @@ use cssparser::{Parser, ToCss, ParseError as CssParseError, BasicParseError}; use euclid::size::TypedSize2D; use std::ascii::AsciiExt; use std::fmt; -use values::specified::AllowedLengthType; define_css_keyword_enum!(UserZoom: "zoom" => Zoom, @@ -141,12 +140,18 @@ impl Zoom { /// /// https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { + use PARSING_MODE_DEFAULT; use cssparser::Token; + use values::specified::AllowedLengthType::NonNegative; match try!(input.next()) { - Token::Percentage(ref value) if AllowedLengthType::NonNegative.is_ok(value.unit_value) => + // TODO: This parse() method should take ParserContext as an + // argument, and pass ParsingMode owned by the ParserContext to + // is_ok() instead of using PARSING_MODE_DEFAULT directly. + // In order to do so, we might want to move these stuff into style::stylesheets::viewport_rule. + Token::Percentage(ref value) if NonNegative.is_ok(PARSING_MODE_DEFAULT, value.unit_value) => Ok(Zoom::Percentage(value.unit_value)), - Token::Number(ref value) if AllowedLengthType::NonNegative.is_ok(value.value) => + Token::Number(ref value) if NonNegative.is_ok(PARSING_MODE_DEFAULT, value.value) => Ok(Zoom::Number(value.value)), Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => Ok(Zoom::Auto), diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 28abf33b13d2..a3c1ebbe2bc9 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -91,7 +91,7 @@ use style::gecko_properties::{self, style_structs}; use style::invalidation::element::restyle_hints::{self, RestyleHint}; use style::media_queries::{MediaList, parse_media_query_list}; use style::parallel; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::properties::{CascadeFlags, ComputedValues, Importance, SourcePropertyDeclaration}; use style::properties::{LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId, StyleBuilder}; use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP; @@ -118,7 +118,7 @@ use style::traversal::{FOR_DEFAULT_STYLES, TraversalDriver, TraversalFlags, UNST use style::traversal::{resolve_style, resolve_default_style}; use style::values::{CustomIdent, KeyframesName}; use style::values::computed::Context; -use style_traits::ToCss; +use style_traits::{PARSING_MODE_DEFAULT, ToCss}; use super::stylesheet_loader::StylesheetLoader; /* @@ -1594,7 +1594,7 @@ fn parse_property_into(declarations: &mut SourcePropertyDeclaration, data: *mut URLExtraData, parsing_mode: structs::ParsingMode, quirks_mode: QuirksMode) -> Result<(), ()> { - use style::parser::ParsingMode; + use style_traits::ParsingMode; let value = unsafe { value.as_ref().unwrap().as_str_unchecked() }; let url_data = unsafe { RefPtr::from_ptr_ref(&data) }; let parsing_mode = ParsingMode::from_bits_truncate(parsing_mode); diff --git a/servo/tests/unit/style/parsing/length.rs b/servo/tests/unit/style/parsing/length.rs index b779208d42e1..8144999f307e 100644 --- a/servo/tests/unit/style/parsing/length.rs +++ b/servo/tests/unit/style/parsing/length.rs @@ -6,12 +6,12 @@ use cssparser::{Parser, ParserInput}; use media_queries::CSSErrorReporterTest; use parsing::parse; use style::context::QuirksMode; -use style::parser::{PARSING_MODE_ALLOW_UNITLESS_LENGTH, Parse, ParserContext}; +use style::parser::{Parse, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; use style::values::Either; use style::values::specified::{LengthOrPercentageOrNumber, Number}; use style::values::specified::length::{AbsoluteLength, Length, NoCalcLength}; -use style_traits::ToCss; +use style_traits::{PARSING_MODE_ALLOW_UNITLESS_LENGTH, ToCss}; #[test] fn test_calc() { diff --git a/servo/tests/unit/style/parsing/mod.rs b/servo/tests/unit/style/parsing/mod.rs index e01b681e3c74..c0c357b390ab 100644 --- a/servo/tests/unit/style/parsing/mod.rs +++ b/servo/tests/unit/style/parsing/mod.rs @@ -10,11 +10,11 @@ use media_queries::CSSErrorReporterTest; use style::context::QuirksMode; use style::font_metrics::ServoMetricsProvider; use style::media_queries::{Device, MediaType}; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::properties::{ComputedValues, StyleBuilder}; use style::stylesheets::{CssRuleType, Origin}; use style::values::computed::{Context, ToComputedValue}; -use style_traits::{ToCss, ParseError}; +use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError}; fn parse(f: F, s: &'static str) -> Result> where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result> { diff --git a/servo/tests/unit/style/parsing/value.rs b/servo/tests/unit/style/parsing/value.rs index 983f7fced47c..7b4f0917c58c 100644 --- a/servo/tests/unit/style/parsing/value.rs +++ b/servo/tests/unit/style/parsing/value.rs @@ -6,10 +6,10 @@ use app_units::Au; use cssparser::{Parser, ParserInput}; use media_queries::CSSErrorReporterTest; use style::context::QuirksMode; -use style::parser::{PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES, ParserContext}; +use style::parser::ParserContext; use style::stylesheets::{CssRuleType, Origin}; use style::values::specified::{AbsoluteLength, NoCalcLength, Number, ViewportPercentageLength}; -use style_traits::HasViewportPercentage; +use style_traits::{PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES, HasViewportPercentage}; #[test] fn length_has_viewport_percentage() { diff --git a/servo/tests/unit/style/properties/mod.rs b/servo/tests/unit/style/properties/mod.rs index 766b7e3e3b52..96d66655f56c 100644 --- a/servo/tests/unit/style/properties/mod.rs +++ b/servo/tests/unit/style/properties/mod.rs @@ -5,9 +5,9 @@ use cssparser::{Parser, ParserInput}; use media_queries::CSSErrorReporterTest; use style::context::QuirksMode; -use style::parser::{PARSING_MODE_DEFAULT, ParserContext}; +use style::parser::ParserContext; use style::stylesheets::{CssRuleType, Origin}; -use style_traits::ParseError; +use style_traits::{PARSING_MODE_DEFAULT, ParseError}; fn parse(f: F, s: &'static str) -> Result> where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result> { diff --git a/servo/tests/unit/style/viewport.rs b/servo/tests/unit/style/viewport.rs index 87c4c54f9b08..f3903f35fc5b 100644 --- a/servo/tests/unit/style/viewport.rs +++ b/servo/tests/unit/style/viewport.rs @@ -9,7 +9,7 @@ use servo_config::prefs::{PREFS, PrefValue}; use servo_url::ServoUrl; use style::context::QuirksMode; use style::media_queries::{Device, MediaList, MediaType}; -use style::parser::{PARSING_MODE_DEFAULT, Parse, ParserContext}; +use style::parser::{Parse, ParserContext}; use style::shared_lock::SharedRwLock; use style::stylearc::Arc; use style::stylesheets::{CssRuleType, Stylesheet, Origin}; @@ -17,7 +17,7 @@ use style::stylesheets::viewport_rule::*; use style::values::specified::LengthOrPercentageOrAuto::{self, Auto}; use style::values::specified::NoCalcLength::{self, ViewportPercentage}; use style::values::specified::ViewportPercentageLength::Vw; -use style_traits::PinchZoomFactor; +use style_traits::{PARSING_MODE_DEFAULT, PinchZoomFactor}; use style_traits::viewport::*; macro_rules! stylesheet {