1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 //! Parsing of the stylesheet contents.
6 
7 use {Namespace, Prefix};
8 use counter_style::{parse_counter_style_body, parse_counter_style_name_definition};
9 use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser};
10 use cssparser::{CowRcStr, SourceLocation, BasicParseError, BasicParseErrorKind};
11 use error_reporting::{ContextualParseError, ParseErrorReporter};
12 use font_face::parse_font_face_block;
13 use media_queries::{parse_media_query_list, MediaList};
14 use parser::{Parse, ParserContext, ParserErrorContext};
15 use properties::parse_property_declaration_list;
16 use selector_parser::{SelectorImpl, SelectorParser};
17 use selectors::SelectorList;
18 use servo_arc::Arc;
19 use shared_lock::{Locked, SharedRwLock};
20 use str::starts_with_ignore_ascii_case;
21 use style_traits::{StyleParseErrorKind, ParseError};
22 use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
23 use stylesheets::{DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule};
24 use stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule};
25 use stylesheets::document_rule::DocumentCondition;
26 use stylesheets::font_feature_values_rule::parse_family_name_list;
27 use stylesheets::keyframes_rule::parse_keyframe_list;
28 use stylesheets::stylesheet::Namespaces;
29 use stylesheets::supports_rule::SupportsCondition;
30 use stylesheets::viewport_rule;
31 use values::{CssUrl, CustomIdent, KeyframesName};
32 use values::computed::font::FamilyName;
33 
34 /// The parser for the top-level rules in a stylesheet.
35 pub struct TopLevelRuleParser<'a, R: 'a> {
36     /// The origin of the stylesheet we're parsing.
37     pub stylesheet_origin: Origin,
38     /// A reference to the lock we need to use to create rules.
39     pub shared_lock: &'a SharedRwLock,
40     /// A reference to a stylesheet loader if applicable, for `@import` rules.
41     pub loader: Option<&'a StylesheetLoader>,
42     /// The top-level parser context.
43     ///
44     /// This won't contain any namespaces, and only nested parsers created with
45     /// `ParserContext::new_with_rule_type` will.
46     pub context: ParserContext<'a>,
47     /// The context required for reporting parse errors.
48     pub error_context: ParserErrorContext<'a, R>,
49     /// The current state of the parser.
50     pub state: State,
51     /// Whether we have tried to parse was invalid due to being in the wrong
52     /// place (e.g. an @import rule was found while in the `Body` state). Reset
53     /// to `false` when `take_had_hierarchy_error` is called.
54     pub had_hierarchy_error: bool,
55     /// The namespace map we use for parsing. Needs to start as `Some()`, and
56     /// will be taken out after parsing namespace rules, and that reference will
57     /// be moved to `ParserContext`.
58     pub namespaces: &'a mut Namespaces,
59 }
60 
61 impl<'b, R> TopLevelRuleParser<'b, R> {
nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b, R>62     fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b, R> {
63         NestedRuleParser {
64             stylesheet_origin: self.stylesheet_origin,
65             shared_lock: self.shared_lock,
66             context: &self.context,
67             error_context: &self.error_context,
68             namespaces: &self.namespaces,
69         }
70     }
71 
72     /// Returns the current state of the parser.
state(&self) -> State73     pub fn state(&self) -> State {
74         self.state
75     }
76 
77     /// Returns whether we previously tried to parse a rule that was invalid
78     /// due to being in the wrong place (e.g. an @import rule was found after
79     /// a regular style rule).  The state of this flag is reset when this
80     /// function is called.
take_had_hierarchy_error(&mut self) -> bool81     pub fn take_had_hierarchy_error(&mut self) -> bool {
82         let had_hierarchy_error = self.had_hierarchy_error;
83         self.had_hierarchy_error = false;
84         had_hierarchy_error
85     }
86 }
87 
88 /// The current state of the parser.
89 #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
90 pub enum State {
91     /// We haven't started parsing rules.
92     Start = 1,
93     /// We're parsing `@import` rules.
94     Imports = 2,
95     /// We're parsing `@namespace` rules.
96     Namespaces = 3,
97     /// We're parsing the main body of the stylesheet.
98     Body = 4,
99 }
100 
101 #[derive(Clone, Debug, MallocSizeOf)]
102 /// Vendor prefix.
103 pub enum VendorPrefix {
104     /// -moz prefix.
105     Moz,
106     /// -webkit prefix.
107     WebKit,
108 }
109 
110 /// A rule prelude for at-rule with block.
111 pub enum AtRuleBlockPrelude {
112     /// A @font-face rule prelude.
113     FontFace(SourceLocation),
114     /// A @font-feature-values rule prelude, with its FamilyName list.
115     FontFeatureValues(Vec<FamilyName>, SourceLocation),
116     /// A @counter-style rule prelude, with its counter style name.
117     CounterStyle(CustomIdent),
118     /// A @media rule prelude, with its media queries.
119     Media(Arc<Locked<MediaList>>, SourceLocation),
120     /// An @supports rule, with its conditional
121     Supports(SupportsCondition, SourceLocation),
122     /// A @viewport rule prelude.
123     Viewport,
124     /// A @keyframes rule, with its animation name and vendor prefix if exists.
125     Keyframes(KeyframesName, Option<VendorPrefix>, SourceLocation),
126     /// A @page rule prelude.
127     Page(SourceLocation),
128     /// A @document rule, with its conditional.
129     Document(DocumentCondition, SourceLocation),
130 }
131 
132 /// A rule prelude for at-rule without block.
133 pub enum AtRuleNonBlockPrelude {
134     /// A @import rule prelude.
135     Import(CssUrl, Arc<Locked<MediaList>>, SourceLocation),
136     /// A @namespace rule prelude.
137     Namespace(Option<Prefix>, Namespace, SourceLocation),
138 }
139 
140 
141 #[cfg(feature = "gecko")]
register_namespace(ns: &Namespace) -> i32142 fn register_namespace(ns: &Namespace) -> i32 {
143     use gecko_bindings::bindings;
144     let id = unsafe { bindings::Gecko_RegisterNamespace(ns.0.as_ptr()) };
145     debug_assert!(id >= 0);
146     id
147 }
148 
149 #[cfg(feature = "servo")]
register_namespace(_: &Namespace)150 fn register_namespace(_: &Namespace) {
151     // servo doesn't use namespace ids
152 }
153 
154 impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a, R> {
155     type PreludeNoBlock = AtRuleNonBlockPrelude;
156     type PreludeBlock = AtRuleBlockPrelude;
157     type AtRule = CssRule;
158     type Error = StyleParseErrorKind<'i>;
159 
parse_prelude<'t>( &mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't> ) -> Result<AtRuleType<AtRuleNonBlockPrelude, AtRuleBlockPrelude>, ParseError<'i>>160     fn parse_prelude<'t>(
161         &mut self,
162         name: CowRcStr<'i>,
163         input: &mut Parser<'i, 't>
164     ) -> Result<AtRuleType<AtRuleNonBlockPrelude, AtRuleBlockPrelude>, ParseError<'i>> {
165         let location = input.current_source_location();
166         match_ignore_ascii_case! { &*name,
167             "import" => {
168                 if self.state > State::Imports {
169                     // "@import must be before any rule but @charset"
170                     self.had_hierarchy_error = true;
171                     return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedImportRule))
172                 }
173 
174                 let url_string = input.expect_url_or_string()?.as_ref().to_owned();
175                 let url = CssUrl::parse_from_string(url_string, &self.context)?;
176 
177                 let media = parse_media_query_list(&self.context, input,
178                                                    self.error_context.error_reporter);
179                 let media = Arc::new(self.shared_lock.wrap(media));
180 
181                 let prelude = AtRuleNonBlockPrelude::Import(url, media, location);
182                 return Ok(AtRuleType::WithoutBlock(prelude));
183             },
184             "namespace" => {
185                 if self.state > State::Namespaces {
186                     // "@namespace must be before any rule but @charset and @import"
187                     self.had_hierarchy_error = true;
188                     return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedNamespaceRule))
189                 }
190 
191                 let prefix = input.try(|i| i.expect_ident_cloned())
192                                   .map(|s| Prefix::from(s.as_ref())).ok();
193                 let maybe_namespace = match input.expect_url_or_string() {
194                     Ok(url_or_string) => url_or_string,
195                     Err(BasicParseError { kind: BasicParseErrorKind::UnexpectedToken(t), location }) => {
196                         return Err(location.new_custom_error(StyleParseErrorKind::UnexpectedTokenWithinNamespace(t)))
197                     }
198                     Err(e) => return Err(e.into()),
199                 };
200                 let url = Namespace::from(maybe_namespace.as_ref());
201                 let prelude = AtRuleNonBlockPrelude::Namespace(prefix, url, location);
202                 return Ok(AtRuleType::WithoutBlock(prelude));
203             },
204             // @charset is removed by rust-cssparser if it’s the first rule in the stylesheet
205             // anything left is invalid.
206             "charset" => {
207                 self.had_hierarchy_error = true;
208                 return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedCharsetRule))
209             }
210             _ => {}
211         }
212 
213         AtRuleParser::parse_prelude(&mut self.nested(), name, input)
214     }
215 
216     #[inline]
parse_block<'t>( &mut self, prelude: AtRuleBlockPrelude, input: &mut Parser<'i, 't> ) -> Result<CssRule, ParseError<'i>>217     fn parse_block<'t>(
218         &mut self,
219         prelude: AtRuleBlockPrelude,
220         input: &mut Parser<'i, 't>
221     ) -> Result<CssRule, ParseError<'i>> {
222         AtRuleParser::parse_block(&mut self.nested(), prelude, input)
223             .map(|rule| { self.state = State::Body; rule })
224     }
225 
226     #[inline]
rule_without_block(&mut self, prelude: AtRuleNonBlockPrelude) -> CssRule227     fn rule_without_block(&mut self, prelude: AtRuleNonBlockPrelude) -> CssRule {
228         match prelude {
229             AtRuleNonBlockPrelude::Import(url, media, location) => {
230                 let loader =
231                     self.loader.expect("Expected a stylesheet loader for @import");
232 
233                 let import_rule = loader.request_stylesheet(
234                     url,
235                     location,
236                     &self.context,
237                     &self.shared_lock,
238                     media,
239                 );
240 
241                 self.state = State::Imports;
242                 CssRule::Import(import_rule)
243             }
244             AtRuleNonBlockPrelude::Namespace(prefix, url, location) => {
245                 let id = register_namespace(&url);
246 
247                 let opt_prefix = if let Some(prefix) = prefix {
248                     self.namespaces
249                         .prefixes
250                         .insert(prefix.clone(), (url.clone(), id));
251                     Some(prefix)
252                 } else {
253                     self.namespaces.default = Some((url.clone(), id));
254                     None
255                 };
256 
257                 self.state = State::Namespaces;
258                 CssRule::Namespace(Arc::new(
259                     self.shared_lock.wrap(NamespaceRule {
260                         prefix: opt_prefix,
261                         url: url,
262                         source_location: location,
263                     })
264                 ))
265             }
266         }
267     }
268 }
269 
270 pub struct QualifiedRuleParserPrelude {
271     selectors: SelectorList<SelectorImpl>,
272     source_location: SourceLocation,
273 }
274 
275 impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for TopLevelRuleParser<'a, R> {
276     type Prelude = QualifiedRuleParserPrelude;
277     type QualifiedRule = CssRule;
278     type Error = StyleParseErrorKind<'i>;
279 
280     #[inline]
parse_prelude<'t>( &mut self, input: &mut Parser<'i, 't>, ) -> Result<QualifiedRuleParserPrelude, ParseError<'i>>281     fn parse_prelude<'t>(
282         &mut self,
283         input: &mut Parser<'i, 't>,
284     ) -> Result<QualifiedRuleParserPrelude, ParseError<'i>> {
285         QualifiedRuleParser::parse_prelude(&mut self.nested(), input)
286     }
287 
288     #[inline]
parse_block<'t>( &mut self, prelude: QualifiedRuleParserPrelude, input: &mut Parser<'i, 't> ) -> Result<CssRule, ParseError<'i>>289     fn parse_block<'t>(
290         &mut self,
291         prelude: QualifiedRuleParserPrelude,
292         input: &mut Parser<'i, 't>
293     ) -> Result<CssRule, ParseError<'i>> {
294         QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
295             .map(|result| { self.state = State::Body; result })
296     }
297 }
298 
299 #[derive(Clone)]  // shallow, relatively cheap .clone
300 struct NestedRuleParser<'a, 'b: 'a, R: 'b> {
301     stylesheet_origin: Origin,
302     shared_lock: &'a SharedRwLock,
303     context: &'a ParserContext<'b>,
304     error_context: &'a ParserErrorContext<'b, R>,
305     namespaces: &'a Namespaces,
306 }
307 
308 impl<'a, 'b, R: ParseErrorReporter> NestedRuleParser<'a, 'b, R> {
parse_nested_rules( &mut self, input: &mut Parser, rule_type: CssRuleType ) -> Arc<Locked<CssRules>>309     fn parse_nested_rules(
310         &mut self,
311         input: &mut Parser,
312         rule_type: CssRuleType
313     ) -> Arc<Locked<CssRules>> {
314         let context = ParserContext::new_with_rule_type(
315             self.context,
316             rule_type,
317             self.namespaces,
318         );
319 
320         let nested_parser = NestedRuleParser {
321             stylesheet_origin: self.stylesheet_origin,
322             shared_lock: self.shared_lock,
323             context: &context,
324             error_context: &self.error_context,
325             namespaces: self.namespaces,
326         };
327 
328         let mut iter = RuleListParser::new_for_nested_rule(input, nested_parser);
329         let mut rules = Vec::new();
330         while let Some(result) = iter.next() {
331             match result {
332                 Ok(rule) => rules.push(rule),
333                 Err((error, slice)) => {
334                     let location = error.location;
335                     let error = ContextualParseError::InvalidRule(slice, error);
336                     self.context.log_css_error(self.error_context, location, error);
337                 }
338             }
339         }
340         CssRules::new(rules, self.shared_lock)
341     }
342 }
343 
344 impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a, 'b, R> {
345     type PreludeNoBlock = AtRuleNonBlockPrelude;
346     type PreludeBlock = AtRuleBlockPrelude;
347     type AtRule = CssRule;
348     type Error = StyleParseErrorKind<'i>;
349 
parse_prelude<'t>( &mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't> ) -> Result<AtRuleType<AtRuleNonBlockPrelude, AtRuleBlockPrelude>, ParseError<'i>>350     fn parse_prelude<'t>(
351         &mut self,
352         name: CowRcStr<'i>,
353         input: &mut Parser<'i, 't>
354     ) -> Result<AtRuleType<AtRuleNonBlockPrelude, AtRuleBlockPrelude>, ParseError<'i>> {
355         let location = input.current_source_location();
356 
357         match_ignore_ascii_case! { &*name,
358             "media" => {
359                 let media_queries = parse_media_query_list(self.context, input,
360                                                            self.error_context.error_reporter);
361                 let arc = Arc::new(self.shared_lock.wrap(media_queries));
362                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Media(arc, location)))
363             },
364             "supports" => {
365                 let cond = SupportsCondition::parse(input)?;
366                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Supports(cond, location)))
367             },
368             "font-face" => {
369                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::FontFace(location)))
370             },
371             "font-feature-values" => {
372                 if !cfg!(feature = "gecko") {
373                     // Support for this rule is not fully implemented in Servo yet.
374                     return Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
375                 }
376                 let family_names = parse_family_name_list(self.context, input)?;
377                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::FontFeatureValues(family_names, location)))
378             },
379             "counter-style" => {
380                 if !cfg!(feature = "gecko") {
381                     // Support for this rule is not fully implemented in Servo yet.
382                     return Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
383                 }
384                 let name = parse_counter_style_name_definition(input)?;
385                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::CounterStyle(name)))
386             },
387             "viewport" => {
388                 if viewport_rule::enabled() {
389                     Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Viewport))
390                 } else {
391                     Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
392                 }
393             },
394             "keyframes" | "-webkit-keyframes" | "-moz-keyframes" => {
395                 let prefix = if starts_with_ignore_ascii_case(&*name, "-webkit-") {
396                     Some(VendorPrefix::WebKit)
397                 } else if starts_with_ignore_ascii_case(&*name, "-moz-") {
398                     Some(VendorPrefix::Moz)
399                 } else {
400                     None
401                 };
402                 if cfg!(feature = "servo") &&
403                    prefix.as_ref().map_or(false, |p| matches!(*p, VendorPrefix::Moz)) {
404                     // Servo should not support @-moz-keyframes.
405                     return Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
406                 }
407                 let name = KeyframesName::parse(self.context, input)?;
408 
409                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Keyframes(name, prefix, location)))
410             },
411             "page" => {
412                 if cfg!(feature = "gecko") {
413                     Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Page(location)))
414                 } else {
415                     Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
416                 }
417             },
418             "-moz-document" => {
419                 if !cfg!(feature = "gecko") {
420                     return Err(input.new_custom_error(
421                         StyleParseErrorKind::UnsupportedAtRule(name.clone())
422                     ))
423                 }
424 
425                 #[cfg(feature = "gecko")]
426                 {
427                     use gecko_bindings::structs;
428 
429                     if self.stylesheet_origin == Origin::Author &&
430                         unsafe { !structs::StylePrefs_sMozDocumentEnabledInContent }
431                     {
432                         return Err(input.new_custom_error(
433                             StyleParseErrorKind::UnsupportedAtRule(name.clone())
434                         ))
435                     }
436                 }
437 
438                 let cond = DocumentCondition::parse(self.context, input)?;
439                 Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Document(cond, location)))
440             },
441             _ => Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone())))
442         }
443     }
444 
parse_block<'t>( &mut self, prelude: AtRuleBlockPrelude, input: &mut Parser<'i, 't> ) -> Result<CssRule, ParseError<'i>>445     fn parse_block<'t>(
446         &mut self,
447         prelude: AtRuleBlockPrelude,
448         input: &mut Parser<'i, 't>
449     ) -> Result<CssRule, ParseError<'i>> {
450         match prelude {
451             AtRuleBlockPrelude::FontFace(location) => {
452                 let context = ParserContext::new_with_rule_type(
453                     self.context,
454                     CssRuleType::FontFace,
455                     self.namespaces,
456                 );
457 
458                 Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap(
459                    parse_font_face_block(&context, self.error_context, input, location).into()))))
460             }
461             AtRuleBlockPrelude::FontFeatureValues(family_names, location) => {
462                 let context = ParserContext::new_with_rule_type(
463                     self.context,
464                     CssRuleType::FontFeatureValues,
465                     self.namespaces,
466                 );
467 
468                 Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap(
469                     FontFeatureValuesRule::parse(&context, self.error_context, input, family_names, location)))))
470             }
471             AtRuleBlockPrelude::CounterStyle(name) => {
472                 let context = ParserContext::new_with_rule_type(
473                     self.context,
474                     CssRuleType::CounterStyle,
475                     self.namespaces,
476                 );
477 
478                 Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap(
479                    parse_counter_style_body(name, &context, self.error_context, input)?.into()))))
480             }
481             AtRuleBlockPrelude::Media(media_queries, location) => {
482                 Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule {
483                     media_queries: media_queries,
484                     rules: self.parse_nested_rules(input, CssRuleType::Media),
485                     source_location: location,
486                 }))))
487             }
488             AtRuleBlockPrelude::Supports(cond, location) => {
489                 let eval_context = ParserContext::new_with_rule_type(
490                     self.context,
491                     CssRuleType::Style,
492                     self.namespaces,
493                 );
494 
495                 let enabled = cond.eval(&eval_context);
496                 Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(SupportsRule {
497                     condition: cond,
498                     rules: self.parse_nested_rules(input, CssRuleType::Supports),
499                     enabled: enabled,
500                     source_location: location,
501                 }))))
502             }
503             AtRuleBlockPrelude::Viewport => {
504                 let context = ParserContext::new_with_rule_type(
505                     self.context,
506                     CssRuleType::Viewport,
507                     self.namespaces,
508                 );
509 
510                 Ok(CssRule::Viewport(Arc::new(self.shared_lock.wrap(
511                    ViewportRule::parse(&context, self.error_context, input)?))))
512             }
513             AtRuleBlockPrelude::Keyframes(name, prefix, location) => {
514                 let context = ParserContext::new_with_rule_type(
515                     self.context,
516                     CssRuleType::Keyframes,
517                     self.namespaces,
518                 );
519 
520                 Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap(KeyframesRule {
521                     name: name,
522                     keyframes: parse_keyframe_list(&context, self.error_context, input, self.shared_lock),
523                     vendor_prefix: prefix,
524                     source_location: location,
525                 }))))
526             }
527             AtRuleBlockPrelude::Page(location) => {
528                 let context = ParserContext::new_with_rule_type(
529                     self.context,
530                     CssRuleType::Page,
531                     self.namespaces,
532                 );
533 
534                 let declarations = parse_property_declaration_list(&context, self.error_context, input);
535                 Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule {
536                     block: Arc::new(self.shared_lock.wrap(declarations)),
537                     source_location: location,
538                 }))))
539             }
540             AtRuleBlockPrelude::Document(cond, location) => {
541                 if cfg!(feature = "gecko") {
542                     Ok(CssRule::Document(Arc::new(self.shared_lock.wrap(DocumentRule {
543                         condition: cond,
544                         rules: self.parse_nested_rules(input, CssRuleType::Document),
545                         source_location: location,
546                     }))))
547                 } else {
548                     unreachable!()
549                 }
550             }
551         }
552     }
553 }
554 
555 impl<'a, 'b, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b, R> {
556     type Prelude = QualifiedRuleParserPrelude;
557     type QualifiedRule = CssRule;
558     type Error = StyleParseErrorKind<'i>;
559 
parse_prelude<'t>( &mut self, input: &mut Parser<'i, 't> ) -> Result<QualifiedRuleParserPrelude, ParseError<'i>>560     fn parse_prelude<'t>(
561         &mut self,
562         input: &mut Parser<'i, 't>
563     ) -> Result<QualifiedRuleParserPrelude, ParseError<'i>> {
564         let selector_parser = SelectorParser {
565             stylesheet_origin: self.stylesheet_origin,
566             namespaces: self.namespaces,
567             url_data: Some(self.context.url_data),
568         };
569 
570         let location = input.current_source_location();
571         let selectors = SelectorList::parse(&selector_parser, input)?;
572 
573         Ok(QualifiedRuleParserPrelude {
574             selectors: selectors,
575             source_location: location,
576         })
577     }
578 
parse_block<'t>( &mut self, prelude: QualifiedRuleParserPrelude, input: &mut Parser<'i, 't> ) -> Result<CssRule, ParseError<'i>>579     fn parse_block<'t>(
580         &mut self,
581         prelude: QualifiedRuleParserPrelude,
582         input: &mut Parser<'i, 't>
583     ) -> Result<CssRule, ParseError<'i>> {
584         let context = ParserContext::new_with_rule_type(
585             self.context,
586             CssRuleType::Style,
587             self.namespaces,
588         );
589 
590         let declarations = parse_property_declaration_list(&context, self.error_context, input);
591         Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
592             selectors: prelude.selectors,
593             block: Arc::new(self.shared_lock.wrap(declarations)),
594             source_location: prelude.source_location,
595         }))))
596     }
597 }
598