diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/cssstyledeclaration.rs | 5 | ||||
-rw-r--r-- | components/script/dom/element.rs | 4 | ||||
-rw-r--r-- | components/script/dom/htmllinkelement.rs | 4 | ||||
-rw-r--r-- | components/script/dom/htmlstyleelement.rs | 4 | ||||
-rw-r--r-- | components/style/Cargo.toml | 3 | ||||
-rw-r--r-- | components/style/lib.rs | 2 | ||||
-rw-r--r-- | components/style/parser.rs | 38 | ||||
-rw-r--r-- | components/style/properties/helpers.mako.rs | 2 | ||||
-rw-r--r-- | components/style/properties/longhand/box.mako.rs | 75 | ||||
-rw-r--r-- | components/style/properties/properties.mako.rs | 27 | ||||
-rw-r--r-- | components/style/selector_matching.rs | 10 | ||||
-rw-r--r-- | components/style/stylesheets.rs | 19 | ||||
-rw-r--r-- | components/style/values.rs | 10 |
13 files changed, 170 insertions, 33 deletions
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 6d537c40ea5..df9251f3888 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -16,6 +16,7 @@ use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Ref; use string_cache::Atom; +use style::parser::ParserContextExtraData; use style::properties::{PropertyDeclaration, Shorthand}; use style::properties::{is_supported_property, parse_one_declaration}; use style::selector_impl::PseudoElement; @@ -240,7 +241,9 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // Step 6 let window = window_from_node(&*self.owner); - let declarations = parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter()); + let declarations = + parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter(), + ParserContextExtraData::default()); // Step 7 let declarations = if let Ok(declarations) = declarations { diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index ec33deb1608..f5832089202 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -86,6 +86,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace, QualName}; use style::element_state::*; +use style::parser::ParserContextExtraData; use style::properties::DeclaredValue; use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute}; @@ -1977,7 +1978,8 @@ impl VirtualMethods for Element { *self.style_attribute.borrow_mut() = mutation.new_value(attr).map(|value| { let win = window_from_node(self); - parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter()) + parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(), + ParserContextExtraData::default()) }); if node.is_in_doc() { node.dirty(NodeDamage::NodeStyleDamaged); diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 18ff43c000b..88de9756267 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -38,6 +38,7 @@ use std::mem; use std::sync::{Arc, Mutex}; use string_cache::Atom; use style::media_queries::{MediaQueryList, parse_media_query_list}; +use style::parser::ParserContextExtraData; use style::servo::Stylesheet; use style::stylesheets::Origin; use url::Url; @@ -307,7 +308,8 @@ impl AsyncResponseListener for StylesheetContext { let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label, Some(environment_encoding), Origin::Author, - win.css_error_reporter()); + win.css_error_reporter(), + ParserContextExtraData::default()); let media = self.media.take().unwrap(); sheet.set_media(Some(media)); let sheet = Arc::new(sheet); diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 8d4a05eb9b7..62395b682d1 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -18,6 +18,7 @@ use layout_interface::{LayoutChan, Msg}; use std::sync::Arc; use string_cache::Atom; use style::media_queries::parse_media_query_list; +use style::parser::ParserContextExtraData; use style::servo::Stylesheet; use style::stylesheets::Origin; @@ -60,7 +61,8 @@ impl HTMLStyleElement { }; let data = node.GetTextContent().expect("Element.textContent must be a string"); - let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter()); + let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter(), + ParserContextExtraData::default()); let mut css_parser = CssParser::new(&mq_str); let media = parse_media_query_list(&mut css_parser); sheet.set_media(Some(media)); diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 5198dc05b14..566506e987e 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -11,7 +11,7 @@ name = "style" path = "lib.rs" [features] -gecko = [] +gecko = ["gecko_bindings"] [dependencies] app_units = {version = "0.2.3", features = ["plugins"]} @@ -20,6 +20,7 @@ cssparser = {version = "0.5.5", features = ["heap_size", "serde-serialization"]} encoding = "0.2" euclid = {version = "0.6.4", features = ["plugins"]} fnv = "1.0" +gecko_bindings = {path = "../../ports/geckolib/gecko_bindings", optional = true} heapsize = "0.3.0" heapsize_plugin = "0.1.2" lazy_static = "0.2" diff --git a/components/style/lib.rs b/components/style/lib.rs index 00d5d079066..4ec45e45e04 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -28,6 +28,8 @@ extern crate cssparser; extern crate encoding; extern crate euclid; extern crate fnv; +#[cfg(feature = "gecko")] +extern crate gecko_bindings; extern crate heapsize; #[allow(unused_extern_crates)] #[macro_use] diff --git a/components/style/parser.rs b/components/style/parser.rs index b044367e8dd..eadb778db55 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -5,20 +5,47 @@ use cssparser::{Parser, SourcePosition}; use error_reporting::ParseErrorReporter; +#[cfg(feature = "gecko")] +use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; use selectors::parser::ParserContext as SelectorParserContext; use stylesheets::Origin; use url::Url; +#[cfg(not(feature = "gecko"))] +pub struct ParserContextExtraData; + +#[cfg(feature = "gecko")] +pub struct ParserContextExtraData { + pub base: Option<GeckoArcURI>, + pub referrer: Option<GeckoArcURI>, + pub principal: Option<GeckoArcPrincipal>, +} + +impl ParserContextExtraData { + #[cfg(not(feature = "gecko"))] + pub fn default() -> ParserContextExtraData { + ParserContextExtraData + } + + #[cfg(feature = "gecko")] + pub fn default() -> ParserContextExtraData { + ParserContextExtraData { base: None, referrer: None, principal: None } + } +} + pub struct ParserContext<'a> { pub stylesheet_origin: Origin, pub base_url: &'a Url, pub selector_context: SelectorParserContext, pub error_reporter: Box<ParseErrorReporter + Send>, + pub extra_data: ParserContextExtraData, } impl<'a> ParserContext<'a> { - pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>) - -> ParserContext<'a> { + pub fn new_with_extra_data(stylesheet_origin: Origin, base_url: &'a Url, + error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) + -> ParserContext<'a> { let mut selector_context = SelectorParserContext::new(); selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent; ParserContext { @@ -26,8 +53,15 @@ impl<'a> ParserContext<'a> { base_url: base_url, selector_context: selector_context, error_reporter: error_reporter, + extra_data: extra_data, } } + + pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>) + -> ParserContext<'a> { + let extra_data = ParserContextExtraData::default(); + ParserContext::new_with_extra_data(stylesheet_origin, base_url, error_reporter, extra_data) + } } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index af052179d2c..86961c89192 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -43,7 +43,7 @@ #![allow(unused_imports)] % if not property.derived_from: use cssparser::Parser; - use parser::ParserContext; + use parser::{ParserContext, ParserContextExtraData}; use properties::{CSSWideKeyword, DeclaredValue, Shorthand}; % endif use error_reporting::ParseErrorReporter; diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 6fd36b71a4d..f80a42c88d2 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -851,3 +851,78 @@ ${helpers.single_keyword("-moz-appearance", gecko_ffi_name="mAppearance", gecko_constant_prefix="NS_THEME", products="gecko")} + +// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding +<%helpers:longhand name="-moz-binding" products="gecko"> + use cssparser::{CssStringWriter, ToCss}; + use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; + use std::fmt::{self, Write}; + use url::Url; + use values::computed::ComputedValueAsSpecified; + + #[derive(PartialEq, Clone, Debug, HeapSizeOf)] + pub struct UrlExtraData { + pub base: GeckoArcURI, + pub referrer: GeckoArcURI, + pub principal: GeckoArcPrincipal, + } + + #[derive(PartialEq, Clone, Debug, HeapSizeOf)] + pub enum SpecifiedValue { + Url(Url, UrlExtraData), + None, + } + + impl ComputedValueAsSpecified for SpecifiedValue {} + + impl ToCss for SpecifiedValue { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + use values::LocalToCss; + match *self { + SpecifiedValue::Url(ref url, _) => { + url.to_css(dest) + } + SpecifiedValue::None => { + try!(dest.write_str("none")); + Ok(()) + } + } + } + } + + pub mod computed_value { + pub type T = super::SpecifiedValue; + } + + #[inline] pub fn get_initial_value() -> SpecifiedValue { + SpecifiedValue::None + } + + pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { + if input.try(|input| input.expect_ident_matching("none")).is_ok() { + return Ok(SpecifiedValue::None); + } + + let url = context.parse_url(&*try!(input.expect_url())); + match context.extra_data { + ParserContextExtraData { + base: Some(ref base), + referrer: Some(ref referrer), + principal: Some(ref principal), + } => { + let extra_data = UrlExtraData { + base: base.clone(), + referrer: referrer.clone(), + principal: principal.clone(), + }; + Ok(SpecifiedValue::Url(url, extra_data)) + }, + _ => { + // FIXME(heycam) should ensure we always have a principal, etc., when parsing + // style attributes and re-parsing due to CSS Variables. + println!("stylo: skipping -moz-binding declaration without ParserContextExtraData"); + Err(()) + }, + } + } +</%helpers:longhand> diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index dc15f7339d0..ec6fe6562e0 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -29,7 +29,7 @@ use euclid::size::Size2D; use string_cache::Atom; use computed_values; use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode}; -use parser::{ParserContext, log_css_error}; +use parser::{ParserContext, ParserContextExtraData, log_css_error}; use selectors::matching::DeclarationBlock; use stylesheets::Origin; use values::AuExtensionMethods; @@ -185,13 +185,18 @@ mod property_bit_field { if let DeclaredValue::WithVariables { ref css, first_token_type, ref base_url, from_shorthand } = *value { + // FIXME(heycam): A ParserContextExtraData should be built from data + // stored in the WithVariables, in case variable expansion results in + // a url() value. + let extra_data = ParserContextExtraData::default(); substitute_variables_${property.ident}_slow(css, first_token_type, base_url, from_shorthand, custom_properties, f, - error_reporter); + error_reporter, + extra_data); } else { f(value); } @@ -206,7 +211,8 @@ mod property_bit_field { from_shorthand: Option<Shorthand>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, f: F, - error_reporter: &mut StdBox<ParseErrorReporter + Send>) + error_reporter: &mut StdBox<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) { f(& ::custom_properties::substitute(css, first_token_type, custom_properties) @@ -215,8 +221,9 @@ mod property_bit_field { // // FIXME(pcwalton): Cloning the error reporter is slow! But so are custom // properties, so whatever... - let context = ParserContext::new( - ::stylesheets::Origin::Author, base_url, (*error_reporter).clone()); + let context = ParserContext::new_with_extra_data( + ::stylesheets::Origin::Author, base_url, (*error_reporter).clone(), + extra_data); Parser::new(&css).parse_entirely(|input| { match from_shorthand { None => { @@ -256,15 +263,17 @@ pub struct PropertyDeclarationBlock { pub normal: Arc<Vec<PropertyDeclaration>>, } -pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>) +pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) -> PropertyDeclarationBlock { - let context = ParserContext::new(Origin::Author, base_url, error_reporter); + let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data); parse_property_declaration_list(&context, &mut Parser::new(input)) } -pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>) +pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) -> Result<Vec<PropertyDeclaration>, ()> { - let context = ParserContext::new(Origin::Author, base_url, error_reporter); + let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data); let mut results = vec![]; match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results) { PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results), diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index c1989348f50..017a7443624 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -9,6 +9,7 @@ use dom::PresentationalHintsSynthetizer; use element_state::*; use error_reporting::StdoutErrorReporter; use media_queries::{Device, MediaType}; +use parser::ParserContextExtraData; use properties::{self, PropertyDeclaration, PropertyDeclarationBlock}; use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet}; use selector_impl::{SelectorImplExt, ServoSelectorImpl}; @@ -46,7 +47,8 @@ lazy_static! { None, None, Origin::UserAgent, - box StdoutErrorReporter); + box StdoutErrorReporter, + ParserContextExtraData::default()); stylesheets.push(ua_stylesheet); } Err(..) => { @@ -57,7 +59,8 @@ lazy_static! { } for &(ref contents, ref url) in &opts::get().user_stylesheets { stylesheets.push(Stylesheet::from_bytes( - &contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter)); + &contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter, + ParserContextExtraData::default())); } stylesheets }; @@ -73,7 +76,8 @@ lazy_static! { None, None, Origin::UserAgent, - box StdoutErrorReporter) + box StdoutErrorReporter, + ParserContextExtraData::default()) }, Err(..) => { error!("Stylist failed to load 'quirks-mode.css'!"); diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 7a978263b2b..4de57e81d40 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -8,7 +8,7 @@ use encoding::EncodingRef; use error_reporting::ParseErrorReporter; use font_face::{FontFaceRule, parse_font_face_block}; use media_queries::{Device, MediaQueryList, parse_media_query_list}; -use parser::{ParserContext, log_css_error}; +use parser::{ParserContext, ParserContextExtraData, log_css_error}; use properties::{PropertyDeclarationBlock, parse_property_declaration_list}; use selectors::parser::{Selector, SelectorImpl, parse_selector_list}; use smallvec::SmallVec; @@ -83,32 +83,37 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> { pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>( input: I, base_url: Url, protocol_encoding_label: Option<&str>, environment_encoding: Option<EncodingRef>, origin: Origin, - error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> { + error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) -> Stylesheet<Impl> { let mut bytes = vec![]; // TODO: incremental decoding and tokenization/parsing for chunk in input { bytes.extend_from_slice(&chunk) } Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label, - environment_encoding, origin, error_reporter) + environment_encoding, origin, error_reporter, + extra_data) } pub fn from_bytes(bytes: &[u8], base_url: Url, protocol_encoding_label: Option<&str>, environment_encoding: Option<EncodingRef>, - origin: Origin, error_reporter: Box<ParseErrorReporter + Send>) + origin: Origin, error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) -> Stylesheet<Impl> { // TODO: bytes.as_slice could be bytes.container_as_bytes() let (string, _) = decode_stylesheet_bytes( bytes, protocol_encoding_label, environment_encoding); - Stylesheet::from_str(&string, base_url, origin, error_reporter) + Stylesheet::from_str(&string, base_url, origin, error_reporter, extra_data) } pub fn from_str(css: &str, base_url: Url, origin: Origin, - error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> { + error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) -> Stylesheet<Impl> { let rule_parser = TopLevelRuleParser { - context: ParserContext::new(origin, &base_url, error_reporter.clone()), + context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter.clone(), + extra_data), state: Cell::new(State::Start), _impl: PhantomData, }; diff --git a/components/style/values.rs b/components/style/values.rs index 2f295bd8775..9492a028cfc 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -90,13 +90,13 @@ pub const FONT_MEDIUM_PX: i32 = 16; pub mod specified { use app_units::Au; - use cssparser::{self, CssStringWriter, Parser, ToCss, Token}; + use cssparser::{self, Parser, ToCss, Token}; use euclid::size::Size2D; use parser::ParserContext; use std::ascii::AsciiExt; use std::cmp; use std::f32::consts::PI; - use std::fmt::{self, Write}; + use std::fmt; use std::ops::Mul; use style_traits::values::specified::AllowedNumericType; use super::AuExtensionMethods; @@ -1224,12 +1224,10 @@ pub mod specified { impl ToCss for Image { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + use values::LocalToCss; match *self { Image::Url(ref url) => { - try!(dest.write_str("url(\"")); - try!(write!(&mut CssStringWriter::new(dest), "{}", url)); - try!(dest.write_str("\")")); - Ok(()) + url.to_css(dest) } Image::LinearGradient(ref gradient) => gradient.to_css(dest) } |