author | Gurzau Raul <rgurzau@mozilla.com> |
Sat, 09 Jun 2018 10:51:07 +0300 | |
changeset 422067 | e8157c8580f89ea168abb77f1b74065f9204f770 |
parent 422066 | 8e8a87c6a518e51b42abf2d12cdfcced8003a4ce (current diff) |
parent 421963 | 35bd1a865ff5262e05f2e421d499e8c42a5df2de (diff) |
child 422068 | caa6f15a7c44361d0cee655971334ed2b5cffcce |
push id | 34114 |
push user | btara@mozilla.com |
push date | Sat, 09 Jun 2018 15:31:58 +0000 |
treeherder | mozilla-central@e02a5155d815 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 62.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/style/CSSPropFlags.h +++ b/layout/style/CSSPropFlags.h @@ -44,18 +44,15 @@ enum class CSSPropFlags : uint8_t // This property can be animated on the compositor. CanAnimateOnCompositor = 1 << 4, // This property is an internal property that is not represented in // the DOM. Properties with this flag are defined in an #ifndef // CSS_PROP_LIST_EXCLUDE_INTERNAL section. Internal = 1 << 5, - - // Whether this property should be serialized by Servo in getComputedStyle. - SerializedByServo = 1 << 6, }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CSSPropFlags) } // namespace mozilla #endif // mozilla_CSSPropFlags_h
--- a/layout/style/ServoBindingList.h +++ b/layout/style/ServoBindingList.h @@ -820,31 +820,28 @@ SERVO_BINDING_FUNC(Servo_StyleSet_GetCom const mozilla::ServoElementSnapshotTable* snapshots, RawServoAnimationValueBorrowed animation) // For canvas font. SERVO_BINDING_FUNC(Servo_SerializeFontValueForCanvas, void, RawServoDeclarationBlockBorrowed declarations, nsAString* buffer) -// GetComputedStyle APIs. +// Get custom property value. SERVO_BINDING_FUNC(Servo_GetCustomPropertyValue, bool, ComputedStyleBorrowed computed_values, const nsAString* name, nsAString* value) SERVO_BINDING_FUNC(Servo_GetCustomPropertiesCount, uint32_t, ComputedStyleBorrowed computed_values) SERVO_BINDING_FUNC(Servo_GetCustomPropertyNameAt, bool, ComputedStyleBorrowed, uint32_t index, nsAString* name) -SERVO_BINDING_FUNC(Servo_GetPropertyValue, void, - ComputedStyleBorrowed computed_values, - nsCSSPropertyID property, nsAString* value) SERVO_BINDING_FUNC(Servo_ProcessInvalidations, void, RawServoStyleSetBorrowed set, RawGeckoElementBorrowed element, const mozilla::ServoElementSnapshotTable* snapshots) SERVO_BINDING_FUNC(Servo_HasPendingRestyleAncestor, bool,
--- a/layout/style/ServoCSSPropList.mako.py +++ b/layout/style/ServoCSSPropList.mako.py @@ -63,60 +63,30 @@ def is_internal(prop): def method(prop): if prop.name == "float": return "CssFloat" if prop.name.startswith("-x-"): return prop.camel_case[1:] return prop.camel_case -# Colors, integers and lengths are easy as well. -# -# TODO(emilio): This will go away once the rest of the longhands have been -# moved or perhaps using a blacklist for the ones with non-layout-dependence -# but other non-trivial dependence like scrollbar colors. -SERIALIZED_PREDEFINED_TYPES = [ - "Color", - "Integer", - "Length", - "Opacity", -] - -def serialized_by_servo(prop): - # If the property requires layout information, no such luck. - if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags: - return False - # No shorthands yet. - if prop.type() == "shorthand": - return False - # Keywords are all fine. - if prop.keyword: - return True - if prop.predefined_type in SERIALIZED_PREDEFINED_TYPES: - return True - # TODO(emilio): Enable the rest of the longhands. - return False - - def flags(prop): result = [] if prop.explicitly_enabled_in_chrome(): result.append("EnabledInUASheetsAndChrome") elif prop.explicitly_enabled_in_ua_sheets(): result.append("EnabledInUASheets") if is_internal(prop): result.append("Internal") if prop.enabled_in == "": result.append("Inaccessible") if "GETCS_NEEDS_LAYOUT_FLUSH" in prop.flags: result.append("GetCSNeedsLayoutFlush") if "CAN_ANIMATE_ON_COMPOSITOR" in prop.flags: result.append("CanAnimateOnCompositor") - if serialized_by_servo(prop): - result.append("SerializedByServo") return ", ".join('"CSSPropFlags::{}"'.format(flag) for flag in result) def pref(prop): if prop.gecko_pref: return '"' + prop.gecko_pref + '"' return '""' def sub_properties(prop):
--- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -430,57 +430,30 @@ nsComputedDOMStyle::GetParentRule() } NS_IMETHODIMP nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName, nsAString& aReturn) { aReturn.Truncate(); - nsCSSPropertyID prop = - nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent); - - const ComputedStyleMap::Entry* entry = nullptr; - if (prop != eCSSPropertyExtra_variable) { - entry = GetComputedStyleMap()->FindEntryForProperty(prop); - if (!entry) { - return NS_OK; - } - } - - const bool layoutFlushIsNeeded = entry && entry->IsLayoutFlushNeeded(); - UpdateCurrentStyleSources(layoutFlushIsNeeded); - if (!mComputedStyle) { - return NS_ERROR_NOT_AVAILABLE; - } - - auto cleanup = mozilla::MakeScopeExit([&] { - ClearCurrentStyleSources(); - }); - - if (!entry) { - MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName)); - const nsAString& name = - Substring(aPropertyName, CSS_CUSTOM_NAME_PREFIX_LENGTH); - Servo_GetCustomPropertyValue(mComputedStyle, &name, &aReturn); - return NS_OK; - } - - if (!nsCSSProps::PropHasFlags(prop, CSSPropFlags::SerializedByServo)) { - if (RefPtr<CSSValue> value = (this->*entry->mGetter)()) { - ErrorResult rv; - nsString text; - value->GetCssText(text, rv); - aReturn.Assign(text); - return rv.StealNSResult(); - } - return NS_OK; - } - - Servo_GetPropertyValue(mComputedStyle, prop, &aReturn); + ErrorResult error; + RefPtr<CSSValue> val = + GetPropertyCSSValueWithoutWarning(aPropertyName, error); + if (error.Failed()) { + return error.StealNSResult(); + } + + if (val) { + nsString text; + val->GetCssText(text, error); + aReturn.Assign(text); + return error.StealNSResult(); + } + return NS_OK; } /* static */ already_AddRefed<ComputedStyle> nsComputedDOMStyle::GetComputedStyle(Element* aElement, nsAtom* aPseudo, StyleType aStyleType) @@ -1009,16 +982,67 @@ nsComputedDOMStyle::ClearCurrentStyleSou ClearComputedStyle(); } mOuterFrame = nullptr; mInnerFrame = nullptr; mPresShell = nullptr; } +already_AddRefed<CSSValue> +nsComputedDOMStyle::GetPropertyCSSValueWithoutWarning( + const nsAString& aPropertyName, + ErrorResult& aRv) +{ + nsCSSPropertyID prop = + nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent); + + bool needsLayoutFlush; + ComputedStyleMap::Entry::ComputeMethod getter; + + if (prop == eCSSPropertyExtra_variable) { + needsLayoutFlush = false; + getter = nullptr; + } else { + const ComputedStyleMap::Entry* propEntry = + GetComputedStyleMap()->FindEntryForProperty(prop); + + if (!propEntry) { +#ifdef DEBUG_ComputedDOMStyle + NS_WARNING(PromiseFlatCString(NS_ConvertUTF16toUTF8(aPropertyName) + + NS_LITERAL_CSTRING(" is not queryable!")).get()); +#endif + + // NOTE: For branches, we should flush here for compatibility! + return nullptr; + } + + needsLayoutFlush = propEntry->IsLayoutFlushNeeded(); + getter = propEntry->mGetter; + } + + UpdateCurrentStyleSources(needsLayoutFlush); + if (!mComputedStyle) { + aRv.Throw(NS_ERROR_NOT_AVAILABLE); + return nullptr; + } + + RefPtr<CSSValue> val; + if (prop == eCSSPropertyExtra_variable) { + val = DoGetCustomProperty(aPropertyName); + } else { + // Call our pointer-to-member-function. + val = (this->*getter)(); + } + + ClearCurrentStyleSources(); + + return val.forget(); +} + NS_IMETHODIMP nsComputedDOMStyle::RemoveProperty(const nsAString& aPropertyName, nsAString& aReturn) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } @@ -7163,16 +7187,36 @@ nsComputedDOMStyle::DoGetAnimationPlaySt } static void MarkComputedStyleMapDirty(const char* aPref, void* aData) { static_cast<ComputedStyleMap*>(aData)->MarkDirty(); } +already_AddRefed<CSSValue> +nsComputedDOMStyle::DoGetCustomProperty(const nsAString& aPropertyName) +{ + MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName)); + + nsString variableValue; + const nsAString& name = Substring(aPropertyName, + CSS_CUSTOM_NAME_PREFIX_LENGTH); + bool present = + Servo_GetCustomPropertyValue(mComputedStyle, &name, &variableValue); + if (!present) { + return nullptr; + } + + RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; + val->SetString(variableValue); + + return val.forget(); +} + void nsComputedDOMStyle::ParentChainChanged(nsIContent* aContent) { NS_ASSERTION(mContent == aContent, "didn't we register mContent?"); NS_ASSERTION(mResolvedComputedStyle, "should have only registered an observer when " "mResolvedComputedStyle is true");
--- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -54,16 +54,20 @@ class nsComputedDOMStyle final : public , public nsStubMutationObserver { private: // Convenience typedefs: typedef nsCSSKTableEntry KTableEntry; typedef mozilla::dom::CSSValue CSSValue; typedef mozilla::StyleGeometryBox StyleGeometryBox; + already_AddRefed<CSSValue> + GetPropertyCSSValueWithoutWarning(const nsAString& aProp, + mozilla::ErrorResult& aRv); + public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsComputedDOMStyle, nsICSSDeclaration) NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER nsresult GetPropertyValue(const nsCSSPropertyID aPropID, nsAString& aValue) override; @@ -608,16 +612,19 @@ private: already_AddRefed<CSSValue> DoGetClipPath(); already_AddRefed<CSSValue> DoGetFilter(); already_AddRefed<CSSValue> DoGetMaskType(); already_AddRefed<CSSValue> DoGetPaintOrder(); already_AddRefed<CSSValue> DoGetContextProperties(); + /* Custom properties */ + already_AddRefed<CSSValue> DoGetCustomProperty(const nsAString& aPropertyName); + /* Helper functions */ void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor); void SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue, const mozilla::StyleComplexColor& aColor); void SetValueForWidgetColor(nsROCSSPrimitiveValue* aValue, const mozilla::StyleComplexColor& aColor, uint8_t aWidgetType); void SetValueToStyleImage(const nsStyleImage& aStyleImage,
--- a/servo/components/style/properties/data.py +++ b/servo/components/style/properties/data.py @@ -221,20 +221,16 @@ class Longhand(object): # discrete). For now, it is still non-animatable. self.animatable = False self.transitionable = False self.animation_value_type = None # See compute_damage for the various values this can take self.servo_restyle_damage = servo_restyle_damage - @staticmethod - def type(): - return "longhand" - def experimental(self, product): if product == "gecko": return bool(self.gecko_pref) return bool(self.servo_pref) # FIXME(emilio): Shorthand and Longhand should really share a base class. def explicitly_enabled_in_ua_sheets(self): return self.enabled_in in ["ua", "chrome"] @@ -360,20 +356,16 @@ class Shorthand(object): if sub.transitionable: transitionable = True break return transitionable animatable = property(get_animatable) transitionable = property(get_transitionable) - @staticmethod - def type(): - return "shorthand" - def experimental(self, product): if product == "gecko": return bool(self.gecko_pref) return bool(self.servo_pref) # FIXME(emilio): Shorthand and Longhand should really share a base class. def explicitly_enabled_in_ua_sheets(self): return self.enabled_in in ["ua", "chrome"] @@ -395,20 +387,16 @@ class Alias(object): self.camel_case = to_camel_case(self.ident) self.original = original self.enabled_in = original.enabled_in self.servo_pref = original.servo_pref self.gecko_pref = gecko_pref self.allowed_in_page_rule = original.allowed_in_page_rule self.allowed_in_keyframe_block = original.allowed_in_keyframe_block - @staticmethod - def type(): - return "alias" - def experimental(self, product): if product == "gecko": return bool(self.gecko_pref) return bool(self.servo_pref) def explicitly_enabled_in_ua_sheets(self): return self.enabled_in in ["ua", "chrome"]
--- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -17,17 +17,18 @@ use custom_properties::CustomPropertiesB use servo_arc::{Arc, UniqueArc}; use smallbitvec::SmallBitVec; use std::borrow::Cow; use std::{ops, ptr}; use std::cell::RefCell; use std::fmt::{self, Write}; use std::mem::{self, ManuallyDrop}; -use cssparser::{Parser, RGBA, TokenSerializationType}; +#[cfg(feature = "servo")] use cssparser::RGBA; +use cssparser::{Parser, TokenSerializationType}; use cssparser::ParserInput; #[cfg(feature = "servo")] use euclid::SideOffsets2D; use context::QuirksMode; use font_metrics::FontMetricsProvider; #[cfg(feature = "gecko")] use gecko_bindings::bindings; #[cfg(feature = "gecko")] use gecko_bindings::structs::{self, nsCSSPropertyID}; #[cfg(feature = "servo")] use logical_geometry::LogicalMargin; #[cfg(feature = "servo")] use computed_values; @@ -39,16 +40,17 @@ use parser::ParserContext; use rule_cache::{RuleCache, RuleCacheConditions}; use selector_parser::PseudoElement; use selectors::parser::SelectorParseErrorKind; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; use shared_lock::StylesheetGuards; use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; use stylesheets::{CssRuleType, Origin, UrlExtraData}; +#[cfg(feature = "servo")] use values::Either; use values::generics::text::LineHeight; use values::computed; use values::computed::NonNegativeLength; use values::serialize_atom_name; use rule_tree::{CascadeLevel, StrongRuleNode}; use self::computed_value_flags::*; use str::{CssString, CssStringBorrow, CssStringWriter}; use style_adjuster::StyleAdjuster; @@ -827,23 +829,23 @@ bitflags! { /// absolutely positioned elements. const ABSPOS_CB = 1 << 2; /// This longhand property applies to ::first-letter. const APPLIES_TO_FIRST_LETTER = 1 << 3; /// This longhand property applies to ::first-line. const APPLIES_TO_FIRST_LINE = 1 << 4; /// This longhand property applies to ::placeholder. const APPLIES_TO_PLACEHOLDER = 1 << 5; - /// This property's getComputedStyle implementation requires layout - /// to be flushed. - const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 6; /* The following flags are currently not used in Rust code, they * only need to be listed in corresponding properties so that * they can be checked in the C++ side via ServoCSSPropList.h. */ + /// This property's getComputedStyle implementation requires layout + /// to be flushed. + const GETCS_NEEDS_LAYOUT_FLUSH = 0; /// This property can be animated on the compositor. const CAN_ANIMATE_ON_COMPOSITOR = 0; } } /// An identifier for a given longhand property. #[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq)] #[repr(u16)] @@ -2607,69 +2609,16 @@ impl ComputedValues { pub fn visited_rules(&self) -> Option<<&StrongRuleNode> { self.visited_style.as_ref().and_then(|s| s.rules.as_ref()) } /// Gets a reference to the custom properties map (if one exists). pub fn custom_properties(&self) -> Option<<&Arc<::custom_properties::CustomPropertiesMap>> { self.custom_properties.as_ref() } - - /// Writes the value of the given longhand as a string in `dest`. - /// - /// Note that the value will usually be the computed value, except for - /// colors, where it's resolved. - pub fn get_longhand_property_value<W>( - &self, - property_id: LonghandId, - dest: &mut CssWriter<W> - ) -> fmt::Result - where - W: Write, - { - // TODO(emilio): Is it worth to merge branches here just like - // PropertyDeclaration::to_css does? - // - // We'd need to get a concept of ~resolved value, which may not be worth - // it. - match property_id { - % for prop in data.longhands: - LonghandId::${prop.camel_case} => { - let style_struct = - self.get_${prop.style_struct.ident.strip("_")}(); - let value = - style_struct - % if prop.logical: - .clone_${prop.ident}(self.writing_mode); - % else: - .clone_${prop.ident}(); - % endif - - % if prop.predefined_type == "Color": - let value = self.resolve_color(value); - % endif - - value.to_css(dest) - } - % endfor - } - } - - /// Resolves the currentColor keyword. - /// - /// Any color value from computed values (except for the 'color' property - /// itself) should go through this method. - /// - /// Usage example: - /// let top_color = - /// style.resolve_color(style.get_border().clone_border_top_color()); - #[inline] - pub fn resolve_color(&self, color: computed::Color) -> RGBA { - color.to_rgba(self.get_color().clone_color()) - } } #[cfg(feature = "servo")] impl ComputedValues { /// Create a new refcounted `ComputedValues` pub fn new( _: &Device, _: Option<<&ComputedValues>, @@ -2772,16 +2721,28 @@ impl ComputedValuesInner { } /// Whether the current style is multicolumn. #[inline] pub fn is_multicol(&self) -> bool { self.get_column().is_multicol() } + /// Resolves the currentColor keyword. + /// + /// Any color value from computed values (except for the 'color' property + /// itself) should go through this method. + /// + /// Usage example: + /// let top_color = style.resolve_color(style.Border.border_top_color); + #[inline] + pub fn resolve_color(&self, color: computed::Color) -> RGBA { + color.to_rgba(self.get_color().color) + } + /// Get the logical computed inline size. #[inline] pub fn content_inline_size(&self) -> computed::LengthOrPercentageOrAuto { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.height } else { position_style.width @@ -2936,29 +2897,29 @@ impl ComputedValuesInner { // Neither perspective nor transform present false } /// Serializes the computed value of this property as a string. pub fn computed_value_to_string(&self, property: PropertyDeclarationId) -> String { match property { - PropertyDeclarationId::Longhand(id) => { - let mut s = String::new(); - self.get_longhand_property_value( - property, - &mut CssWriter::new(&mut s) - ).unwrap(); - s - } + % for style_struct in data.active_style_structs(): + % for longhand in style_struct.longhands: + PropertyDeclarationId::Longhand(LonghandId::${longhand.camel_case}) => { + self.${style_struct.ident}.${longhand.ident}.to_css_string() + } + % endfor + % endfor PropertyDeclarationId::Custom(name) => { self.custom_properties .as_ref() .and_then(|map| map.get(name)) - .map_or(String::new(), |value| value.to_css_string()) + .map(|value| value.to_css_string()) + .unwrap_or(String::new()) } } } } % if product == "gecko": pub use ::servo_arc::RawOffsetArc as BuilderArc; /// Clone an arc, returning a regular arc
--- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -5128,35 +5128,16 @@ pub extern "C" fn Servo_StyleSet_HasDocu ) -> bool { let state = DocumentState::from_bits_truncate(state); let data = PerDocumentStyleData::from_ffi(raw_data).borrow(); data.stylist.has_document_state_dependency(state) } #[no_mangle] -pub unsafe extern "C" fn Servo_GetPropertyValue( - computed_values: ComputedStyleBorrowed, - prop: nsCSSPropertyID, - value: *mut nsAString, -) { - use style::properties::PropertyFlags; - - let longhand = LonghandId::from_nscsspropertyid(prop).expect("Not a longhand?"); - debug_assert!( - !longhand.flags().contains(PropertyFlags::GETCS_NEEDS_LAYOUT_FLUSH), - "We're not supposed to serialize layout-dependent properties" - ); - computed_values.get_longhand_property_value( - longhand, - &mut CssWriter::new(&mut *value), - ).unwrap(); -} - -#[no_mangle] pub unsafe extern "C" fn Servo_GetCustomPropertyValue( computed_values: ComputedStyleBorrowed, name: *const nsAString, value: *mut nsAString, ) -> bool { let custom_properties = match computed_values.custom_properties() { Some(p) => p, None => return false,