Auto merge of #16802 - emilio:slim-down-slc, r=bholley

style: Slim down SharedStyleContext, and do various other cleanups around the style crate.

This slims down SharedStyleContext, in preparation for a few things.

First, I would like to eventually move the stylist to the document in Servo, in
order for it to hold the StyleSheetSet.

Also, this gets rid of a fair amount of overhead while creating it in stylo.

Fixes bug 1363245.

<!-- 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/16802)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-05-12 08:56:47 -05:00 committed by GitHub
commit eeb1ee9723
11 changed files with 171 additions and 141 deletions

View file

@ -38,7 +38,6 @@ use style::logical_geometry::{WritingMode, BlockFlowDirection, InlineBaseDirecti
use style::properties::{style_structs, PropertyId, PropertyDeclarationId, LonghandId}; use style::properties::{style_structs, PropertyId, PropertyDeclarationId, LonghandId};
use style::properties::longhands::{display, position}; use style::properties::longhands::{display, position};
use style::selector_parser::PseudoElement; use style::selector_parser::PseudoElement;
use style::stylist::Stylist;
use style_traits::ToCss; use style_traits::ToCss;
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
use webrender_traits::ClipId; use webrender_traits::ClipId;
@ -54,9 +53,6 @@ pub struct LayoutThreadData {
/// The root stacking context. /// The root stacking context.
pub display_list: Option<Arc<DisplayList>>, pub display_list: Option<Arc<DisplayList>>,
/// Performs CSS selector matching and style resolution.
pub stylist: ::StyleArc<Stylist>,
/// A queued response for the union of the content boxes of a node. /// A queued response for the union of the content boxes of a node.
pub content_box_response: Option<Rect<Au>>, pub content_box_response: Option<Rect<Au>>,

View file

@ -95,6 +95,7 @@ use servo_config::resource_files::read_resource_file;
use servo_geometry::max_rect; use servo_geometry::max_rect;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::{Cell, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -131,6 +132,9 @@ pub struct LayoutThread {
/// The URL of the pipeline that we belong to. /// The URL of the pipeline that we belong to.
url: ServoUrl, url: ServoUrl,
/// Performs CSS selector matching and style resolution.
stylist: Stylist,
/// Is the current reflow of an iframe, as opposed to a root window? /// Is the current reflow of an iframe, as opposed to a root window?
is_iframe: bool, is_iframe: bool,
@ -165,7 +169,7 @@ pub struct LayoutThread {
font_cache_thread: FontCacheThread, font_cache_thread: FontCacheThread,
/// Is this the first reflow in this LayoutThread? /// Is this the first reflow in this LayoutThread?
first_reflow: bool, first_reflow: Cell<bool>,
/// The workers that we use for parallel operation. /// The workers that we use for parallel operation.
parallel_traversal: Option<rayon::ThreadPool>, parallel_traversal: Option<rayon::ThreadPool>,
@ -175,7 +179,7 @@ pub struct LayoutThread {
/// Starts at zero, and increased by one every time a layout completes. /// Starts at zero, and increased by one every time a layout completes.
/// This can be used to easily check for invalid stale data. /// This can be used to easily check for invalid stale data.
generation: u32, generation: Cell<u32>,
/// A channel on which new animations that have been triggered by style recalculation can be /// A channel on which new animations that have been triggered by style recalculation can be
/// sent. /// sent.
@ -188,7 +192,7 @@ pub struct LayoutThread {
outstanding_web_fonts: Arc<AtomicUsize>, outstanding_web_fonts: Arc<AtomicUsize>,
/// The root of the flow tree. /// The root of the flow tree.
root_flow: Option<FlowRef>, root_flow: RefCell<Option<FlowRef>>,
/// The document-specific shared lock used for author-origin stylesheets /// The document-specific shared lock used for author-origin stylesheets
document_shared_lock: Option<SharedRwLock>, document_shared_lock: Option<SharedRwLock>,
@ -200,7 +204,7 @@ pub struct LayoutThread {
expired_animations: StyleArc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>, expired_animations: StyleArc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
/// A counter for epoch messages /// A counter for epoch messages
epoch: Epoch, epoch: Cell<Epoch>,
/// The size of the viewport. This may be different from the size of the screen due to viewport /// The size of the viewport. This may be different from the size of the screen due to viewport
/// constraints. /// constraints.
@ -414,7 +418,7 @@ impl LayoutThread {
let font_cache_receiver = let font_cache_receiver =
ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_font_cache_receiver); ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_font_cache_receiver);
let stylist = StyleArc::new(Stylist::new(device)); let stylist = Stylist::new(device);
let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0)); let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0));
let ua_stylesheets = &*UA_STYLESHEETS; let ua_stylesheets = &*UA_STYLESHEETS;
let guard = ua_stylesheets.shared_lock.read(); let guard = ua_stylesheets.shared_lock.read();
@ -439,27 +443,27 @@ impl LayoutThread {
mem_profiler_chan: mem_profiler_chan, mem_profiler_chan: mem_profiler_chan,
image_cache: image_cache.clone(), image_cache: image_cache.clone(),
font_cache_thread: font_cache_thread, font_cache_thread: font_cache_thread,
first_reflow: true, first_reflow: Cell::new(true),
font_cache_receiver: font_cache_receiver, font_cache_receiver: font_cache_receiver,
font_cache_sender: ipc_font_cache_sender, font_cache_sender: ipc_font_cache_sender,
parallel_traversal: parallel_traversal, parallel_traversal: parallel_traversal,
parallel_flag: true, parallel_flag: true,
generation: 0, generation: Cell::new(0),
new_animations_sender: new_animations_sender, new_animations_sender: new_animations_sender,
new_animations_receiver: new_animations_receiver, new_animations_receiver: new_animations_receiver,
outstanding_web_fonts: outstanding_web_fonts_counter, outstanding_web_fonts: outstanding_web_fonts_counter,
root_flow: None, root_flow: RefCell::new(None),
document_shared_lock: None, document_shared_lock: None,
running_animations: StyleArc::new(RwLock::new(HashMap::new())), running_animations: StyleArc::new(RwLock::new(HashMap::new())),
expired_animations: StyleArc::new(RwLock::new(HashMap::new())), expired_animations: StyleArc::new(RwLock::new(HashMap::new())),
epoch: Epoch(0), epoch: Cell::new(Epoch(0)),
viewport_size: Size2D::new(Au(0), Au(0)), viewport_size: Size2D::new(Au(0), Au(0)),
webrender_api: webrender_api_sender.create_api(), webrender_api: webrender_api_sender.create_api(),
stylist: stylist,
rw_data: Arc::new(Mutex::new( rw_data: Arc::new(Mutex::new(
LayoutThreadData { LayoutThreadData {
constellation_chan: constellation_chan, constellation_chan: constellation_chan,
display_list: None, display_list: None,
stylist: stylist,
content_box_response: None, content_box_response: None,
content_boxes_response: Vec::new(), content_boxes_response: Vec::new(),
client_rect_response: Rect::zero(), client_rect_response: Rect::zero(),
@ -507,9 +511,8 @@ impl LayoutThread {
} }
// Create a layout context for use in building display lists, hit testing, &c. // Create a layout context for use in building display lists, hit testing, &c.
fn build_layout_context<'a>(&self, fn build_layout_context<'a>(&'a self,
guards: StylesheetGuards<'a>, guards: StylesheetGuards<'a>,
rw_data: &LayoutThreadData,
request_images: bool, request_images: bool,
snapshot_map: &'a SnapshotMap) snapshot_map: &'a SnapshotMap)
-> LayoutContext<'a> { -> LayoutContext<'a> {
@ -519,12 +522,12 @@ impl LayoutThread {
LayoutContext { LayoutContext {
id: self.id, id: self.id,
style_context: SharedStyleContext { style_context: SharedStyleContext {
stylist: rw_data.stylist.clone(), stylist: &self.stylist,
options: StyleSystemOptions::default(), options: StyleSystemOptions::default(),
guards: guards, guards: guards,
running_animations: self.running_animations.clone(), running_animations: self.running_animations.clone(),
expired_animations: self.expired_animations.clone(), expired_animations: self.expired_animations.clone(),
error_reporter: Box::new(self.error_reporter.clone()), error_reporter: &self.error_reporter,
local_context_creation_data: Mutex::new(thread_local_style_context_creation_data), local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),
timer: self.timer.clone(), timer: self.timer.clone(),
quirks_mode: self.quirks_mode.unwrap(), quirks_mode: self.quirks_mode.unwrap(),
@ -605,7 +608,7 @@ impl LayoutThread {
Msg::AddStylesheet(style_info) => { Msg::AddStylesheet(style_info) => {
self.handle_add_stylesheet(style_info, possibly_locked_rw_data) self.handle_add_stylesheet(style_info, possibly_locked_rw_data)
} }
Msg::SetQuirksMode(mode) => self.handle_set_quirks_mode(possibly_locked_rw_data, mode), Msg::SetQuirksMode(mode) => self.handle_set_quirks_mode(mode),
Msg::GetRPC(response_chan) => { Msg::GetRPC(response_chan) => {
response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as
Box<LayoutRPC + Send>).unwrap(); Box<LayoutRPC + Send>).unwrap();
@ -631,7 +634,7 @@ impl LayoutThread {
}, },
Msg::GetCurrentEpoch(sender) => { Msg::GetCurrentEpoch(sender) => {
let _rw_data = possibly_locked_rw_data.lock(); let _rw_data = possibly_locked_rw_data.lock();
sender.send(self.epoch).unwrap(); sender.send(self.epoch.get()).unwrap();
}, },
Msg::AdvanceClockMs(how_many, do_tick) => { Msg::AdvanceClockMs(how_many, do_tick) => {
self.handle_advance_clock_ms(how_many, possibly_locked_rw_data, do_tick); self.handle_advance_clock_ms(how_many, possibly_locked_rw_data, do_tick);
@ -676,11 +679,10 @@ impl LayoutThread {
size: display_list.map_or(0, |sc| sc.heap_size_of_children()), size: display_list.map_or(0, |sc| sc.heap_size_of_children()),
}); });
let stylist = rw_data.stylist.as_ref();
reports.push(Report { reports.push(Report {
path: path![formatted_url, "layout-thread", "stylist"], path: path![formatted_url, "layout-thread", "stylist"],
kind: ReportKind::ExplicitJemallocHeapSize, kind: ReportKind::ExplicitJemallocHeapSize,
size: stylist.heap_size_of_children(), size: self.stylist.heap_size_of_children(),
}); });
// The LayoutThread has data in Persistent TLS... // The LayoutThread has data in Persistent TLS...
@ -752,10 +754,10 @@ impl LayoutThread {
let rw_data = possibly_locked_rw_data.lock(); let rw_data = possibly_locked_rw_data.lock();
let guard = stylesheet.shared_lock.read(); let guard = stylesheet.shared_lock.read();
if stylesheet.is_effective_for_device(&rw_data.stylist.device, &guard) { if stylesheet.is_effective_for_device(&self.stylist.device, &guard) {
add_font_face_rules(&*stylesheet, add_font_face_rules(&*stylesheet,
&guard, &guard,
&rw_data.stylist.device, &self.stylist.device,
&self.font_cache_thread, &self.font_cache_thread,
&self.font_cache_sender, &self.font_cache_sender,
&self.outstanding_web_fonts); &self.outstanding_web_fonts);
@ -776,12 +778,8 @@ impl LayoutThread {
} }
/// Sets quirks mode for the document, causing the quirks mode stylesheet to be used. /// Sets quirks mode for the document, causing the quirks mode stylesheet to be used.
fn handle_set_quirks_mode<'a, 'b>(&self, fn handle_set_quirks_mode<'a, 'b>(&mut self, quirks_mode: QuirksMode) {
possibly_locked_rw_data: &mut RwData<'a, 'b>, self.stylist.set_quirks_mode(quirks_mode);
quirks_mode: QuirksMode) {
let mut rw_data = possibly_locked_rw_data.lock();
StyleArc::get_mut(&mut rw_data.stylist).unwrap().set_quirks_mode(quirks_mode);
possibly_locked_rw_data.block(rw_data);
} }
fn try_get_layout_root<N: LayoutNode>(&self, node: N) -> Option<FlowRef> { fn try_get_layout_root<N: LayoutNode>(&self, node: N) -> Option<FlowRef> {
@ -843,7 +841,7 @@ impl LayoutThread {
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the /// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
/// reflow goal and query type need it, builds the display list. /// reflow goal and query type need it, builds the display list.
fn compute_abs_pos_and_build_display_list(&mut self, fn compute_abs_pos_and_build_display_list(&self,
data: &Reflow, data: &Reflow,
query_type: Option<&ReflowQueryType>, query_type: Option<&ReflowQueryType>,
document: Option<&ServoLayoutDocument>, document: Option<&ServoLayoutDocument>,
@ -882,7 +880,7 @@ impl LayoutThread {
let root_size = { let root_size = {
let root_flow = flow::base(layout_root); let root_flow = flow::base(layout_root);
if rw_data.stylist.viewport_constraints().is_some() { if self.stylist.viewport_constraints().is_some() {
root_flow.position.size.to_physical(root_flow.writing_mode) root_flow.position.size.to_physical(root_flow.writing_mode)
} else { } else {
root_flow.overflow.scroll.size root_flow.overflow.scroll.size
@ -938,13 +936,14 @@ impl LayoutThread {
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(), let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px()); self.viewport_size.height.to_f32_px());
self.epoch.next(); let mut epoch = self.epoch.get();
let Epoch(epoch_number) = self.epoch; epoch.next();
self.epoch.set(epoch);
let viewport_size = webrender_traits::LayoutSize::from_untyped(&viewport_size); let viewport_size = webrender_traits::LayoutSize::from_untyped(&viewport_size);
self.webrender_api.set_display_list( self.webrender_api.set_display_list(
Some(get_root_flow_background_color(layout_root)), Some(get_root_flow_background_color(layout_root)),
webrender_traits::Epoch(epoch_number), webrender_traits::Epoch(epoch.0),
viewport_size, viewport_size,
builder.finalize(), builder.finalize(),
true); true);
@ -1038,11 +1037,10 @@ impl LayoutThread {
self.document_shared_lock = Some(document_shared_lock.clone()); self.document_shared_lock = Some(document_shared_lock.clone());
let author_guard = document_shared_lock.read(); let author_guard = document_shared_lock.read();
let device = Device::new(MediaType::Screen, initial_viewport); let device = Device::new(MediaType::Screen, initial_viewport);
StyleArc::get_mut(&mut rw_data.stylist).unwrap() self.stylist.set_device(device, &author_guard, &data.document_stylesheets);
.set_device(device, &author_guard, &data.document_stylesheets);
self.viewport_size = self.viewport_size =
rw_data.stylist.viewport_constraints().map_or(current_screen_size, |constraints| { self.stylist.viewport_constraints().map_or(current_screen_size, |constraints| {
debug!("Viewport constraints: {:?}", constraints); debug!("Viewport constraints: {:?}", constraints);
// other rules are evaluated against the actual viewport // other rules are evaluated against the actual viewport
@ -1052,7 +1050,7 @@ impl LayoutThread {
let viewport_size_changed = self.viewport_size != old_viewport_size; let viewport_size_changed = self.viewport_size != old_viewport_size;
if viewport_size_changed { if viewport_size_changed {
if let Some(constraints) = rw_data.stylist.viewport_constraints() { if let Some(constraints) = self.stylist.viewport_constraints() {
// let the constellation know about the viewport constraints // let the constellation know about the viewport constraints
rw_data.constellation_chan rw_data.constellation_chan
.send(ConstellationMsg::ViewportConstrained(self.id, constraints.clone())) .send(ConstellationMsg::ViewportConstrained(self.id, constraints.clone()))
@ -1092,8 +1090,8 @@ impl LayoutThread {
let mut extra_data = ExtraStyleData { let mut extra_data = ExtraStyleData {
marker: PhantomData, marker: PhantomData,
}; };
let needs_dirtying = StyleArc::get_mut(&mut rw_data.stylist).unwrap().update( let needs_dirtying = self.stylist.update(
&data.document_stylesheets, data.document_stylesheets.iter(),
&guards, &guards,
Some(ua_stylesheets), Some(ua_stylesheets),
data.stylesheets_changed, data.stylesheets_changed,
@ -1158,7 +1156,7 @@ impl LayoutThread {
// Create a layout context for use throughout the following passes. // Create a layout context for use throughout the following passes.
let mut layout_context = let mut layout_context =
self.build_layout_context(guards.clone(), &*rw_data, true, &map); self.build_layout_context(guards.clone(), true, &map);
// NB: Type inference falls apart here for some reason, so we need to be very verbose. :-( // NB: Type inference falls apart here for some reason, so we need to be very verbose. :-(
let traversal_driver = if self.parallel_flag && self.parallel_traversal.is_some() { let traversal_driver = if self.parallel_flag && self.parallel_traversal.is_some() {
@ -1185,7 +1183,7 @@ impl LayoutThread {
|| { || {
// Perform CSS selector matching and flow construction. // Perform CSS selector matching and flow construction.
if traversal_driver.is_parallel() { if traversal_driver.is_parallel() {
let pool = self.parallel_traversal.as_mut().unwrap(); let pool = self.parallel_traversal.as_ref().unwrap();
// Parallel mode // Parallel mode
parallel::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>( parallel::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>(
&traversal, element, token, pool); &traversal, element, token, pool);
@ -1208,7 +1206,7 @@ impl LayoutThread {
0); 0);
// Retrieve the (possibly rebuilt) root flow. // Retrieve the (possibly rebuilt) root flow.
self.root_flow = self.try_get_layout_root(element.as_node()); *self.root_flow.borrow_mut() = self.try_get_layout_root(element.as_node());
} }
for element in elements_with_snapshot { for element in elements_with_snapshot {
@ -1229,7 +1227,7 @@ impl LayoutThread {
unsafe { layout_context.style_context.stylist.rule_tree.maybe_gc(); } unsafe { layout_context.style_context.stylist.rule_tree.maybe_gc(); }
// Perform post-style recalculation layout passes. // Perform post-style recalculation layout passes.
if let Some(mut root_flow) = self.root_flow.clone() { if let Some(mut root_flow) = self.root_flow.borrow().clone() {
self.perform_post_style_recalc_layout_passes(&mut root_flow, self.perform_post_style_recalc_layout_passes(&mut root_flow,
&data.reflow_info, &data.reflow_info,
Some(&data.query_type), Some(&data.query_type),
@ -1243,7 +1241,7 @@ impl LayoutThread {
&mut layout_context); &mut layout_context);
} }
fn respond_to_query_if_necessary(&mut self, fn respond_to_query_if_necessary(&self,
query_type: &ReflowQueryType, query_type: &ReflowQueryType,
rw_data: &mut LayoutThreadData, rw_data: &mut LayoutThreadData,
context: &mut LayoutContext) { context: &mut LayoutContext) {
@ -1253,7 +1251,7 @@ impl LayoutThread {
}; };
rw_data.pending_images = pending_images; rw_data.pending_images = pending_images;
let mut root_flow = match self.root_flow.clone() { let mut root_flow = match self.root_flow.borrow().clone() {
Some(root_flow) => root_flow, Some(root_flow) => root_flow,
None => return, None => return,
}; };
@ -1390,7 +1388,7 @@ impl LayoutThread {
println!("**** pipeline={}\tForDisplay\tSpecial\tAnimationTick", self.id); println!("**** pipeline={}\tForDisplay\tSpecial\tAnimationTick", self.id);
} }
if let Some(mut root_flow) = self.root_flow.clone() { if let Some(mut root_flow) = self.root_flow.borrow().clone() {
let reflow_info = Reflow { let reflow_info = Reflow {
goal: ReflowGoal::ForDisplay, goal: ReflowGoal::ForDisplay,
page_clip_rect: max_rect(), page_clip_rect: max_rect(),
@ -1407,7 +1405,6 @@ impl LayoutThread {
}; };
let snapshots = SnapshotMap::new(); let snapshots = SnapshotMap::new();
let mut layout_context = self.build_layout_context(guards, let mut layout_context = self.build_layout_context(guards,
&*rw_data,
false, false,
&snapshots); &snapshots);
@ -1432,7 +1429,7 @@ impl LayoutThread {
} }
} }
fn perform_post_style_recalc_layout_passes(&mut self, fn perform_post_style_recalc_layout_passes(&self,
root_flow: &mut FlowRef, root_flow: &mut FlowRef,
data: &Reflow, data: &Reflow,
query_type: Option<&ReflowQueryType>, query_type: Option<&ReflowQueryType>,
@ -1486,7 +1483,7 @@ impl LayoutThread {
|| { || {
let profiler_metadata = self.profiler_metadata(); let profiler_metadata = self.profiler_metadata();
if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_mut()) { if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_ref()) {
// Parallel mode. // Parallel mode.
LayoutThread::solve_constraints_parallel(traversal, LayoutThread::solve_constraints_parallel(traversal,
FlowRef::deref_mut(root_flow), FlowRef::deref_mut(root_flow),
@ -1515,31 +1512,31 @@ impl LayoutThread {
context); context);
} }
fn perform_post_main_layout_passes(&mut self, fn perform_post_main_layout_passes(&self,
data: &Reflow, data: &Reflow,
query_type: Option<&ReflowQueryType>, query_type: Option<&ReflowQueryType>,
document: Option<&ServoLayoutDocument>, document: Option<&ServoLayoutDocument>,
rw_data: &mut LayoutThreadData, rw_data: &mut LayoutThreadData,
layout_context: &mut LayoutContext) { layout_context: &mut LayoutContext) {
// Build the display list if necessary, and send it to the painter. // Build the display list if necessary, and send it to the painter.
if let Some(mut root_flow) = self.root_flow.clone() { if let Some(mut root_flow) = self.root_flow.borrow().clone() {
self.compute_abs_pos_and_build_display_list(data, self.compute_abs_pos_and_build_display_list(data,
query_type, query_type,
document, document,
FlowRef::deref_mut(&mut root_flow), FlowRef::deref_mut(&mut root_flow),
&mut *layout_context, &mut *layout_context,
rw_data); rw_data);
self.first_reflow = false; self.first_reflow.set(false);
if opts::get().trace_layout { if opts::get().trace_layout {
layout_debug::end_trace(self.generation); layout_debug::end_trace(self.generation.get());
} }
if opts::get().dump_flow_tree { if opts::get().dump_flow_tree {
root_flow.print("Post layout flow tree".to_owned()); root_flow.print("Post layout flow tree".to_owned());
} }
self.generation += 1; self.generation.set(self.generation.get() + 1);
} }
} }
@ -1563,7 +1560,7 @@ impl LayoutThread {
} else { } else {
TimerMetadataFrameType::RootWindow TimerMetadataFrameType::RootWindow
}, },
incremental: if self.first_reflow { incremental: if self.first_reflow.get() {
TimerMetadataReflowType::FirstReflow TimerMetadataReflowType::FirstReflow
} else { } else {
TimerMetadataReflowType::Incremental TimerMetadataReflowType::Incremental

View file

@ -399,6 +399,7 @@ impl PropertyAnimation {
// //
// TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a // TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
// cloneable part and a non-cloneable part.. // cloneable part and a non-cloneable part..
#[cfg(feature = "servo")]
pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>, pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>,
opaque_node: OpaqueNode, opaque_node: OpaqueNode,
unsafe_node: UnsafeNode, unsafe_node: UnsafeNode,
@ -755,6 +756,7 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
} }
/// Update the style in the node when it finishes. /// Update the style in the node when it finishes.
#[cfg(feature = "servo")]
pub fn complete_expired_transitions(node: OpaqueNode, style: &mut Arc<ComputedValues>, pub fn complete_expired_transitions(node: OpaqueNode, style: &mut Arc<ComputedValues>,
context: &SharedStyleContext) -> bool { context: &SharedStyleContext) -> bool {
let had_animations_to_expire; let had_animations_to_expire;

View file

@ -4,7 +4,8 @@
//! The context within which style is calculated. //! The context within which style is calculated.
use animation::{Animation, PropertyAnimation}; #[cfg(feature = "servo")] use animation::Animation;
use animation::PropertyAnimation;
use app_units::Au; use app_units::Au;
use bit_vec::BitVec; use bit_vec::BitVec;
use bloom::StyleBloom; use bloom::StyleBloom;
@ -17,18 +18,18 @@ use fnv::FnvHashMap;
use font_metrics::FontMetricsProvider; use font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")] use gecko_bindings::structs; #[cfg(feature = "gecko")] use gecko_bindings::structs;
use matching::StyleSharingCandidateCache; use matching::StyleSharingCandidateCache;
use parking_lot::RwLock; #[cfg(feature = "servo")] use parking_lot::RwLock;
#[cfg(feature = "gecko")] use properties::ComputedValues; #[cfg(feature = "gecko")] use properties::ComputedValues;
use selector_parser::SnapshotMap; use selector_parser::SnapshotMap;
use selectors::matching::ElementSelectorFlags; use selectors::matching::ElementSelectorFlags;
#[cfg(feature = "servo")] use servo_config::opts; #[cfg(feature = "servo")] use servo_config::opts;
use shared_lock::StylesheetGuards; use shared_lock::StylesheetGuards;
use std::collections::HashMap; #[cfg(feature = "servo")] use std::collections::HashMap;
#[cfg(not(feature = "servo"))] use std::env; #[cfg(feature = "gecko")] use std::env;
use std::fmt; use std::fmt;
use std::ops::Add; use std::ops::Add;
use std::sync::Mutex; #[cfg(feature = "servo")] use std::sync::Mutex;
use std::sync::mpsc::Sender; #[cfg(feature = "servo")] use std::sync::mpsc::Sender;
use stylearc::Arc; use stylearc::Arc;
use stylist::Stylist; use stylist::Stylist;
use thread_state; use thread_state;
@ -37,10 +38,12 @@ use timer::Timer;
use traversal::{DomTraversal, TraversalFlags}; use traversal::{DomTraversal, TraversalFlags};
/// This structure is used to create a local style context from a shared one. /// This structure is used to create a local style context from a shared one.
#[cfg(feature = "servo")]
pub struct ThreadLocalStyleContextCreationInfo { pub struct ThreadLocalStyleContextCreationInfo {
new_animations_sender: Sender<Animation>, new_animations_sender: Sender<Animation>,
} }
#[cfg(feature = "servo")]
impl ThreadLocalStyleContextCreationInfo { impl ThreadLocalStyleContextCreationInfo {
/// Trivially constructs a `ThreadLocalStyleContextCreationInfo`. /// Trivially constructs a `ThreadLocalStyleContextCreationInfo`.
pub fn new(animations_sender: Sender<Animation>) -> Self { pub fn new(animations_sender: Sender<Animation>) -> Self {
@ -106,7 +109,7 @@ impl Default for StyleSystemOptions {
/// shared among the worker threads. /// shared among the worker threads.
pub struct SharedStyleContext<'a> { pub struct SharedStyleContext<'a> {
/// The CSS selector stylist. /// The CSS selector stylist.
pub stylist: Arc<Stylist>, pub stylist: &'a Stylist,
/// Configuration options. /// Configuration options.
pub options: StyleSystemOptions, pub options: StyleSystemOptions,
@ -114,17 +117,8 @@ pub struct SharedStyleContext<'a> {
/// Guards for pre-acquired locks /// Guards for pre-acquired locks
pub guards: StylesheetGuards<'a>, pub guards: StylesheetGuards<'a>,
/// The animations that are currently running.
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
/// The list of animations that have expired since the last style recalculation.
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
///The CSS error reporter for all CSS loaded in this layout thread ///The CSS error reporter for all CSS loaded in this layout thread
pub error_reporter: Box<ParseErrorReporter>, pub error_reporter: &'a ParseErrorReporter,
/// Data needed to create the thread-local style context from the shared one.
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
/// The current timer for transitions and animations. This is needed to test /// The current timer for transitions and animations. This is needed to test
/// them. /// them.
@ -138,6 +132,19 @@ pub struct SharedStyleContext<'a> {
/// A map with our snapshots in order to handle restyle hints. /// A map with our snapshots in order to handle restyle hints.
pub snapshot_map: &'a SnapshotMap, pub snapshot_map: &'a SnapshotMap,
/// The animations that are currently running.
#[cfg(feature = "servo")]
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
/// The list of animations that have expired since the last style recalculation.
#[cfg(feature = "servo")]
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
/// Data needed to create the thread-local style context from the shared one.
#[cfg(feature = "servo")]
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
} }
impl<'a> SharedStyleContext<'a> { impl<'a> SharedStyleContext<'a> {
@ -400,6 +407,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
pub bloom_filter: StyleBloom<E>, pub bloom_filter: StyleBloom<E>,
/// A channel on which new animations that have been triggered by style /// A channel on which new animations that have been triggered by style
/// recalculation can be sent. /// recalculation can be sent.
#[cfg(feature = "servo")]
pub new_animations_sender: Sender<Animation>, pub new_animations_sender: Sender<Animation>,
/// A set of tasks to be run (on the parent thread) in sequential mode after /// A set of tasks to be run (on the parent thread) in sequential mode after
/// the rest of the styling is complete. This is useful for infrequently-needed /// the rest of the styling is complete. This is useful for infrequently-needed
@ -421,6 +429,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
impl<E: TElement> ThreadLocalStyleContext<E> { impl<E: TElement> ThreadLocalStyleContext<E> {
/// Creates a new `ThreadLocalStyleContext` from a shared one. /// Creates a new `ThreadLocalStyleContext` from a shared one.
#[cfg(feature = "servo")]
pub fn new(shared: &SharedStyleContext) -> Self { pub fn new(shared: &SharedStyleContext) -> Self {
ThreadLocalStyleContext { ThreadLocalStyleContext {
style_sharing_candidate_cache: StyleSharingCandidateCache::new(), style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
@ -434,6 +443,20 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
} }
} }
#[cfg(feature = "gecko")]
/// Creates a new `ThreadLocalStyleContext` from a shared one.
pub fn new(shared: &SharedStyleContext) -> Self {
ThreadLocalStyleContext {
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
bloom_filter: StyleBloom::new(),
tasks: Vec::new(),
selector_flags: SelectorFlagsMap::new(),
statistics: TraversalStatistics::default(),
current_element_info: None,
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
}
}
/// Notes when the style system starts traversing an element. /// Notes when the style system starts traversing an element.
pub fn begin_element(&mut self, element: E, data: &ElementData) { pub fn begin_element(&mut self, element: E, data: &ElementData) {
debug_assert!(self.current_element_info.is_none()); debug_assert!(self.current_element_info.is_none());

View file

@ -18,14 +18,14 @@ use std::collections::HashMap;
use std::sync::mpsc::{Receiver, Sender, channel}; use std::sync::mpsc::{Receiver, Sender, channel};
use stylearc::Arc; use stylearc::Arc;
use stylesheet_set::StylesheetSet; use stylesheet_set::StylesheetSet;
use stylesheets::{FontFaceRule, Origin, Stylesheet}; use stylesheets::{FontFaceRule, Origin};
use stylist::{ExtraStyleData, Stylist}; use stylist::{ExtraStyleData, Stylist};
/// The container for data that a Servo-backed Gecko document needs to style /// The container for data that a Servo-backed Gecko document needs to style
/// itself. /// itself.
pub struct PerDocumentStyleDataImpl { pub struct PerDocumentStyleDataImpl {
/// Rule processor. /// Rule processor.
pub stylist: Arc<Stylist>, pub stylist: Stylist,
/// List of stylesheets, mirrored from Gecko. /// List of stylesheets, mirrored from Gecko.
pub stylesheets: StylesheetSet, pub stylesheets: StylesheetSet,
@ -60,7 +60,7 @@ impl PerDocumentStyleData {
let (new_anims_sender, new_anims_receiver) = channel(); let (new_anims_sender, new_anims_receiver) = channel();
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl { PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
stylist: Arc::new(Stylist::new(device)), stylist: Stylist::new(device),
stylesheets: StylesheetSet::new(), stylesheets: StylesheetSet::new(),
new_animations_sender: new_anims_sender, new_animations_sender: new_anims_sender,
new_animations_receiver: new_anims_receiver, new_animations_receiver: new_anims_receiver,
@ -86,10 +86,7 @@ impl PerDocumentStyleDataImpl {
/// ///
/// Implies also a stylesheet flush. /// Implies also a stylesheet flush.
pub fn reset_device(&mut self, guard: &SharedRwLockReadGuard) { pub fn reset_device(&mut self, guard: &SharedRwLockReadGuard) {
{ Arc::get_mut(&mut self.stylist.device).unwrap().reset();
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
Arc::get_mut(&mut stylist.device).unwrap().reset();
}
self.stylesheets.force_dirty(); self.stylesheets.force_dirty();
self.flush_stylesheets(guard); self.flush_stylesheets(guard);
} }
@ -100,21 +97,18 @@ impl PerDocumentStyleDataImpl {
return; return;
} }
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
let mut extra_data = ExtraStyleData { let mut extra_data = ExtraStyleData {
font_faces: &mut self.font_faces, font_faces: &mut self.font_faces,
}; };
let author_style_disabled = self.stylesheets.author_style_disabled(); let author_style_disabled = self.stylesheets.author_style_disabled();
let mut stylesheets = Vec::<Arc<Stylesheet>>::new(); self.stylist.clear();
self.stylesheets.flush(&mut stylesheets); self.stylist.rebuild(self.stylesheets.flush(),
stylist.clear(); &StylesheetGuards::same(guard),
stylist.rebuild(stylesheets.as_slice(), /* ua_sheets = */ None,
&StylesheetGuards::same(guard), /* stylesheets_changed = */ true,
/* ua_sheets = */ None, author_style_disabled,
/* stylesheets_changed = */ true, &mut extra_data);
author_style_disabled,
&mut extra_data);
} }
/// Get the default computed values for this document. /// Get the default computed values for this document.
@ -125,8 +119,7 @@ impl PerDocumentStyleDataImpl {
/// Clear the stylist. This will be a no-op if the stylist is /// Clear the stylist. This will be a no-op if the stylist is
/// already cleared; the stylist handles that. /// already cleared; the stylist handles that.
pub fn clear_stylist(&mut self) { pub fn clear_stylist(&mut self) {
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap(); self.stylist.clear();
stylist.clear();
} }
} }

View file

@ -8,7 +8,6 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use Atom; use Atom;
use animation::{self, Animation, PropertyAnimation};
use atomic_refcell::AtomicRefMut; use atomic_refcell::AtomicRefMut;
use bit_vec::BitVec; use bit_vec::BitVec;
use cache::{LRUCache, LRUCacheMutIterator}; use cache::{LRUCache, LRUCacheMutIterator};
@ -721,6 +720,8 @@ trait PrivateMatchMethods: TElement {
old_values: &mut Option<Arc<ComputedValues>>, old_values: &mut Option<Arc<ComputedValues>>,
new_values: &mut Arc<ComputedValues>, new_values: &mut Arc<ComputedValues>,
_primary_style: &ComputedStyle) { _primary_style: &ComputedStyle) {
use animation;
let possibly_expired_animations = let possibly_expired_animations =
&mut context.thread_local.current_element_info.as_mut().unwrap() &mut context.thread_local.current_element_info.as_mut().unwrap()
.possibly_expired_animations; .possibly_expired_animations;
@ -806,11 +807,14 @@ trait PrivateMatchMethods: TElement {
} }
} }
#[cfg(feature = "servo")]
fn update_animations_for_cascade(&self, fn update_animations_for_cascade(&self,
context: &SharedStyleContext, context: &SharedStyleContext,
style: &mut Arc<ComputedValues>, style: &mut Arc<ComputedValues>,
possibly_expired_animations: &mut Vec<PropertyAnimation>, possibly_expired_animations: &mut Vec<::animation::PropertyAnimation>,
font_metrics: &FontMetricsProvider) { font_metrics: &FontMetricsProvider) {
use animation::{self, Animation};
// Finish any expired transitions. // Finish any expired transitions.
let this_opaque = self.as_node().opaque(); let this_opaque = self.as_node().opaque();
animation::complete_expired_transitions(this_opaque, style, context); animation::complete_expired_transitions(this_opaque, style, context);

View file

@ -4,6 +4,7 @@
//! A centralized set of stylesheets for a document. //! A centralized set of stylesheets for a document.
use std::slice;
use stylearc::Arc; use stylearc::Arc;
use stylesheets::Stylesheet; use stylesheets::Stylesheet;
@ -14,6 +15,17 @@ pub struct StylesheetSetEntry {
sheet: Arc<Stylesheet>, sheet: Arc<Stylesheet>,
} }
/// A iterator over the stylesheets of a list of entries in the StylesheetSet.
#[derive(Clone)]
pub struct StylesheetIterator<'a>(slice::Iter<'a, StylesheetSetEntry>);
impl<'a> Iterator for StylesheetIterator<'a> {
type Item = &'a Arc<Stylesheet>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|entry| &entry.sheet)
}
}
/// The set of stylesheets effective for a given document. /// The set of stylesheets effective for a given document.
pub struct StylesheetSet { pub struct StylesheetSet {
/// The actual list of all the stylesheets that apply to the given document, /// The actual list of all the stylesheets that apply to the given document,
@ -108,12 +120,11 @@ impl StylesheetSet {
self.dirty self.dirty
} }
/// Flush the current set, unmarking it as dirty. /// Flush the current set, unmarking it as dirty, and returns an iterator
pub fn flush(&mut self, sheets: &mut Vec<Arc<Stylesheet>>) { /// over the new stylesheet list.
pub fn flush(&mut self) -> StylesheetIterator {
self.dirty = false; self.dirty = false;
for entry in &self.entries { StylesheetIterator(self.entries.iter())
sheets.push(entry.sheet.clone())
}
} }
/// Mark the stylesheets as dirty, because something external may have /// Mark the stylesheets as dirty, because something external may have

View file

@ -296,13 +296,15 @@ impl Stylist {
/// This method resets all the style data each time the stylesheets change /// This method resets all the style data each time the stylesheets change
/// (which is indicated by the `stylesheets_changed` parameter), or the /// (which is indicated by the `stylesheets_changed` parameter), or the
/// device is dirty, which means we need to re-evaluate media queries. /// device is dirty, which means we need to re-evaluate media queries.
pub fn rebuild<'a>(&mut self, pub fn rebuild<'a, 'b, I>(&mut self,
doc_stylesheets: &[Arc<Stylesheet>], doc_stylesheets: I,
guards: &StylesheetGuards, guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>, ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool, stylesheets_changed: bool,
author_style_disabled: bool, author_style_disabled: bool,
extra_data: &mut ExtraStyleData<'a>) -> bool { extra_data: &mut ExtraStyleData<'a>) -> bool
where I: Iterator<Item = &'b Arc<Stylesheet>> + Clone,
{
debug_assert!(!self.is_cleared || self.is_device_dirty); debug_assert!(!self.is_cleared || self.is_device_dirty);
self.is_cleared = false; self.is_cleared = false;
@ -315,7 +317,7 @@ impl Stylist {
let cascaded_rule = ViewportRule { let cascaded_rule = ViewportRule {
declarations: viewport::Cascade::from_stylesheets( declarations: viewport::Cascade::from_stylesheets(
doc_stylesheets, guards.author, &self.device doc_stylesheets.clone(), guards.author, &self.device
).finish(), ).finish(),
}; };
@ -345,7 +347,7 @@ impl Stylist {
} }
// Only use author stylesheets if author styles are enabled. // Only use author stylesheets if author styles are enabled.
let sheets_to_add = doc_stylesheets.iter().filter(|s| { let sheets_to_add = doc_stylesheets.filter(|s| {
!author_style_disabled || s.origin != Origin::Author !author_style_disabled || s.origin != Origin::Author
}); });
@ -366,13 +368,15 @@ impl Stylist {
/// clear the stylist and then rebuild it. Chances are, you want to use /// clear the stylist and then rebuild it. Chances are, you want to use
/// either clear() or rebuild(), with the latter done lazily, instead. /// either clear() or rebuild(), with the latter done lazily, instead.
pub fn update<'a>(&mut self, pub fn update<'a, 'b, I>(&mut self,
doc_stylesheets: &[Arc<Stylesheet>], doc_stylesheets: I,
guards: &StylesheetGuards, guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>, ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool, stylesheets_changed: bool,
author_style_disabled: bool, author_style_disabled: bool,
extra_data: &mut ExtraStyleData<'a>) -> bool { extra_data: &mut ExtraStyleData<'a>) -> bool
where I: Iterator<Item = &'b Arc<Stylesheet>> + Clone,
{
debug_assert!(!self.is_cleared || self.is_device_dirty); debug_assert!(!self.is_cleared || self.is_device_dirty);
// We have to do a dirtiness check before clearing, because if // We have to do a dirtiness check before clearing, because if
@ -385,7 +389,9 @@ impl Stylist {
author_style_disabled, extra_data) author_style_disabled, extra_data)
} }
fn add_stylesheet<'a>(&mut self, stylesheet: &Stylesheet, guard: &SharedRwLockReadGuard, fn add_stylesheet<'a>(&mut self,
stylesheet: &Stylesheet,
guard: &SharedRwLockReadGuard,
extra_data: &mut ExtraStyleData<'a>) { extra_data: &mut ExtraStyleData<'a>) {
if stylesheet.disabled() || !stylesheet.is_effective_for_device(&self.device, guard) { if stylesheet.disabled() || !stylesheet.is_effective_for_device(&self.device, guard) {
return; return;
@ -711,10 +717,12 @@ impl Stylist {
/// FIXME(emilio): The semantics of the device for Servo and Gecko are /// FIXME(emilio): The semantics of the device for Servo and Gecko are
/// different enough we may want to unify them. /// different enough we may want to unify them.
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
pub fn set_device(&mut self, mut device: Device, guard: &SharedRwLockReadGuard, pub fn set_device(&mut self,
mut device: Device,
guard: &SharedRwLockReadGuard,
stylesheets: &[Arc<Stylesheet>]) { stylesheets: &[Arc<Stylesheet>]) {
let cascaded_rule = ViewportRule { let cascaded_rule = ViewportRule {
declarations: viewport::Cascade::from_stylesheets(stylesheets, guard, &device).finish(), declarations: viewport::Cascade::from_stylesheets(stylesheets.iter(), guard, &device).finish(),
}; };
self.viewport_constraints = self.viewport_constraints =

View file

@ -26,6 +26,7 @@ use std::iter::Enumerate;
use std::str::Chars; use std::str::Chars;
use style_traits::{PinchZoomFactor, ToCss}; use style_traits::{PinchZoomFactor, ToCss};
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom}; use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
use stylearc::Arc;
use stylesheets::{Stylesheet, Origin}; use stylesheets::{Stylesheet, Origin};
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
use values::specified::{NoCalcLength, LengthOrPercentageOrAuto, ViewportPercentageLength}; use values::specified::{NoCalcLength, LengthOrPercentageOrAuto, ViewportPercentageLength};
@ -329,7 +330,6 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
} }
impl Parse for ViewportRule { impl Parse for ViewportRule {
#[allow(missing_docs)]
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let parser = ViewportRuleParser { context: context }; let parser = ViewportRuleParser { context: context };
@ -545,14 +545,15 @@ impl Cascade {
} }
} }
pub fn from_stylesheets<'a, I>(stylesheets: I, guard: &SharedRwLockReadGuard, pub fn from_stylesheets<'a, I>(stylesheets: I,
device: &Device) -> Self guard: &SharedRwLockReadGuard,
where I: IntoIterator, device: &Device)
I::Item: AsRef<Stylesheet>, -> Self
where I: Iterator<Item = &'a Arc<Stylesheet>>,
{ {
let mut cascade = Self::new(); let mut cascade = Self::new();
for stylesheet in stylesheets { for stylesheet in stylesheets {
stylesheet.as_ref().effective_viewport_rules(device, guard, |rule| { stylesheet.effective_viewport_rules(device, guard, |rule| {
for declaration in &rule.declarations { for declaration in &rule.declarations {
cascade.add(Cow::Borrowed(declaration)) cascade.add(Cow::Borrowed(declaration))
} }

View file

@ -11,9 +11,8 @@ use std::borrow::Cow;
use std::env; use std::env;
use std::fmt::Write; use std::fmt::Write;
use std::ptr; use std::ptr;
use std::sync::Mutex;
use style::context::{QuirksMode, SharedStyleContext, StyleContext}; use style::context::{QuirksMode, SharedStyleContext, StyleContext};
use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInfo}; use style::context::ThreadLocalStyleContext;
use style::data::{ElementData, ElementStyles, RestyleData}; use style::data::{ElementData, ElementStyles, RestyleData};
use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants}; use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants};
use style::dom::{ShowSubtreeData, TElement, TNode}; use style::dom::{ShowSubtreeData, TElement, TNode};
@ -149,24 +148,19 @@ unsafe fn dummy_url_data() -> &'static RefPtr<URLExtraData> {
RefPtr::from_ptr_ref(&DUMMY_URL_DATA) RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
} }
static DEFAULT_ERROR_REPORTER: RustLogReporter = RustLogReporter;
fn create_shared_context<'a>(global_style_data: &GlobalStyleData, fn create_shared_context<'a>(global_style_data: &GlobalStyleData,
guard: &'a SharedRwLockReadGuard, guard: &'a SharedRwLockReadGuard,
per_doc_data: &PerDocumentStyleDataImpl, per_doc_data: &'a PerDocumentStyleDataImpl,
traversal_flags: TraversalFlags, traversal_flags: TraversalFlags,
snapshot_map: &'a ServoElementSnapshotTable) snapshot_map: &'a ServoElementSnapshotTable)
-> SharedStyleContext<'a> { -> SharedStyleContext<'a> {
let local_context_data =
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
SharedStyleContext { SharedStyleContext {
stylist: per_doc_data.stylist.clone(), stylist: &per_doc_data.stylist,
options: global_style_data.options.clone(), options: global_style_data.options.clone(),
guards: StylesheetGuards::same(guard), guards: StylesheetGuards::same(guard),
running_animations: per_doc_data.running_animations.clone(), error_reporter: &DEFAULT_ERROR_REPORTER,
expired_animations: per_doc_data.expired_animations.clone(),
// FIXME(emilio): Stop boxing here.
error_reporter: Box::new(RustLogReporter),
local_context_creation_data: Mutex::new(local_context_data),
timer: Timer::new(), timer: Timer::new(),
// FIXME Find the real QuirksMode information for this document // FIXME Find the real QuirksMode information for this document
quirks_mode: QuirksMode::NoQuirks, quirks_mode: QuirksMode::NoQuirks,
@ -2025,9 +2019,10 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
} }
// We don't have the style ready. Go ahead and compute it as necessary. // We don't have the style ready. Go ahead and compute it as necessary.
let data = doc_data.borrow();
let shared = create_shared_context(&global_style_data, let shared = create_shared_context(&global_style_data,
&guard, &guard,
&mut doc_data.borrow_mut(), &data,
TraversalFlags::empty(), TraversalFlags::empty(),
unsafe { &*snapshots }); unsafe { &*snapshots });
let mut tlc = ThreadLocalStyleContext::new(&shared); let mut tlc = ThreadLocalStyleContext::new(&shared);

View file

@ -25,7 +25,7 @@ macro_rules! stylesheet {
stylesheet!($css, $origin, $error_reporter, SharedRwLock::new()) stylesheet!($css, $origin, $error_reporter, SharedRwLock::new())
}; };
($css:expr, $origin:ident, $error_reporter:expr, $shared_lock:expr) => { ($css:expr, $origin:ident, $error_reporter:expr, $shared_lock:expr) => {
Box::new(Stylesheet::from_str( Arc::new(Stylesheet::from_str(
$css, $css,
ServoUrl::parse("http://localhost").unwrap(), ServoUrl::parse("http://localhost").unwrap(),
Origin::$origin, Origin::$origin,
@ -269,7 +269,7 @@ fn multiple_stylesheets_cascading() {
Author, error_reporter, shared_lock.clone()) Author, error_reporter, shared_lock.clone())
]; ];
let declarations = Cascade::from_stylesheets(&stylesheets, &shared_lock.read(), &device).finish(); let declarations = Cascade::from_stylesheets(stylesheets.iter(), &shared_lock.read(), &device).finish();
assert_decl_len!(declarations == 3); assert_decl_len!(declarations == 3);
assert_decl_eq!(&declarations[0], UserAgent, Zoom: Zoom::Number(1.)); assert_decl_eq!(&declarations[0], UserAgent, Zoom: Zoom::Number(1.));
assert_decl_eq!(&declarations[1], User, MinHeight: viewport_length!(200., px)); assert_decl_eq!(&declarations[1], User, MinHeight: viewport_length!(200., px));
@ -283,7 +283,7 @@ fn multiple_stylesheets_cascading() {
stylesheet!("@viewport { min-width: 300px !important; min-height: 300px !important; zoom: 3 !important; }", stylesheet!("@viewport { min-width: 300px !important; min-height: 300px !important; zoom: 3 !important; }",
Author, error_reporter, shared_lock.clone()) Author, error_reporter, shared_lock.clone())
]; ];
let declarations = Cascade::from_stylesheets(&stylesheets, &shared_lock.read(), &device).finish(); let declarations = Cascade::from_stylesheets(stylesheets.iter(), &shared_lock.read(), &device).finish();
assert_decl_len!(declarations == 3); assert_decl_len!(declarations == 3);
assert_decl_eq!(&declarations[0], UserAgent, MinWidth: viewport_length!(100., px), !important); assert_decl_eq!(&declarations[0], UserAgent, MinWidth: viewport_length!(100., px), !important);
assert_decl_eq!(&declarations[1], User, MinHeight: viewport_length!(200., px), !important); assert_decl_eq!(&declarations[1], User, MinHeight: viewport_length!(200., px), !important);