mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
style: [css-nesting] Update cssparser again
This changes the cssparser setup to: * Avoid having to do copies of the ParsingContext all over the place, which is useful because I plan to stash more nesting state in there. * Use the new RuleBodyParser which allows parsing qualified rules, declarations, and so on. Though we still don't use this anywhere. The next step is to join NestedRuleParser and PropertyDeclarationParser, so that we can parse declarations in a lot of the nested rules as well. Differential Revision: https://phabricator.services.mozilla.com/D178053
This commit is contained in:
parent
32f1989a5c
commit
920a1c1f08
15 changed files with 336 additions and 336 deletions
|
@ -13,7 +13,7 @@ use crate::str::CssStringWriter;
|
||||||
use crate::values::specified::Integer;
|
use crate::values::specified::Integer;
|
||||||
use crate::values::CustomIdent;
|
use crate::values::CustomIdent;
|
||||||
use crate::Atom;
|
use crate::Atom;
|
||||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, QualifiedRuleParser};
|
use cssparser::{AtRuleParser, RuleBodyParser, RuleBodyItemParser, DeclarationParser, QualifiedRuleParser};
|
||||||
use cssparser::{CowRcStr, Parser, SourceLocation, Token};
|
use cssparser::{CowRcStr, Parser, SourceLocation, Token};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
@ -86,11 +86,11 @@ pub fn parse_counter_style_body<'i, 't>(
|
||||||
let start = input.current_source_location();
|
let start = input.current_source_location();
|
||||||
let mut rule = CounterStyleRuleData::empty(name, location);
|
let mut rule = CounterStyleRuleData::empty(name, location);
|
||||||
{
|
{
|
||||||
let parser = CounterStyleRuleParser {
|
let mut parser = CounterStyleRuleParser {
|
||||||
context: context,
|
context,
|
||||||
rule: &mut rule,
|
rule: &mut rule,
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
if let Err((error, slice)) = declaration {
|
if let Err((error, slice)) = declaration {
|
||||||
let location = error.location;
|
let location = error.location;
|
||||||
|
@ -159,6 +159,11 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for CounterStyleRuleParser<'a, 'b> {
|
||||||
|
fn parse_qualified(&self) -> bool { false }
|
||||||
|
fn parse_declarations(&self) -> bool { true }
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! checker {
|
macro_rules! checker {
|
||||||
($self:ident._($value:ident)) => {};
|
($self:ident._($value:ident)) => {};
|
||||||
($self:ident. $checker:ident($value:ident)) => {
|
($self:ident. $checker:ident($value:ident)) => {
|
||||||
|
@ -219,15 +224,17 @@ macro_rules! counter_style_descriptors {
|
||||||
type Declaration = ();
|
type Declaration = ();
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
|
|
||||||
fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>)
|
fn parse_value<'t>(
|
||||||
-> Result<(), ParseError<'i>> {
|
&mut self,
|
||||||
|
name: CowRcStr<'i>,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<(), ParseError<'i>> {
|
||||||
match_ignore_ascii_case! { &*name,
|
match_ignore_ascii_case! { &*name,
|
||||||
$(
|
$(
|
||||||
$name => {
|
$name => {
|
||||||
// DeclarationParser also calls parse_entirely
|
// DeclarationParser also calls parse_entirely so we’d normally not
|
||||||
// so we’d normally not need to,
|
// need to, but in this case we do because we set the value as a side
|
||||||
// but in this case we do because we set the value as a side effect
|
// effect rather than returning it.
|
||||||
// rather than returning it.
|
|
||||||
let value = input.parse_entirely(|i| Parse::parse(self.context, i))?;
|
let value = input.parse_entirely(|i| Parse::parse(self.context, i))?;
|
||||||
self.rule.$ident = Some(value)
|
self.rule.$ident = Some(value)
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,8 +27,8 @@ use crate::values::specified::NonNegativePercentage;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use cssparser::UnicodeRange;
|
use cssparser::UnicodeRange;
|
||||||
use cssparser::{
|
use cssparser::{
|
||||||
AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Parser, QualifiedRuleParser,
|
AtRuleParser, CowRcStr, RuleBodyParser, RuleBodyItemParser, DeclarationParser, Parser,
|
||||||
SourceLocation,
|
QualifiedRuleParser, SourceLocation,
|
||||||
};
|
};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
@ -470,11 +470,11 @@ pub fn parse_font_face_block(
|
||||||
) -> FontFaceRuleData {
|
) -> FontFaceRuleData {
|
||||||
let mut rule = FontFaceRuleData::empty(location);
|
let mut rule = FontFaceRuleData::empty(location);
|
||||||
{
|
{
|
||||||
let parser = FontFaceRuleParser {
|
let mut parser = FontFaceRuleParser {
|
||||||
context: context,
|
context,
|
||||||
rule: &mut rule,
|
rule: &mut rule,
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
if let Err((error, slice)) = declaration {
|
if let Err((error, slice)) = declaration {
|
||||||
let location = error.location;
|
let location = error.location;
|
||||||
|
@ -566,6 +566,11 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for FontFaceRuleParser<'a, 'b> {
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for FontFaceRuleParser<'a, 'b> {
|
||||||
|
fn parse_qualified(&self) -> bool { false }
|
||||||
|
fn parse_declarations(&self) -> bool { true }
|
||||||
|
}
|
||||||
|
|
||||||
fn font_tech_enabled() -> bool {
|
fn font_tech_enabled() -> bool {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
return static_prefs::pref!("layout.css.font-tech.enabled");
|
return static_prefs::pref!("layout.css.font-tech.enabled");
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||||
use crate::stylesheets::{CssRuleType, Namespaces, Origin, UrlExtraData};
|
use crate::stylesheets::{CssRuleType, Namespaces, Origin, UrlExtraData};
|
||||||
use crate::use_counters::UseCounters;
|
use crate::use_counters::UseCounters;
|
||||||
use cssparser::{Parser, SourceLocation, UnicodeRange};
|
use cssparser::{Parser, SourceLocation, UnicodeRange};
|
||||||
|
use std::borrow::Cow;
|
||||||
use style_traits::{OneOrMoreSeparated, ParseError, ParsingMode, Separator};
|
use style_traits::{OneOrMoreSeparated, ParseError, ParsingMode, Separator};
|
||||||
|
|
||||||
/// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko.
|
/// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko.
|
||||||
|
@ -53,7 +54,7 @@ pub struct ParserContext<'a> {
|
||||||
/// The active error reporter, or none if error reporting is disabled.
|
/// The active error reporter, or none if error reporting is disabled.
|
||||||
error_reporter: Option<&'a dyn ParseErrorReporter>,
|
error_reporter: Option<&'a dyn ParseErrorReporter>,
|
||||||
/// The currently active namespaces.
|
/// The currently active namespaces.
|
||||||
pub namespaces: Option<&'a Namespaces>,
|
pub namespaces: Cow<'a, Namespaces>,
|
||||||
/// The use counters we want to record while parsing style rules, if any.
|
/// The use counters we want to record while parsing style rules, if any.
|
||||||
pub use_counters: Option<&'a UseCounters>,
|
pub use_counters: Option<&'a UseCounters>,
|
||||||
}
|
}
|
||||||
|
@ -67,6 +68,7 @@ impl<'a> ParserContext<'a> {
|
||||||
rule_type: Option<CssRuleType>,
|
rule_type: Option<CssRuleType>,
|
||||||
parsing_mode: ParsingMode,
|
parsing_mode: ParsingMode,
|
||||||
quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
|
namespaces: Cow<'a, Namespaces>,
|
||||||
error_reporter: Option<&'a dyn ParseErrorReporter>,
|
error_reporter: Option<&'a dyn ParseErrorReporter>,
|
||||||
use_counters: Option<&'a UseCounters>,
|
use_counters: Option<&'a UseCounters>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -77,29 +79,17 @@ impl<'a> ParserContext<'a> {
|
||||||
parsing_mode,
|
parsing_mode,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
error_reporter,
|
error_reporter,
|
||||||
namespaces: None,
|
namespaces,
|
||||||
use_counters,
|
use_counters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a parser context based on a previous context, but with a modified
|
/// Temporarily sets the rule_type and executes the callback function, returning its result.
|
||||||
/// rule type.
|
pub fn nest_for_rule<R>(&mut self, rule_type: CssRuleType, cb: impl FnOnce(&mut Self) -> R) -> R {
|
||||||
#[inline]
|
let old_rule_type = std::mem::replace(&mut self.rule_type, Some(rule_type));
|
||||||
pub fn new_with_rule_type(
|
let r = cb(self);
|
||||||
context: &'a ParserContext,
|
self.rule_type = old_rule_type;
|
||||||
rule_type: CssRuleType,
|
r
|
||||||
namespaces: &'a Namespaces,
|
|
||||||
) -> ParserContext<'a> {
|
|
||||||
Self {
|
|
||||||
stylesheet_origin: context.stylesheet_origin,
|
|
||||||
url_data: context.url_data,
|
|
||||||
rule_type: Some(rule_type),
|
|
||||||
parsing_mode: context.parsing_mode,
|
|
||||||
quirks_mode: context.quirks_mode,
|
|
||||||
namespaces: Some(namespaces),
|
|
||||||
error_reporter: context.error_reporter,
|
|
||||||
use_counters: context.use_counters,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether we're in a @page rule.
|
/// Whether we're in a @page rule.
|
||||||
|
|
|
@ -26,8 +26,8 @@ use crate::str::{CssString, CssStringWriter};
|
||||||
use crate::stylesheets::{layer_rule::LayerOrder, CssRuleType, Origin, UrlExtraData};
|
use crate::stylesheets::{layer_rule::LayerOrder, CssRuleType, Origin, UrlExtraData};
|
||||||
use crate::values::computed::Context;
|
use crate::values::computed::Context;
|
||||||
use cssparser::{
|
use cssparser::{
|
||||||
parse_important, AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Delimiter,
|
parse_important, AtRuleParser, CowRcStr, DeclarationParser, Delimiter, ParseErrorKind, Parser,
|
||||||
ParseErrorKind, Parser, ParserInput, QualifiedRuleParser,
|
ParserInput, QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use selectors::SelectorList;
|
use selectors::SelectorList;
|
||||||
|
@ -582,8 +582,9 @@ impl PropertyDeclarationBlock {
|
||||||
.all_shorthand
|
.all_shorthand
|
||||||
.declarations()
|
.declarations()
|
||||||
.any(|decl| {
|
.any(|decl| {
|
||||||
!self.contains(decl.id()) ||
|
!self.contains(decl.id())
|
||||||
self.declarations
|
|| self
|
||||||
|
.declarations
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|&(_, ref d)| d.id() == decl.id())
|
.find(|&(_, ref d)| d.id() == decl.id())
|
||||||
|
@ -625,9 +626,9 @@ impl PropertyDeclarationBlock {
|
||||||
}
|
}
|
||||||
return DeclarationUpdate::UpdateInPlace { pos };
|
return DeclarationUpdate::UpdateInPlace { pos };
|
||||||
}
|
}
|
||||||
if !needs_append &&
|
if !needs_append
|
||||||
id.logical_group() == Some(logical_group) &&
|
&& id.logical_group() == Some(logical_group)
|
||||||
id.is_logical() != longhand_id.is_logical()
|
&& id.is_logical() != longhand_id.is_logical()
|
||||||
{
|
{
|
||||||
needs_append = true;
|
needs_append = true;
|
||||||
}
|
}
|
||||||
|
@ -1292,6 +1293,7 @@ pub fn parse_style_attribute(
|
||||||
Some(rule_type),
|
Some(rule_type),
|
||||||
ParsingMode::DEFAULT,
|
ParsingMode::DEFAULT,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
|
/* namespaces = */ Default::default(),
|
||||||
error_reporter,
|
error_reporter,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1322,6 +1324,7 @@ pub fn parse_one_declaration_into(
|
||||||
Some(rule_type),
|
Some(rule_type),
|
||||||
parsing_mode,
|
parsing_mode,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
|
/* namespaces = */ Default::default(),
|
||||||
error_reporter,
|
error_reporter,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1411,6 +1414,12 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, Importance, StyleParseErrorKind<'i>> for PropertyDeclarationParser<'a, 'b> {
|
||||||
|
fn parse_declarations(&self) -> bool { true }
|
||||||
|
// TODO(emilio): Nesting.
|
||||||
|
fn parse_qualified(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
|
type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
|
||||||
|
|
||||||
fn alias_of_known_property(name: &str) -> Option<PropertyId> {
|
fn alias_of_known_property(name: &str) -> Option<PropertyId> {
|
||||||
|
@ -1498,12 +1507,12 @@ pub fn parse_property_declaration_list(
|
||||||
) -> PropertyDeclarationBlock {
|
) -> PropertyDeclarationBlock {
|
||||||
let mut declarations = SourcePropertyDeclaration::new();
|
let mut declarations = SourcePropertyDeclaration::new();
|
||||||
let mut block = PropertyDeclarationBlock::new();
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
let parser = PropertyDeclarationParser {
|
let mut parser = PropertyDeclarationParser {
|
||||||
context,
|
context,
|
||||||
last_parsed_property_id: None,
|
last_parsed_property_id: None,
|
||||||
declarations: &mut declarations,
|
declarations: &mut declarations,
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
let mut errors = SmallParseErrorVec::new();
|
let mut errors = SmallParseErrorVec::new();
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
match declaration {
|
match declaration {
|
||||||
|
|
|
@ -1769,6 +1769,7 @@ impl UnparsedValue {
|
||||||
None,
|
None,
|
||||||
ParsingMode::DEFAULT,
|
ParsingMode::DEFAULT,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
|
/* namespaces = */ Default::default(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,8 +19,8 @@ use crate::values::computed::font::FamilyName;
|
||||||
use crate::values::serialize_atom_identifier;
|
use crate::values::serialize_atom_identifier;
|
||||||
use crate::Atom;
|
use crate::Atom;
|
||||||
use cssparser::{
|
use cssparser::{
|
||||||
AtRuleParser, BasicParseErrorKind, CowRcStr, DeclarationListParser, DeclarationParser, Parser,
|
AtRuleParser, BasicParseErrorKind, CowRcStr, RuleBodyParser, RuleBodyItemParser, Parser,
|
||||||
ParserState, QualifiedRuleParser, RuleListParser, SourceLocation, Token,
|
ParserState, QualifiedRuleParser, DeclarationParser, SourceLocation, Token,
|
||||||
};
|
};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
@ -215,13 +215,21 @@ where
|
||||||
let value = input.parse_entirely(|i| T::parse(self.context, i))?;
|
let value = input.parse_entirely(|i| T::parse(self.context, i))?;
|
||||||
let new = FFVDeclaration {
|
let new = FFVDeclaration {
|
||||||
name: Atom::from(&*name),
|
name: Atom::from(&*name),
|
||||||
value: value,
|
value,
|
||||||
};
|
};
|
||||||
update_or_push(&mut self.declarations, new);
|
update_or_push(&mut self.declarations, new);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i, T> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for FFVDeclarationsParser<'a, 'b, T>
|
||||||
|
where
|
||||||
|
T: Parse,
|
||||||
|
{
|
||||||
|
fn parse_declarations(&self) -> bool { true }
|
||||||
|
fn parse_qualified(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! font_feature_values_blocks {
|
macro_rules! font_feature_values_blocks {
|
||||||
(
|
(
|
||||||
blocks = [
|
blocks = [
|
||||||
|
@ -265,18 +273,16 @@ macro_rules! font_feature_values_blocks {
|
||||||
location: SourceLocation,
|
location: SourceLocation,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut rule = FontFeatureValuesRule::new(family_names, location);
|
let mut rule = FontFeatureValuesRule::new(family_names, location);
|
||||||
|
let mut parser = FontFeatureValuesRuleParser {
|
||||||
{
|
context,
|
||||||
let mut iter = RuleListParser::new_for_nested_rule(input, FontFeatureValuesRuleParser {
|
rule: &mut rule,
|
||||||
context: context,
|
};
|
||||||
rule: &mut rule,
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
});
|
while let Some(result) = iter.next() {
|
||||||
while let Some(result) = iter.next() {
|
if let Err((error, slice)) = result {
|
||||||
if let Err((error, slice)) = result {
|
let location = error.location;
|
||||||
let location = error.location;
|
let error = ContextualParseError::UnsupportedRule(slice, error);
|
||||||
let error = ContextualParseError::UnsupportedRule(slice, error);
|
context.log_css_error(location, error);
|
||||||
context.log_css_error(location, error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rule
|
rule
|
||||||
|
@ -348,9 +354,8 @@ macro_rules! font_feature_values_blocks {
|
||||||
|
|
||||||
/// Updates with new value if same `ident` exists, otherwise pushes to the vector.
|
/// Updates with new value if same `ident` exists, otherwise pushes to the vector.
|
||||||
fn update_or_push<T>(vec: &mut Vec<FFVDeclaration<T>>, element: FFVDeclaration<T>) {
|
fn update_or_push<T>(vec: &mut Vec<FFVDeclaration<T>>, element: FFVDeclaration<T>) {
|
||||||
let position = vec.iter().position(|ref val| val.name == element.name);
|
if let Some(item) = vec.iter_mut().find(|item| item.name == element.name) {
|
||||||
if let Some(index) = position {
|
item.value = element.value;
|
||||||
vec[index].value = element.value;
|
|
||||||
} else {
|
} else {
|
||||||
vec.push(element);
|
vec.push(element);
|
||||||
}
|
}
|
||||||
|
@ -409,12 +414,12 @@ macro_rules! font_feature_values_blocks {
|
||||||
match prelude {
|
match prelude {
|
||||||
$(
|
$(
|
||||||
BlockType::$ident_camel => {
|
BlockType::$ident_camel => {
|
||||||
let parser = FFVDeclarationsParser {
|
let mut parser = FFVDeclarationsParser {
|
||||||
context: &self.context,
|
context: &self.context,
|
||||||
declarations: &mut self.rule.$ident,
|
declarations: &mut self.rule.$ident,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
if let Err((error, slice)) = declaration {
|
if let Err((error, slice)) = declaration {
|
||||||
let location = error.location;
|
let location = error.location;
|
||||||
|
@ -431,6 +436,16 @@ macro_rules! font_feature_values_blocks {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'i> DeclarationParser<'i> for FontFeatureValuesRuleParser<'a> {
|
||||||
|
type Declaration = ();
|
||||||
|
type Error = StyleParseErrorKind<'i>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for FontFeatureValuesRuleParser<'a> {
|
||||||
|
fn parse_declarations(&self) -> bool { false }
|
||||||
|
fn parse_qualified(&self) -> bool { true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
//! [font-palette-values]: https://drafts.csswg.org/css-fonts/#font-palette-values
|
//! [font-palette-values]: https://drafts.csswg.org/css-fonts/#font-palette-values
|
||||||
|
|
||||||
use crate::error_reporting::ContextualParseError;
|
use crate::error_reporting::ContextualParseError;
|
||||||
use crate::parser::{Parse, ParserContext};
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::gecko_bindings::{
|
use crate::gecko_bindings::{
|
||||||
bindings::Gecko_AppendPaletteValueHashEntry,
|
bindings::Gecko_AppendPaletteValueHashEntry,
|
||||||
|
@ -16,20 +15,22 @@ use crate::gecko_bindings::{
|
||||||
structs::gfx::FontPaletteValueSet_PaletteValues_kDark,
|
structs::gfx::FontPaletteValueSet_PaletteValues_kDark,
|
||||||
structs::gfx::FontPaletteValueSet_PaletteValues_kLight,
|
structs::gfx::FontPaletteValueSet_PaletteValues_kLight,
|
||||||
};
|
};
|
||||||
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use crate::str::CssStringWriter;
|
use crate::str::CssStringWriter;
|
||||||
|
use crate::stylesheets::font_feature_values_rule::parse_family_name_list;
|
||||||
use crate::values::computed::font::FamilyName;
|
use crate::values::computed::font::FamilyName;
|
||||||
use crate::values::specified::Color as SpecifiedColor;
|
use crate::values::specified::Color as SpecifiedColor;
|
||||||
use crate::values::specified::NonNegativeInteger;
|
use crate::values::specified::NonNegativeInteger;
|
||||||
use crate::values::DashedIdent;
|
use crate::values::DashedIdent;
|
||||||
use cssparser::{AtRuleParser, CowRcStr};
|
use cssparser::{
|
||||||
use cssparser::{DeclarationParser, DeclarationListParser, Parser};
|
AtRuleParser, CowRcStr, DeclarationParser, Parser, QualifiedRuleParser, RuleBodyItemParser,
|
||||||
use cssparser::{QualifiedRuleParser, SourceLocation};
|
RuleBodyParser, SourceLocation,
|
||||||
use std::fmt::{self, Write};
|
};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
|
||||||
use style_traits::{Comma, OneOrMoreSeparated};
|
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use crate::stylesheets::font_feature_values_rule::parse_family_name_list;
|
use std::fmt::{self, Write};
|
||||||
|
use style_traits::{Comma, OneOrMoreSeparated};
|
||||||
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
|
@ -121,18 +122,17 @@ impl FontPaletteValuesRule {
|
||||||
location: SourceLocation,
|
location: SourceLocation,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut rule = FontPaletteValuesRule::new(name, location);
|
let mut rule = FontPaletteValuesRule::new(name, location);
|
||||||
{
|
let mut parser = FontPaletteValuesDeclarationParser {
|
||||||
let parser = FontPaletteValuesDeclarationParser {
|
context,
|
||||||
context: context,
|
rule: &mut rule,
|
||||||
rule: &mut rule,
|
};
|
||||||
};
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
while let Some(declaration) = iter.next() {
|
||||||
while let Some(declaration) = iter.next() {
|
if let Err((error, slice)) = declaration {
|
||||||
if let Err((error, slice)) = declaration {
|
let location = error.location;
|
||||||
let location = error.location;
|
let error =
|
||||||
let error = ContextualParseError::UnsupportedFontPaletteValuesDescriptor(slice, error);
|
ContextualParseError::UnsupportedFontPaletteValuesDescriptor(slice, error);
|
||||||
context.log_css_error(location, error);
|
context.log_css_error(location, error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rule
|
rule
|
||||||
|
@ -167,19 +167,18 @@ impl FontPaletteValuesRule {
|
||||||
for ref family in self.family_names.iter() {
|
for ref family in self.family_names.iter() {
|
||||||
let family = family.name.to_ascii_lowercase();
|
let family = family.name.to_ascii_lowercase();
|
||||||
let palette_values = unsafe {
|
let palette_values = unsafe {
|
||||||
Gecko_AppendPaletteValueHashEntry(
|
Gecko_AppendPaletteValueHashEntry(dest, family.as_ptr(), self.name.0.as_ptr())
|
||||||
dest,
|
|
||||||
family.as_ptr(),
|
|
||||||
self.name.0.as_ptr()
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
if let Some(base_palette) = &self.base_palette {
|
if let Some(base_palette) = &self.base_palette {
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_SetFontPaletteBase(palette_values, match &base_palette {
|
Gecko_SetFontPaletteBase(
|
||||||
FontPaletteBase::Light => FontPaletteValueSet_PaletteValues_kLight,
|
palette_values,
|
||||||
FontPaletteBase::Dark => FontPaletteValueSet_PaletteValues_kDark,
|
match &base_palette {
|
||||||
FontPaletteBase::Index(i) => i.0.value() as i32,
|
FontPaletteBase::Light => FontPaletteValueSet_PaletteValues_kLight,
|
||||||
});
|
FontPaletteBase::Dark => FontPaletteValueSet_PaletteValues_kDark,
|
||||||
|
FontPaletteBase::Index(i) => i.0.value() as i32,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for c in &self.override_colors {
|
for c in &self.override_colors {
|
||||||
|
@ -233,13 +232,13 @@ fn parse_override_colors<'i, 't>(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'i> DeclarationParser<'i> for FontPaletteValuesDeclarationParser<'a> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for FontPaletteValuesDeclarationParser<'a> {
|
||||||
type Declaration = ();
|
type Declaration = ();
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
|
|
||||||
fn parse_value<'t>(
|
fn parse_value<'t>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: CowRcStr<'i>,
|
name: CowRcStr<'i>,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<(), ParseError<'i>> {
|
) -> Result<(), ParseError<'i>> {
|
||||||
match_ignore_ascii_case! { &*name,
|
match_ignore_ascii_case! { &*name,
|
||||||
"font-family" => {
|
"font-family" => {
|
||||||
|
@ -256,3 +255,14 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for FontPaletteValuesDeclarationParser<'a
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>>
|
||||||
|
for FontPaletteValuesDeclarationParser<'a>
|
||||||
|
{
|
||||||
|
fn parse_declarations(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn parse_qualified(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::shared_lock::{
|
||||||
};
|
};
|
||||||
use crate::str::CssStringWriter;
|
use crate::str::CssStringWriter;
|
||||||
use crate::stylesheets::{
|
use crate::stylesheets::{
|
||||||
layer_rule::LayerName, stylesheet::Namespaces, supports_rule::SupportsCondition, CssRule,
|
layer_rule::LayerName, supports_rule::SupportsCondition, CssRule,
|
||||||
CssRuleType, StylesheetInDocument,
|
CssRuleType, StylesheetInDocument,
|
||||||
};
|
};
|
||||||
use crate::values::CssUrl;
|
use crate::values::CssUrl;
|
||||||
|
@ -243,8 +243,7 @@ impl ImportRule {
|
||||||
/// whole import rule or parse the media query list or what not.
|
/// whole import rule or parse the media query list or what not.
|
||||||
pub fn parse_layer_and_supports<'i, 't>(
|
pub fn parse_layer_and_supports<'i, 't>(
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
context: &ParserContext,
|
context: &mut ParserContext,
|
||||||
namespaces: &Namespaces,
|
|
||||||
) -> (ImportLayer, Option<ImportSupportsCondition>) {
|
) -> (ImportLayer, Option<ImportSupportsCondition>) {
|
||||||
let layer = if input
|
let layer = if input
|
||||||
.try_parse(|input| input.expect_ident_matching("layer"))
|
.try_parse(|input| input.expect_ident_matching("layer"))
|
||||||
|
@ -273,9 +272,9 @@ impl ImportRule {
|
||||||
input
|
input
|
||||||
.try_parse(SupportsCondition::parse_for_import)
|
.try_parse(SupportsCondition::parse_for_import)
|
||||||
.map(|condition| {
|
.map(|condition| {
|
||||||
let eval_context =
|
let enabled = context.nest_for_rule(CssRuleType::Style, |context| {
|
||||||
ParserContext::new_with_rule_type(context, CssRuleType::Style, namespaces);
|
condition.eval(context)
|
||||||
let enabled = condition.eval(&eval_context, namespaces);
|
});
|
||||||
ImportSupportsCondition { condition, enabled }
|
ImportSupportsCondition { condition, enabled }
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
|
|
|
@ -19,11 +19,12 @@ use crate::stylesheets::rule_parser::VendorPrefix;
|
||||||
use crate::stylesheets::{CssRuleType, StylesheetContents};
|
use crate::stylesheets::{CssRuleType, StylesheetContents};
|
||||||
use crate::values::{serialize_percentage, KeyframesName};
|
use crate::values::{serialize_percentage, KeyframesName};
|
||||||
use cssparser::{
|
use cssparser::{
|
||||||
parse_one_rule, DeclarationListParser, DeclarationParser, ParserState, SourceLocation, Token,
|
parse_one_rule, AtRuleParser, CowRcStr, DeclarationParser, Parser, ParserInput, ParserState,
|
||||||
|
QualifiedRuleParser, RuleBodyItemParser, RuleBodyParser, SourceLocation, Token,
|
||||||
};
|
};
|
||||||
use cssparser::{AtRuleParser, CowRcStr, Parser, ParserInput, QualifiedRuleParser, RuleListParser};
|
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
use std::borrow::Cow;
|
||||||
use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
|
||||||
|
|
||||||
/// A [`@keyframes`][keyframes] rule.
|
/// A [`@keyframes`][keyframes] rule.
|
||||||
|
@ -217,16 +218,16 @@ impl Keyframe {
|
||||||
Some(CssRuleType::Keyframe),
|
Some(CssRuleType::Keyframe),
|
||||||
ParsingMode::DEFAULT,
|
ParsingMode::DEFAULT,
|
||||||
parent_stylesheet_contents.quirks_mode,
|
parent_stylesheet_contents.quirks_mode,
|
||||||
|
Cow::Borrowed(&*namespaces),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
context.namespaces = Some(&*namespaces);
|
|
||||||
let mut input = ParserInput::new(css);
|
let mut input = ParserInput::new(css);
|
||||||
let mut input = Parser::new(&mut input);
|
let mut input = Parser::new(&mut input);
|
||||||
|
|
||||||
let mut declarations = SourcePropertyDeclaration::new();
|
let mut declarations = SourcePropertyDeclaration::new();
|
||||||
let mut rule_parser = KeyframeListParser {
|
let mut rule_parser = KeyframeListParser {
|
||||||
context: &context,
|
context: &mut context,
|
||||||
shared_lock: &lock,
|
shared_lock: &lock,
|
||||||
declarations: &mut declarations,
|
declarations: &mut declarations,
|
||||||
};
|
};
|
||||||
|
@ -526,43 +527,39 @@ impl KeyframesAnimation {
|
||||||
/// 40%, 60%, 100% {
|
/// 40%, 60%, 100% {
|
||||||
/// width: 100%;
|
/// width: 100%;
|
||||||
/// }
|
/// }
|
||||||
struct KeyframeListParser<'a> {
|
struct KeyframeListParser<'a, 'b> {
|
||||||
context: &'a ParserContext<'a>,
|
context: &'a mut ParserContext<'b>,
|
||||||
shared_lock: &'a SharedRwLock,
|
shared_lock: &'a SharedRwLock,
|
||||||
declarations: &'a mut SourcePropertyDeclaration,
|
declarations: &'a mut SourcePropertyDeclaration,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a keyframe list from CSS input.
|
/// Parses a keyframe list from CSS input.
|
||||||
pub fn parse_keyframe_list(
|
pub fn parse_keyframe_list<'a>(
|
||||||
context: &ParserContext,
|
context: &mut ParserContext<'a>,
|
||||||
input: &mut Parser,
|
input: &mut Parser,
|
||||||
shared_lock: &SharedRwLock,
|
shared_lock: &SharedRwLock,
|
||||||
) -> Vec<Arc<Locked<Keyframe>>> {
|
) -> 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(
|
let mut parser = KeyframeListParser {
|
||||||
input,
|
context,
|
||||||
KeyframeListParser {
|
shared_lock,
|
||||||
context,
|
declarations: &mut declarations,
|
||||||
shared_lock,
|
};
|
||||||
declarations: &mut declarations,
|
RuleBodyParser::new(input, &mut parser).filter_map(Result::ok) .collect()
|
||||||
},
|
|
||||||
)
|
|
||||||
.filter_map(Result::ok)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for KeyframeListParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = Arc<Locked<Keyframe>>;
|
type AtRule = Arc<Locked<Keyframe>>;
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeListParser<'a, 'b> {
|
||||||
|
type Declaration = Arc<Locked<Keyframe>>;
|
||||||
|
type Error = StyleParseErrorKind<'i>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a, 'b> {
|
||||||
type Prelude = KeyframeSelector;
|
type Prelude = KeyframeSelector;
|
||||||
type QualifiedRule = Arc<Locked<Keyframe>>;
|
type QualifiedRule = Arc<Locked<Keyframe>>;
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
|
@ -589,33 +586,30 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
|
||||||
start: &ParserState,
|
start: &ParserState,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self::QualifiedRule, ParseError<'i>> {
|
) -> Result<Self::QualifiedRule, ParseError<'i>> {
|
||||||
let context = ParserContext::new_with_rule_type(
|
|
||||||
self.context,
|
|
||||||
CssRuleType::Keyframe,
|
|
||||||
self.context.namespaces.unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let parser = KeyframeDeclarationParser {
|
|
||||||
context: &context,
|
|
||||||
declarations: self.declarations,
|
|
||||||
};
|
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
|
||||||
let mut block = PropertyDeclarationBlock::new();
|
let mut block = PropertyDeclarationBlock::new();
|
||||||
while let Some(declaration) = iter.next() {
|
let declarations = &mut self.declarations;
|
||||||
match declaration {
|
self.context.nest_for_rule(CssRuleType::Keyframe, |context| {
|
||||||
Ok(()) => {
|
let mut parser = KeyframeDeclarationParser {
|
||||||
block.extend(iter.parser.declarations.drain(), Importance::Normal);
|
context: &context,
|
||||||
},
|
declarations,
|
||||||
Err((error, slice)) => {
|
};
|
||||||
iter.parser.declarations.clear();
|
let mut iter = RuleBodyParser::new(input, &mut parser);
|
||||||
let location = error.location;
|
while let Some(declaration) = iter.next() {
|
||||||
let error =
|
match declaration {
|
||||||
ContextualParseError::UnsupportedKeyframePropertyDeclaration(slice, error);
|
Ok(()) => {
|
||||||
context.log_css_error(location, error);
|
block.extend(iter.parser.declarations.drain(), Importance::Normal);
|
||||||
},
|
},
|
||||||
|
Err((error, slice)) => {
|
||||||
|
iter.parser.declarations.clear();
|
||||||
|
let location = error.location;
|
||||||
|
let error =
|
||||||
|
ContextualParseError::UnsupportedKeyframePropertyDeclaration(slice, error);
|
||||||
|
context.log_css_error(location, error);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// `parse_important` is not called here, `!important` is not allowed in keyframe blocks.
|
||||||
}
|
}
|
||||||
// `parse_important` is not called here, `!important` is not allowed in keyframe blocks.
|
});
|
||||||
}
|
|
||||||
Ok(Arc::new(self.shared_lock.wrap(Keyframe {
|
Ok(Arc::new(self.shared_lock.wrap(Keyframe {
|
||||||
selector,
|
selector,
|
||||||
block: Arc::new(self.shared_lock.wrap(block)),
|
block: Arc::new(self.shared_lock.wrap(block)),
|
||||||
|
@ -624,6 +618,11 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, Arc<Locked<Keyframe>>, StyleParseErrorKind<'i>> for KeyframeListParser<'a, 'b> {
|
||||||
|
fn parse_qualified(&self) -> bool { true }
|
||||||
|
fn parse_declarations(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
struct KeyframeDeclarationParser<'a, 'b: 'a> {
|
struct KeyframeDeclarationParser<'a, 'b: 'a> {
|
||||||
context: &'a ParserContext<'b>,
|
context: &'a ParserContext<'b>,
|
||||||
declarations: &'a mut SourcePropertyDeclaration,
|
declarations: &'a mut SourcePropertyDeclaration,
|
||||||
|
@ -668,3 +667,8 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, (), StyleParseErrorKind<'i>> for KeyframeDeclarationParser<'a, 'b> {
|
||||||
|
fn parse_qualified(&self) -> bool { false }
|
||||||
|
fn parse_declarations(&self) -> bool { true }
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ use cssparser::{parse_one_rule, Parser, ParserInput};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use std::mem::{self, ManuallyDrop};
|
use std::mem::{self, ManuallyDrop};
|
||||||
|
@ -401,12 +402,14 @@ impl CssRule {
|
||||||
allow_import_rules: AllowImportRules,
|
allow_import_rules: AllowImportRules,
|
||||||
) -> Result<Self, RulesMutateError> {
|
) -> Result<Self, RulesMutateError> {
|
||||||
let url_data = parent_stylesheet_contents.url_data.read();
|
let url_data = parent_stylesheet_contents.url_data.read();
|
||||||
|
let namespaces = parent_stylesheet_contents.namespaces.read();
|
||||||
let context = ParserContext::new(
|
let context = ParserContext::new(
|
||||||
parent_stylesheet_contents.origin,
|
parent_stylesheet_contents.origin,
|
||||||
&url_data,
|
&url_data,
|
||||||
None,
|
None,
|
||||||
ParsingMode::DEFAULT,
|
ParsingMode::DEFAULT,
|
||||||
parent_stylesheet_contents.quirks_mode,
|
parent_stylesheet_contents.quirks_mode,
|
||||||
|
Cow::Borrowed(&*namespaces),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -414,8 +417,6 @@ impl CssRule {
|
||||||
let mut input = ParserInput::new(css);
|
let mut input = ParserInput::new(css);
|
||||||
let mut input = Parser::new(&mut input);
|
let mut input = Parser::new(&mut input);
|
||||||
|
|
||||||
let mut guard = parent_stylesheet_contents.namespaces.write();
|
|
||||||
|
|
||||||
// nested rules are in the body state
|
// nested rules are in the body state
|
||||||
let mut rule_parser = TopLevelRuleParser {
|
let mut rule_parser = TopLevelRuleParser {
|
||||||
context,
|
context,
|
||||||
|
@ -423,7 +424,6 @@ impl CssRule {
|
||||||
loader,
|
loader,
|
||||||
state,
|
state,
|
||||||
dom_error: None,
|
dom_error: None,
|
||||||
namespaces: &mut *guard,
|
|
||||||
insert_rule_context: Some(insert_rule_context),
|
insert_rule_context: Some(insert_rule_context),
|
||||||
allow_import_rules,
|
allow_import_rules,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,6 @@ use crate::stylesheets::font_feature_values_rule::parse_family_name_list;
|
||||||
use crate::stylesheets::import_rule::{ImportRule, ImportLayer, ImportSupportsCondition};
|
use crate::stylesheets::import_rule::{ImportRule, ImportLayer, ImportSupportsCondition};
|
||||||
use crate::stylesheets::keyframes_rule::parse_keyframe_list;
|
use crate::stylesheets::keyframes_rule::parse_keyframe_list;
|
||||||
use crate::stylesheets::layer_rule::{LayerBlockRule, LayerName, LayerStatementRule};
|
use crate::stylesheets::layer_rule::{LayerBlockRule, LayerName, LayerStatementRule};
|
||||||
use crate::stylesheets::stylesheet::Namespaces;
|
|
||||||
use crate::stylesheets::supports_rule::SupportsCondition;
|
use crate::stylesheets::supports_rule::SupportsCondition;
|
||||||
use crate::stylesheets::{
|
use crate::stylesheets::{
|
||||||
viewport_rule, AllowImportRules, CorsMode, CssRule, CssRuleType, CssRules, DocumentRule,
|
viewport_rule, AllowImportRules, CorsMode, CssRule, CssRuleType, CssRules, DocumentRule,
|
||||||
|
@ -31,8 +30,8 @@ use crate::values::computed::font::FamilyName;
|
||||||
use crate::values::{CssUrl, CustomIdent, DashedIdent, KeyframesName};
|
use crate::values::{CssUrl, CustomIdent, DashedIdent, KeyframesName};
|
||||||
use crate::{Namespace, Prefix};
|
use crate::{Namespace, Prefix};
|
||||||
use cssparser::{
|
use cssparser::{
|
||||||
AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, Parser, ParserState,
|
AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, DeclarationParser, Parser,
|
||||||
QualifiedRuleParser, RuleListParser, SourcePosition,
|
ParserState, QualifiedRuleParser, RuleBodyParser, RuleBodyItemParser, SourcePosition,
|
||||||
};
|
};
|
||||||
use selectors::SelectorList;
|
use selectors::SelectorList;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -83,9 +82,6 @@ pub struct TopLevelRuleParser<'a> {
|
||||||
/// A reference to a stylesheet loader if applicable, for `@import` rules.
|
/// A reference to a stylesheet loader if applicable, for `@import` rules.
|
||||||
pub loader: Option<&'a dyn StylesheetLoader>,
|
pub loader: Option<&'a dyn StylesheetLoader>,
|
||||||
/// The top-level parser context.
|
/// The top-level parser context.
|
||||||
///
|
|
||||||
/// This won't contain any namespaces, and only nested parsers created with
|
|
||||||
/// `ParserContext::new_with_rule_type` will.
|
|
||||||
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,
|
||||||
|
@ -93,22 +89,17 @@ pub struct TopLevelRuleParser<'a> {
|
||||||
/// place (e.g. an @import rule was found while in the `Body` state). Reset
|
/// place (e.g. an @import rule was found while in the `Body` state). Reset
|
||||||
/// to `false` when `take_had_hierarchy_error` is called.
|
/// to `false` when `take_had_hierarchy_error` is called.
|
||||||
pub dom_error: Option<RulesMutateError>,
|
pub dom_error: Option<RulesMutateError>,
|
||||||
/// The namespace map we use for parsing. Needs to start as `Some()`, and
|
|
||||||
/// will be taken out after parsing namespace rules, and that reference will
|
|
||||||
/// be moved to `ParserContext`.
|
|
||||||
pub namespaces: &'a mut Namespaces,
|
|
||||||
/// The info we need insert a rule in a list.
|
/// The info we need insert a rule in a list.
|
||||||
pub insert_rule_context: Option<InsertRuleContext<'a>>,
|
pub insert_rule_context: Option<InsertRuleContext<'a>>,
|
||||||
/// Whether @import rules will be allowed.
|
/// Whether @import rules will be allowed.
|
||||||
pub allow_import_rules: AllowImportRules,
|
pub allow_import_rules: AllowImportRules,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> TopLevelRuleParser<'b> {
|
impl<'a> TopLevelRuleParser<'a> {
|
||||||
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> {
|
fn nested<'b>(&'b mut self) -> NestedRuleParser<'b, 'a> {
|
||||||
NestedRuleParser {
|
NestedRuleParser {
|
||||||
shared_lock: self.shared_lock,
|
shared_lock: self.shared_lock,
|
||||||
context: &self.context,
|
context: &mut self.context,
|
||||||
namespaces: &self.namespaces,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +232,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||||
let url_string = input.expect_url_or_string()?.as_ref().to_owned();
|
let url_string = input.expect_url_or_string()?.as_ref().to_owned();
|
||||||
let url = CssUrl::parse_from_string(url_string, &self.context, CorsMode::None);
|
let url = CssUrl::parse_from_string(url_string, &self.context, CorsMode::None);
|
||||||
|
|
||||||
let (layer, supports) = ImportRule::parse_layer_and_supports(input, &self.context, self.namespaces);
|
let (layer, supports) = ImportRule::parse_layer_and_supports(input, &mut self.context);
|
||||||
|
|
||||||
let media = MediaList::parse(&self.context, input);
|
let media = MediaList::parse(&self.context, input);
|
||||||
let media = Arc::new(self.shared_lock.wrap(media));
|
let media = Arc::new(self.shared_lock.wrap(media));
|
||||||
|
@ -334,11 +325,12 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||||
CssRule::Import(import_rule)
|
CssRule::Import(import_rule)
|
||||||
},
|
},
|
||||||
AtRulePrelude::Namespace(prefix, url) => {
|
AtRulePrelude::Namespace(prefix, url) => {
|
||||||
|
let namespaces = self.context.namespaces.to_mut();
|
||||||
let prefix = if let Some(prefix) = prefix {
|
let prefix = if let Some(prefix) = prefix {
|
||||||
self.namespaces.prefixes.insert(prefix.clone(), url.clone());
|
namespaces.prefixes.insert(prefix.clone(), url.clone());
|
||||||
Some(prefix)
|
Some(prefix)
|
||||||
} else {
|
} else {
|
||||||
self.namespaces.default = Some(url.clone());
|
namespaces.default = Some(url.clone());
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -398,40 +390,40 @@ impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)] // shallow, relatively cheap .clone
|
|
||||||
struct NestedRuleParser<'a, 'b: 'a> {
|
struct NestedRuleParser<'a, 'b: 'a> {
|
||||||
shared_lock: &'a SharedRwLock,
|
shared_lock: &'a SharedRwLock,
|
||||||
context: &'a ParserContext<'b>,
|
context: &'a mut ParserContext<'b>,
|
||||||
namespaces: &'a Namespaces,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> NestedRuleParser<'a, 'b> {
|
impl<'a, 'b> NestedRuleParser<'a, 'b> {
|
||||||
|
fn nest_for_rule<R>(&mut self, rule_type: CssRuleType, cb: impl FnOnce(&mut Self) -> R) -> R {
|
||||||
|
let old_rule_type = self.context.rule_type.take();
|
||||||
|
self.context.rule_type = Some(rule_type);
|
||||||
|
let r = cb(self);
|
||||||
|
self.context.rule_type = old_rule_type;
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_nested_rules(
|
fn parse_nested_rules(
|
||||||
&mut self,
|
&mut self,
|
||||||
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(self.context, rule_type, self.namespaces);
|
self.nest_for_rule(rule_type, |parser| {
|
||||||
|
let mut iter = RuleBodyParser::new(input, parser);
|
||||||
let nested_parser = NestedRuleParser {
|
let mut rules = Vec::new();
|
||||||
shared_lock: self.shared_lock,
|
while let Some(result) = iter.next() {
|
||||||
context: &context,
|
match result {
|
||||||
namespaces: self.namespaces,
|
Ok(rule) => rules.push(rule),
|
||||||
};
|
Err((error, slice)) => {
|
||||||
|
let location = error.location;
|
||||||
let mut iter = RuleListParser::new_for_nested_rule(input, nested_parser);
|
let error = ContextualParseError::InvalidRule(slice, error);
|
||||||
let mut rules = Vec::new();
|
iter.parser.context.log_css_error(location, error);
|
||||||
while let Some(result) = iter.next() {
|
},
|
||||||
match result {
|
}
|
||||||
Ok(rule) => rules.push(rule),
|
|
||||||
Err((error, slice)) => {
|
|
||||||
let location = error.location;
|
|
||||||
let error = ContextualParseError::InvalidRule(slice, error);
|
|
||||||
self.context.log_css_error(location, error);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
CssRules::new(rules, iter.parser.shared_lock)
|
||||||
CssRules::new(rules, self.shared_lock)
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,61 +528,45 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
) -> Result<CssRule, ParseError<'i>> {
|
) -> Result<CssRule, ParseError<'i>> {
|
||||||
match prelude {
|
match prelude {
|
||||||
AtRulePrelude::FontFace => {
|
AtRulePrelude::FontFace => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
self.nest_for_rule(CssRuleType::FontFace, |p| {
|
||||||
self.context,
|
Ok(CssRule::FontFace(Arc::new(p.shared_lock.wrap(
|
||||||
CssRuleType::FontFace,
|
parse_font_face_block(&p.context, input, start.source_location()).into(),
|
||||||
self.namespaces,
|
))))
|
||||||
);
|
})
|
||||||
|
|
||||||
Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap(
|
|
||||||
parse_font_face_block(&context, input, start.source_location()).into(),
|
|
||||||
))))
|
|
||||||
},
|
},
|
||||||
AtRulePrelude::FontFeatureValues(family_names) => {
|
AtRulePrelude::FontFeatureValues(family_names) => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
self.nest_for_rule(CssRuleType::FontFeatureValues, |p| {
|
||||||
self.context,
|
Ok(CssRule::FontFeatureValues(Arc::new(p.shared_lock.wrap(
|
||||||
CssRuleType::FontFeatureValues,
|
FontFeatureValuesRule::parse(
|
||||||
self.namespaces,
|
&p.context,
|
||||||
);
|
input,
|
||||||
|
family_names,
|
||||||
Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap(
|
start.source_location(),
|
||||||
FontFeatureValuesRule::parse(
|
),
|
||||||
&context,
|
))))
|
||||||
input,
|
})
|
||||||
family_names,
|
|
||||||
start.source_location(),
|
|
||||||
),
|
|
||||||
))))
|
|
||||||
},
|
},
|
||||||
AtRulePrelude::FontPaletteValues(name) => {
|
AtRulePrelude::FontPaletteValues(name) => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
self.nest_for_rule(CssRuleType::FontPaletteValues, |p| {
|
||||||
self.context,
|
Ok(CssRule::FontPaletteValues(Arc::new(p.shared_lock.wrap(
|
||||||
CssRuleType::FontPaletteValues,
|
FontPaletteValuesRule::parse(
|
||||||
self.namespaces,
|
&p.context,
|
||||||
);
|
input,
|
||||||
|
name,
|
||||||
Ok(CssRule::FontPaletteValues(Arc::new(self.shared_lock.wrap(
|
start.source_location(),
|
||||||
FontPaletteValuesRule::parse(
|
),
|
||||||
&context,
|
))))
|
||||||
input,
|
})
|
||||||
name,
|
|
||||||
start.source_location(),
|
|
||||||
),
|
|
||||||
))))
|
|
||||||
},
|
},
|
||||||
AtRulePrelude::CounterStyle(name) => {
|
AtRulePrelude::CounterStyle(name) => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
self.nest_for_rule(CssRuleType::CounterStyle, |p| {
|
||||||
self.context,
|
Ok(CssRule::CounterStyle(Arc::new(
|
||||||
CssRuleType::CounterStyle,
|
p.shared_lock.wrap(
|
||||||
self.namespaces,
|
parse_counter_style_body(name, &p.context, input, start.source_location())?
|
||||||
);
|
.into(),
|
||||||
|
),
|
||||||
Ok(CssRule::CounterStyle(Arc::new(
|
)))
|
||||||
self.shared_lock.wrap(
|
})
|
||||||
parse_counter_style_body(name, &context, input, start.source_location())?
|
|
||||||
.into(),
|
|
||||||
),
|
|
||||||
)))
|
|
||||||
},
|
},
|
||||||
AtRulePrelude::Media(media_queries) => {
|
AtRulePrelude::Media(media_queries) => {
|
||||||
Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule {
|
Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule {
|
||||||
|
@ -600,13 +576,9 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
}))))
|
}))))
|
||||||
},
|
},
|
||||||
AtRulePrelude::Supports(condition) => {
|
AtRulePrelude::Supports(condition) => {
|
||||||
let eval_context = ParserContext::new_with_rule_type(
|
let enabled = self.nest_for_rule(CssRuleType::Style, |p| {
|
||||||
self.context,
|
condition.eval(&p.context)
|
||||||
CssRuleType::Style,
|
});
|
||||||
self.namespaces,
|
|
||||||
);
|
|
||||||
|
|
||||||
let enabled = condition.eval(&eval_context, self.namespaces);
|
|
||||||
Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(
|
Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(
|
||||||
SupportsRule {
|
SupportsRule {
|
||||||
condition,
|
condition,
|
||||||
|
@ -617,40 +589,28 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
))))
|
))))
|
||||||
},
|
},
|
||||||
AtRulePrelude::Viewport => {
|
AtRulePrelude::Viewport => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
self.nest_for_rule(CssRuleType::Viewport, |p| {
|
||||||
self.context,
|
Ok(CssRule::Viewport(Arc::new(
|
||||||
CssRuleType::Viewport,
|
p.shared_lock.wrap(ViewportRule::parse(&p.context, input)?),
|
||||||
self.namespaces,
|
)))
|
||||||
);
|
})
|
||||||
|
|
||||||
Ok(CssRule::Viewport(Arc::new(
|
|
||||||
self.shared_lock.wrap(ViewportRule::parse(&context, input)?),
|
|
||||||
)))
|
|
||||||
},
|
},
|
||||||
AtRulePrelude::Keyframes(name, vendor_prefix) => {
|
AtRulePrelude::Keyframes(name, vendor_prefix) => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
self.nest_for_rule(CssRuleType::Keyframe, |p| {
|
||||||
self.context,
|
Ok(CssRule::Keyframes(Arc::new(p.shared_lock.wrap(
|
||||||
CssRuleType::Keyframes,
|
KeyframesRule {
|
||||||
self.namespaces,
|
name,
|
||||||
);
|
keyframes: parse_keyframe_list(&mut p.context, input, p.shared_lock),
|
||||||
|
vendor_prefix,
|
||||||
Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap(
|
source_location: start.source_location(),
|
||||||
KeyframesRule {
|
},
|
||||||
name,
|
))))
|
||||||
keyframes: parse_keyframe_list(&context, input, self.shared_lock),
|
})
|
||||||
vendor_prefix,
|
|
||||||
source_location: start.source_location(),
|
|
||||||
},
|
|
||||||
))))
|
|
||||||
},
|
},
|
||||||
AtRulePrelude::Page(selectors) => {
|
AtRulePrelude::Page(selectors) => {
|
||||||
let context = ParserContext::new_with_rule_type(
|
let declarations = self.nest_for_rule(CssRuleType::Page, |p| {
|
||||||
self.context,
|
parse_property_declaration_list(&p.context, input, None)
|
||||||
CssRuleType::Page,
|
});
|
||||||
self.namespaces,
|
|
||||||
);
|
|
||||||
|
|
||||||
let declarations = parse_property_declaration_list(&context, input, None);
|
|
||||||
Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule {
|
Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule {
|
||||||
selectors,
|
selectors,
|
||||||
block: Arc::new(self.shared_lock.wrap(declarations)),
|
block: Arc::new(self.shared_lock.wrap(declarations)),
|
||||||
|
@ -763,7 +723,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
) -> Result<Self::Prelude, ParseError<'i>> {
|
) -> Result<Self::Prelude, ParseError<'i>> {
|
||||||
let selector_parser = SelectorParser {
|
let selector_parser = SelectorParser {
|
||||||
stylesheet_origin: self.context.stylesheet_origin,
|
stylesheet_origin: self.context.stylesheet_origin,
|
||||||
namespaces: self.namespaces,
|
namespaces: &self.context.namespaces,
|
||||||
url_data: self.context.url_data,
|
url_data: self.context.url_data,
|
||||||
for_supports_rule: false,
|
for_supports_rule: false,
|
||||||
};
|
};
|
||||||
|
@ -780,10 +740,9 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
start: &ParserState,
|
start: &ParserState,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<CssRule, ParseError<'i>> {
|
) -> Result<CssRule, ParseError<'i>> {
|
||||||
let context =
|
let declarations = self.nest_for_rule(CssRuleType::Style, |p| {
|
||||||
ParserContext::new_with_rule_type(self.context, CssRuleType::Style, self.namespaces);
|
parse_property_declaration_list(&p.context, input, Some(&selectors))
|
||||||
|
});
|
||||||
let declarations = parse_property_declaration_list(&context, input, Some(&selectors));
|
|
||||||
let block = Arc::new(self.shared_lock.wrap(declarations));
|
let block = Arc::new(self.shared_lock.wrap(declarations));
|
||||||
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
|
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
|
||||||
selectors,
|
selectors,
|
||||||
|
@ -793,3 +752,14 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
}))))
|
}))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> DeclarationParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
|
type Declaration = CssRule;
|
||||||
|
type Error = StyleParseErrorKind<'i>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, CssRule, StyleParseErrorKind<'i>> for NestedRuleParser<'a, 'b> {
|
||||||
|
fn parse_qualified(&self) -> bool { true }
|
||||||
|
// TODO: Nesting.
|
||||||
|
fn parse_declarations(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
|
@ -15,13 +15,12 @@ use crate::stylesheets::rules_iterator::{NestedRuleIterationCondition, RulesIter
|
||||||
use crate::stylesheets::{CssRule, CssRules, Origin, UrlExtraData};
|
use crate::stylesheets::{CssRule, CssRules, Origin, UrlExtraData};
|
||||||
use crate::use_counters::UseCounters;
|
use crate::use_counters::UseCounters;
|
||||||
use crate::{Namespace, Prefix};
|
use crate::{Namespace, Prefix};
|
||||||
use cssparser::{Parser, ParserInput, RuleListParser};
|
use cssparser::{Parser, ParserInput, StyleSheetParser};
|
||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::mem;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use style_traits::ParsingMode;
|
use style_traits::ParsingMode;
|
||||||
|
|
||||||
|
@ -86,12 +85,10 @@ impl StylesheetContents {
|
||||||
allow_import_rules: AllowImportRules,
|
allow_import_rules: AllowImportRules,
|
||||||
sanitization_data: Option<&mut SanitizationData>,
|
sanitization_data: Option<&mut SanitizationData>,
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let namespaces = RwLock::new(Namespaces::default());
|
let (namespaces, rules, source_map_url, source_url) = Stylesheet::parse_rules(
|
||||||
let (rules, source_map_url, source_url) = Stylesheet::parse_rules(
|
|
||||||
css,
|
css,
|
||||||
&url_data,
|
&url_data,
|
||||||
origin,
|
origin,
|
||||||
&mut *namespaces.write(),
|
|
||||||
&shared_lock,
|
&shared_lock,
|
||||||
stylesheet_loader,
|
stylesheet_loader,
|
||||||
error_reporter,
|
error_reporter,
|
||||||
|
@ -106,7 +103,7 @@ impl StylesheetContents {
|
||||||
rules: CssRules::new(rules, &shared_lock),
|
rules: CssRules::new(rules, &shared_lock),
|
||||||
origin,
|
origin,
|
||||||
url_data: RwLock::new(url_data),
|
url_data: RwLock::new(url_data),
|
||||||
namespaces,
|
namespaces: RwLock::new(namespaces),
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
source_map_url: RwLock::new(source_map_url),
|
source_map_url: RwLock::new(source_map_url),
|
||||||
source_url: RwLock::new(source_url),
|
source_url: RwLock::new(source_url),
|
||||||
|
@ -426,14 +423,11 @@ impl Stylesheet {
|
||||||
line_number_offset: u32,
|
line_number_offset: u32,
|
||||||
allow_import_rules: AllowImportRules,
|
allow_import_rules: AllowImportRules,
|
||||||
) {
|
) {
|
||||||
let namespaces = RwLock::new(Namespaces::default());
|
|
||||||
|
|
||||||
// FIXME: Consider adding use counters to Servo?
|
// FIXME: Consider adding use counters to Servo?
|
||||||
let (rules, source_map_url, source_url) = Self::parse_rules(
|
let (namespaces, rules, source_map_url, source_url) = Self::parse_rules(
|
||||||
css,
|
css,
|
||||||
&url_data,
|
&url_data,
|
||||||
existing.contents.origin,
|
existing.contents.origin,
|
||||||
&mut *namespaces.write(),
|
|
||||||
&existing.shared_lock,
|
&existing.shared_lock,
|
||||||
stylesheet_loader,
|
stylesheet_loader,
|
||||||
error_reporter,
|
error_reporter,
|
||||||
|
@ -445,10 +439,7 @@ impl Stylesheet {
|
||||||
);
|
);
|
||||||
|
|
||||||
*existing.contents.url_data.write() = url_data;
|
*existing.contents.url_data.write() = url_data;
|
||||||
mem::swap(
|
*existing.contents.namespaces.write() = namespaces;
|
||||||
&mut *existing.contents.namespaces.write(),
|
|
||||||
&mut *namespaces.write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Acquire the lock *after* parsing, to minimize the exclusive section.
|
// Acquire the lock *after* parsing, to minimize the exclusive section.
|
||||||
let mut guard = existing.shared_lock.write();
|
let mut guard = existing.shared_lock.write();
|
||||||
|
@ -461,7 +452,6 @@ impl Stylesheet {
|
||||||
css: &str,
|
css: &str,
|
||||||
url_data: &UrlExtraData,
|
url_data: &UrlExtraData,
|
||||||
origin: Origin,
|
origin: Origin,
|
||||||
namespaces: &mut Namespaces,
|
|
||||||
shared_lock: &SharedRwLock,
|
shared_lock: &SharedRwLock,
|
||||||
stylesheet_loader: Option<&dyn StylesheetLoader>,
|
stylesheet_loader: Option<&dyn StylesheetLoader>,
|
||||||
error_reporter: Option<&dyn ParseErrorReporter>,
|
error_reporter: Option<&dyn ParseErrorReporter>,
|
||||||
|
@ -470,7 +460,7 @@ impl Stylesheet {
|
||||||
use_counters: Option<&UseCounters>,
|
use_counters: Option<&UseCounters>,
|
||||||
allow_import_rules: AllowImportRules,
|
allow_import_rules: AllowImportRules,
|
||||||
mut sanitization_data: Option<&mut SanitizationData>,
|
mut sanitization_data: Option<&mut SanitizationData>,
|
||||||
) -> (Vec<CssRule>, Option<String>, Option<String>) {
|
) -> (Namespaces, Vec<CssRule>, Option<String>, Option<String>) {
|
||||||
let mut rules = Vec::new();
|
let mut rules = Vec::new();
|
||||||
let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset);
|
let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset);
|
||||||
let mut input = Parser::new(&mut input);
|
let mut input = Parser::new(&mut input);
|
||||||
|
@ -481,23 +471,23 @@ impl Stylesheet {
|
||||||
None,
|
None,
|
||||||
ParsingMode::DEFAULT,
|
ParsingMode::DEFAULT,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
|
/* namespaces = */ Default::default(),
|
||||||
error_reporter,
|
error_reporter,
|
||||||
use_counters,
|
use_counters,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rule_parser = TopLevelRuleParser {
|
let mut rule_parser = TopLevelRuleParser {
|
||||||
shared_lock,
|
shared_lock,
|
||||||
loader: stylesheet_loader,
|
loader: stylesheet_loader,
|
||||||
context,
|
context,
|
||||||
state: State::Start,
|
state: State::Start,
|
||||||
dom_error: None,
|
dom_error: None,
|
||||||
insert_rule_context: None,
|
insert_rule_context: None,
|
||||||
namespaces,
|
|
||||||
allow_import_rules,
|
allow_import_rules,
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
|
let mut iter = StyleSheetParser::new(&mut input, &mut rule_parser);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let result = match iter.next() {
|
let result = match iter.next() {
|
||||||
|
@ -532,7 +522,7 @@ impl Stylesheet {
|
||||||
|
|
||||||
let source_map_url = input.current_source_map_url().map(String::from);
|
let source_map_url = input.current_source_map_url().map(String::from);
|
||||||
let source_url = input.current_source_url().map(String::from);
|
let source_url = input.current_source_url().map(String::from);
|
||||||
(rules, source_map_url, source_url)
|
(rule_parser.context.namespaces.into_owned(), rules, source_map_url, source_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an empty stylesheet and parses it with a given base url, origin
|
/// Creates an empty stylesheet and parses it with a given base url, origin
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::selector_parser::{SelectorImpl, SelectorParser};
|
||||||
use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
|
use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
|
||||||
use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use crate::str::CssStringWriter;
|
use crate::str::CssStringWriter;
|
||||||
use crate::stylesheets::{CssRuleType, CssRules, Namespaces};
|
use crate::stylesheets::{CssRuleType, CssRules};
|
||||||
use cssparser::parse_important;
|
use cssparser::parse_important;
|
||||||
use cssparser::{Delimiter, Parser, SourceLocation, Token};
|
use cssparser::{Delimiter, Parser, SourceLocation, Token};
|
||||||
use cssparser::{ParseError as CssParseError, ParserInput};
|
use cssparser::{ParseError as CssParseError, ParserInput};
|
||||||
|
@ -228,15 +228,15 @@ impl SupportsCondition {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a supports condition
|
/// Evaluate a supports condition
|
||||||
pub fn eval(&self, cx: &ParserContext, namespaces: &Namespaces) -> bool {
|
pub fn eval(&self, cx: &ParserContext) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
SupportsCondition::Not(ref cond) => !cond.eval(cx, namespaces),
|
SupportsCondition::Not(ref cond) => !cond.eval(cx),
|
||||||
SupportsCondition::Parenthesized(ref cond) => cond.eval(cx, namespaces),
|
SupportsCondition::Parenthesized(ref cond) => cond.eval(cx),
|
||||||
SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx, namespaces)),
|
SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)),
|
||||||
SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx, namespaces)),
|
SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)),
|
||||||
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
|
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
|
||||||
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
|
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
|
||||||
SupportsCondition::Selector(ref selector) => selector.eval(cx, namespaces),
|
SupportsCondition::Selector(ref selector) => selector.eval(cx),
|
||||||
SupportsCondition::FontFormat(ref format) => eval_font_format(format),
|
SupportsCondition::FontFormat(ref format) => eval_font_format(format),
|
||||||
SupportsCondition::FontTech(ref tech) => eval_font_tech(tech),
|
SupportsCondition::FontTech(ref tech) => eval_font_tech(tech),
|
||||||
SupportsCondition::FutureSyntax(_) => false,
|
SupportsCondition::FutureSyntax(_) => false,
|
||||||
|
@ -374,13 +374,13 @@ impl ToCss for RawSelector {
|
||||||
|
|
||||||
impl RawSelector {
|
impl RawSelector {
|
||||||
/// Tries to evaluate a `selector()` function.
|
/// Tries to evaluate a `selector()` function.
|
||||||
pub fn eval(&self, context: &ParserContext, namespaces: &Namespaces) -> bool {
|
pub fn eval(&self, context: &ParserContext) -> bool {
|
||||||
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
|
input
|
||||||
.parse_entirely(|input| -> Result<(), CssParseError<()>> {
|
.parse_entirely(|input| -> Result<(), CssParseError<()>> {
|
||||||
let parser = SelectorParser {
|
let parser = SelectorParser {
|
||||||
namespaces,
|
namespaces: &context.namespaces,
|
||||||
stylesheet_origin: context.stylesheet_origin,
|
stylesheet_origin: context.stylesheet_origin,
|
||||||
url_data: context.url_data,
|
url_data: context.url_data,
|
||||||
for_supports_rule: true,
|
for_supports_rule: true,
|
||||||
|
|
|
@ -25,8 +25,8 @@ use crate::values::specified::{self, NoCalcLength};
|
||||||
use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength};
|
use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{
|
use cssparser::{
|
||||||
parse_important, AtRuleParser, CowRcStr, DeclarationListParser, DeclarationParser, Parser,
|
parse_important, AtRuleParser, CowRcStr, DeclarationParser, Parser, QualifiedRuleParser,
|
||||||
QualifiedRuleParser,
|
RuleBodyItemParser, RuleBodyParser,
|
||||||
};
|
};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
|
@ -233,15 +233,17 @@ fn parse_shorthand<'i, 't>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ViewportDeclarations = Vec<ViewportDescriptorDeclaration>;
|
||||||
|
|
||||||
impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = Vec<ViewportDescriptorDeclaration>;
|
type AtRule = ViewportDeclarations;
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type QualifiedRule = Vec<ViewportDescriptorDeclaration>;
|
type QualifiedRule = ViewportDeclarations;
|
||||||
type Error = StyleParseErrorKind<'i>;
|
type Error = StyleParseErrorKind<'i>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +310,11 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'i> RuleBodyItemParser<'i, ViewportDeclarations, StyleParseErrorKind<'i>> for ViewportRuleParser<'a, 'b> {
|
||||||
|
fn parse_declarations(&self) -> bool { true }
|
||||||
|
fn parse_qualified(&self) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
/// A `@viewport` rule.
|
/// A `@viewport` rule.
|
||||||
#[derive(Clone, Debug, PartialEq, ToShmem)]
|
#[derive(Clone, Debug, PartialEq, ToShmem)]
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||||
|
@ -337,10 +344,10 @@ impl ViewportRule {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let parser = ViewportRuleParser { context };
|
let mut parser = ViewportRuleParser { context };
|
||||||
|
|
||||||
let mut cascade = Cascade::new();
|
let mut cascade = Cascade::new();
|
||||||
let mut parser = DeclarationListParser::new(input, parser);
|
let mut parser = RuleBodyParser::new(input, &mut parser);
|
||||||
while let Some(result) = parser.next() {
|
while let Some(result) = parser.next() {
|
||||||
match result {
|
match result {
|
||||||
Ok(declarations) => {
|
Ok(declarations) => {
|
||||||
|
@ -455,9 +462,7 @@ impl ViewportRule {
|
||||||
|
|
||||||
let declarations: Vec<_> = declarations.into_iter().filter_map(|entry| entry).collect();
|
let declarations: Vec<_> = declarations.into_iter().filter_map(|entry| entry).collect();
|
||||||
if !declarations.is_empty() {
|
if !declarations.is_empty() {
|
||||||
Some(ViewportRule {
|
Some(ViewportRule { declarations })
|
||||||
declarations: declarations,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -784,8 +789,8 @@ impl MaybeNew for ViewportConstraints {
|
||||||
min_zoom: min_zoom.map(PinchZoomFactor::new),
|
min_zoom: min_zoom.map(PinchZoomFactor::new),
|
||||||
max_zoom: max_zoom.map(PinchZoomFactor::new),
|
max_zoom: max_zoom.map(PinchZoomFactor::new),
|
||||||
|
|
||||||
user_zoom: user_zoom,
|
user_zoom,
|
||||||
orientation: orientation,
|
orientation,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -879,12 +879,7 @@ impl Parse for Attr {
|
||||||
|
|
||||||
/// Get the Namespace for a given prefix from the namespace map.
|
/// Get the Namespace for a given prefix from the namespace map.
|
||||||
fn get_namespace_for_prefix(prefix: &Prefix, context: &ParserContext) -> Option<Namespace> {
|
fn get_namespace_for_prefix(prefix: &Prefix, context: &ParserContext) -> Option<Namespace> {
|
||||||
context
|
context.namespaces.prefixes.get(prefix).cloned()
|
||||||
.namespaces
|
|
||||||
.as_ref()?
|
|
||||||
.prefixes
|
|
||||||
.get(prefix)
|
|
||||||
.map(|x| x.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attr {
|
impl Attr {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue