From 5a55978478bca98115bd274560e2cbbb15d347b1 Mon Sep 17 00:00:00 2001 From: Julian Descottes Date: Wed, 27 Mar 2019 12:12:55 +0000 Subject: [PATCH 01/59] style: Augment CSS errors with the CSS selector. Differential Revision: https://phabricator.services.mozilla.com/D24894 --- components/style/error_reporting.rs | 6 ++++-- components/style/properties/declaration_block.rs | 8 ++++++-- components/style/stylesheets/rule_parser.rs | 6 +++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/components/style/error_reporting.rs b/components/style/error_reporting.rs index c58964c057a..9d54f62e318 100644 --- a/components/style/error_reporting.rs +++ b/components/style/error_reporting.rs @@ -10,12 +10,14 @@ use crate::stylesheets::UrlExtraData; use cssparser::{BasicParseErrorKind, ParseErrorKind, SourceLocation, Token}; use std::fmt; use style_traits::ParseError; +use crate::selector_parser::{SelectorImpl}; +use selectors::SelectorList; /// Errors that can be encountered while parsing CSS. #[derive(Debug)] pub enum ContextualParseError<'a> { /// A property declaration was not recognized. - UnsupportedPropertyDeclaration(&'a str, ParseError<'a>), + UnsupportedPropertyDeclaration(&'a str, ParseError<'a>, Option<&'a SelectorList>), /// A font face descriptor was not recognized. UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>), /// A font feature values descriptor was not recognized. @@ -121,7 +123,7 @@ impl<'a> fmt::Display for ContextualParseError<'a> { } match *self { - ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err) => { + ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err, _selectors) => { write!(f, "Unsupported property declaration: '{}', ", decl)?; parse_error_to_str(err, f) }, diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index e4396e764a4..5a2fd6f2236 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -25,6 +25,8 @@ use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCs use crate::stylesheets::{CssRuleType, Origin, UrlExtraData}; use super::*; use crate::values::computed::Context; +use crate::selector_parser::{SelectorImpl}; +use selectors::SelectorList; /// The animation rules. /// @@ -1211,7 +1213,7 @@ pub fn parse_style_attribute( ); let mut input = ParserInput::new(input); - parse_property_declaration_list(&context, &mut Parser::new(&mut input)) + parse_property_declaration_list(&context, &mut Parser::new(&mut input), None) } /// Parse a given property declaration. Can result in multiple @@ -1248,6 +1250,7 @@ pub fn parse_one_declaration_into( let error = ContextualParseError::UnsupportedPropertyDeclaration( parser.slice_from(start_position), err, + None ); context.log_css_error(location, error); }) @@ -1312,6 +1315,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> { pub fn parse_property_declaration_list( context: &ParserContext, input: &mut Parser, + selectors: Option<&SelectorList> ) -> PropertyDeclarationBlock { let mut declarations = SourcePropertyDeclaration::new(); let mut block = PropertyDeclarationBlock::new(); @@ -1338,7 +1342,7 @@ pub fn parse_property_declaration_list( } let location = error.location; - let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error); + let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error, selectors); context.log_css_error(location, error); } } diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index a780ebce250..8f4cb088cf0 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -9,7 +9,7 @@ use crate::error_reporting::ContextualParseError; use crate::font_face::parse_font_face_block; use crate::media_queries::MediaList; use crate::parser::{Parse, ParserContext}; -use crate::properties::parse_property_declaration_list; +use crate::properties::{parse_property_declaration_list}; use crate::selector_parser::{SelectorImpl, SelectorParser}; use crate::shared_lock::{Locked, SharedRwLock}; use crate::str::starts_with_ignore_ascii_case; @@ -548,7 +548,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { self.namespaces, ); - let declarations = parse_property_declaration_list(&context, input); + let declarations = parse_property_declaration_list(&context, input, None); Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule { block: Arc::new(self.shared_lock.wrap(declarations)), source_location, @@ -596,7 +596,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> { let context = ParserContext::new_with_rule_type(self.context, CssRuleType::Style, self.namespaces); - let declarations = parse_property_declaration_list(&context, input); + let declarations = parse_property_declaration_list(&context, input, Some(&selectors)); let block = Arc::new(self.shared_lock.wrap(declarations)); Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule { selectors, From 1f73c524bd240ece2db99ef39f5f4441742cb06b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 27 Mar 2019 15:03:20 +0000 Subject: [PATCH 02/59] style: Follow the list-item definition from the spec a bit more closely. The HTML restriction doesn't match any browser. This matches Edge, though I filed https://github.com/w3c/csswg-drafts/issues/3766 about the pseudo-element condition. Differential Revision: https://phabricator.services.mozilla.com/D24936 --- components/style/style_adjuster.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 070a2299969..91e4bba992b 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -728,10 +728,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// /// https://drafts.csswg.org/css-lists-3/#declaring-a-list-item #[cfg(feature = "gecko")] - fn adjust_for_list_item(&mut self, element: Option) - where - E: TElement, - { + fn adjust_for_list_item(&mut self) { use crate::properties::longhands::counter_increment::computed_value::T as ComputedIncrement; use crate::values::generics::counters::CounterPair; use crate::values::specified::list::MozListReversed; @@ -743,9 +740,6 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { if self.style.pseudo.is_some() { return; } - if !element.map_or(false, |e| e.is_html_element()) { - return; - } // Note that we map
  • to 'counter-set: list-item INTEGER; // counter-increment: list-item 0;' so we'll return here unless the author // explicitly specified something else. @@ -833,7 +827,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { #[cfg(feature = "gecko")] { self.adjust_for_appearance(element); - self.adjust_for_list_item(element); + self.adjust_for_list_item(); } self.set_bits(); } From 76c0ae565eef1408fc3f1c99d99fa532172793cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 28 Mar 2019 13:50:13 +0000 Subject: [PATCH 03/59] style: Fix ::marker invalidation when we need to potentially insert a marker as a result of a style change. Differential Revision: https://phabricator.services.mozilla.com/D24888 --- .../style/invalidation/element/invalidator.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs index 7ed97c0b197..371c0771183 100644 --- a/components/style/invalidation/element/invalidator.rs +++ b/components/style/invalidation/element/invalidator.rs @@ -750,8 +750,19 @@ where // // Note that we'll also restyle the pseudo-element because // it would match this invalidation. - if self.processor.invalidates_on_eager_pseudo_element() && pseudo.is_eager() { - invalidated_self = true; + if self.processor.invalidates_on_eager_pseudo_element() { + if pseudo.is_eager() { + invalidated_self = true; + } + // If we start or stop matching some marker rules, and + // don't have a marker, then we need to restyle the + // element to potentially create one. + // + // Same caveats as for other eager pseudos apply, this + // could be more fine-grained. + if pseudo.is_marker() && self.element.marker_pseudo_element().is_none() { + invalidated_self = true; + } } } From bd77cd64b93e528fe50d5b1f04756ca02f9a5ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 29 Mar 2019 11:12:12 +0000 Subject: [PATCH 04/59] style: Refactor some enabledness checks. There are some common checks that could get some easy-to-use aliases. Differential Revision: https://phabricator.services.mozilla.com/D25117 --- .../media_queries/media_feature_expression.rs | 3 +- components/style/parser.rs | 13 ++ components/style/stylesheets/supports_rule.rs | 3 +- components/style/values/specified/box.rs | 197 +++++++++--------- 4 files changed, 111 insertions(+), 105 deletions(-) diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs index 6a9db93e889..53e24ae5b17 100644 --- a/components/style/media_queries/media_feature_expression.rs +++ b/components/style/media_queries/media_feature_expression.rs @@ -17,7 +17,6 @@ use crate::parser::{Parse, ParserContext}; #[cfg(feature = "servo")] use crate::servo::media_queries::MEDIA_FEATURES; use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; -use crate::stylesheets::Origin; use crate::values::computed::{self, ToComputedValue}; use crate::values::specified::{Integer, Length, Number, Resolution}; use crate::values::{serialize_atom_identifier, CSSFloat}; @@ -290,7 +289,7 @@ impl MediaFeatureExpression { let mut requirements = ParsingRequirements::empty(); - if context.chrome_rules_enabled() || context.stylesheet_origin == Origin::UserAgent { + if context.in_ua_or_chrome_sheet() { requirements.insert(ParsingRequirements::CHROME_AND_UA_ONLY); } diff --git a/components/style/parser.rs b/components/style/parser.rs index 6e9d4496cd7..f3190f7f72b 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -146,10 +146,23 @@ impl<'a> ParserContext<'a> { error_reporter.report_error(self.url_data, location, error) } + /// Whether we're in a user-agent stylesheet. + #[inline] + pub fn in_ua_sheet(&self) -> bool { + self.stylesheet_origin == Origin::UserAgent + } + /// Returns whether chrome-only rules should be parsed. + #[inline] pub fn chrome_rules_enabled(&self) -> bool { self.url_data.is_chrome() || self.stylesheet_origin == Origin::User } + + /// Whether we're in a user-agent stylesheet or chrome rules are enabled. + #[inline] + pub fn in_ua_or_chrome_sheet(&self) -> bool { + self.in_ua_sheet() || self.chrome_rules_enabled() + } } /// A trait to abstract parsing of a specified value given a `ParserContext` and diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index 45f6f97812d..3ed0595aa44 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -223,8 +223,7 @@ impl SupportsCondition { #[cfg(feature = "gecko")] fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool { use crate::gecko_bindings::bindings; - use crate::stylesheets::Origin; - if cx.stylesheet_origin != Origin::UserAgent && !cx.chrome_rules_enabled() { + if !cx.in_ua_or_chrome_sheet() { return false; } unsafe { bindings::Gecko_GetBoolPrefValue(name.as_ptr()) } diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index ab81d4c3450..11ab02f045f 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -21,22 +21,17 @@ use std::fmt::{self, Write}; use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; -fn in_ua_or_chrome_sheet(context: &ParserContext) -> bool { - use crate::stylesheets::Origin; - context.stylesheet_origin == Origin::UserAgent || context.chrome_rules_enabled() -} - #[cfg(feature = "gecko")] fn moz_display_values_enabled(context: &ParserContext) -> bool { use crate::gecko_bindings::structs; - in_ua_or_chrome_sheet(context) || + context.in_ua_or_chrome_sheet() || unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled } } #[cfg(feature = "gecko")] fn moz_box_display_values_enabled(context: &ParserContext) -> bool { use crate::gecko_bindings::structs; - in_ua_or_chrome_sheet(context) || + context.in_ua_or_chrome_sheet() || unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled } @@ -988,27 +983,27 @@ pub enum Appearance { /// A typical dialog button. Button, /// Various arrows that go in buttons - #[parse(condition = "in_ua_or_chrome_sheet")] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] ButtonArrowDown, - #[parse(condition = "in_ua_or_chrome_sheet")] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] ButtonArrowNext, - #[parse(condition = "in_ua_or_chrome_sheet")] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] ButtonArrowPrevious, - #[parse(condition = "in_ua_or_chrome_sheet")] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] ButtonArrowUp, /// A rectangular button that contains complex content /// like images (e.g. HTML