diff options
-rw-r--r-- | components/style/media_queries.rs | 4 | ||||
-rw-r--r-- | components/style/stylesheets.rs | 121 |
2 files changed, 92 insertions, 33 deletions
diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs index 9bdfcfc748d..a450995c565 100644 --- a/components/style/media_queries.rs +++ b/components/style/media_queries.rs @@ -297,4 +297,8 @@ impl MediaList { } }) } + + pub fn is_empty(&self) -> bool { + self.media_queries.is_empty() + } } diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 1933d98e583..1689953ba8a 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -56,6 +56,12 @@ pub struct Namespaces { #[derive(Debug)] pub struct CssRules(pub Vec<CssRule>); +impl CssRules { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + pub enum RulesMutateError { Syntax, IndexSize, @@ -106,8 +112,9 @@ impl CssRules { // Step 3, 4 // XXXManishearth should we also store the namespace map? - let (new_rule, new_state) = try!(CssRule::parse(&rule, parent_stylesheet, - ParserContextExtraData::default(), state)); + let (new_rule, new_state) = + try!(CssRule::parse(&rule, parent_stylesheet, + ParserContextExtraData::default(), state)); // Step 5 // Computes the maximum allowed parser state at a given index. @@ -464,54 +471,102 @@ impl Stylesheet { environment_encoding: Option<EncodingRef>, origin: Origin, media: MediaList, + stylesheet_loader: Option<&StylesheetLoader>, error_reporter: Box<ParseErrorReporter + Send>, extra_data: ParserContextExtraData) -> Stylesheet { let (string, _) = decode_stylesheet_bytes( bytes, protocol_encoding_label, environment_encoding); - Stylesheet::from_str(&string, base_url, origin, media, error_reporter, extra_data) + Stylesheet::from_str(&string, + base_url, + origin, + media, + stylesheet_loader, + error_reporter, + extra_data) + } + + pub fn update_from_bytes(existing: &Stylesheet, + bytes: &[u8], + protocol_encoding_label: Option<&str>, + environment_encoding: Option<EncodingRef>, + stylesheet_loader: Option<&StylesheetLoader>, + error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) { + assert!(existing.rules.read().is_empty()); + let (string, _) = decode_stylesheet_bytes( + bytes, protocol_encoding_label, environment_encoding); + Self::update_from_str(existing, + &string, + stylesheet_loader, + error_reporter, + extra_data) } - pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin, media: MediaList, - error_reporter: Box<ParseErrorReporter + Send>, - extra_data: ParserContextExtraData) -> Stylesheet { - let mut namespaces = Namespaces::default(); - let mut rules = vec![]; - let dirty_on_viewport_size_change; + pub fn update_from_str(existing: &Stylesheet, + css: &str, + stylesheet_loader: Option<&StylesheetLoader>, + error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) { + let mut rules = existing.rules.write(); + let mut namespaces = existing.namespaces.write(); + + assert!(rules.is_empty()); + + let mut input = Parser::new(css); + let rule_parser = TopLevelRuleParser { + stylesheet_origin: existing.origin, + namespaces: &mut namespaces, + loader: stylesheet_loader, + context: ParserContext::new_with_extra_data(existing.origin, + &existing.base_url, + error_reporter, + extra_data), + state: Cell::new(State::Start), + }; + + input.look_for_viewport_percentages(); + { - let rule_parser = TopLevelRuleParser { - stylesheet_origin: origin, - namespaces: &mut namespaces, - context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter, extra_data), - state: Cell::new(State::Start), - }; - let mut input = Parser::new(css); - input.look_for_viewport_percentages(); - { - let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser); - while let Some(result) = iter.next() { - match result { - Ok(rule) => rules.push(rule), - Err(range) => { - let pos = range.start; - let message = format!("Invalid rule: '{}'", iter.input.slice(range)); - log_css_error(iter.input, pos, &*message, &iter.parser.context); - } + let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser); + while let Some(result) = iter.next() { + match result { + Ok(rule) => rules.0.push(rule), + Err(range) => { + let pos = range.start; + let message = format!("Invalid rule: '{}'", iter.input.slice(range)); + log_css_error(iter.input, pos, &*message, &iter.parser.context); } } } - dirty_on_viewport_size_change = input.seen_viewport_percentages(); } - Stylesheet { + existing.dirty_on_viewport_size_change + .store(input.seen_viewport_percentages(), Ordering::Release); + } + + pub fn from_str(css: &str, base_url: ServoUrl, origin: Origin, + media: MediaList, + stylesheet_loader: Option<&StylesheetLoader>, + error_reporter: Box<ParseErrorReporter + Send>, + extra_data: ParserContextExtraData) -> Stylesheet { + let s = Stylesheet { origin: origin, base_url: base_url, - namespaces: RwLock::new(namespaces), - rules: CssRules::new(rules), + namespaces: RwLock::new(Namespaces::default()), + rules: CssRules::new(vec![]), media: Arc::new(RwLock::new(media)), - dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change), + dirty_on_viewport_size_change: AtomicBool::new(false), disabled: AtomicBool::new(false), - } + }; + + Self::update_from_str(&s, + css, + stylesheet_loader, + error_reporter, + extra_data); + + s } pub fn dirty_on_viewport_size_change(&self) -> bool { |