Auto merge of #16663 - emilio:style-builder, r=bholley

style: Add a StyleBuilder struct to avoid refcount and atomic CAS during the cascade.

This should fix most of the complaints that caused
https://bugzilla.mozilla.org/show_bug.cgi?id=1360889 to be open, and also fix a
bunch of other FIXMEs across the style system.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16663)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-04-30 18:31:41 -05:00 committed by GitHub
commit bf0bf4f4b4
11 changed files with 279 additions and 120 deletions

View file

@ -16,7 +16,7 @@ use gecko_bindings::structs::{nsMediaFeature_ValueType, nsMediaFeature_RangeType
use gecko_bindings::structs::RawGeckoPresContextOwned;
use media_queries::MediaType;
use parser::ParserContext;
use properties::ComputedValues;
use properties::{ComputedValues, StyleBuilder};
use std::fmt::{self, Write};
use std::sync::Arc;
use str::starts_with_ignore_ascii_case;
@ -552,6 +552,7 @@ impl Expression {
let default_values = device.default_computed_values();
let provider = get_metrics_provider_for_product();
// http://dev.w3.org/csswg/mediaqueries3/#units
@ -561,10 +562,9 @@ impl Expression {
device: device,
inherited_style: default_values,
layout_parent_style: default_values,
// This cloning business is kind of dumb.... It's because Context
// insists on having an actual ComputedValues inside itself.
style: default_values.clone(),
style: StyleBuilder::for_derived_style(default_values),
font_metrics_provider: &provider,
cached_system_font: None,
in_media_query: true,
// TODO: pass the correct value here.
quirks_mode: quirks_mode,

View file

@ -102,25 +102,6 @@ pub struct ComputedValues {
}
impl ComputedValues {
/// Inherits style from the parent element, accounting for the default
/// computed values that need to be provided as well.
pub fn inherit_from(parent: &Self, default: &Self) -> Self {
ComputedValues {
custom_properties: parent.custom_properties.clone(),
writing_mode: parent.writing_mode,
root_font_size: parent.root_font_size,
font_size_keyword: parent.font_size_keyword,
cached_system_font: None,
% for style_struct in data.style_structs:
% if style_struct.inherited:
${style_struct.ident}: parent.${style_struct.ident}.clone(),
% else:
${style_struct.ident}: default.${style_struct.ident}.clone(),
% endif
% endfor
}
}
pub fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
writing_mode: WritingMode,
root_font_size: Au,
@ -168,6 +149,11 @@ impl ComputedValues {
pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
&self.${style_struct.ident}
}
pub fn ${style_struct.name_lower}_arc(&self) -> &Arc<style_structs::${style_struct.name}> {
&self.${style_struct.ident}
}
#[inline]
pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
Arc::make_mut(&mut self.${style_struct.ident})
@ -175,7 +161,7 @@ impl ComputedValues {
% endfor
pub fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> {
self.custom_properties.as_ref().map(|x| x.clone())
self.custom_properties.clone()
}
#[allow(non_snake_case)]
@ -183,12 +169,6 @@ impl ComputedValues {
!self.get_box().gecko.mBinding.mPtr.mRawPtr.is_null()
}
#[allow(non_snake_case)]
pub fn in_top_layer(&self) -> bool {
matches!(self.get_box().clone__moz_top_layer(),
longhands::_moz_top_layer::SpecifiedValue::top)
}
// FIXME(bholley): Implement this properly.
#[inline]
pub fn is_multicol(&self) -> bool { false }

View file

@ -478,7 +478,7 @@
SpecifiedValue::Keyword(v) => v,
SpecifiedValue::System(_) => {
% if product == "gecko":
_cx.style.cached_system_font.as_ref().unwrap().${to_rust_ident(name)}
_cx.cached_system_font.as_ref().unwrap().${to_rust_ident(name)}
% else:
unreachable!()
% endif

View file

@ -50,7 +50,7 @@
SpecifiedValue::Value(v) => v,
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
_context.style.cached_system_font.as_ref().unwrap().${name}
_context.cached_system_font.as_ref().unwrap().${name}
</%self:nongecko_unreachable>
}
}
@ -270,7 +270,7 @@
SpecifiedValue::Values(ref v) => computed_value::T(v.clone()),
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
_cx.style.cached_system_font.as_ref().unwrap().font_family.clone()
_cx.cached_system_font.as_ref().unwrap().font_family.clone()
</%self:nongecko_unreachable>
}
}
@ -532,7 +532,7 @@ ${helpers.single_keyword_system("font-variant-caps",
},
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
context.style.cached_system_font.as_ref().unwrap().font_weight.clone()
context.cached_system_font.as_ref().unwrap().font_weight.clone()
</%self:nongecko_unreachable>
}
}
@ -809,7 +809,7 @@ ${helpers.single_keyword_system("font-variant-caps",
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
context.style.cached_system_font.as_ref().unwrap().font_size
context.cached_system_font.as_ref().unwrap().font_size
</%self:nongecko_unreachable>
}
}
@ -982,7 +982,7 @@ ${helpers.single_keyword_system("font-variant-caps",
SpecifiedValue::Number(ref n) => computed_value::T::Number(n.to_computed_value(context)),
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
context.style.cached_system_font.as_ref().unwrap().font_size_adjust
context.cached_system_font.as_ref().unwrap().font_size_adjust
</%self:nongecko_unreachable>
}
}
@ -1966,7 +1966,7 @@ ${helpers.single_keyword_system("font-variant-position",
}
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
_context.style.cached_system_font.as_ref().unwrap().font_language_override
_context.cached_system_font.as_ref().unwrap().font_language_override
</%self:nongecko_unreachable>
}
}
@ -2365,11 +2365,11 @@ ${helpers.single_keyword("-moz-math-variant",
/// Must be called before attempting to compute a system font
/// specified value
pub fn resolve_system_font(system: SystemFont, context: &mut Context) {
if context.style.cached_system_font.is_none() {
if context.cached_system_font.is_none() {
let computed = system.to_computed_value(context);
context.style.cached_system_font = Some(computed);
context.cached_system_font = Some(computed);
}
debug_assert!(system == context.style.cached_system_font.as_ref().unwrap().system_font)
debug_assert!(system == context.cached_system_font.as_ref().unwrap().system_font)
}
#[derive(Clone, Debug)]

View file

@ -13,6 +13,7 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::fmt;
use std::ops::Deref;
use std::sync::Arc;
use app_units::Au;
@ -1725,6 +1726,12 @@ impl ComputedValues {
&self.${style_struct.ident}
}
/// Gets an immutable reference to the refcounted value that wraps
/// `${style_struct.name}`.
pub fn ${style_struct.name_lower}_arc(&self) -> &Arc<style_structs::${style_struct.name}> {
&self.${style_struct.ident}
}
/// Get a mutable reference to the ${style_struct.name} struct.
#[inline]
pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
@ -1737,18 +1744,13 @@ impl ComputedValues {
/// Cloning the Arc here is fine because it only happens in the case where
/// we have custom properties, and those are both rare and expensive.
fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> {
self.custom_properties.as_ref().map(|x| x.clone())
self.custom_properties.clone()
}
/// Whether this style has a -moz-binding value. This is always false for
/// Servo for obvious reasons.
pub fn has_moz_binding(&self) -> bool { false }
/// Whether this style has a top-layer style. That's implemented in Gecko
/// via the -moz-top-layer property, but servo doesn't have any concept of a
/// top layer (yet, it's needed for fullscreen).
pub fn in_top_layer(&self) -> bool { false }
/// Returns whether this style's display value is equal to contents.
///
/// Since this isn't supported in Servo, this is always false for Servo.
@ -1967,22 +1969,6 @@ impl ComputedValues {
}
}
impl ComputedValues {
/// Returns whether this computed style represents a floated object.
pub fn floated(&self) -> bool {
self.get_box().clone_float() != longhands::float::computed_value::T::none
}
/// Returns whether this computed style represents an out of flow-positioned
/// object.
pub fn out_of_flow_positioned(&self) -> bool {
use properties::longhands::position::computed_value::T as position;
matches!(self.get_box().clone_position(),
position::absolute | position::fixed)
}
}
/// Return a WritingMode bitflags from the relevant CSS properties.
pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> WritingMode {
use logical_geometry;
@ -2034,6 +2020,176 @@ pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> Wri
flags
}
/// A reference to a style struct of the parent, or our own style struct.
pub enum StyleStructRef<'a, T: 'a> {
/// A borrowed struct from the parent, for example, for inheriting style.
Borrowed(&'a Arc<T>),
/// An owned struct, that we've already mutated.
Owned(T),
}
impl<'a, T: 'a> StyleStructRef<'a, T>
where T: Clone,
{
/// Ensure a mutable reference of this value exists, either cloning the
/// borrowed value, or returning the owned one.
pub fn mutate(&mut self) -> &mut T {
if let StyleStructRef::Borrowed(v) = *self {
*self = StyleStructRef::Owned((**v).clone());
}
match *self {
StyleStructRef::Owned(ref mut v) => v,
StyleStructRef::Borrowed(..) => unreachable!(),
}
}
/// Returns an `Arc` to the internal struct, constructing one if
/// appropriate.
pub fn build(self) -> Arc<T> {
match self {
StyleStructRef::Owned(v) => Arc::new(v),
StyleStructRef::Borrowed(v) => v.clone(),
}
}
}
impl<'a, T: 'a> Deref for StyleStructRef<'a, T> {
type Target = T;
fn deref(&self) -> &T {
match *self {
StyleStructRef::Owned(ref v) => v,
StyleStructRef::Borrowed(v) => &**v,
}
}
}
/// A type used to compute a struct with minimal overhead.
///
/// This allows holding references to the parent/default computed values without
/// actually cloning them, until we either build the style, or mutate the
/// inherited value.
pub struct StyleBuilder<'a> {
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
/// The writing mode flags.
///
/// TODO(emilio): Make private.
pub writing_mode: WritingMode,
/// The font size of the root element.
pub root_font_size: Au,
/// The keyword behind the current font-size property, if any.
pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
% for style_struct in data.active_style_structs():
${style_struct.ident}: StyleStructRef<'a, style_structs::${style_struct.name}>,
% endfor
}
impl<'a> StyleBuilder<'a> {
/// Trivially construct a `StyleBuilder`.
pub fn new(
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
writing_mode: WritingMode,
root_font_size: Au,
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
% for style_struct in data.active_style_structs():
${style_struct.ident}: &'a Arc<style_structs::${style_struct.name}>,
% endfor
) -> Self {
StyleBuilder {
custom_properties: custom_properties,
writing_mode: writing_mode,
root_font_size: root_font_size,
font_size_keyword: font_size_keyword,
% for style_struct in data.active_style_structs():
${style_struct.ident}: StyleStructRef::Borrowed(${style_struct.ident}),
% endfor
}
}
/// Creates a StyleBuilder holding only references to the structs of `s`, in
/// order to create a derived style.
pub fn for_derived_style(s: &'a ComputedValues) -> Self {
Self::for_inheritance(s, s)
}
/// Inherits style from the parent element, accounting for the default
/// computed values that need to be provided as well.
pub fn for_inheritance(parent: &'a ComputedValues, default: &'a ComputedValues) -> Self {
Self::new(parent.custom_properties(),
parent.writing_mode,
parent.root_font_size,
parent.font_size_keyword,
% for style_struct in data.active_style_structs():
% if style_struct.inherited:
parent.${style_struct.name_lower}_arc(),
% else:
default.${style_struct.name_lower}_arc(),
% endif
% endfor
)
}
% for style_struct in data.active_style_structs():
/// Gets an immutable view of the current `${style_struct.name}` style.
pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
&self.${style_struct.ident}
}
/// Gets a mutable view of the current `${style_struct.name}` style.
pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
self.${style_struct.ident}.mutate()
}
% endfor
/// Returns whether this computed style represents a floated object.
pub fn floated(&self) -> bool {
self.get_box().clone_float() != longhands::float::computed_value::T::none
}
/// Returns whether this computed style represents an out of flow-positioned
/// object.
pub fn out_of_flow_positioned(&self) -> bool {
use properties::longhands::position::computed_value::T as position;
matches!(self.get_box().clone_position(),
position::absolute | position::fixed)
}
/// Whether this style has a top-layer style. That's implemented in Gecko
/// via the -moz-top-layer property, but servo doesn't have any concept of a
/// top layer (yet, it's needed for fullscreen).
#[cfg(feature = "servo")]
pub fn in_top_layer(&self) -> bool { false }
/// Whether this style has a top-layer style.
#[cfg(feature = "gecko")]
pub fn in_top_layer(&self) -> bool {
matches!(self.get_box().clone__moz_top_layer(),
longhands::_moz_top_layer::computed_value::T::top)
}
/// Turns this `StyleBuilder` into a proper `ComputedValues` instance.
pub fn build(self) -> ComputedValues {
ComputedValues::new(self.custom_properties,
self.writing_mode,
self.root_font_size,
self.font_size_keyword,
% for style_struct in data.active_style_structs():
self.${style_struct.ident}.build(),
% endfor
)
}
/// Get the custom properties map if necessary.
///
/// Cloning the Arc here is fine because it only happens in the case where
/// we have custom properties, and those are both rare and expensive.
fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> {
self.custom_properties.clone()
}
}
#[cfg(feature = "servo")]
pub use self::lazy_static_module::INITIAL_SERVO_VALUES;
@ -2202,26 +2358,26 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
::custom_properties::finish_cascade(
custom_properties, &inherited_custom_properties);
let starting_style = if !flags.contains(INHERIT_ALL) {
ComputedValues::new(custom_properties,
let builder = if !flags.contains(INHERIT_ALL) {
StyleBuilder::new(custom_properties,
WritingMode::empty(),
inherited_style.root_font_size,
inherited_style.font_size_keyword,
% for style_struct in data.active_style_structs():
% if style_struct.inherited:
inherited_style.clone_${style_struct.name_lower}(),
inherited_style.${style_struct.name_lower}_arc(),
% else:
default_style.clone_${style_struct.name_lower}(),
default_style.${style_struct.name_lower}_arc(),
% endif
% endfor
)
} else {
ComputedValues::new(custom_properties,
StyleBuilder::new(custom_properties,
WritingMode::empty(),
inherited_style.root_font_size,
inherited_style.font_size_keyword,
% for style_struct in data.active_style_structs():
inherited_style.clone_${style_struct.name_lower}(),
inherited_style.${style_struct.name_lower}_arc(),
% endfor
)
};
@ -2231,8 +2387,9 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
device: device,
inherited_style: inherited_style,
layout_parent_style: layout_parent_style,
style: starting_style,
style: builder,
font_metrics_provider: font_metrics_provider,
cached_system_font: None,
in_media_query: false,
quirks_mode: quirks_mode,
};
@ -2382,9 +2539,11 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
let mut style = context.style;
{
StyleAdjuster::new(&mut style, is_root_element)
.adjust(context.layout_parent_style,
flags.contains(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP));
}
% if product == "gecko":
// FIXME(emilio): This is effectively creating a new nsStyleBackground
@ -2408,12 +2567,12 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
}
% endif
style
style.build()
}
/// See StyleAdjuster::adjust_for_border_width.
pub fn adjust_border_width(style: &mut ComputedValues) {
pub fn adjust_border_width(style: &mut StyleBuilder) {
% for side in ["top", "right", "bottom", "left"]:
// Like calling to_computed_value, which wouldn't type check.
if style.get_border().clone_border_${side}_style().none_or_hidden() &&

View file

@ -11,7 +11,7 @@ use euclid::{Size2D, TypedSize2D};
use font_metrics::ServoMetricsProvider;
use media_queries::MediaType;
use parser::ParserContext;
use properties::ComputedValues;
use properties::{ComputedValues, StyleBuilder};
use std::fmt;
use style_traits::{CSSPixel, ToCss};
use style_traits::viewport::ViewportConstraints;
@ -185,14 +185,13 @@ impl Range<specified::Length> {
device: device,
inherited_style: default_values,
layout_parent_style: default_values,
// This cloning business is kind of dumb.... It's because Context
// insists on having an actual ComputedValues inside itself.
style: default_values.clone(),
style: StyleBuilder::for_derived_style(default_values),
// Servo doesn't support font metrics
// A real provider will be needed here once we do; since
// ch units can exist in media queries.
font_metrics_provider: &ServoMetricsProvider,
in_media_query: true,
cached_system_font: None,
quirks_mode: quirks_mode,
};

View file

@ -6,7 +6,7 @@
//! for it to adhere to the CSS spec.
use app_units::Au;
use properties::{self, ComputedValues};
use properties::{self, ComputedValues, StyleBuilder};
use properties::longhands::display::computed_value::T as display;
use properties::longhands::float::computed_value::T as float;
use properties::longhands::overflow_x::computed_value::T as overflow;
@ -14,14 +14,14 @@ use properties::longhands::position::computed_value::T as position;
/// An unsized struct that implements all the adjustment methods.
pub struct StyleAdjuster<'a> {
style: &'a mut ComputedValues,
pub struct StyleAdjuster<'a, 'b: 'a> {
style: &'a mut StyleBuilder<'b>,
is_root_element: bool,
}
impl<'a> StyleAdjuster<'a> {
impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
/// Trivially constructs a new StyleAdjuster.
pub fn new(style: &'a mut ComputedValues, is_root_element: bool) -> Self {
pub fn new(style: &'a mut StyleBuilder<'b>, is_root_element: bool) -> Self {
StyleAdjuster {
style: style,
is_root_element: is_root_element,
@ -264,7 +264,7 @@ impl<'a> StyleAdjuster<'a> {
///
/// When comparing to Gecko, this is similar to the work done by
/// `nsStyleContext::ApplyStyleFixups`.
pub fn adjust(mut self,
pub fn adjust(&mut self,
layout_parent_style: &ComputedValues,
skip_root_and_element_display_fixup: bool) {
self.adjust_for_top_layer();

View file

@ -8,7 +8,9 @@ use context::QuirksMode;
use euclid::size::Size2D;
use font_metrics::FontMetricsProvider;
use media_queries::Device;
use properties::ComputedValues;
#[cfg(feature = "gecko")]
use properties;
use properties::{ComputedValues, StyleBuilder};
use std::fmt;
use style_traits::ToCss;
use super::{CSSFloat, CSSInteger, RGBA};
@ -53,10 +55,23 @@ pub struct Context<'a> {
/// isn't `contents`.
pub layout_parent_style: &'a ComputedValues,
/// Values access through this need to be in the properties "computed
/// Values accessed through this need to be in the properties "computed
/// early": color, text-decoration, font-size, display, position, float,
/// border-*-style, outline-style, font-family, writing-mode...
pub style: ComputedValues,
pub style: StyleBuilder<'a>,
/// A cached computed system font value, for use by gecko.
///
/// See properties/longhands/font.mako.rs
#[cfg(feature = "gecko")]
pub cached_system_font: Option<properties::longhands::system_font::ComputedSystemFont>,
/// A dummy option for servo so initializing a computed::Context isn't
/// painful.
///
/// TODO(emilio): Make constructors for Context, and drop this.
#[cfg(feature = "servo")]
pub cached_system_font: Option<()>,
/// A font metrics provider, used to access font metrics to implement
/// font-relative units.
@ -78,9 +93,9 @@ impl<'a> Context<'a> {
pub fn inherited_style(&self) -> &ComputedValues { &self.inherited_style }
/// The current style. Note that only "eager" properties should be accessed
/// from here, see the comment in the member.
pub fn style(&self) -> &ComputedValues { &self.style }
pub fn style(&self) -> &StyleBuilder { &self.style }
/// A mutable reference to the current style.
pub fn mutate_style(&mut self) -> &mut ComputedValues { &mut self.style }
pub fn mutate_style(&mut self) -> &mut StyleBuilder<'a> { &mut self.style }
}
/// A trait to represent the conversion between computed and specified values.

View file

@ -17,6 +17,7 @@ use euclid::size::TypedSize2D;
use font_metrics::get_metrics_provider_for_product;
use media_queries::Device;
use parser::{Parse, ParserContext, log_css_error};
use properties::StyleBuilder;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use std::ascii::AsciiExt;
use std::borrow::Cow;
@ -678,14 +679,17 @@ impl MaybeNew for ViewportConstraints {
let provider = get_metrics_provider_for_product();
let default_values = device.default_computed_values();
// TODO(emilio): Stop cloning `ComputedValues` around!
let context = Context {
is_root_element: false,
device: device,
inherited_style: device.default_computed_values(),
layout_parent_style: device.default_computed_values(),
style: device.default_computed_values().clone(),
inherited_style: default_values,
layout_parent_style: default_values,
style: StyleBuilder::for_derived_style(default_values),
font_metrics_provider: &provider,
cached_system_font: None,
in_media_query: false,
quirks_mode: quirks_mode,
};

View file

@ -72,7 +72,7 @@ use style::keyframes::KeyframesStepValue;
use style::media_queries::{MediaList, parse_media_query_list};
use style::parallel;
use style::parser::{LengthParsingMode, ParserContext};
use style::properties::{CascadeFlags, ComputedValues, Importance, ParsedDeclaration};
use style::properties::{CascadeFlags, ComputedValues, Importance, ParsedDeclaration, StyleBuilder};
use style::properties::{PropertyDeclarationBlock, PropertyId};
use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
use style::properties::animated_properties::{AnimationValue, ComputeDistance, Interpolate, TransitionProperty};
@ -1002,14 +1002,14 @@ pub extern "C" fn Servo_ComputedValues_Inherit(
let for_text = target == structs::InheritTarget::Text;
let style = if let Some(reference) = maybe_arc.as_ref() {
let mut style =
ComputedValues::inherit_from(reference,
StyleBuilder::for_inheritance(reference,
&data.default_computed_values());
if for_text {
StyleAdjuster::new(&mut style, /* is_root = */ false)
.adjust_for_text();
}
Arc::new(style)
Arc::new(style.build())
} else {
debug_assert!(!for_text);
data.default_computed_values().clone()
@ -2002,8 +2002,9 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis
device: &data.stylist.device,
inherited_style: parent_style.unwrap_or(default_values),
layout_parent_style: parent_style.unwrap_or(default_values),
style: (**style).clone(),
style: StyleBuilder::for_derived_style(&style),
font_metrics_provider: &metrics,
cached_system_font: None,
in_media_query: false,
quirks_mode: QuirksMode::NoQuirks,
};

View file

@ -8,7 +8,7 @@ use std::f32::consts::PI;
use style::context::QuirksMode;
use style::font_metrics::ServoMetricsProvider;
use style::media_queries::{Device, MediaType};
use style::properties::ComputedValues;
use style::properties::{ComputedValues, StyleBuilder};
use style::values::computed;
use style::values::computed::{Angle, Context, ToComputedValue};
use style::values::specified;
@ -49,7 +49,8 @@ fn test_linear_gradient() {
device: &device,
inherited_style: initial_style,
layout_parent_style: initial_style,
style: initial_style.clone(),
style: StyleBuilder::for_derived_style(&initial_style),
cached_system_font: None,
font_metrics_provider: &ServoMetricsProvider,
in_media_query: false,
quirks_mode: QuirksMode::NoQuirks,