diff --git a/components/style/parser.rs b/components/style/parser.rs index 8bfefc414cb8..7085dacb36f9 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -8,7 +8,8 @@ use context::QuirksMode; use cssparser::{Parser, SourcePosition, UnicodeRange}; use error_reporting::ParseErrorReporter; use style_traits::OneOrMoreCommaSeparated; -use stylesheets::{CssRuleType, Origin, UrlExtraData}; +use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces}; +use parking_lot::RwLock; bitflags! { /// The mode to use when parsing values. @@ -81,6 +82,8 @@ pub struct ParserContext<'a> { pub parsing_mode: ParsingMode, /// The quirks mode of this stylesheet. pub quirks_mode: QuirksMode, + /// The list of all namespaces active in the current stylesheet + pub namespaces: Option<&'a RwLock>, } impl<'a> ParserContext<'a> { @@ -100,6 +103,7 @@ impl<'a> ParserContext<'a> { line_number_offset: 0u64, parsing_mode: parsing_mode, quirks_mode: quirks_mode, + namespaces: None, } } @@ -125,6 +129,7 @@ impl<'a> ParserContext<'a> { line_number_offset: context.line_number_offset, parsing_mode: context.parsing_mode, quirks_mode: context.quirks_mode, + namespaces: context.namespaces, } } @@ -144,6 +149,7 @@ impl<'a> ParserContext<'a> { line_number_offset: line_number_offset, parsing_mode: parsing_mode, quirks_mode: quirks_mode, + namespaces: None, } } diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 8c01c2adf22e..cb21c63d9334 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -38,9 +38,9 @@ use servo_config::prefs::PREFS; use servo_url::ServoUrl; use shared_lock::{SharedRwLock, Locked, ToCssWithGuard, SharedRwLockReadGuard}; use smallvec::SmallVec; +use std::{fmt, mem}; use std::borrow::Borrow; use std::cell::Cell; -use std::fmt; use std::mem::align_of; use std::os::raw::c_void; use std::slice; @@ -476,13 +476,13 @@ impl CssRule { loader: Option<&StylesheetLoader>) -> Result<(Self, State), SingleRuleParseError> { let error_reporter = NullReporter; - let mut namespaces = parent_stylesheet.namespaces.write(); - let context = ParserContext::new(parent_stylesheet.origin, - &parent_stylesheet.url_data, - &error_reporter, - None, - PARSING_MODE_DEFAULT, - parent_stylesheet.quirks_mode); + let mut context = ParserContext::new(parent_stylesheet.origin, + &parent_stylesheet.url_data, + &error_reporter, + None, + PARSING_MODE_DEFAULT, + parent_stylesheet.quirks_mode); + context.namespaces = Some(&parent_stylesheet.namespaces); let mut input = Parser::new(css); // nested rules are in the body state @@ -493,7 +493,6 @@ impl CssRule { shared_lock: &parent_stylesheet.shared_lock, loader: loader, state: Cell::new(state), - namespaces: &mut namespaces, }; match parse_one_rule(&mut input, &mut rule_parser) { Ok(result) => Ok((result, rule_parser.state.get())), @@ -1210,14 +1209,14 @@ impl Stylesheet { stylesheet_loader: Option<&StylesheetLoader>, error_reporter: &ParseErrorReporter, line_number_offset: u64) { - let mut namespaces = Namespaces::default(); + let namespaces = RwLock::new(Namespaces::default()); // FIXME: we really should update existing.url_data with the given url_data, // otherwise newly inserted rule may not have the right base url. let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules( - css, url_data, existing.origin, &mut namespaces, + css, url_data, existing.origin, &namespaces, &existing.shared_lock, stylesheet_loader, error_reporter, existing.quirks_mode, line_number_offset); - *existing.namespaces.write() = namespaces; + mem::swap(&mut *existing.namespaces.write(), &mut *namespaces.write()); existing.dirty_on_viewport_size_change .store(dirty_on_viewport_size_change, Ordering::Release); @@ -1229,7 +1228,7 @@ impl Stylesheet { fn parse_rules(css: &str, url_data: &UrlExtraData, origin: Origin, - namespaces: &mut Namespaces, + namespaces: &RwLock, shared_lock: &SharedRwLock, stylesheet_loader: Option<&StylesheetLoader>, error_reporter: &ParseErrorReporter, @@ -1238,14 +1237,15 @@ impl Stylesheet { -> (Vec, bool) { let mut rules = Vec::new(); let mut input = Parser::new(css); + let mut context = ParserContext::new_with_line_number_offset(origin, url_data, error_reporter, + line_number_offset, PARSING_MODE_DEFAULT, + quirks_mode); + context.namespaces = Some(namespaces); let rule_parser = TopLevelRuleParser { stylesheet_origin: origin, - namespaces: namespaces, shared_lock: shared_lock, loader: stylesheet_loader, - context: ParserContext::new_with_line_number_offset(origin, url_data, error_reporter, - line_number_offset, PARSING_MODE_DEFAULT, - quirks_mode), + context: context, state: Cell::new(State::Start), }; @@ -1283,15 +1283,15 @@ impl Stylesheet { quirks_mode: QuirksMode, line_number_offset: u64) -> Stylesheet { - let mut namespaces = Namespaces::default(); + let namespaces = RwLock::new(Namespaces::default()); let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules( - css, &url_data, origin, &mut namespaces, + css, &url_data, origin, &namespaces, &shared_lock, stylesheet_loader, error_reporter, quirks_mode, line_number_offset, ); Stylesheet { origin: origin, url_data: url_data, - namespaces: RwLock::new(namespaces), + namespaces: namespaces, rules: CssRules::new(rules, &shared_lock), media: media, shared_lock: shared_lock, @@ -1470,7 +1470,6 @@ impl StylesheetLoader for NoOpLoader { struct TopLevelRuleParser<'a> { stylesheet_origin: Origin, - namespaces: &'a mut Namespaces, shared_lock: &'a SharedRwLock, loader: Option<&'a StylesheetLoader>, context: ParserContext<'a>, @@ -1483,7 +1482,6 @@ impl<'b> TopLevelRuleParser<'b> { stylesheet_origin: self.stylesheet_origin, shared_lock: self.shared_lock, context: &self.context, - namespaces: self.namespaces, } } } @@ -1588,10 +1586,12 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> { let opt_prefix = if let Ok(prefix) = prefix_result { let prefix = Prefix::from(prefix); - self.namespaces.prefixes.insert(prefix.clone(), url.clone()); + self.context.namespaces.expect("namespaces must be set whilst parsing rules") + .write().prefixes.insert(prefix.clone(), url.clone()); Some(prefix) } else { - self.namespaces.default = Some(url.clone()); + self.context.namespaces.expect("namespaces must be set whilst parsing rules") + .write().default = Some(url.clone()); None }; @@ -1650,7 +1650,6 @@ struct NestedRuleParser<'a, 'b: 'a> { stylesheet_origin: Origin, shared_lock: &'a SharedRwLock, context: &'a ParserContext<'b>, - namespaces: &'b Namespaces, } impl<'a, 'b> NestedRuleParser<'a, 'b> { @@ -1660,7 +1659,6 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> { stylesheet_origin: self.stylesheet_origin, shared_lock: self.shared_lock, context: &context, - namespaces: self.namespaces, }; let mut iter = RuleListParser::new_for_nested_rule(input, nested_parser); let mut rules = Vec::new(); @@ -1836,9 +1834,10 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> { type QualifiedRule = CssRule; fn parse_prelude(&mut self, input: &mut Parser) -> Result, ()> { + let ns = self.context.namespaces.expect("namespaces must be set when parsing rules").read(); let selector_parser = SelectorParser { stylesheet_origin: self.stylesheet_origin, - namespaces: self.namespaces, + namespaces: &*ns, }; SelectorList::parse(&selector_parser, input) }