Bug 1369588 - Move ParsingMode into style_traits. r?emilio draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Wed, 14 Jun 2017 08:12:59 +0900
changeset 593652 6fe2cb68294185857f5575a05452df97f89e383b
parent 593475 91134c95d68cbcfe984211fa3cbd28d610361ef1
child 593653 f331676834b4b1d507fd5c50d31bfc1b4d48b3f4
push id63759
push userhikezoe@mozilla.com
push dateTue, 13 Jun 2017 23:18:05 +0000
reviewersemilio
bugs1369588
milestone56.0a1
Bug 1369588 - Move ParsingMode into style_traits. r?emilio MozReview-Commit-ID: KSzv84JjHmr
servo/Cargo.lock
servo/components/script/dom/css.rs
servo/components/script/dom/cssmediarule.rs
servo/components/script/dom/cssstyledeclaration.rs
servo/components/script/dom/csssupportsrule.rs
servo/components/script/dom/htmllinkelement.rs
servo/components/script/dom/htmlstyleelement.rs
servo/components/script/dom/medialist.rs
servo/components/script/dom/window.rs
servo/components/style/parser.rs
servo/components/style/properties/declaration_block.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/stylesheets/keyframes_rule.rs
servo/components/style/stylesheets/mod.rs
servo/components/style/stylesheets/stylesheet.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/lib.rs
servo/ports/geckolib/glue.rs
servo/tests/unit/style/parsing/length.rs
servo/tests/unit/style/parsing/mod.rs
servo/tests/unit/style/parsing/value.rs
servo/tests/unit/style/properties/mod.rs
servo/tests/unit/style/viewport.rs
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -2967,16 +2967,17 @@ dependencies = [
  "style_traits 0.0.1",
 ]
 
 [[package]]
 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)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
