aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-06-02 13:40:26 +0200
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-06-02 14:38:05 +0200
commitbbd85ccbda2ced5994205a4362cca92b7e4837ab (patch)
tree0262b3542c7972820eb11430b2fe118b00d33ab0
parent26ef0f6178341d7155ac0d3bb2654f2f613bdee1 (diff)
downloadservo-bbd85ccbda2ced5994205a4362cca92b7e4837ab.tar.gz
servo-bbd85ccbda2ced5994205a4362cca92b7e4837ab.zip
style: Simplify the namespace setup for stylesheet parsing.
-rw-r--r--components/style/parser.rs40
-rw-r--r--components/style/stylesheets.rs170
-rw-r--r--components/style/values/specified/mod.rs24
3 files changed, 156 insertions, 78 deletions
diff --git a/components/style/parser.rs b/components/style/parser.rs
index cad388651f9..162c690c87c 100644
--- a/components/style/parser.rs
+++ b/components/style/parser.rs
@@ -7,7 +7,6 @@
use context::QuirksMode;
use cssparser::{Parser, SourcePosition, UnicodeRange};
use error_reporting::ParseErrorReporter;
-use parking_lot::RwLock;
use style_traits::OneOrMoreCommaSeparated;
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
@@ -82,8 +81,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<Namespaces>>,
+ /// The currently active namespaces.
+ pub namespaces: Option<&'a Namespaces>,
}
impl<'a> ParserContext<'a> {
@@ -108,19 +107,21 @@ impl<'a> ParserContext<'a> {
}
/// Create a parser context for on-the-fly parsing in CSSOM
- pub fn new_for_cssom(url_data: &'a UrlExtraData,
- error_reporter: &'a ParseErrorReporter,
- rule_type: Option<CssRuleType>,
- parsing_mode: ParsingMode,
- quirks_mode: QuirksMode)
- -> ParserContext<'a> {
+ pub fn new_for_cssom(
+ url_data: &'a UrlExtraData,
+ error_reporter: &'a ParseErrorReporter,
+ rule_type: Option<CssRuleType>,
+ parsing_mode: ParsingMode,
+ quirks_mode: QuirksMode
+ ) -> ParserContext<'a> {
Self::new(Origin::Author, url_data, error_reporter, rule_type, parsing_mode, quirks_mode)
}
/// Create a parser context based on a previous context, but with a modified rule type.
- pub fn new_with_rule_type(context: &'a ParserContext,
- rule_type: Option<CssRuleType>)
- -> ParserContext<'a> {
+ pub fn new_with_rule_type(
+ context: &'a ParserContext,
+ rule_type: Option<CssRuleType>
+ ) -> ParserContext<'a> {
ParserContext {
stylesheet_origin: context.stylesheet_origin,
url_data: context.url_data,
@@ -134,13 +135,14 @@ impl<'a> ParserContext<'a> {
}
/// Create a parser context for inline CSS which accepts additional line offset argument.
- pub fn new_with_line_number_offset(stylesheet_origin: Origin,
- url_data: &'a UrlExtraData,
- error_reporter: &'a ParseErrorReporter,
- line_number_offset: u64,
- parsing_mode: ParsingMode,
- quirks_mode: QuirksMode)
- -> ParserContext<'a> {
+ pub fn new_with_line_number_offset(
+ stylesheet_origin: Origin,
+ url_data: &'a UrlExtraData,
+ error_reporter: &'a ParseErrorReporter,
+ line_number_offset: u64,
+ parsing_mode: ParsingMode,
+ quirks_mode: QuirksMode
+ ) -> ParserContext<'a> {
ParserContext {
stylesheet_origin: stylesheet_origin,
url_data: url_data,
diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs
index 1f3345b0810..6347e39f0e9 100644
--- a/components/style/stylesheets.rs
+++ b/components/style/stylesheets.rs
@@ -478,15 +478,19 @@ impl CssRule {
loader: Option<&StylesheetLoader>)
-> Result<(Self, State), SingleRuleParseError> {
let error_reporter = NullReporter;
- 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 context = ParserContext::new(
+ parent_stylesheet.origin,
+ &parent_stylesheet.url_data,
+ &error_reporter,
+ None,
+ PARSING_MODE_DEFAULT,
+ parent_stylesheet.quirks_mode
+ );
+
let mut input = Parser::new(css);
+ let mut guard = parent_stylesheet.namespaces.write();
+
// nested rules are in the body state
let state = state.unwrap_or(State::Body);
let mut rule_parser = TopLevelRuleParser {
@@ -495,6 +499,7 @@ impl CssRule {
shared_lock: &parent_stylesheet.shared_lock,
loader: loader,
state: state,
+ namespaces: Some(&mut *guard),
};
match parse_one_rule(&mut input, &mut rule_parser) {
Ok(result) => Ok((result, rule_parser.state)),
@@ -509,8 +514,10 @@ impl CssRule {
}
/// Deep clones this CssRule.
- fn deep_clone_with_lock(&self,
- lock: &SharedRwLock) -> CssRule {
+ fn deep_clone_with_lock(
+ &self,
+ lock: &SharedRwLock
+ ) -> CssRule {
let guard = lock.read();
match *self {
CssRule::Namespace(ref arc) => {
@@ -1214,10 +1221,19 @@ impl Stylesheet {
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, &namespaces,
- &existing.shared_lock, stylesheet_loader, error_reporter,
- existing.quirks_mode, line_number_offset);
+ let (rules, dirty_on_viewport_size_change) =
+ Stylesheet::parse_rules(
+ css,
+ url_data,
+ existing.origin,
+ &mut *namespaces.write(),
+ &existing.shared_lock,
+ stylesheet_loader,
+ error_reporter,
+ existing.quirks_mode,
+ line_number_offset
+ );
+
mem::swap(&mut *existing.namespaces.write(), &mut *namespaces.write());
existing.dirty_on_viewport_size_change
.store(dirty_on_viewport_size_change, Ordering::Release);
@@ -1227,35 +1243,45 @@ impl Stylesheet {
*existing.rules.write_with(&mut guard) = CssRules(rules);
}
- fn parse_rules(css: &str,
- url_data: &UrlExtraData,
- origin: Origin,
- namespaces: &RwLock<Namespaces>,
- shared_lock: &SharedRwLock,
- stylesheet_loader: Option<&StylesheetLoader>,
- error_reporter: &ParseErrorReporter,
- quirks_mode: QuirksMode,
- line_number_offset: u64)
- -> (Vec<CssRule>, bool) {
+ fn parse_rules(
+ css: &str,
+ url_data: &UrlExtraData,
+ origin: Origin,
+ namespaces: &mut Namespaces,
+ shared_lock: &SharedRwLock,
+ stylesheet_loader: Option<&StylesheetLoader>,
+ error_reporter: &ParseErrorReporter,
+ quirks_mode: QuirksMode,
+ line_number_offset: u64
+ ) -> (Vec<CssRule>, 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 context =
+ ParserContext::new_with_line_number_offset(
+ origin,
+ url_data,
+ error_reporter,
+ line_number_offset,
+ PARSING_MODE_DEFAULT,
+ quirks_mode
+ );
+
let rule_parser = TopLevelRuleParser {
stylesheet_origin: origin,
shared_lock: shared_lock,
loader: stylesheet_loader,
context: context,
state: State::Start,
+ namespaces: Some(namespaces),
};
input.look_for_viewport_percentages();
{
- let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
+ let mut iter =
+ RuleListParser::new_for_stylesheet(&mut input, rule_parser);
+
while let Some(result) = iter.next() {
match result {
Ok(rule) => rules.push(rule),
@@ -1288,9 +1314,17 @@ impl Stylesheet {
-> Stylesheet {
let namespaces = RwLock::new(Namespaces::default());
let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules(
- css, &url_data, origin, &namespaces,
- &shared_lock, stylesheet_loader, error_reporter, quirks_mode, line_number_offset,
+ css,
+ &url_data,
+ origin,
+ &mut *namespaces.write(),
+ &shared_lock,
+ stylesheet_loader,
+ error_reporter,
+ quirks_mode,
+ line_number_offset,
);
+
Stylesheet {
origin: origin,
url_data: url_data,
@@ -1477,6 +1511,7 @@ struct TopLevelRuleParser<'a> {
loader: Option<&'a StylesheetLoader>,
context: ParserContext<'a>,
state: State,
+ namespaces: Option<&'a mut Namespaces>,
}
impl<'b> TopLevelRuleParser<'b> {
@@ -1548,8 +1583,11 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
type Prelude = AtRulePrelude;
type AtRule = CssRule;
- fn parse_prelude(&mut self, name: &str, input: &mut Parser)
- -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
+ fn parse_prelude(
+ &mut self,
+ name: &str,
+ input: &mut Parser
+ ) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
let location = get_location_with_offset(input.current_source_location(),
self.context.line_number_offset);
match_ignore_ascii_case! { name,
@@ -1608,14 +1646,16 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
let id = register_namespace(&url)?;
+ let mut namespaces = self.namespaces.as_mut().unwrap();
+
let opt_prefix = if let Ok(prefix) = prefix_result {
let prefix = Prefix::from(prefix);
- self.context.namespaces.expect("namespaces must be set whilst parsing rules")
- .write().prefixes.insert(prefix.clone(), (url.clone(), id));
+ namespaces
+ .prefixes
+ .insert(prefix.clone(), (url.clone(), id));
Some(prefix)
} else {
- self.context.namespaces.expect("namespaces must be set whilst parsing rules")
- .write().default = Some((url.clone(), id));
+ namespaces.default = Some((url.clone(), id));
None
};
@@ -1638,6 +1678,13 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
return Err(());
}
self.state = State::Body;
+
+ // "Freeze" the namespace map (no more namespace rules can be parsed
+ // after this point), and stick it in the context.
+ if self.namespaces.is_some() {
+ let namespaces = &*self.namespaces.take().unwrap();
+ self.context.namespaces = Some(namespaces);
+ }
AtRuleParser::parse_prelude(&mut self.nested(), name, input)
}
@@ -1655,12 +1702,23 @@ impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
#[inline]
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
self.state = State::Body;
+
+ // "Freeze" the namespace map (no more namespace rules can be parsed
+ // after this point), and stick it in the context.
+ if self.namespaces.is_some() {
+ let namespaces = &*self.namespaces.take().unwrap();
+ self.context.namespaces = Some(namespaces);
+ }
+
QualifiedRuleParser::parse_prelude(&mut self.nested(), input)
}
#[inline]
- fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
- -> Result<CssRule, ()> {
+ fn parse_block(
+ &mut self,
+ prelude: SelectorList<SelectorImpl>,
+ input: &mut Parser
+ ) -> Result<CssRule, ()> {
QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
}
}
@@ -1673,13 +1731,19 @@ struct NestedRuleParser<'a, 'b: 'a> {
}
impl<'a, 'b> NestedRuleParser<'a, 'b> {
- fn parse_nested_rules(&self, input: &mut Parser, rule_type: CssRuleType) -> Arc<Locked<CssRules>> {
+ fn parse_nested_rules(
+ &mut self,
+ input: &mut Parser,
+ rule_type: CssRuleType
+ ) -> Arc<Locked<CssRules>> {
let context = ParserContext::new_with_rule_type(self.context, Some(rule_type));
+
let nested_parser = NestedRuleParser {
stylesheet_origin: self.stylesheet_origin,
shared_lock: self.shared_lock,
context: &context,
};
+
let mut iter = RuleListParser::new_for_nested_rule(input, nested_parser);
let mut rules = Vec::new();
while let Some(result) = iter.next() {
@@ -1710,10 +1774,17 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
type Prelude = AtRulePrelude;
type AtRule = CssRule;
- fn parse_prelude(&mut self, name: &str, input: &mut Parser)
- -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
- let location = get_location_with_offset(input.current_source_location(),
- self.context.line_number_offset);
+ fn parse_prelude(
+ &mut self,
+ name: &str,
+ input: &mut Parser
+ ) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
+ let location =
+ get_location_with_offset(
+ input.current_source_location(),
+ self.context.line_number_offset
+ );
+
match_ignore_ascii_case! { name,
"media" => {
let media_queries = parse_media_query_list(self.context, input);
@@ -1854,16 +1925,19 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
type QualifiedRule = CssRule;
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
- let ns = self.context.namespaces.expect("namespaces must be set when parsing rules").read();
let selector_parser = SelectorParser {
stylesheet_origin: self.stylesheet_origin,
- namespaces: &*ns,
+ namespaces: self.context.namespaces.unwrap(),
};
+
SelectorList::parse(&selector_parser, input)
}
- fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
- -> Result<CssRule, ()> {
+ fn parse_block(
+ &mut self,
+ prelude: SelectorList<SelectorImpl>,
+ input: &mut Parser
+ ) -> Result<CssRule, ()> {
let location = get_location_with_offset(input.current_source_location(),
self.context.line_number_offset);
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style));
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 0131bdb5f28..877040bfd33 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -1396,23 +1396,25 @@ impl Parse for Attr {
#[cfg(feature = "gecko")]
/// Get the namespace id from the namespace map
-pub fn get_id_for_namespace(namespace: &Namespace, context: &ParserContext) -> Result<NamespaceId, ()> {
- if let Some(map) = context.namespaces {
- if let Some(ref entry) = map.read().prefixes.get(&namespace.0) {
- Ok(entry.1)
- } else {
- Err(())
+fn get_id_for_namespace(namespace: &Namespace, context: &ParserContext) -> Result<NamespaceId, ()> {
+ let namespaces_map = match context.namespaces {
+ Some(map) => map,
+ None => {
+ // If we don't have a namespace map (e.g. in inline styles)
+ // we can't parse namespaces
+ return Err(());
}
- } else {
- // if we don't have a namespace map (e.g. in inline styles)
- // we can't parse namespaces
- Err(())
+ };
+
+ match namespaces_map.prefixes.get(&namespace.0) {
+ Some(entry) => Ok(entry.1),
+ None => Err(()),
}
}
#[cfg(feature = "servo")]
/// Get the namespace id from the namespace map
-pub fn get_id_for_namespace(_: &Namespace, _: &ParserContext) -> Result<NamespaceId, ()> {
+fn get_id_for_namespace(_: &Namespace, _: &ParserContext) -> Result<NamespaceId, ()> {
Ok(())
}