diff options
24 files changed, 194 insertions, 69 deletions
diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index c8ae6c3b236..e050418a11e 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -38,6 +38,9 @@ path = "../script_traits" [dependencies.style] path = "../style" +[dependencies.style_traits] +path = "../style_traits" + [dependencies.plugins] path = "../plugins" diff --git a/components/layout/context.rs b/components/layout/context.rs index 624fb01a127..dcfece7f618 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -27,6 +27,7 @@ use std::rc::Rc; use std::sync::mpsc::{Sender, channel}; use std::sync::{Arc, Mutex, RwLock}; use style::selector_matching::Stylist; +use style_traits::ParseErrorReporter; use url::Url; use util::mem::HeapSizeOf; use util::opts; @@ -127,6 +128,9 @@ pub struct SharedLayoutContext { /// Why is this reflow occurring pub goal: ReflowGoal, + + ///The CSS error reporter for all CSS loaded in this layout thread + pub error_reporter: Box<ParseErrorReporter + Sync> } pub struct LayoutContext<'a> { diff --git a/components/layout/css/matching.rs b/components/layout/css/matching.rs index cec72c7a211..83d17463712 100644 --- a/components/layout/css/matching.rs +++ b/components/layout/css/matching.rs @@ -27,6 +27,7 @@ use string_cache::{Atom, Namespace}; use style::node::TElementAttributes; use style::properties::{ComputedValues, PropertyDeclaration, cascade}; use style::selector_matching::{DeclarationBlock, Stylist}; +use style_traits::ParseErrorReporter; use util::arc_ptr_eq; use util::cache::{LRUCache, SimpleHashCache}; use util::opts; @@ -456,7 +457,8 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { applicable_declarations, shareable, Some(&***parent_style), - cached_computed_values); + cached_computed_values, + layout_context.error_reporter.clone()); cacheable = cacheable && is_cacheable; this_style = the_style } @@ -465,7 +467,8 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { applicable_declarations, shareable, None, - None); + None, + layout_context.error_reporter.clone()); cacheable = cacheable && is_cacheable; this_style = the_style } diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 411611d6a0a..9aac21f7a88 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -49,6 +49,7 @@ use script::layout_interface::Animation; use script::layout_interface::{LayoutRPC, OffsetParentResponse}; use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType}; use script::layout_interface::{ScriptLayoutChan, ScriptReflow}; +use script::reporter::CSSErrorReporter; use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel}; use sequential; use serde_json; @@ -64,6 +65,7 @@ use style::computed_values::{filter, mix_blend_mode}; use style::media_queries::{Device, MediaType}; use style::selector_matching::{Stylist, USER_OR_USER_AGENT_STYLESHEETS}; use style::stylesheets::{CSSRuleIteratorExt, Stylesheet}; +use style_traits::ParseErrorReporter; use url::Url; use util::geometry::MAX_RECT; use util::ipc::OptionalIpcSender; @@ -211,6 +213,10 @@ pub struct LayoutTask { /// /// All the other elements of this struct are read-only. rw_data: Arc<Mutex<LayoutTaskData>>, + + /// The CSS error reporter for all CSS loaded in this layout thread + error_reporter: CSSErrorReporter, + } impl LayoutTaskFactory for LayoutTask { @@ -438,6 +444,7 @@ impl LayoutTask { resolved_style_response: None, offset_parent_response: OffsetParentResponse::empty(), })), + error_reporter: CSSErrorReporter, } } @@ -476,6 +483,7 @@ impl LayoutTask { goal: goal, running_animations: self.running_animations.clone(), expired_animations: self.expired_animations.clone(), + error_reporter: self.error_reporter.clone(), } } @@ -557,7 +565,6 @@ impl LayoutTask { goal: ReflowGoal::ForDisplay, page_clip_rect: MAX_RECT, }; - let mut layout_context = self.build_shared_layout_context(&*rw_data, false, &self.url, diff --git a/components/layout/lib.rs b/components/layout/lib.rs index dd41d926b29..a19bf5aa42e 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -53,6 +53,7 @@ extern crate serde_json; extern crate smallvec; #[macro_use(atom, ns)] extern crate string_cache; extern crate style; +extern crate style_traits; extern crate unicode_bidi; extern crate unicode_script; extern crate url; diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 04c9e98bed5..f30c63db4a0 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -36,6 +36,9 @@ path = "../devtools_traits" [dependencies.style] path = "../style" +[dependencies.style_traits] +path = "../style_traits" + [dependencies.canvas] path = "../canvas" diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 14285dc4c2e..64b6f738d2f 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -18,6 +18,7 @@ use std::cell::Ref; use string_cache::Atom; use style::properties::{PropertyDeclaration, Shorthand}; use style::properties::{is_supported_property, parse_one_declaration}; +use style_traits::ParseErrorReporter; use util::str::{DOMString, str_join}; // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface @@ -240,7 +241,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // Step 6 let window = window_from_node(&*self.owner); - let declarations = parse_one_declaration(&property, &value, &window.get_url()); + let declarations = parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter()); // Step 7 let declarations = if let Ok(declarations) = declarations { diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 92ac3c8e1b2..f7640d3e7ff 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -80,6 +80,7 @@ use style::properties::longhands::{self, background_image, border_spacing, font_ use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute}; use style::values::CSSFloat; use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage}; +use style_traits::ParseErrorReporter; use url::UrlParser; use util::mem::HeapSizeOf; use util::str::{DOMString, LengthOrPercentageOrAuto}; @@ -1514,7 +1515,8 @@ impl VirtualMethods for Element { // Modifying the `style` attribute might change style. *self.style_attribute.borrow_mut() = mutation.new_value(attr).map(|value| { - parse_style_attribute(&value, &doc.base_url()) + let win = window_from_node(self); + parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter()) }); if node.is_in_doc() { doc.content_changed(node, NodeDamage::NodeStyleDamaged); diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index b0954796b8d..2687d758948 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -281,13 +281,17 @@ impl AsyncResponseListener for StylesheetContext { let environment_encoding = UTF_8 as EncodingRef; let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); let final_url = metadata.final_url; + + let elem = self.elem.root(); + let win = window_from_node(&*elem); + let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label, - Some(environment_encoding), Origin::Author); + Some(environment_encoding), Origin::Author, + win.css_error_reporter()); let media = self.media.take().unwrap(); sheet.set_media(Some(media)); let sheet = Arc::new(sheet); - let elem = self.elem.root(); let elem = elem.r(); let document = document_from_node(elem); let document = document.r(); diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 42c4d0315ac..8eba6b5982f 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -58,7 +58,7 @@ impl HTMLStyleElement { }; let data = node.GetTextContent().expect("Element.textContent must be a string"); - let mut sheet = Stylesheet::from_str(&data, url, Origin::Author); + let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter()); 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/script/dom/window.rs b/components/script/dom/window.rs index 2910632a76f..f8af9be77b5 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -52,6 +52,7 @@ use net_traits::storage_task::{StorageTask, StorageType}; use num::traits::ToPrimitive; use page::Page; use profile_traits::mem; +use reporter::CSSErrorReporter; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; use script_task::{ScriptChan, ScriptPort, MainThreadScriptMsg, RunnableWrapper}; use script_task::{SendableMainThreadScriptChan, MainThreadScriptChan}; @@ -70,6 +71,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::TryRecvError::{Disconnected, Empty}; use std::sync::mpsc::{Sender, channel}; use string_cache::Atom; +use style_traits::ParseErrorReporter; use time; use timers::{ActiveTimers, IsInterval, ScheduledCallback, TimerCallback, TimerHandle}; use url::Url; @@ -216,6 +218,8 @@ pub struct Window { /// A flag to prevent async events from attempting to interact with this window. #[ignore_heap_size_of = "defined in std"] ignore_further_async_events: Arc<AtomicBool>, + + error_reporter: CSSErrorReporter, } impl Window { @@ -289,6 +293,10 @@ impl Window { pub fn storage_task(&self) -> StorageTask { self.storage_task.clone() } + + pub fn css_error_reporter(&self) -> Box<ParseErrorReporter + Send> { + return self.error_reporter.clone(); + } } // https://html.spec.whatwg.org/multipage/#atob @@ -1243,7 +1251,7 @@ impl Window { lchan.send(Msg::GetRPC(rpc_send)).unwrap(); rpc_recv.recv().unwrap() }; - + let error_reporter = CSSErrorReporter; let win = box Window { eventtarget: EventTarget::new_inherited(), script_chan: script_chan, @@ -1288,8 +1296,8 @@ impl Window { devtools_markers: DOMRefCell::new(HashSet::new()), devtools_wants_updates: Cell::new(false), webdriver_script_chan: DOMRefCell::new(None), - ignore_further_async_events: Arc::new(AtomicBool::new(false)), + error_reporter: error_reporter }; WindowBinding::Wrap(runtime.cx(), win) diff --git a/components/script/lib.rs b/components/script/lib.rs index 0d0278f7172..4f1d9f66cd0 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -42,6 +42,7 @@ extern crate log; extern crate profile_traits; #[macro_use] extern crate style; +extern crate style_traits; #[macro_use] extern crate util; extern crate angle; @@ -90,6 +91,7 @@ mod mem; mod network_listener; pub mod page; pub mod parse; +pub mod reporter; #[allow(unsafe_code)] pub mod script_task; pub mod textinput; diff --git a/components/script/reporter.rs b/components/script/reporter.rs new file mode 100644 index 00000000000..16958201103 --- /dev/null +++ b/components/script/reporter.rs @@ -0,0 +1,25 @@ +/* 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, SourcePosition}; +use log; +use style_traits::ParseErrorReporter; + +#[derive(JSTraceable, HeapSizeOf)] +pub struct CSSErrorReporter; + +impl ParseErrorReporter for CSSErrorReporter { + fn report_error(&self, input: &mut Parser, position: SourcePosition, message: &str) { + if log_enabled!(log::LogLevel::Info) { + let location = input.source_location(position); + // TODO eventually this will got into a "web console" or something. + info!("{}:{} {}", location.line, location.column, message) + } + } + + fn clone(&self) -> Box<ParseErrorReporter + Send + Sync> { + let error_reporter = box CSSErrorReporter; + return error_reporter; + } +} diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 0f0aeee6b1a..4c9aa7f6df0 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1028,6 +1028,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", + "style_traits 0.0.1", "unicode-bidi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1550,6 +1551,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", + "style_traits 0.0.1", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/style/parser.rs b/components/style/parser.rs index 67f35fa0976..8570bc777d1 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -6,6 +6,7 @@ use cssparser::{Parser, SourcePosition}; use log; use selectors::parser::ParserContext as SelectorParserContext; +use style_traits::ParseErrorReporter; use stylesheets::Origin; use url::{Url, UrlParser}; @@ -13,16 +14,19 @@ pub struct ParserContext<'a> { pub stylesheet_origin: Origin, pub base_url: &'a Url, pub selector_context: SelectorParserContext, + pub error_reporter: Box<ParseErrorReporter + Send> } impl<'a> ParserContext<'a> { - pub fn new(stylesheet_origin: Origin, base_url: &'a Url) -> ParserContext<'a> { + pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>) + -> ParserContext<'a> { let mut selector_context = SelectorParserContext::new(); selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent; ParserContext { stylesheet_origin: stylesheet_origin, base_url: base_url, selector_context: selector_context, + error_reporter: error_reporter, } } } diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 418ea637b2f..f1f4656f8e5 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -22,7 +22,7 @@ use euclid::SideOffsets2D; use euclid::size::Size2D; use fnv::FnvHasher; use string_cache::Atom; - +use style_traits::ParseErrorReporter; use computed_values; use parser::{ParserContext, log_css_error}; use selectors::matching::DeclarationBlock; @@ -135,6 +135,7 @@ pub mod longhands { use properties::{ComputedValues, PropertyDeclaration}; use std::collections::HashMap; use std::sync::Arc; + use style_traits::ParseErrorReporter; use values::computed::ToComputedValue; use values::{computed, specified}; use string_cache::Atom; @@ -145,7 +146,8 @@ pub mod longhands { inherited_style: &ComputedValues, context: &computed::Context, seen: &mut PropertyBitField, - cacheable: &mut bool) { + cacheable: &mut bool, + error_reporter: Box<ParseErrorReporter + Send>) { let declared_value = match *declaration { PropertyDeclaration::${property.camel_case}(ref declared_value) => { declared_value @@ -174,7 +176,7 @@ pub mod longhands { .${property.ident} .clone() } - } + }, error_reporter.clone() ); Arc::make_mut(&mut style.${THIS_STYLE_STRUCT.ident}).${property.ident} = computed_value; @@ -186,7 +188,8 @@ pub mod longhands { inherited_style, context, seen, - cacheable); + cacheable, + error_reporter); % endif % else: // Do not allow stylesheets to set derived properties. @@ -533,7 +536,8 @@ pub mod longhands { _inherited_style: &ComputedValues, context: &computed::Context, _seen: &mut PropertyBitField, - _cacheable: &mut bool) { + _cacheable: &mut bool, + _error_reporter: Box<ParseErrorReporter + Send>) { Arc::make_mut(&mut style.box_)._servo_display_for_hypothetical_box = longhands::_servo_display_for_hypothetical_box::derive_from_display( *computed_value, @@ -2234,7 +2238,8 @@ pub mod longhands { _inherited_style: &ComputedValues, context: &computed::Context, _seen: &mut PropertyBitField, - _cacheable: &mut bool) { + _cacheable: &mut bool, + _error_reporter: Box<ParseErrorReporter + Send>) { Arc::make_mut(&mut style.inheritedtext)._servo_text_decorations_in_effect = longhands::_servo_text_decorations_in_effect::derive_from_text_decoration( *computed_value, @@ -5613,7 +5618,7 @@ mod property_bit_field { fn substitute_variables_${property.ident}<F, R>( value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, - f: F) + f: F, error_reporter: Box<ParseErrorReporter + Send>) -> R where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) -> R { @@ -5625,7 +5630,7 @@ mod property_bit_field { .and_then(|css| { // As of this writing, only the base URL is used for property values: let context = ParserContext::new( - ::stylesheets::Origin::Author, base_url); + ::stylesheets::Origin::Author, base_url, error_reporter); Parser::new(&css).parse_entirely(|input| { match from_shorthand { None => { @@ -5668,15 +5673,15 @@ pub struct PropertyDeclarationBlock { pub normal: Arc<Vec<PropertyDeclaration>>, } - -pub fn parse_style_attribute(input: &str, base_url: &Url) -> PropertyDeclarationBlock { - let context = ParserContext::new(Origin::Author, base_url); +pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: Box<ParseErrorReporter + Send>) + -> PropertyDeclarationBlock { + let context = ParserContext::new(Origin::Author, base_url, error_reporter); parse_property_declaration_list(&context, &mut Parser::new(input)) } -pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url) +pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: Box<ParseErrorReporter + Send>) -> Result<Vec<PropertyDeclaration>, ()> { - let context = ParserContext::new(Origin::Author, base_url); + let context = ParserContext::new(Origin::Author, base_url, error_reporter); let mut results = vec![]; match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results) { PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results), @@ -6389,7 +6394,8 @@ fn cascade_with_cached_declarations( parent_style: &ComputedValues, cached_style: &ComputedValues, custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, - context: &computed::Context) + context: &computed::Context, + error_reporter: Box<ParseErrorReporter + Send>) -> ComputedValues { % for style_struct in STYLE_STRUCTS: % if style_struct.inherited: @@ -6433,7 +6439,7 @@ fn cascade_with_cached_declarations( .clone() } DeclaredValue::WithVariables { .. } => unreachable!() - } + }, error_reporter.clone() ); Arc::make_mut(&mut style_${style_struct.ident}) .${property.ident} = computed_value; @@ -6488,7 +6494,8 @@ type CascadePropertyFn = extern "Rust" fn(declaration: &PropertyDeclaration, inherited_style: &ComputedValues, context: &computed::Context, seen: &mut PropertyBitField, - cacheable: &mut bool); + cacheable: &mut bool, + error_reporter: Box<ParseErrorReporter + Send>); // This is a thread-local rather than a lazy static to avoid atomic operations when cascading // properties. @@ -6533,7 +6540,8 @@ pub fn cascade(viewport_size: Size2D<Au>, applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>], shareable: bool, parent_style: Option< &ComputedValues >, - cached_style: Option< &ComputedValues >) + cached_style: Option< &ComputedValues >, + error_reporter: Box<ParseErrorReporter + Send>) -> (ComputedValues, bool) { let initial_values = &*INITIAL_VALUES; let (is_root_element, inherited_style) = match parent_style { @@ -6588,7 +6596,7 @@ pub fn cascade(viewport_size: Size2D<Au>, // This assumes that the computed and specified values have the same Rust type. macro_rules! get_specified( - ($style_struct_getter: ident, $property: ident, $declared_value: expr) => { + ($style_struct_getter: ident, $property: ident, $declared_value: expr, $error_reporter: expr) => { concat_idents!(substitute_variables_, $property)( $declared_value, &custom_properties, |value| match *value { DeclaredValue::Value(specified_value) => specified_value, @@ -6597,7 +6605,7 @@ pub fn cascade(viewport_size: Size2D<Au>, inherited_style.$style_struct_getter().$property.clone() } DeclaredValue::WithVariables { .. } => unreachable!() - } + }, $error_reporter.clone() ) }; ); @@ -6636,7 +6644,7 @@ pub fn cascade(viewport_size: Size2D<Au>, DeclaredValue::Initial => longhands::font_size::get_initial_value(), DeclaredValue::Inherit => context.inherited_font_size, DeclaredValue::WithVariables { .. } => unreachable!(), - } + }, error_reporter.clone() ); } PropertyDeclaration::Color(ref value) => { @@ -6648,35 +6656,35 @@ pub fn cascade(viewport_size: Size2D<Au>, DeclaredValue::Initial => longhands::color::get_initial_value(), DeclaredValue::Inherit => inherited_style.get_color().color.clone(), DeclaredValue::WithVariables { .. } => unreachable!(), - } + }, error_reporter.clone() ); } PropertyDeclaration::Display(ref value) => { - context.display = get_specified!(get_box, display, value); + context.display = get_specified!(get_box, display, value, error_reporter.clone()); } PropertyDeclaration::Position(ref value) => { - context.positioned = match get_specified!(get_box, position, value) { + context.positioned = match get_specified!(get_box, position, value, error_reporter.clone()) { longhands::position::SpecifiedValue::absolute | longhands::position::SpecifiedValue::fixed => true, _ => false, } } PropertyDeclaration::OverflowX(ref value) => { - context.overflow_x = get_specified!(get_box, overflow_x, value); + context.overflow_x = get_specified!(get_box, overflow_x, value, error_reporter.clone()); } PropertyDeclaration::OverflowY(ref value) => { - context.overflow_y = get_specified!(get_box, overflow_y, value); + context.overflow_y = get_specified!(get_box, overflow_y, value, error_reporter.clone()); } PropertyDeclaration::Float(ref value) => { - context.floated = get_specified!(get_box, float, value) + context.floated = get_specified!(get_box, float, value, error_reporter.clone()) != longhands::float::SpecifiedValue::none; } PropertyDeclaration::TextDecoration(ref value) => { - context.text_decoration = get_specified!(get_text, text_decoration, value); + context.text_decoration = get_specified!(get_text, text_decoration, value, error_reporter.clone()); } PropertyDeclaration::OutlineStyle(ref value) => { context.outline_style_present = - match get_specified!(get_outline, outline_style, value) { + match get_specified!(get_outline, outline_style, value, error_reporter.clone()) { BorderStyle::none => false, _ => true, }; @@ -6684,7 +6692,7 @@ pub fn cascade(viewport_size: Size2D<Au>, % for side in ["top", "right", "bottom", "left"]: PropertyDeclaration::Border${side.capitalize()}Style(ref value) => { context.border_${side}_present = - match get_specified!(get_border, border_${side}_style, value) { + match get_specified!(get_border, border_${side}_style, value, error_reporter.clone()) { BorderStyle::none | BorderStyle::hidden => false, _ => true, }; @@ -6702,7 +6710,8 @@ pub fn cascade(viewport_size: Size2D<Au>, parent_style, cached_style, custom_properties, - &context), false) + &context, + error_reporter), false) } (_, _) => {} } @@ -6746,7 +6755,8 @@ pub fn cascade(viewport_size: Size2D<Au>, inherited_style, &context, &mut seen, - &mut cacheable); + &mut cacheable, + error_reporter.clone()); } } }); diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index f4b2168fc26..f87754d137e 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -2,6 +2,8 @@ * 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, SourcePosition}; +use log; use media_queries::{Device, MediaType}; use node::TElementAttributes; use properties::{PropertyDeclaration, PropertyDeclarationBlock}; @@ -14,6 +16,7 @@ use selectors::parser::PseudoElement; use selectors::states::*; use smallvec::VecLike; use std::process; +use style_traits::ParseErrorReporter; use style_traits::viewport::ViewportConstraints; use stylesheets::{CSSRuleIteratorExt, Origin, Stylesheet}; use url::Url; @@ -24,6 +27,20 @@ use viewport::{MaybeNew, ViewportRuleCascade}; pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>; +struct StdoutErrorReporter; + +impl ParseErrorReporter for StdoutErrorReporter { + fn report_error(&self, input: &mut Parser, position: SourcePosition, message: &str) { + if log_enabled!(log::LogLevel::Info) { + let location = input.source_location(position); + info!("{}:{} {}", location.line, location.column, message) + } + } + + fn clone(&self) -> Box<ParseErrorReporter + Send + Sync> { + box StdoutErrorReporter + } +} lazy_static! { pub static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet> = { @@ -38,7 +55,8 @@ lazy_static! { Url::parse(&format!("chrome:///{:?}", filename)).unwrap(), None, None, - Origin::UserAgent); + Origin::UserAgent, + box StdoutErrorReporter); stylesheets.push(ua_stylesheet); } Err(..) => { @@ -49,7 +67,7 @@ lazy_static! { } for &(ref contents, ref url) in &opts::get().user_stylesheets { stylesheets.push(Stylesheet::from_bytes( - &contents, url.clone(), None, None, Origin::User)); + &contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter)); } stylesheets }; @@ -64,7 +82,8 @@ lazy_static! { url!("chrome:///quirks-mode.css"), None, None, - Origin::UserAgent) + Origin::UserAgent, + box StdoutErrorReporter) }, Err(..) => { error!("Stylist failed to load 'quirks-mode.css'!"); diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 70a3a3db74d..e3af16929dc 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -16,10 +16,12 @@ use std::cell::Cell; use std::iter::Iterator; use std::slice; use string_cache::{Atom, Namespace}; +use style_traits::ParseErrorReporter; use url::Url; use util::mem::HeapSizeOf; use viewport::ViewportRule; + /// Each style rule has an origin, which determines where it enters the cascade. /// /// http://dev.w3.org/csswg/css-cascade/#cascading-origins @@ -80,31 +82,33 @@ pub struct StyleRule { impl Stylesheet { 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) -> Stylesheet { + environment_encoding: Option<EncodingRef>, origin: Origin, + error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet { let mut bytes = vec![]; // TODO: incremental decoding and tokenization/parsing for chunk in input { bytes.push_all(&chunk) } Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label, - environment_encoding, origin) + environment_encoding, origin, error_reporter) } pub fn from_bytes(bytes: &[u8], base_url: Url, protocol_encoding_label: Option<&str>, environment_encoding: Option<EncodingRef>, - origin: Origin) + origin: Origin, error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet { // 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) + Stylesheet::from_str(&string, base_url, origin, error_reporter) } - pub fn from_str(css: &str, base_url: Url, origin: Origin) -> Stylesheet { + pub fn from_str(css: &str, base_url: Url, origin: Origin, + error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet { let rule_parser = TopLevelRuleParser { - context: ParserContext::new(origin, &base_url), + context: ParserContext::new(origin, &base_url, error_reporter), state: Cell::new(State::Start), }; let mut input = Parser::new(css); diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs index 2589bb961d6..6d088cc7e0d 100644 --- a/components/style_traits/lib.rs +++ b/components/style_traits/lib.rs @@ -24,3 +24,9 @@ extern crate util; #[macro_use] pub mod values; pub mod viewport; + +use cssparser::{Parser, SourcePosition}; +pub trait ParseErrorReporter { + fn report_error(&self, input: &mut Parser, position: SourcePosition, message: &str); + fn clone(&self) -> Box<ParseErrorReporter + Send + Sync>; +} diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 20a1aa4c50f..2de39d4ecf3 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -977,6 +977,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", + "style_traits 0.0.1", "unicode-bidi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1464,6 +1465,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", + "style_traits 0.0.1", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 7166f8cde37..8084dc7a380 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -957,6 +957,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", + "style_traits 0.0.1", "unicode-bidi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1444,6 +1445,7 @@ dependencies = [ "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", + "style_traits 0.0.1", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/tests/unit/style/media_queries.rs b/tests/unit/style/media_queries.rs index 6a3d79baba4..c0c4b4a3f5e 100644 --- a/tests/unit/style/media_queries.rs +++ b/tests/unit/style/media_queries.rs @@ -3,16 +3,28 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use app_units::Au; +use cssparser::{Parser, SourcePosition}; use euclid::size::Size2D; use std::borrow::ToOwned; use style::media_queries::*; use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt}; use style::values::specified; +use style_traits::ParseErrorReporter; +pub struct CSSErrorReporterTest; + +impl ParseErrorReporter for CSSErrorReporterTest { + fn report_error(&self, _input: &mut Parser, _position: SourcePosition, _message: &str) { + } + fn clone(&self) -> Box<ParseErrorReporter + Send + Sync> { + let error_reporter = Box::new(CSSErrorReporterTest); + return error_reporter; + } +} fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) { let url = url!("http://localhost"); - let stylesheet = Stylesheet::from_str(css, url, Origin::Author); + let stylesheet = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest)); let mut rule_count = 0; for rule in stylesheet.rules().media() { rule_count += 1; @@ -23,7 +35,7 @@ fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) fn media_query_test(device: &Device, css: &str, expected_rule_count: usize) { let url = url!("http://localhost"); - let ss = Stylesheet::from_str(css, url, Origin::Author); + let ss = Stylesheet::from_str(css, url, Origin::Author, Box::new(CSSErrorReporterTest)); let rule_count = ss.effective_rules(device).style().count(); assert!(rule_count == expected_rule_count, css.to_owned()); } diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 89a0b235da7..d18c3db3c1c 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cssparser; +use media_queries::CSSErrorReporterTest; use selectors::parser::*; use std::borrow::ToOwned; use std::sync::Arc; @@ -10,7 +11,6 @@ use string_cache::Atom; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands}; use style::stylesheets::{CSSRule, StyleRule, Origin, Stylesheet}; - #[test] fn test_parse_stylesheet() { let css = r" @@ -21,7 +21,7 @@ fn test_parse_stylesheet() { #d1 > .ok { background: blue; } "; let url = url!("about::test"); - let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent); + let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent, Box::new(CSSErrorReporterTest)); assert_eq!(stylesheet, Stylesheet { origin: Origin::UserAgent, media: None, diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs index f3f70fde710..f23346b53fb 100644 --- a/tests/unit/style/viewport.rs +++ b/tests/unit/style/viewport.rs @@ -5,6 +5,7 @@ use cssparser::Parser; use euclid::scale_factor::ScaleFactor; use euclid::size::Size2D; +use media_queries::CSSErrorReporterTest; use style::media_queries::{Device, MediaType}; use style::parser::ParserContext; use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt}; @@ -12,11 +13,12 @@ use style::values::specified::Length::{self, ViewportPercentage}; use style::values::specified::LengthOrPercentageOrAuto::{self, Auto}; use style::values::specified::ViewportPercentageLength::Vw; use style::viewport::*; +use style_traits::ParseErrorReporter; use style_traits::viewport::*; macro_rules! stylesheet { - ($css:expr, $origin:ident) => { - Stylesheet::from_str($css, url!("http://localhost"), Origin::$origin); + ($css:expr, $origin:ident, $error_reporter:expr) => { + Stylesheet::from_str($css, url!("http://localhost"), Origin::$origin, $error_reporter); } } @@ -27,8 +29,7 @@ fn test_viewport_rule<F>(css: &str, { ::util::prefs::set_pref("layout.viewport.enabled", ::util::prefs::PrefValue::Boolean(true)); - - let stylesheet = stylesheet!(css, Author); + let stylesheet = stylesheet!(css, Author, Box::new(CSSErrorReporterTest)); let mut rule_count = 0; for rule in stylesheet.effective_rules(&device).viewport() { rule_count += 1; @@ -244,11 +245,11 @@ fn multiple_stylesheets_cascading() { ::util::prefs::set_pref("layout.viewport.enabled", ::util::prefs::PrefValue::Boolean(true)); let device = Device::new(MediaType::Screen, Size2D::typed(800., 600.)); - + let error_reporter = CSSErrorReporterTest; let stylesheets = vec![ - stylesheet!("@viewport { min-width: 100px; min-height: 100px; zoom: 1; }", UserAgent), - stylesheet!("@viewport { min-width: 200px; min-height: 200px; }", User), - stylesheet!("@viewport { min-width: 300px; }", Author)]; + stylesheet!("@viewport { min-width: 100px; min-height: 100px; zoom: 1; }", UserAgent, error_reporter.clone()), + stylesheet!("@viewport { min-width: 200px; min-height: 200px; }", User, error_reporter.clone()), + stylesheet!("@viewport { min-width: 300px; }", Author, error_reporter.clone())]; let declarations = stylesheets.iter() .flat_map(|s| s.effective_rules(&device).viewport()) @@ -260,11 +261,11 @@ fn multiple_stylesheets_cascading() { assert_decl_eq!(&declarations[2], Author, MinWidth: viewport_length!(300., px)); let stylesheets = vec![ - stylesheet!("@viewport { min-width: 100px !important; }", UserAgent), - stylesheet!("@viewport { min-width: 200px !important; min-height: 200px !important; }", User), - stylesheet!( - "@viewport { min-width: 300px !important; min-height: 300px !important; zoom: 3 !important; }", Author)]; - + stylesheet!("@viewport { min-width: 100px !important; }", UserAgent, error_reporter.clone()), + stylesheet!("@viewport { min-width: 200px !important; min-height: 200px !important; }", + User, error_reporter.clone()), + stylesheet!("@viewport { min-width: 300px !important; min-height: 300px !important; zoom: 3 !important; }", + Author, error_reporter.clone())]; let declarations = stylesheets.iter() .flat_map(|s| s.effective_rules(&device).viewport()) .cascade() @@ -278,7 +279,7 @@ fn multiple_stylesheets_cascading() { #[test] fn constrain_viewport() { let url = url!("http://localhost"); - let context = ParserContext::new(Origin::Author, &url); + let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest)); macro_rules! from_css { ($css:expr) => { |