style: Cleanup ParserContext::new_with_rule_type.

This commit is contained in:
Emilio Cobos Álvarez 2017-08-18 15:24:39 +02:00
parent 4763d05cf0
commit a962c54928
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
8 changed files with 118 additions and 40 deletions

View file

@ -36,9 +36,13 @@ impl CSS {
decl.push_str(&value); decl.push_str(&value);
let decl = Declaration(decl); let decl = Declaration(decl);
let url = win.Document().url(); let url = win.Document().url();
let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports), let context = ParserContext::new_for_cssom(
PARSING_MODE_DEFAULT, &url,
QuirksMode::NoQuirks); win.css_error_reporter(),
Some(CssRuleType::Style),
PARSING_MODE_DEFAULT,
QuirksMode::NoQuirks
);
decl.eval(&context) decl.eval(&context)
} }
@ -49,9 +53,13 @@ impl CSS {
let cond = parse_condition_or_declaration(&mut input); let cond = parse_condition_or_declaration(&mut input);
if let Ok(cond) = cond { if let Ok(cond) = cond {
let url = win.Document().url(); let url = win.Document().url();
let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports), let context = ParserContext::new_for_cssom(
PARSING_MODE_DEFAULT, &url,
QuirksMode::NoQuirks); win.css_error_reporter(),
Some(CssRuleType::Style),
PARSING_MODE_DEFAULT,
QuirksMode::NoQuirks
);
cond.eval(&context) cond.eval(&context)
} else { } else {
false false

View file

@ -102,17 +102,18 @@ impl<'a> ParserContext<'a> {
/// Create a parser context based on a previous context, but with a modified rule type. /// Create a parser context based on a previous context, but with a modified rule type.
pub fn new_with_rule_type( pub fn new_with_rule_type(
context: &'a ParserContext, context: &'a ParserContext,
rule_type: Option<CssRuleType> rule_type: CssRuleType,
namespaces: &'a Namespaces,
) -> ParserContext<'a> { ) -> ParserContext<'a> {
ParserContext { ParserContext {
stylesheet_origin: context.stylesheet_origin, stylesheet_origin: context.stylesheet_origin,
url_data: context.url_data, url_data: context.url_data,
error_reporter: context.error_reporter, error_reporter: context.error_reporter,
rule_type: rule_type, rule_type: Some(rule_type),
line_number_offset: context.line_number_offset, line_number_offset: context.line_number_offset,
parsing_mode: context.parsing_mode, parsing_mode: context.parsing_mode,
quirks_mode: context.quirks_mode, quirks_mode: context.quirks_mode,
namespaces: context.namespaces, namespaces: Some(namespaces),
} }
} }

View file

@ -322,14 +322,17 @@ macro_rules! font_feature_values_blocks {
} }
} }
fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>) fn parse_block<'t>(
-> Result<Self::AtRule, ParseError<'i>> { &mut self,
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFeatureValues)); prelude: Self::Prelude,
input: &mut Parser<'i, 't>
) -> Result<Self::AtRule, ParseError<'i>> {
debug_assert_eq!(self.context.rule_type(), CssRuleType::FontFeatureValues);
match prelude { match prelude {
$( $(
BlockType::$ident_camel => { BlockType::$ident_camel => {
let parser = FFVDeclarationsParser { let parser = FFVDeclarationsParser {
context: &context, context: &self.context,
declarations: &mut self.rule.$ident, declarations: &mut self.rule.$ident,
}; };
@ -338,7 +341,7 @@ macro_rules! font_feature_values_blocks {
if let Err(err) = declaration { if let Err(err) = declaration {
let error = ContextualParseError::UnsupportedKeyframePropertyDeclaration( let error = ContextualParseError::UnsupportedKeyframePropertyDeclaration(
err.slice, err.error); err.slice, err.error);
context.log_css_error(err.location, error); self.context.log_css_error(err.location, error);
} }
} }
}, },

View file

@ -450,8 +450,14 @@ struct KeyframeListParser<'a> {
} }
/// Parses a keyframe list from CSS input. /// Parses a keyframe list from CSS input.
pub fn parse_keyframe_list(context: &ParserContext, input: &mut Parser, shared_lock: &SharedRwLock) pub fn parse_keyframe_list(
-> Vec<Arc<Locked<Keyframe>>> { context: &ParserContext,
input: &mut Parser,
shared_lock: &SharedRwLock
) -> Vec<Arc<Locked<Keyframe>>> {
debug_assert!(context.namespaces.is_some(),
"Parsing a keyframe list from a context without namespaces?");
let mut declarations = SourcePropertyDeclaration::new(); let mut declarations = SourcePropertyDeclaration::new();
RuleListParser::new_for_nested_rule(input, KeyframeListParser { RuleListParser::new_for_nested_rule(input, KeyframeListParser {
context: context, context: context,
@ -487,7 +493,13 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>) fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>)
-> Result<Self::QualifiedRule, ParseError<'i>> { -> Result<Self::QualifiedRule, ParseError<'i>> {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframe)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::Keyframe,
self.context.namespaces.unwrap(),
);
let parser = KeyframeDeclarationParser { let parser = KeyframeDeclarationParser {
context: &context, context: &context,
declarations: self.declarations, declarations: self.declarations,

View file

@ -134,7 +134,7 @@ impl MallocSizeOfWithGuard for CssRule {
} }
#[allow(missing_docs)] #[allow(missing_docs)]
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum CssRuleType { pub enum CssRuleType {
// https://drafts.csswg.org/cssom/#the-cssrule-interface // https://drafts.csswg.org/cssom/#the-cssrule-interface
Style = 1, Style = 1,

View file

@ -44,9 +44,8 @@ pub struct TopLevelRuleParser<'a> {
pub loader: Option<&'a StylesheetLoader>, pub loader: Option<&'a StylesheetLoader>,
/// The top-level parser context. /// The top-level parser context.
/// ///
/// This won't contain any namespaces, and will only be filled right because /// This won't contain any namespaces, and only nested parsers created with
/// parsing style rules, on the assumption that they're the only rules that /// `ParserContext::new_with_rule_type` will.
/// need them.
pub context: ParserContext<'a>, pub context: ParserContext<'a>,
/// The current state of the parser. /// The current state of the parser.
pub state: State, pub state: State,
@ -295,10 +294,8 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> {
input: &mut Parser, input: &mut Parser,
rule_type: CssRuleType rule_type: CssRuleType
) -> Arc<Locked<CssRules>> { ) -> Arc<Locked<CssRules>> {
let context = ParserContext::new_with_rule_type( let context =
self.context, ParserContext::new_with_rule_type(self.context, rule_type, self.namespaces);
Some(rule_type),
);
let nested_parser = NestedRuleParser { let nested_parser = NestedRuleParser {
stylesheet_origin: self.stylesheet_origin, stylesheet_origin: self.stylesheet_origin,
@ -423,17 +420,33 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
) -> Result<CssRule, ParseError<'i>> { ) -> Result<CssRule, ParseError<'i>> {
match prelude { match prelude {
AtRulePrelude::FontFace(location) => { AtRulePrelude::FontFace(location) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFace)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::FontFace,
self.namespaces,
);
Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap( Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap(
parse_font_face_block(&context, input, location).into())))) parse_font_face_block(&context, input, location).into()))))
} }
AtRulePrelude::FontFeatureValues(family_names, location) => { AtRulePrelude::FontFeatureValues(family_names, location) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFeatureValues)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::FontFeatureValues,
self.namespaces,
);
Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap( Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap(
FontFeatureValuesRule::parse(&context, input, family_names, location))))) FontFeatureValuesRule::parse(&context, input, family_names, location)))))
} }
AtRulePrelude::CounterStyle(name) => { AtRulePrelude::CounterStyle(name) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::CounterStyle)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::CounterStyle,
self.namespaces,
);
Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap( Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap(
parse_counter_style_body(name, &context, input)?.into())))) parse_counter_style_body(name, &context, input)?.into()))))
} }
@ -445,7 +458,13 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
})))) }))))
} }
AtRulePrelude::Supports(cond, location) => { AtRulePrelude::Supports(cond, location) => {
let enabled = cond.eval(self.context); let eval_context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::Style,
self.namespaces,
);
let enabled = cond.eval(&eval_context);
Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(SupportsRule { Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(SupportsRule {
condition: cond, condition: cond,
rules: self.parse_nested_rules(input, CssRuleType::Supports), rules: self.parse_nested_rules(input, CssRuleType::Supports),
@ -454,12 +473,23 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
})))) }))))
} }
AtRulePrelude::Viewport => { AtRulePrelude::Viewport => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Viewport)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::Viewport,
self.namespaces,
);
Ok(CssRule::Viewport(Arc::new(self.shared_lock.wrap( Ok(CssRule::Viewport(Arc::new(self.shared_lock.wrap(
ViewportRule::parse(&context, input)?)))) ViewportRule::parse(&context, input)?))))
} }
AtRulePrelude::Keyframes(name, prefix, location) => { AtRulePrelude::Keyframes(name, prefix, location) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframes)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::Keyframes,
self.namespaces,
);
Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap(KeyframesRule { Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap(KeyframesRule {
name: name, name: name,
keyframes: parse_keyframe_list(&context, input, self.shared_lock), keyframes: parse_keyframe_list(&context, input, self.shared_lock),
@ -468,7 +498,12 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
})))) }))))
} }
AtRulePrelude::Page(location) => { AtRulePrelude::Page(location) => {
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Page)); let context =
ParserContext::new_with_rule_type(
self.context,
CssRuleType::Page,
self.namespaces,
);
let declarations = parse_property_declaration_list(&context, input); let declarations = parse_property_declaration_list(&context, input);
Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule { Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule {
block: Arc::new(self.shared_lock.wrap(declarations)), block: Arc::new(self.shared_lock.wrap(declarations)),
@ -520,8 +555,12 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
prelude: QualifiedRuleParserPrelude, prelude: QualifiedRuleParserPrelude,
input: &mut Parser<'i, 't> input: &mut Parser<'i, 't>
) -> Result<CssRule, ParseError<'i>> { ) -> Result<CssRule, ParseError<'i>> {
let mut context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style)); let context =
context.namespaces = Some(self.namespaces); ParserContext::new_with_rule_type(
self.context,
CssRuleType::Style,
self.namespaces,
);
let declarations = parse_property_declaration_list(&context, input); let declarations = parse_property_declaration_list(&context, input);
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule { Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
selectors: prelude.selectors, selectors: prelude.selectors,

View file

@ -241,16 +241,19 @@ impl Declaration {
/// Determine if a declaration parses /// Determine if a declaration parses
/// ///
/// https://drafts.csswg.org/css-conditional-3/#support-definition /// https://drafts.csswg.org/css-conditional-3/#support-definition
pub fn eval(&self, cx: &ParserContext) -> bool { pub fn eval(&self, context: &ParserContext) -> bool {
debug_assert_eq!(context.rule_type(), CssRuleType::Style);
let mut input = ParserInput::new(&self.0); let mut input = ParserInput::new(&self.0);
let mut input = Parser::new(&mut input); let mut input = Parser::new(&mut input);
input.parse_entirely(|input| { input.parse_entirely(|input| {
let prop = input.expect_ident().unwrap().as_ref().to_owned(); let prop = input.expect_ident().unwrap().as_ref().to_owned();
input.expect_colon().unwrap(); input.expect_colon().unwrap();
let context = ParserContext::new_with_rule_type(cx, Some(CssRuleType::Style));
let property_context = PropertyParserContext::new(&context); let property_context = PropertyParserContext::new(&context);
let id = PropertyId::parse(&prop, Some(&property_context)) let id = PropertyId::parse(&prop, Some(&property_context))
.map_err(|_| StyleParseError::UnspecifiedError)?; .map_err(|_| StyleParseError::UnspecifiedError)?;
let mut declarations = SourcePropertyDeclaration::new(); let mut declarations = SourcePropertyDeclaration::new();
input.parse_until_before(Delimiter::Bang, |input| { input.parse_until_before(Delimiter::Bang, |input| {
PropertyDeclaration::parse_into(&mut declarations, id, &context, input) PropertyDeclaration::parse_into(&mut declarations, id, &context, input)

View file

@ -1508,6 +1508,11 @@ pub extern "C" fn Servo_KeyframesRule_AppendRule(
let css = unsafe { css.as_ref().unwrap().as_str_unchecked() }; let css = unsafe { css.as_ref().unwrap().as_str_unchecked() };
let contents = StylesheetContents::as_arc(&contents); let contents = StylesheetContents::as_arc(&contents);
let global_style_data = &*GLOBAL_STYLE_DATA; let global_style_data = &*GLOBAL_STYLE_DATA;
// FIXME(emilio): What happens with namespaces here?
//
// We seem to ignore it, but someone could still set content: attr(..) from
// a declaration inside the keyframe block.
match Keyframe::parse(css, &contents, &global_style_data.shared_lock) { match Keyframe::parse(css, &contents, &global_style_data.shared_lock) {
Ok(keyframe) => { Ok(keyframe) => {
write_locked_arc(rule, |rule: &mut KeyframesRule| { write_locked_arc(rule, |rule: &mut KeyframesRule| {
@ -2811,9 +2816,16 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
if let Ok(cond) = cond { if let Ok(cond) = cond {
let url_data = unsafe { dummy_url_data() }; let url_data = unsafe { dummy_url_data() };
let reporter = NullReporter; let reporter = NullReporter;
let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Style), // NOTE(emilio): The supports API is not associated to any stylesheet,
PARSING_MODE_DEFAULT, // so the fact that there are no namespace map here is fine.
QuirksMode::NoQuirks); let context =
ParserContext::new_for_cssom(
url_data,
&reporter,
Some(CssRuleType::Style),
PARSING_MODE_DEFAULT,
QuirksMode::NoQuirks,
);
cond.eval(&context) cond.eval(&context)
} else { } else {
false false