--- a/servo/components/script/dom/css.rs
+++ b/servo/components/script/dom/css.rs
@@ -5,19 +5,20 @@
 use cssparser::{Parser, ParserInput, serialize_identifier};
 use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
 use dom::bindings::error::Fallible;
 use dom::bindings::reflector::Reflector;
 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 {
     reflector_: Reflector,
 }
 
 impl CSS {
     /// http://dev.w3.org/csswg/cssom/#serialize-an-identifier
--- a/servo/components/script/dom/cssmediarule.rs
+++ b/servo/components/script/dom/cssmediarule.rs
@@ -11,21 +11,21 @@ use dom::bindings::reflector::{DomObject
 use dom::bindings::str::DOMString;
 use dom::cssconditionrule::CSSConditionRule;
 use dom::cssrule::SpecificCSSRule;
 use dom::cssstylesheet::CSSStyleSheet;
 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 {
     cssconditionrule: CSSConditionRule,
     #[ignore_heap_size_of = "Arc"]
     mediarule: Arc<Locked<MediaRule>>,
     medialist: MutNullableJS<MediaList>,
 }
--- a/servo/components/script/dom/cssstyledeclaration.rs
+++ b/servo/components/script/dom/cssstyledeclaration.rs
@@ -12,23 +12,22 @@ use dom::bindings::str::DOMString;
 use dom::cssrule::CSSRule;
 use dom::element::Element;
 use dom::node::{Node, window_from_node, document_from_node};
 use dom::window::Window;
 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]
 pub struct CSSStyleDeclaration {
     reflector_: Reflector,
     owner: CSSStyleOwner,
     readonly: bool,
     pseudo: Option<PseudoElement>,
--- a/servo/components/script/dom/csssupportsrule.rs
+++ b/servo/components/script/dom/csssupportsrule.rs
@@ -8,22 +8,22 @@ use dom::bindings::codegen::Bindings::Wi
 use dom::bindings::js::Root;
 use dom::bindings::reflector::{DomObject, reflect_dom_object};
 use dom::bindings::str::DOMString;
 use dom::cssconditionrule::CSSConditionRule;
 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 {
     cssconditionrule: CSSConditionRule,
     #[ignore_heap_size_of = "Arc"]
     supportsrule: Arc<Locked<SupportsRule>>,
 }
 
--- a/servo/components/script/dom/htmllinkelement.rs
+++ b/servo/components/script/dom/htmllinkelement.rs
@@ -27,20 +27,21 @@ use net_traits::ReferrerPolicy;
 use script_layout_interface::message::Msg;
 use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg};
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 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);
 
 #[derive(JSTraceable, PartialEq, Clone, Copy, HeapSizeOf)]
 pub struct RequestGenerationId(u32);
 
 impl RequestGenerationId {
--- a/servo/components/script/dom/htmlstyleelement.rs
+++ b/servo/components/script/dom/htmlstyleelement.rs
@@ -18,19 +18,20 @@ use dom::node::{ChildrenMutation, Node, 
 use dom::stylesheet::StyleSheet as DOMStyleSheet;
 use dom::virtualmethods::VirtualMethods;
 use dom_struct::dom_struct;
 use html5ever::{LocalName, Prefix};
 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]
 pub struct HTMLStyleElement {
     htmlelement: HTMLElement,
     #[ignore_heap_size_of = "Arc"]
     stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>,
     cssom_stylesheet: MutNullableJS<CSSStyleSheet>,
--- a/servo/components/script/dom/medialist.rs
+++ b/servo/components/script/dom/medialist.rs
@@ -9,21 +9,21 @@ use dom::bindings::codegen::Bindings::Wi
 use dom::bindings::js::{JS, Root};
 use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
 use dom::bindings::str::DOMString;
 use dom::cssstylesheet::CSSStyleSheet;
 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 {
     reflector_: Reflector,
     parent_stylesheet: JS<CSSStyleSheet>,
     #[ignore_heap_size_of = "Arc"]
     media_queries: Arc<Locked<StyleMediaList>>,
 }
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -102,22 +102,23 @@ use std::mem;
 use std::rc::Rc;
 use std::sync::{Arc, Mutex};
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::mpsc::{Sender, channel};
 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;
 use task_source::networking::NetworkingTaskSource;
 use task_source::user_interaction::UserInteractionTaskSource;
 use time;
 use timers::{IsInterval, TimerCallback};
 #[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
--- a/servo/components/style/parser.rs
+++ b/servo/components/style/parser.rs
@@ -2,47 +2,21 @@
  * 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/. */
 
 //! The context within which CSS code is parsed.
 
 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]
 pub fn assert_parsing_mode_match() {
     use gecko_bindings::structs;
 
     macro_rules! check_parsing_modes {
         ( $( $a:ident => $b:ident ),*, ) => {
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -5,23 +5,23 @@
 //! A property declaration block.
 
 #![deny(missing_docs)]
 
 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::*;
 use values::computed::Context;
 #[cfg(feature = "gecko")] use properties::animated_properties::AnimationValueMap;
 
 /// The animation rules.
 ///
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -26,23 +26,23 @@ use error_reporting::ParseErrorReporter;
 use computed_values;
 use context::QuirksMode;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")] use gecko_bindings::bindings;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::{self, nsCSSPropertyID};
 #[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;
 use values::computed;
 use cascade_info::CascadeInfo;
 use rule_tree::{CascadeLevel, StrongRuleNode};
 use style_adjuster::StyleAdjuster;
 #[cfg(feature = "servo")] use values::specified::BorderStyle;
--- a/servo/components/style/stylesheets/keyframes_rule.rs
+++ b/servo/components/style/stylesheets/keyframes_rule.rs
@@ -2,27 +2,27 @@
  * 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/. */
 
 //! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
 
 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;
 use properties::animated_properties::TransitionProperty;
 use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
 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;
 use values::KeyframesName;
 
 /// A [`@keyframes`][keyframes] rule.
 ///
 /// [keyframes]: https://drafts.csswg.org/css-animations/#keyframes
--- a/servo/components/style/stylesheets/mod.rs
+++ b/servo/components/style/stylesheets/mod.rs
@@ -19,19 +19,20 @@ mod rule_parser;
 mod rules_iterator;
 mod style_rule;
 mod stylesheet;
 pub mod supports_rule;
 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;
 pub use self::document_rule::DocumentRule;
 pub use self::font_face_rule::FontFaceRule;
 pub use self::import_rule::ImportRule;
 pub use self::keyframes_rule::KeyframesRule;
 pub use self::loader::StylesheetLoader;
--- a/servo/components/style/stylesheets/stylesheet.rs
+++ b/servo/components/style/stylesheets/stylesheet.rs
@@ -4,20 +4,21 @@
 
 use {Prefix, Namespace};
 use context::QuirksMode;
 use cssparser::{Parser, RuleListParser, ParserInput};
 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;
 use stylesheets::memory::{MallocSizeOfFn, MallocSizeOfWithGuard};
 use stylesheets::rule_parser::{State, TopLevelRuleParser};
 use stylesheets::rules_iterator::{EffectiveRules, EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator};
 use values::specified::NamespaceId;
 
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -11,15 +11,16 @@ path = "lib.rs"
 
 [features]
 servo = ["heapsize", "heapsize_derive", "serde", "serde_derive",
          "cssparser/heapsize", "cssparser/serde"]
 gecko = []
 
 [dependencies]
 app_units = "0.4.1"
+bitflags = "0.7"
 cssparser = "0.14.0"
 euclid = "0.13"
 heapsize = {version = "0.4", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 selectors = { path = "../selectors" }
 serde = {version = "0.9", optional = true}
 serde_derive = {version = "0.9", optional = true}
--- a/servo/components/style_traits/lib.rs
+++ b/servo/components/style_traits/lib.rs
@@ -9,16 +9,17 @@
 #![crate_name = "style_traits"]
 #![crate_type = "rlib"]
 
 #![deny(unsafe_code, missing_docs)]
 
 #![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;
 #[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
 extern crate selectors;
 #[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
 
 use selectors::parser::SelectorParseError;
@@ -135,8 +136,37 @@ impl<'a> From<StyleParseError<'a>> for P
     }
 }
 
 impl<'a> From<PropertyDeclarationParseError> for ParseError<'a> {
     fn from(this: PropertyDeclarationParseError) -> Self {
         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)
+    }
+}
+
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -85,17 +85,17 @@ use style::gecko_bindings::structs::nsID
 use style::gecko_bindings::structs::nsStyleTransformMatrix::MatrixTransformOperator;
 use style::gecko_bindings::structs::nsresult;
 use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasFFI, HasArcFFI, HasBoxFFI};
 use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
 use style::gecko_bindings::sugar::refptr::RefPtr;
 use style::gecko_properties::{self, style_structs};
 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;
 use style::properties::animated_properties::{Animatable, AnimationValue, TransitionProperty};
 use style::properties::parse_one_declaration_into;
 use style::restyle_hints::{self, RestyleHint};
 use style::rule_tree::StyleSource;
 use style::selector_parser::PseudoElementCascadeType;
@@ -113,17 +113,17 @@ use style::stylesheets::supports_rule::p
 use style::stylist::RuleInclusion;
 use style::thread_state;
 use style::timer::Timer;
 use style::traversal::{ANIMATION_ONLY, DomTraversal, FOR_CSS_RULE_CHANGES, FOR_RECONSTRUCT};
 use style::traversal::{FOR_DEFAULT_STYLES, TraversalDriver, TraversalFlags, UNSTYLED_CHILDREN_ONLY};
 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;
 
 /*
  * For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
  * the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
  * those signatures as well, giving us a second declaration of all the Servo_* functions in this
  * crate. If there's a mismatch, LLVM will assert and abort, which is a rather awful thing to
  * depend on but good enough for our purposes.
@@ -1589,17 +1589,17 @@ pub extern "C" fn Servo_StyleSet_CompatM
 }
 
 fn parse_property_into(declarations: &mut SourcePropertyDeclaration,
                        property_id: PropertyId,
                        value: *const nsACString,
                        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);
 
     parse_one_declaration_into(
         declarations,
         property_id,
         value,
--- a/servo/tests/unit/style/parsing/length.rs
+++ b/servo/tests/unit/style/parsing/length.rs
@@ -1,22 +1,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 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() {
     assert!(parse(Length::parse, "calc(1px+ 2px)").is_err());
     assert!(parse(Length::parse, "calc(calc(1px) + calc(1px + 4px))").is_ok());
     assert!(parse(Length::parse, "calc( 1px + 2px )").is_ok());
     assert!(parse(Length::parse, "calc(1px + 2px )").is_ok());
     assert!(parse(Length::parse, "calc( 1px + 2px)").is_ok());
--- a/servo/tests/unit/style/parsing/mod.rs
+++ b/servo/tests/unit/style/parsing/mod.rs
@@ -5,21 +5,21 @@
 //! Tests for parsing and serialization of values/properties
 
 use cssparser::{Parser, ParserInput};
 use euclid::size::TypedSize2D;
 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<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>>
 where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>> {
     let mut input = ParserInput::new(s);
     parse_input(f, &mut input)
 }
 
 fn parse_input<'i: 't, 't, T, F>(f: F, input: &'t mut ParserInput<'i>) -> Result<T, ParseError<'i>>
--- a/servo/tests/unit/style/parsing/value.rs
+++ b/servo/tests/unit/style/parsing/value.rs
@@ -1,20 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 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() {
     let l = NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.));
     assert!(l.has_viewport_percentage());
     let l = NoCalcLength::Absolute(AbsoluteLength::Px(Au(100).to_f32_px()));
     assert!(!l.has_viewport_percentage());
 }
--- a/servo/tests/unit/style/properties/mod.rs
+++ b/servo/tests/unit/style/properties/mod.rs
@@ -1,18 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 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<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>>
 where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>> {
     let mut input = ParserInput::new(s);
     parse_input(f, &mut input)
 }
 
 fn parse_input<'i: 't, 't, T, F>(f: F, input: &'t mut ParserInput<'i>) -> Result<T, ParseError<'i>>
--- a/servo/tests/unit/style/viewport.rs
+++ b/servo/tests/unit/style/viewport.rs
@@ -4,25 +4,25 @@
 
 use cssparser::{Parser, ParserInput};
 use euclid::size::TypedSize2D;
 use media_queries::CSSErrorReporterTest;
 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};
 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 {
     ($css:expr, $origin:ident, $error_reporter:expr) => {
         stylesheet!($css, $origin, $error_reporter, SharedRwLock::new())
     };
     ($css:expr, $origin:ident, $error_reporter:expr, $shared_lock:expr) => {
         Arc::new(Stylesheet::from_str(
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -897,16 +897,17 @@ dependencies = [
  "synstructure 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.1 (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)",
  "selectors 0.19.0",
 ]
 
 [[package]]
 name = "syn"
 version = "0.11.8"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -884,16 +884,17 @@ dependencies = [
  "synstructure 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.1 (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)",
  "selectors 0.19.0",
 ]
 
 [[package]]
 name = "syn"
 version = "0.11.8"