mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Replace RwLock<StyleRule> with Locked<StyleRule>
This commit is contained in:
parent
57724e5a37
commit
aeffca2a59
33 changed files with 279 additions and 334 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2757,7 +2757,6 @@ dependencies = [
|
||||||
"num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pdqsort 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pdqsort 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2783,7 +2782,6 @@ dependencies = [
|
||||||
"cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -446,7 +446,7 @@ fn translate_including_floats(cur_b: &mut Au, delta: Au, floats: &mut Floats) {
|
||||||
///
|
///
|
||||||
/// Note that flows with position 'fixed' just form a flat list as they all
|
/// Note that flows with position 'fixed' just form a flat list as they all
|
||||||
/// have the Root flow as their CB.
|
/// have the Root flow as their CB.
|
||||||
pub struct AbsoluteAssignBSizesTraversal<'a>(pub &'a SharedStyleContext);
|
pub struct AbsoluteAssignBSizesTraversal<'a>(pub &'a SharedStyleContext<'a>);
|
||||||
|
|
||||||
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
|
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -311,7 +311,7 @@ impl InlineFragmentsAccumulator {
|
||||||
/// An object that knows how to create flows.
|
/// An object that knows how to create flows.
|
||||||
pub struct FlowConstructor<'a, N: ThreadSafeLayoutNode> {
|
pub struct FlowConstructor<'a, N: ThreadSafeLayoutNode> {
|
||||||
/// The layout context.
|
/// The layout context.
|
||||||
pub layout_context: &'a LayoutContext,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
/// Satisfy the compiler about the unused parameters, which we use to improve the ergonomics of
|
/// Satisfy the compiler about the unused parameters, which we use to improve the ergonomics of
|
||||||
/// the ensuing impl {} by removing the need to parameterize all the methods individually.
|
/// the ensuing impl {} by removing the need to parameterize all the methods individually.
|
||||||
phantom2: PhantomData<N>,
|
phantom2: PhantomData<N>,
|
||||||
|
@ -320,7 +320,7 @@ pub struct FlowConstructor<'a, N: ThreadSafeLayoutNode> {
|
||||||
impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
FlowConstructor<'a, ConcreteThreadSafeLayoutNode> {
|
FlowConstructor<'a, ConcreteThreadSafeLayoutNode> {
|
||||||
/// Creates a new flow constructor.
|
/// Creates a new flow constructor.
|
||||||
pub fn new(layout_context: &'a LayoutContext) -> Self {
|
pub fn new(layout_context: &'a LayoutContext<'a>) -> Self {
|
||||||
FlowConstructor {
|
FlowConstructor {
|
||||||
layout_context: layout_context,
|
layout_context: layout_context,
|
||||||
phantom2: PhantomData,
|
phantom2: PhantomData,
|
||||||
|
@ -660,10 +660,9 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
|
|
||||||
let mut style = node.style(self.style_context());
|
let mut style = node.style(self.style_context());
|
||||||
if node_is_input_or_text_area {
|
if node_is_input_or_text_area {
|
||||||
style = self.style_context()
|
let context = self.style_context();
|
||||||
.stylist
|
style = context.stylist.style_for_anonymous_box(
|
||||||
.style_for_anonymous_box(&PseudoElement::ServoInputText,
|
&context.guards, &PseudoElement::ServoInputText, &style)
|
||||||
&style)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.create_fragments_for_node_text_content(&mut initial_fragments, node, &style)
|
self.create_fragments_for_node_text_content(&mut initial_fragments, node, &style)
|
||||||
|
@ -1096,11 +1095,14 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let mut legalizer = Legalizer::new();
|
let mut legalizer = Legalizer::new();
|
||||||
|
|
||||||
let table_style = node.style(self.style_context());
|
let table_style;
|
||||||
let wrapper_style = self.style_context()
|
let wrapper_style;
|
||||||
.stylist
|
{
|
||||||
.style_for_anonymous_box(&PseudoElement::ServoTableWrapper,
|
let context = self.style_context();
|
||||||
&table_style);
|
table_style = node.style(context);
|
||||||
|
wrapper_style = context.stylist.style_for_anonymous_box(
|
||||||
|
&context.guards, &PseudoElement::ServoTableWrapper, &table_style);
|
||||||
|
}
|
||||||
let wrapper_fragment =
|
let wrapper_fragment =
|
||||||
Fragment::from_opaque_node_and_style(node.opaque(),
|
Fragment::from_opaque_node_and_style(node.opaque(),
|
||||||
PseudoElementType::Normal,
|
PseudoElementType::Normal,
|
||||||
|
@ -2080,8 +2082,7 @@ impl Legalizer {
|
||||||
let reference_block = reference.as_block();
|
let reference_block = reference.as_block();
|
||||||
let mut new_style = reference_block.fragment.style.clone();
|
let mut new_style = reference_block.fragment.style.clone();
|
||||||
for pseudo in pseudos {
|
for pseudo in pseudos {
|
||||||
new_style = context.stylist.style_for_anonymous_box(pseudo,
|
new_style = context.stylist.style_for_anonymous_box(&context.guards, pseudo, &new_style)
|
||||||
&new_style)
|
|
||||||
}
|
}
|
||||||
let fragment = reference_block.fragment
|
let fragment = reference_block.fragment
|
||||||
.create_similar_anonymous_fragment(new_style,
|
.create_similar_anonymous_fragment(new_style,
|
||||||
|
|
|
@ -75,9 +75,9 @@ pub fn heap_size_of_persistent_local_context() -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layout information shared among all workers. This must be thread-safe.
|
/// Layout information shared among all workers. This must be thread-safe.
|
||||||
pub struct LayoutContext {
|
pub struct LayoutContext<'a> {
|
||||||
/// Bits shared by the layout and style system.
|
/// Bits shared by the layout and style system.
|
||||||
pub style_context: SharedStyleContext,
|
pub style_context: SharedStyleContext<'a>,
|
||||||
|
|
||||||
/// The shared image cache thread.
|
/// The shared image cache thread.
|
||||||
pub image_cache_thread: Mutex<ImageCacheThread>,
|
pub image_cache_thread: Mutex<ImageCacheThread>,
|
||||||
|
@ -95,7 +95,7 @@ pub struct LayoutContext {
|
||||||
pub pending_images: Option<Mutex<Vec<PendingImage>>>
|
pub pending_images: Option<Mutex<Vec<PendingImage>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for LayoutContext {
|
impl<'a> Drop for LayoutContext<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !thread::panicking() {
|
if !thread::panicking() {
|
||||||
if let Some(ref pending_images) = self.pending_images {
|
if let Some(ref pending_images) = self.pending_images {
|
||||||
|
@ -105,7 +105,7 @@ impl Drop for LayoutContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutContext {
|
impl<'a> LayoutContext<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn shared_context(&self) -> &SharedStyleContext {
|
pub fn shared_context(&self) -> &SharedStyleContext {
|
||||||
&self.style_context
|
&self.style_context
|
||||||
|
|
|
@ -121,7 +121,7 @@ fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DisplayListBuildState<'a> {
|
pub struct DisplayListBuildState<'a> {
|
||||||
pub layout_context: &'a LayoutContext,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
pub root_stacking_context: StackingContext,
|
pub root_stacking_context: StackingContext,
|
||||||
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
|
pub items: HashMap<StackingContextId, Vec<DisplayItem>>,
|
||||||
pub stacking_context_children: HashMap<StackingContextId, Vec<StackingContext>>,
|
pub stacking_context_children: HashMap<StackingContextId, Vec<StackingContext>>,
|
||||||
|
|
|
@ -97,7 +97,7 @@ static KATAKANA_IROHA: [char; 47] = [
|
||||||
/// The generated content resolution traversal.
|
/// The generated content resolution traversal.
|
||||||
pub struct ResolveGeneratedContent<'a> {
|
pub struct ResolveGeneratedContent<'a> {
|
||||||
/// The layout context.
|
/// The layout context.
|
||||||
layout_context: &'a LayoutContext,
|
layout_context: &'a LayoutContext<'a>,
|
||||||
/// The counter representing an ordered list item.
|
/// The counter representing an ordered list item.
|
||||||
list_item: Counter,
|
list_item: Counter,
|
||||||
/// Named CSS counters.
|
/// Named CSS counters.
|
||||||
|
|
|
@ -22,20 +22,20 @@ use style::traversal::PerLevelTraversalData;
|
||||||
use wrapper::{GetRawData, LayoutNodeHelpers, LayoutNodeLayoutData};
|
use wrapper::{GetRawData, LayoutNodeHelpers, LayoutNodeLayoutData};
|
||||||
use wrapper::ThreadSafeLayoutNodeHelpers;
|
use wrapper::ThreadSafeLayoutNodeHelpers;
|
||||||
|
|
||||||
pub struct RecalcStyleAndConstructFlows {
|
pub struct RecalcStyleAndConstructFlows<'a> {
|
||||||
context: LayoutContext,
|
context: LayoutContext<'a>,
|
||||||
driver: TraversalDriver,
|
driver: TraversalDriver,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecalcStyleAndConstructFlows {
|
impl<'a> RecalcStyleAndConstructFlows<'a> {
|
||||||
pub fn layout_context(&self) -> &LayoutContext {
|
pub fn layout_context(&self) -> &LayoutContext<'a> {
|
||||||
&self.context
|
&self.context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecalcStyleAndConstructFlows {
|
impl<'a> RecalcStyleAndConstructFlows<'a> {
|
||||||
/// Creates a traversal context, taking ownership of the shared layout context.
|
/// Creates a traversal context, taking ownership of the shared layout context.
|
||||||
pub fn new(context: LayoutContext, driver: TraversalDriver) -> Self {
|
pub fn new(context: LayoutContext<'a>, driver: TraversalDriver) -> Self {
|
||||||
RecalcStyleAndConstructFlows {
|
RecalcStyleAndConstructFlows {
|
||||||
context: context,
|
context: context,
|
||||||
driver: driver,
|
driver: driver,
|
||||||
|
@ -44,13 +44,13 @@ impl RecalcStyleAndConstructFlows {
|
||||||
|
|
||||||
/// Consumes this traversal context, returning ownership of the shared layout
|
/// Consumes this traversal context, returning ownership of the shared layout
|
||||||
/// context to the caller.
|
/// context to the caller.
|
||||||
pub fn destroy(self) -> LayoutContext {
|
pub fn destroy(self) -> LayoutContext<'a> {
|
||||||
self.context
|
self.context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
impl<E> DomTraversal<E> for RecalcStyleAndConstructFlows
|
impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a>
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
E::ConcreteNode: LayoutNode,
|
E::ConcreteNode: LayoutNode,
|
||||||
{
|
{
|
||||||
|
@ -152,7 +152,7 @@ fn construct_flows_at<N>(context: &LayoutContext,
|
||||||
/// The bubble-inline-sizes traversal, the first part of layout computation. This computes
|
/// The bubble-inline-sizes traversal, the first part of layout computation. This computes
|
||||||
/// preferred and intrinsic inline-sizes and bubbles them up the tree.
|
/// preferred and intrinsic inline-sizes and bubbles them up the tree.
|
||||||
pub struct BubbleISizes<'a> {
|
pub struct BubbleISizes<'a> {
|
||||||
pub layout_context: &'a LayoutContext,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
|
impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
|
||||||
|
@ -171,7 +171,7 @@ impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
|
||||||
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
|
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct AssignISizes<'a> {
|
pub struct AssignISizes<'a> {
|
||||||
pub layout_context: &'a LayoutContext,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
|
impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
|
||||||
|
@ -191,7 +191,7 @@ impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
|
||||||
/// positions. In Gecko this corresponds to `Reflow`.
|
/// positions. In Gecko this corresponds to `Reflow`.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct AssignBSizes<'a> {
|
pub struct AssignBSizes<'a> {
|
||||||
pub layout_context: &'a LayoutContext,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for AssignBSizes<'a> {
|
impl<'a> PostorderFlowTraversal for AssignBSizes<'a> {
|
||||||
|
@ -220,7 +220,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizes<'a> {
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct ComputeAbsolutePositions<'a> {
|
pub struct ComputeAbsolutePositions<'a> {
|
||||||
pub layout_context: &'a LayoutContext,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
||||||
|
|
|
@ -114,8 +114,9 @@ use style::error_reporting::StdoutErrorReporter;
|
||||||
use style::logical_geometry::LogicalPoint;
|
use style::logical_geometry::LogicalPoint;
|
||||||
use style::media_queries::{Device, MediaType};
|
use style::media_queries::{Device, MediaType};
|
||||||
use style::parser::ParserContextExtraData;
|
use style::parser::ParserContextExtraData;
|
||||||
|
use style::servo::AUTHOR_SHARED_LOCK;
|
||||||
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
||||||
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard};
|
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ReadGuards};
|
||||||
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
|
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
|
||||||
use style::stylist::Stylist;
|
use style::stylist::Stylist;
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
|
@ -215,7 +216,7 @@ pub struct LayoutThread {
|
||||||
WebRenderImageInfo,
|
WebRenderImageInfo,
|
||||||
BuildHasherDefault<FnvHasher>>>>,
|
BuildHasherDefault<FnvHasher>>>>,
|
||||||
|
|
||||||
// Webrender interface.
|
/// Webrender interface.
|
||||||
webrender_api: webrender_traits::RenderApi,
|
webrender_api: webrender_traits::RenderApi,
|
||||||
|
|
||||||
/// The timer object to control the timing of the animations. This should
|
/// The timer object to control the timing of the animations. This should
|
||||||
|
@ -498,16 +499,18 @@ 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(&self,
|
fn build_layout_context<'a>(&self,
|
||||||
rw_data: &LayoutThreadData,
|
guards: ReadGuards<'a>,
|
||||||
request_images: bool)
|
rw_data: &LayoutThreadData,
|
||||||
-> LayoutContext {
|
request_images: bool)
|
||||||
|
-> LayoutContext<'a> {
|
||||||
let thread_local_style_context_creation_data =
|
let thread_local_style_context_creation_data =
|
||||||
ThreadLocalStyleContextCreationInfo::new(self.new_animations_sender.clone());
|
ThreadLocalStyleContextCreationInfo::new(self.new_animations_sender.clone());
|
||||||
|
|
||||||
LayoutContext {
|
LayoutContext {
|
||||||
style_context: SharedStyleContext {
|
style_context: SharedStyleContext {
|
||||||
stylist: rw_data.stylist.clone(),
|
stylist: rw_data.stylist.clone(),
|
||||||
|
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: Box::new(self.error_reporter.clone()),
|
||||||
|
@ -941,7 +944,6 @@ impl LayoutThread {
|
||||||
possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||||
let document = unsafe { ServoLayoutNode::new(&data.document) };
|
let document = unsafe { ServoLayoutNode::new(&data.document) };
|
||||||
let document = document.as_document().unwrap();
|
let document = document.as_document().unwrap();
|
||||||
let style_guard = document.style_shared_lock().read();
|
|
||||||
self.quirks_mode = Some(document.quirks_mode());
|
self.quirks_mode = Some(document.quirks_mode());
|
||||||
|
|
||||||
// FIXME(pcwalton): Combine `ReflowGoal` and `ReflowQueryType`. Then remove this assert.
|
// FIXME(pcwalton): Combine `ReflowGoal` and `ReflowQueryType`. Then remove this assert.
|
||||||
|
@ -1017,9 +1019,11 @@ impl LayoutThread {
|
||||||
Au::from_f32_px(initial_viewport.height));
|
Au::from_f32_px(initial_viewport.height));
|
||||||
|
|
||||||
// Calculate the actual viewport as per DEVICE-ADAPT § 6
|
// Calculate the actual viewport as per DEVICE-ADAPT § 6
|
||||||
|
|
||||||
|
let author_guard = document.style_shared_lock().read();
|
||||||
let device = Device::new(MediaType::Screen, initial_viewport);
|
let device = Device::new(MediaType::Screen, initial_viewport);
|
||||||
Arc::get_mut(&mut rw_data.stylist).unwrap()
|
Arc::get_mut(&mut rw_data.stylist).unwrap()
|
||||||
.set_device(device, &style_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| {
|
rw_data.stylist.viewport_constraints().map_or(current_screen_size, |constraints| {
|
||||||
|
@ -1063,10 +1067,16 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the entire flow tree is invalid, then it will be reflowed anyhow.
|
// If the entire flow tree is invalid, then it will be reflowed anyhow.
|
||||||
|
let ua_stylesheets = &*UA_STYLESHEETS;
|
||||||
|
let ua_or_user_guard = ua_stylesheets.shared_lock.read();
|
||||||
|
let guards = ReadGuards {
|
||||||
|
author: &author_guard,
|
||||||
|
ua_or_user: &ua_or_user_guard,
|
||||||
|
};
|
||||||
let needs_dirtying = Arc::get_mut(&mut rw_data.stylist).unwrap().update(
|
let needs_dirtying = Arc::get_mut(&mut rw_data.stylist).unwrap().update(
|
||||||
&data.document_stylesheets,
|
&data.document_stylesheets,
|
||||||
&style_guard,
|
&guards,
|
||||||
Some(&*UA_STYLESHEETS),
|
Some(ua_stylesheets),
|
||||||
data.stylesheets_changed);
|
data.stylesheets_changed);
|
||||||
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
||||||
if needs_dirtying {
|
if needs_dirtying {
|
||||||
|
@ -1113,7 +1123,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 = self.build_layout_context(&*rw_data, true);
|
let mut layout_context = self.build_layout_context(guards.clone(), &*rw_data, true);
|
||||||
|
|
||||||
// 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() {
|
||||||
|
@ -1172,7 +1182,7 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts::get().dump_rule_tree {
|
if opts::get().dump_rule_tree {
|
||||||
layout_context.style_context.stylist.rule_tree.dump_stdout();
|
layout_context.style_context.stylist.rule_tree.dump_stdout(&guards);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GC the rule tree if some heuristics are met.
|
// GC the rule tree if some heuristics are met.
|
||||||
|
@ -1341,7 +1351,13 @@ impl LayoutThread {
|
||||||
page_clip_rect: max_rect(),
|
page_clip_rect: max_rect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut layout_context = self.build_layout_context(&*rw_data, false);
|
let author_guard = AUTHOR_SHARED_LOCK.read();
|
||||||
|
let ua_or_user_guard = UA_STYLESHEETS.shared_lock.read();
|
||||||
|
let guards = ReadGuards {
|
||||||
|
author: &author_guard,
|
||||||
|
ua_or_user: &ua_or_user_guard,
|
||||||
|
};
|
||||||
|
let mut layout_context = self.build_layout_context(guards, &*rw_data, false);
|
||||||
|
|
||||||
if let Some(mut root_flow) = self.root_flow.clone() {
|
if let Some(mut root_flow) = self.root_flow.clone() {
|
||||||
// Perform an abbreviated style recalc that operates without access to the DOM.
|
// Perform an abbreviated style recalc that operates without access to the DOM.
|
||||||
|
|
|
@ -550,7 +550,7 @@ unsafe impl JSTraceable for StyleLocked<NamespaceRule> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl JSTraceable for RwLock<StyleRule> {
|
unsafe impl JSTraceable for StyleLocked<StyleRule> {
|
||||||
unsafe fn trace(&self, _trc: *mut JSTracer) {
|
unsafe fn trace(&self, _trc: *mut JSTracer) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,20 @@ use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSSt
|
||||||
use dom::cssstylesheet::CSSStyleSheet;
|
use dom::cssstylesheet::CSSStyleSheet;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::shared_lock::ToCssWithGuard;
|
use style::shared_lock::{Locked, ToCssWithGuard};
|
||||||
use style::stylesheets::StyleRule;
|
use style::stylesheets::StyleRule;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct CSSStyleRule {
|
pub struct CSSStyleRule {
|
||||||
cssrule: CSSRule,
|
cssrule: CSSRule,
|
||||||
#[ignore_heap_size_of = "Arc"]
|
#[ignore_heap_size_of = "Arc"]
|
||||||
stylerule: Arc<RwLock<StyleRule>>,
|
stylerule: Arc<Locked<StyleRule>>,
|
||||||
style_decl: MutNullableJS<CSSStyleDeclaration>,
|
style_decl: MutNullableJS<CSSStyleDeclaration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSStyleRule {
|
impl CSSStyleRule {
|
||||||
fn new_inherited(parent_stylesheet: &CSSStyleSheet, stylerule: Arc<RwLock<StyleRule>>)
|
fn new_inherited(parent_stylesheet: &CSSStyleSheet, stylerule: Arc<Locked<StyleRule>>)
|
||||||
-> CSSStyleRule {
|
-> CSSStyleRule {
|
||||||
CSSStyleRule {
|
CSSStyleRule {
|
||||||
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
cssrule: CSSRule::new_inherited(parent_stylesheet),
|
||||||
|
@ -37,7 +36,7 @@ impl CSSStyleRule {
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
|
pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
|
||||||
stylerule: Arc<RwLock<StyleRule>>) -> Root<CSSStyleRule> {
|
stylerule: Arc<Locked<StyleRule>>) -> Root<CSSStyleRule> {
|
||||||
reflect_dom_object(box CSSStyleRule::new_inherited(parent_stylesheet, stylerule),
|
reflect_dom_object(box CSSStyleRule::new_inherited(parent_stylesheet, stylerule),
|
||||||
window,
|
window,
|
||||||
CSSStyleRuleBinding::Wrap)
|
CSSStyleRuleBinding::Wrap)
|
||||||
|
@ -52,7 +51,7 @@ impl SpecificCSSRule for CSSStyleRule {
|
||||||
|
|
||||||
fn get_css(&self) -> DOMString {
|
fn get_css(&self) -> DOMString {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
self.stylerule.read().to_css_string(&guard).into()
|
self.stylerule.read_with(&guard).to_css_string(&guard).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,11 +59,16 @@ impl CSSStyleRuleMethods for CSSStyleRule {
|
||||||
// https://drafts.csswg.org/cssom/#dom-cssstylerule-style
|
// https://drafts.csswg.org/cssom/#dom-cssstylerule-style
|
||||||
fn Style(&self) -> Root<CSSStyleDeclaration> {
|
fn Style(&self) -> Root<CSSStyleDeclaration> {
|
||||||
self.style_decl.or_init(|| {
|
self.style_decl.or_init(|| {
|
||||||
CSSStyleDeclaration::new(self.global().as_window(),
|
let guard = self.cssrule.shared_lock().read();
|
||||||
CSSStyleOwner::CSSRule(JS::from_ref(self.upcast()),
|
CSSStyleDeclaration::new(
|
||||||
self.stylerule.read().block.clone()),
|
self.global().as_window(),
|
||||||
None,
|
CSSStyleOwner::CSSRule(
|
||||||
CSSModificationAccess::ReadWrite)
|
JS::from_ref(self.upcast()),
|
||||||
|
self.stylerule.read_with(&guard).block.clone()
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
CSSModificationAccess::ReadWrite
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ use style::attr::AttrValue;
|
||||||
use style::context::{QuirksMode, ReflowGoal};
|
use style::context::{QuirksMode, ReflowGoal};
|
||||||
use style::restyle_hints::{RestyleHint, RESTYLE_STYLE_ATTRIBUTE};
|
use style::restyle_hints::{RestyleHint, RESTYLE_STYLE_ATTRIBUTE};
|
||||||
use style::selector_parser::{RestyleDamage, Snapshot};
|
use style::selector_parser::{RestyleDamage, Snapshot};
|
||||||
|
use style::servo::AUTHOR_SHARED_LOCK;
|
||||||
use style::shared_lock::SharedRwLock as StyleSharedRwLock;
|
use style::shared_lock::SharedRwLock as StyleSharedRwLock;
|
||||||
use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join};
|
use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join};
|
||||||
use style::stylesheets::Stylesheet;
|
use style::stylesheets::Stylesheet;
|
||||||
|
@ -2131,7 +2132,7 @@ impl Document {
|
||||||
scripts: Default::default(),
|
scripts: Default::default(),
|
||||||
anchors: Default::default(),
|
anchors: Default::default(),
|
||||||
applets: Default::default(),
|
applets: Default::default(),
|
||||||
style_shared_lock: StyleSharedRwLock::new(),
|
style_shared_lock: AUTHOR_SHARED_LOCK.clone(),
|
||||||
stylesheets: DOMRefCell::new(None),
|
stylesheets: DOMRefCell::new(None),
|
||||||
stylesheets_changed_since_reflow: Cell::new(false),
|
stylesheets_changed_since_reflow: Cell::new(false),
|
||||||
stylesheet_list: MutNullableJS::new(None),
|
stylesheet_list: MutNullableJS::new(None),
|
||||||
|
|
|
@ -405,6 +405,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
|
||||||
let mut data = self.get_style_data().unwrap().borrow_mut();
|
let mut data = self.get_style_data().unwrap().borrow_mut();
|
||||||
let new_style =
|
let new_style =
|
||||||
context.stylist.precomputed_values_for_pseudo(
|
context.stylist.precomputed_values_for_pseudo(
|
||||||
|
&context.guards,
|
||||||
&style_pseudo,
|
&style_pseudo,
|
||||||
Some(data.styles().primary.values()),
|
Some(data.styles().primary.values()),
|
||||||
CascadeFlags::empty());
|
CascadeFlags::empty());
|
||||||
|
@ -421,6 +422,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
|
||||||
let new_style =
|
let new_style =
|
||||||
context.stylist
|
context.stylist
|
||||||
.lazily_compute_pseudo_element_style(
|
.lazily_compute_pseudo_element_style(
|
||||||
|
&context.guards,
|
||||||
unsafe { &self.unsafe_get() },
|
unsafe { &self.unsafe_get() },
|
||||||
&style_pseudo,
|
&style_pseudo,
|
||||||
data.styles().primary.values());
|
data.styles().primary.values());
|
||||||
|
|
|
@ -40,7 +40,6 @@ nsstring_vendor = {path = "gecko_bindings/nsstring_vendor", optional = true}
|
||||||
num-integer = "0.1.32"
|
num-integer = "0.1.32"
|
||||||
num-traits = "0.1.32"
|
num-traits = "0.1.32"
|
||||||
ordered-float = "0.4"
|
ordered-float = "0.4"
|
||||||
owning_ref = "0.2.2"
|
|
||||||
parking_lot = "0.3.3"
|
parking_lot = "0.3.3"
|
||||||
pdqsort = "0.1.0"
|
pdqsort = "0.1.0"
|
||||||
rayon = "0.6"
|
rayon = "0.6"
|
||||||
|
|
|
@ -17,6 +17,7 @@ use parking_lot::RwLock;
|
||||||
use selector_parser::PseudoElement;
|
use selector_parser::PseudoElement;
|
||||||
use selectors::matching::ElementSelectorFlags;
|
use selectors::matching::ElementSelectorFlags;
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
|
use shared_lock::ReadGuards;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -61,10 +62,13 @@ pub enum QuirksMode {
|
||||||
///
|
///
|
||||||
/// There's exactly one of these during a given restyle traversal, and it's
|
/// There's exactly one of these during a given restyle traversal, and it's
|
||||||
/// shared among the worker threads.
|
/// shared among the worker threads.
|
||||||
pub struct SharedStyleContext {
|
pub struct SharedStyleContext<'a> {
|
||||||
/// The CSS selector stylist.
|
/// The CSS selector stylist.
|
||||||
pub stylist: Arc<Stylist>,
|
pub stylist: Arc<Stylist>,
|
||||||
|
|
||||||
|
/// Guards for pre-acquired locks
|
||||||
|
pub guards: ReadGuards<'a>,
|
||||||
|
|
||||||
/// The animations that are currently running.
|
/// The animations that are currently running.
|
||||||
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||||
|
|
||||||
|
@ -85,7 +89,7 @@ pub struct SharedStyleContext {
|
||||||
pub quirks_mode: QuirksMode,
|
pub quirks_mode: QuirksMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedStyleContext {
|
impl<'a> SharedStyleContext<'a> {
|
||||||
/// Return a suitable viewport size in order to be used for viewport units.
|
/// Return a suitable viewport size in order to be used for viewport units.
|
||||||
pub fn viewport_size(&self) -> Size2D<Au> {
|
pub fn viewport_size(&self) -> Size2D<Au> {
|
||||||
self.stylist.device.au_viewport_size()
|
self.stylist.device.au_viewport_size()
|
||||||
|
@ -306,7 +310,7 @@ impl<E: TElement> Drop for ThreadLocalStyleContext<E> {
|
||||||
/// shared style context, and a mutable reference to a local one.
|
/// shared style context, and a mutable reference to a local one.
|
||||||
pub struct StyleContext<'a, E: TElement + 'a> {
|
pub struct StyleContext<'a, E: TElement + 'a> {
|
||||||
/// The shared style context reference.
|
/// The shared style context reference.
|
||||||
pub shared: &'a SharedStyleContext,
|
pub shared: &'a SharedStyleContext<'a>,
|
||||||
/// The thread-local style context (mutable) reference.
|
/// The thread-local style context (mutable) reference.
|
||||||
pub thread_local: &'a mut ThreadLocalStyleContext<E>,
|
pub thread_local: &'a mut ThreadLocalStyleContext<E>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,18 +51,7 @@ impl_arc_ffi!(ComputedValues => ServoComputedValues
|
||||||
impl_arc_ffi!(RwLock<PropertyDeclarationBlock> => RawServoDeclarationBlock
|
impl_arc_ffi!(RwLock<PropertyDeclarationBlock> => RawServoDeclarationBlock
|
||||||
[Servo_DeclarationBlock_AddRef, Servo_DeclarationBlock_Release]);
|
[Servo_DeclarationBlock_AddRef, Servo_DeclarationBlock_Release]);
|
||||||
|
|
||||||
/// FIXME: Remove once StyleRule is actually in Locked<_>
|
impl_arc_ffi!(Locked<StyleRule> => RawServoStyleRule
|
||||||
pub trait HackHackHack {
|
|
||||||
fn as_arc<'a>(ptr: &'a &RawServoStyleRule) -> &'a ::std::sync::Arc<RwLock<StyleRule>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HackHackHack for Locked<StyleRule> {
|
|
||||||
fn as_arc<'a>(ptr: &'a &RawServoStyleRule) -> &'a ::std::sync::Arc<RwLock<StyleRule>> {
|
|
||||||
RwLock::<StyleRule>::as_arc(ptr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_arc_ffi!(RwLock<StyleRule> => RawServoStyleRule
|
|
||||||
[Servo_StyleRule_AddRef, Servo_StyleRule_Release]);
|
[Servo_StyleRule_AddRef, Servo_StyleRule_Release]);
|
||||||
|
|
||||||
impl_arc_ffi!(Locked<ImportRule> => RawServoImportRule
|
impl_arc_ffi!(Locked<ImportRule> => RawServoImportRule
|
||||||
|
|
|
@ -13,7 +13,7 @@ use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use shared_lock::SharedRwLockReadGuard;
|
use shared_lock::{ReadGuards, SharedRwLockReadGuard};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||||
|
@ -97,7 +97,7 @@ impl PerDocumentStyleDataImpl {
|
||||||
pub fn flush_stylesheets(&mut self, guard: &SharedRwLockReadGuard) {
|
pub fn flush_stylesheets(&mut self, guard: &SharedRwLockReadGuard) {
|
||||||
if self.stylesheets_changed {
|
if self.stylesheets_changed {
|
||||||
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
let mut stylist = Arc::get_mut(&mut self.stylist).unwrap();
|
||||||
stylist.update(&self.stylesheets, guard, None, true);
|
stylist.update(&self.stylesheets, &ReadGuards::same(guard), None, true);
|
||||||
self.stylesheets_changed = false;
|
self.stylesheets_changed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,14 @@ use traversal::{DomTraversal, PerLevelTraversalData, TraversalDriver, recalc_sty
|
||||||
|
|
||||||
/// This is the simple struct that Gecko uses to encapsulate a DOM traversal for
|
/// This is the simple struct that Gecko uses to encapsulate a DOM traversal for
|
||||||
/// styling.
|
/// styling.
|
||||||
pub struct RecalcStyleOnly {
|
pub struct RecalcStyleOnly<'a> {
|
||||||
shared: SharedStyleContext,
|
shared: SharedStyleContext<'a>,
|
||||||
driver: TraversalDriver,
|
driver: TraversalDriver,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecalcStyleOnly {
|
impl<'a> RecalcStyleOnly<'a> {
|
||||||
/// Create a `RecalcStyleOnly` traversal from a `SharedStyleContext`.
|
/// Create a `RecalcStyleOnly` traversal from a `SharedStyleContext`.
|
||||||
pub fn new(shared: SharedStyleContext, driver: TraversalDriver) -> Self {
|
pub fn new(shared: SharedStyleContext<'a>, driver: TraversalDriver) -> Self {
|
||||||
RecalcStyleOnly {
|
RecalcStyleOnly {
|
||||||
shared: shared,
|
shared: shared,
|
||||||
driver: driver,
|
driver: driver,
|
||||||
|
@ -28,10 +28,11 @@ impl RecalcStyleOnly {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly {
|
impl<'recalc, 'le> DomTraversal<GeckoElement<'le>> for RecalcStyleOnly<'recalc> {
|
||||||
type ThreadLocalContext = ThreadLocalStyleContext<GeckoElement<'le>>;
|
type ThreadLocalContext = ThreadLocalStyleContext<GeckoElement<'le>>;
|
||||||
|
|
||||||
fn process_preorder(&self, traversal_data: &mut PerLevelTraversalData,
|
fn process_preorder(&self,
|
||||||
|
traversal_data: &mut PerLevelTraversalData,
|
||||||
thread_local: &mut Self::ThreadLocalContext,
|
thread_local: &mut Self::ThreadLocalContext,
|
||||||
node: GeckoNode<'le>)
|
node: GeckoNode<'le>)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,7 +60,6 @@ extern crate matches;
|
||||||
extern crate num_integer;
|
extern crate num_integer;
|
||||||
extern crate num_traits;
|
extern crate num_traits;
|
||||||
extern crate ordered_float;
|
extern crate ordered_float;
|
||||||
extern crate owning_ref;
|
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate pdqsort;
|
extern crate pdqsort;
|
||||||
extern crate rayon;
|
extern crate rayon;
|
||||||
|
@ -99,7 +98,6 @@ pub mod keyframes;
|
||||||
pub mod logical_geometry;
|
pub mod logical_geometry;
|
||||||
pub mod matching;
|
pub mod matching;
|
||||||
pub mod media_queries;
|
pub mod media_queries;
|
||||||
pub mod owning_handle;
|
|
||||||
pub mod parallel;
|
pub mod parallel;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod restyle_hints;
|
pub mod restyle_hints;
|
||||||
|
|
|
@ -541,6 +541,7 @@ trait PrivateMatchMethods: TElement {
|
||||||
let values =
|
let values =
|
||||||
Arc::new(cascade(&shared_context.stylist.device,
|
Arc::new(cascade(&shared_context.stylist.device,
|
||||||
rule_node,
|
rule_node,
|
||||||
|
&shared_context.guards,
|
||||||
inherited_values,
|
inherited_values,
|
||||||
layout_parent_style,
|
layout_parent_style,
|
||||||
Some(&mut cascade_info),
|
Some(&mut cascade_info),
|
||||||
|
@ -784,6 +785,7 @@ pub trait MatchMethods : TElement {
|
||||||
style_attribute,
|
style_attribute,
|
||||||
animation_rules,
|
animation_rules,
|
||||||
None,
|
None,
|
||||||
|
&context.shared.guards,
|
||||||
&mut applicable_declarations,
|
&mut applicable_declarations,
|
||||||
&mut flags);
|
&mut flags);
|
||||||
let primary_rule_node = compute_rule_node(context, &mut applicable_declarations);
|
let primary_rule_node = compute_rule_node(context, &mut applicable_declarations);
|
||||||
|
@ -809,6 +811,7 @@ pub trait MatchMethods : TElement {
|
||||||
Some(context.thread_local.bloom_filter.filter()),
|
Some(context.thread_local.bloom_filter.filter()),
|
||||||
None, pseudo_animation_rules,
|
None, pseudo_animation_rules,
|
||||||
Some(&pseudo),
|
Some(&pseudo),
|
||||||
|
&context.shared.guards,
|
||||||
&mut applicable_declarations,
|
&mut applicable_declarations,
|
||||||
&mut flags);
|
&mut flags);
|
||||||
|
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
|
||||||
#![deny(missing_docs)]
|
|
||||||
|
|
||||||
//! A handle that encapsulate a reference to a given data along with its owner.
|
|
||||||
|
|
||||||
use owning_ref::StableAddress;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
|
|
||||||
/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows
|
|
||||||
/// consumers to pass around an owned object and a dependent reference,
|
|
||||||
/// `OwningHandle` contains an owned object and a dependent _object_.
|
|
||||||
///
|
|
||||||
/// `OwningHandle` can encapsulate a `RefMut` along with its associated
|
|
||||||
/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`.
|
|
||||||
/// However, the API is completely generic and there are no restrictions on
|
|
||||||
/// what types of owning and dependent objects may be used.
|
|
||||||
///
|
|
||||||
/// `OwningHandle` is created by passing an owner object (which dereferences
|
|
||||||
/// to a stable address) along with a callback which receives a pointer to
|
|
||||||
/// that stable location. The callback may then dereference the pointer and
|
|
||||||
/// mint a dependent object, with the guarantee that the returned object will
|
|
||||||
/// not outlive the referent of the pointer.
|
|
||||||
///
|
|
||||||
/// This does foist some unsafety onto the callback, which needs an `unsafe`
|
|
||||||
/// block to dereference the pointer. It would be almost good enough for
|
|
||||||
/// OwningHandle to pass a transmuted &'static reference to the callback
|
|
||||||
/// since the lifetime is infinite as far as the minted handle is concerned.
|
|
||||||
/// However, even an `Fn` callback can still allow the reference to escape
|
|
||||||
/// via a `StaticMutex` or similar, which technically violates the safety
|
|
||||||
/// contract. Some sort of language support in the lifetime system could
|
|
||||||
/// make this API a bit nicer.
|
|
||||||
pub struct OwningHandle<O, H>
|
|
||||||
where O: StableAddress,
|
|
||||||
H: Deref,
|
|
||||||
{
|
|
||||||
handle: H,
|
|
||||||
_owner: O,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<O, H> Deref for OwningHandle<O, H>
|
|
||||||
where O: StableAddress,
|
|
||||||
H: Deref,
|
|
||||||
{
|
|
||||||
type Target = H::Target;
|
|
||||||
fn deref(&self) -> &H::Target {
|
|
||||||
self.handle.deref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl<O, H> StableAddress for OwningHandle<O, H>
|
|
||||||
where O: StableAddress,
|
|
||||||
H: StableAddress,
|
|
||||||
{}
|
|
||||||
|
|
||||||
impl<O, H> DerefMut for OwningHandle<O, H>
|
|
||||||
where O: StableAddress,
|
|
||||||
H: DerefMut,
|
|
||||||
{
|
|
||||||
fn deref_mut(&mut self) -> &mut H::Target {
|
|
||||||
self.handle.deref_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<O, H> OwningHandle<O, H>
|
|
||||||
where O: StableAddress,
|
|
||||||
H: Deref,
|
|
||||||
{
|
|
||||||
/// Create a new OwningHandle. The provided callback will be invoked with
|
|
||||||
/// a pointer to the object owned by `o`, and the returned value is stored
|
|
||||||
/// as the object to which this `OwningHandle` will forward `Deref` and
|
|
||||||
/// `DerefMut`.
|
|
||||||
pub fn new<F>(o: O, f: F) -> Self
|
|
||||||
where F: Fn(*const O::Target) -> H,
|
|
||||||
{
|
|
||||||
let h: H;
|
|
||||||
{
|
|
||||||
h = f(o.deref() as *const O::Target);
|
|
||||||
}
|
|
||||||
|
|
||||||
OwningHandle {
|
|
||||||
handle: h,
|
|
||||||
_owner: o,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -31,6 +31,7 @@ use parser::{Parse, ParserContext, ParserContextExtraData};
|
||||||
use properties::animated_properties::TransitionProperty;
|
use properties::animated_properties::TransitionProperty;
|
||||||
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
|
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
use shared_lock::ReadGuards;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use stylesheets::Origin;
|
use stylesheets::Origin;
|
||||||
#[cfg(feature = "servo")] use values::Either;
|
#[cfg(feature = "servo")] use values::Either;
|
||||||
|
@ -1860,6 +1861,7 @@ bitflags! {
|
||||||
///
|
///
|
||||||
pub fn cascade(device: &Device,
|
pub fn cascade(device: &Device,
|
||||||
rule_node: &StrongRuleNode,
|
rule_node: &StrongRuleNode,
|
||||||
|
guards: &ReadGuards,
|
||||||
parent_style: Option<<&ComputedValues>,
|
parent_style: Option<<&ComputedValues>,
|
||||||
layout_parent_style: Option<<&ComputedValues>,
|
layout_parent_style: Option<<&ComputedValues>,
|
||||||
cascade_info: Option<<&mut CascadeInfo>,
|
cascade_info: Option<<&mut CascadeInfo>,
|
||||||
|
@ -1882,11 +1884,12 @@ pub fn cascade(device: &Device,
|
||||||
|
|
||||||
// Hold locks until after the apply_declarations() call returns.
|
// Hold locks until after the apply_declarations() call returns.
|
||||||
// Use filter_map because the root node has no style source.
|
// Use filter_map because the root node has no style source.
|
||||||
let lock_guards = rule_node.self_and_ancestors().filter_map(|node| {
|
let declaration_blocks = rule_node.self_and_ancestors().filter_map(|node| {
|
||||||
node.style_source().map(|source| (source.read(), node.importance()))
|
let guard = node.cascade_level().guard(guards);
|
||||||
|
node.style_source().map(|source| (source.read(guard), node.importance()))
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
let iter_declarations = || {
|
let iter_declarations = || {
|
||||||
lock_guards.iter().flat_map(|&(ref source, source_importance)| {
|
declaration_blocks.iter().flat_map(|&(ref source, source_importance)| {
|
||||||
source.declarations().iter()
|
source.declarations().iter()
|
||||||
// Yield declarations later in source order (with more precedence) first.
|
// Yield declarations later in source order (with more precedence) first.
|
||||||
.rev()
|
.rev()
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
use arc_ptr_eq;
|
use arc_ptr_eq;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use owning_handle::OwningHandle;
|
|
||||||
use parking_lot::{RwLock, RwLockReadGuard};
|
use parking_lot::{RwLock, RwLockReadGuard};
|
||||||
use properties::{Importance, PropertyDeclarationBlock};
|
use properties::{Importance, PropertyDeclarationBlock};
|
||||||
|
use shared_lock::{Locked, ReadGuards, SharedRwLockReadGuard};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -52,35 +52,11 @@ pub struct RuleTree {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum StyleSource {
|
pub enum StyleSource {
|
||||||
/// A style rule stable pointer.
|
/// A style rule stable pointer.
|
||||||
Style(Arc<RwLock<StyleRule>>),
|
Style(Arc<Locked<StyleRule>>),
|
||||||
/// A declaration block stable pointer.
|
/// A declaration block stable pointer.
|
||||||
Declarations(Arc<RwLock<PropertyDeclarationBlock>>),
|
Declarations(Arc<RwLock<PropertyDeclarationBlock>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
type StyleSourceGuardHandle<'a> =
|
|
||||||
OwningHandle<
|
|
||||||
RwLockReadGuard<'a, StyleRule>,
|
|
||||||
RwLockReadGuard<'a, PropertyDeclarationBlock>>;
|
|
||||||
|
|
||||||
/// A guard for a given style source.
|
|
||||||
pub enum StyleSourceGuard<'a> {
|
|
||||||
/// A guard for a style rule.
|
|
||||||
Style(StyleSourceGuardHandle<'a>),
|
|
||||||
/// A guard for a declaration block.
|
|
||||||
Declarations(RwLockReadGuard<'a, PropertyDeclarationBlock>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ::std::ops::Deref for StyleSourceGuard<'a> {
|
|
||||||
type Target = PropertyDeclarationBlock;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match *self {
|
|
||||||
StyleSourceGuard::Declarations(ref block) => &*block,
|
|
||||||
StyleSourceGuard::Style(ref handle) => &*handle,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StyleSource {
|
impl StyleSource {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ptr_equals(&self, other: &Self) -> bool {
|
fn ptr_equals(&self, other: &Self) -> bool {
|
||||||
|
@ -92,28 +68,27 @@ impl StyleSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump<W: Write>(&self, writer: &mut W) {
|
fn dump<W: Write>(&self, guard: &SharedRwLockReadGuard, writer: &mut W) {
|
||||||
use self::StyleSource::*;
|
use self::StyleSource::*;
|
||||||
|
|
||||||
if let Style(ref rule) = *self {
|
if let Style(ref rule) = *self {
|
||||||
let _ = write!(writer, "{:?}", rule.read().selectors);
|
let rule = rule.read_with(guard);
|
||||||
|
let _ = write!(writer, "{:?}", rule.selectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = write!(writer, " -> {:?}", self.read().declarations());
|
let _ = write!(writer, " -> {:?}", self.read(guard).declarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the style source guard, and obtain thus read access to the
|
/// Read the style source guard, and obtain thus read access to the
|
||||||
/// underlying property declaration block.
|
/// underlying property declaration block.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read<'a>(&'a self) -> StyleSourceGuard<'a> {
|
pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard)
|
||||||
use self::StyleSource::*;
|
-> RwLockReadGuard<'a, PropertyDeclarationBlock> {
|
||||||
match *self {
|
let block = match *self {
|
||||||
Style(ref rule) => {
|
StyleSource::Style(ref rule) => &rule.read_with(guard).block,
|
||||||
let owning_ref = OwningHandle::new(rule.read(), |r| unsafe { &*r }.block.read());
|
StyleSource::Declarations(ref block) => block,
|
||||||
StyleSourceGuard::Style(owning_ref)
|
};
|
||||||
}
|
block.read()
|
||||||
Declarations(ref block) => StyleSourceGuard::Declarations(block.read()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,15 +112,15 @@ impl RuleTree {
|
||||||
self.root.clone()
|
self.root.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump<W: Write>(&self, writer: &mut W) {
|
fn dump<W: Write>(&self, guards: &ReadGuards, writer: &mut W) {
|
||||||
let _ = writeln!(writer, " + RuleTree");
|
let _ = writeln!(writer, " + RuleTree");
|
||||||
self.root.get().dump(writer, 0);
|
self.root.get().dump(guards, writer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dump the rule tree to stdout.
|
/// Dump the rule tree to stdout.
|
||||||
pub fn dump_stdout(&self) {
|
pub fn dump_stdout(&self, guards: &ReadGuards) {
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
self.dump(&mut stdout);
|
self.dump(guards, &mut stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert the given rules, that must be in proper order by specifity, and
|
/// Insert the given rules, that must be in proper order by specifity, and
|
||||||
|
@ -307,6 +282,17 @@ pub enum CascadeLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CascadeLevel {
|
impl CascadeLevel {
|
||||||
|
/// Select a lock guard for this level
|
||||||
|
pub fn guard<'a>(&self, guards: &'a ReadGuards<'a>) -> &'a SharedRwLockReadGuard<'a> {
|
||||||
|
match *self {
|
||||||
|
CascadeLevel::UANormal |
|
||||||
|
CascadeLevel::UserNormal |
|
||||||
|
CascadeLevel::UserImportant |
|
||||||
|
CascadeLevel::UAImportant => guards.ua_or_user,
|
||||||
|
_ => guards.author,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns whether this cascade level is unique per element, in which case
|
/// Returns whether this cascade level is unique per element, in which case
|
||||||
/// we can replace the path in the cascade without fear.
|
/// we can replace the path in the cascade without fear.
|
||||||
pub fn is_unique_per_element(&self) -> bool {
|
pub fn is_unique_per_element(&self) -> bool {
|
||||||
|
@ -450,7 +436,7 @@ impl RuleNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump<W: Write>(&self, writer: &mut W, indent: usize) {
|
fn dump<W: Write>(&self, guards: &ReadGuards, writer: &mut W, indent: usize) {
|
||||||
const INDENT_INCREMENT: usize = 4;
|
const INDENT_INCREMENT: usize = 4;
|
||||||
|
|
||||||
for _ in 0..indent {
|
for _ in 0..indent {
|
||||||
|
@ -467,7 +453,7 @@ impl RuleNode {
|
||||||
|
|
||||||
match self.source {
|
match self.source {
|
||||||
Some(ref source) => {
|
Some(ref source) => {
|
||||||
source.dump(writer);
|
source.dump(self.level.guard(guards), writer);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if indent != 0 {
|
if indent != 0 {
|
||||||
|
@ -479,7 +465,7 @@ impl RuleNode {
|
||||||
|
|
||||||
let _ = write!(writer, "\n");
|
let _ = write!(writer, "\n");
|
||||||
for child in self.iter_children() {
|
for child in self.iter_children() {
|
||||||
child.get().dump(writer, indent + INDENT_INCREMENT);
|
child.get().dump(guards, writer, indent + INDENT_INCREMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,6 +613,11 @@ impl StrongRuleNode {
|
||||||
self.get().source.as_ref()
|
self.get().source.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The cascade level for this node
|
||||||
|
pub fn cascade_level(&self) -> CascadeLevel {
|
||||||
|
self.get().level
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the importance that this rule node represents.
|
/// Get the importance that this rule node represents.
|
||||||
pub fn importance(&self) -> Importance {
|
pub fn importance(&self) -> Importance {
|
||||||
self.get().level.importance()
|
self.get().level.importance()
|
||||||
|
|
|
@ -9,3 +9,13 @@
|
||||||
pub mod media_queries;
|
pub mod media_queries;
|
||||||
pub mod restyle_damage;
|
pub mod restyle_damage;
|
||||||
pub mod selector_parser;
|
pub mod selector_parser;
|
||||||
|
|
||||||
|
use shared_lock::SharedRwLock;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
/// Per-process shared lock for author-origin stylesheets
|
||||||
|
///
|
||||||
|
/// FIXME: make it per-document or per-pipeline instead:
|
||||||
|
/// https://github.com/servo/servo/issues/16027
|
||||||
|
pub static ref AUTHOR_SHARED_LOCK: SharedRwLock = SharedRwLock::new();
|
||||||
|
}
|
||||||
|
|
|
@ -177,3 +177,23 @@ pub trait ToCssWithGuard {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Guards for a document
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ReadGuards<'a> {
|
||||||
|
/// For author-origin stylesheets
|
||||||
|
pub author: &'a SharedRwLockReadGuard<'a>,
|
||||||
|
|
||||||
|
/// For user-agent-origin and user-origin stylesheets
|
||||||
|
pub ua_or_user: &'a SharedRwLockReadGuard<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ReadGuards<'a> {
|
||||||
|
/// Same guard for all origins
|
||||||
|
pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
|
||||||
|
ReadGuards {
|
||||||
|
author: guard,
|
||||||
|
ua_or_user: guard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -215,7 +215,7 @@ pub enum CssRule {
|
||||||
|
|
||||||
Namespace(Arc<Locked<NamespaceRule>>),
|
Namespace(Arc<Locked<NamespaceRule>>),
|
||||||
Import(Arc<Locked<ImportRule>>),
|
Import(Arc<Locked<ImportRule>>),
|
||||||
Style(Arc<RwLock<StyleRule>>),
|
Style(Arc<Locked<StyleRule>>),
|
||||||
Media(Arc<Locked<MediaRule>>),
|
Media(Arc<Locked<MediaRule>>),
|
||||||
FontFace(Arc<Locked<FontFaceRule>>),
|
FontFace(Arc<Locked<FontFaceRule>>),
|
||||||
Viewport(Arc<Locked<ViewportRule>>),
|
Viewport(Arc<Locked<ViewportRule>>),
|
||||||
|
@ -380,7 +380,7 @@ impl ToCssWithGuard for CssRule {
|
||||||
match *self {
|
match *self {
|
||||||
CssRule::Namespace(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
CssRule::Namespace(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||||
CssRule::Import(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
CssRule::Import(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||||
CssRule::Style(ref lock) => lock.read().to_css(guard, dest),
|
CssRule::Style(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||||
CssRule::FontFace(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
CssRule::FontFace(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||||
CssRule::Viewport(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
CssRule::Viewport(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||||
CssRule::Keyframes(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
CssRule::Keyframes(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||||
|
@ -736,18 +736,6 @@ rule_filter! {
|
||||||
effective_supports_rules(Supports => SupportsRule),
|
effective_supports_rules(Supports => SupportsRule),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME: Remove once StyleRule is actually in Locked<_>
|
|
||||||
pub trait RwLockStyleRulePretendLockedStyleRule<T> {
|
|
||||||
/// Pretend we’re Locked<_>
|
|
||||||
fn read_with(&self, guard: &SharedRwLockReadGuard) -> ::parking_lot::RwLockReadGuard<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RwLockStyleRulePretendLockedStyleRule<StyleRule> for RwLock<StyleRule> {
|
|
||||||
fn read_with(&self, _: &SharedRwLockReadGuard) -> ::parking_lot::RwLockReadGuard<StyleRule> {
|
|
||||||
self.read()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The stylesheet loader is the abstraction used to trigger network requests
|
/// The stylesheet loader is the abstraction used to trigger network requests
|
||||||
/// for `@import` rules.
|
/// for `@import` rules.
|
||||||
pub trait StylesheetLoader {
|
pub trait StylesheetLoader {
|
||||||
|
@ -1030,7 +1018,7 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
|
|
||||||
fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
|
fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
|
||||||
-> Result<CssRule, ()> {
|
-> Result<CssRule, ()> {
|
||||||
Ok(CssRule::Style(Arc::new(RwLock::new(StyleRule {
|
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
|
||||||
selectors: prelude,
|
selectors: prelude,
|
||||||
block: Arc::new(RwLock::new(parse_property_declaration_list(self.context, input)))
|
block: Arc::new(RwLock::new(parse_property_declaration_list(self.context, input)))
|
||||||
}))))
|
}))))
|
||||||
|
|
|
@ -28,7 +28,7 @@ use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONA
|
||||||
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_complex_selector};
|
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_complex_selector};
|
||||||
use selectors::parser::{Selector, SimpleSelector, LocalName as LocalNameSelector, ComplexSelector};
|
use selectors::parser::{Selector, SimpleSelector, LocalName as LocalNameSelector, ComplexSelector};
|
||||||
use selectors::parser::SelectorMethods;
|
use selectors::parser::SelectorMethods;
|
||||||
use shared_lock::SharedRwLockReadGuard;
|
use shared_lock::{Locked, SharedRwLockReadGuard, ReadGuards};
|
||||||
use sink::Push;
|
use sink::Push;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
@ -159,7 +159,7 @@ impl Stylist {
|
||||||
/// 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 update(&mut self,
|
pub fn update(&mut self,
|
||||||
doc_stylesheets: &[Arc<Stylesheet>],
|
doc_stylesheets: &[Arc<Stylesheet>],
|
||||||
doc_guard: &SharedRwLockReadGuard,
|
guards: &ReadGuards,
|
||||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
ua_stylesheets: Option<&UserAgentStylesheets>,
|
||||||
stylesheets_changed: bool) -> bool {
|
stylesheets_changed: bool) -> bool {
|
||||||
if !(self.is_device_dirty || stylesheets_changed) {
|
if !(self.is_device_dirty || stylesheets_changed) {
|
||||||
|
@ -168,7 +168,7 @@ impl Stylist {
|
||||||
|
|
||||||
let cascaded_rule = ViewportRule {
|
let cascaded_rule = ViewportRule {
|
||||||
declarations: viewport::Cascade::from_stylesheets(
|
declarations: viewport::Cascade::from_stylesheets(
|
||||||
doc_stylesheets, doc_guard, &self.device
|
doc_stylesheets, guards.author, &self.device
|
||||||
).finish(),
|
).finish(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,18 +196,17 @@ impl Stylist {
|
||||||
self.non_common_style_affecting_attributes_selectors.clear();
|
self.non_common_style_affecting_attributes_selectors.clear();
|
||||||
|
|
||||||
if let Some(ua_stylesheets) = ua_stylesheets {
|
if let Some(ua_stylesheets) = ua_stylesheets {
|
||||||
let ua_guard = ua_stylesheets.shared_lock.read();
|
|
||||||
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
||||||
self.add_stylesheet(&stylesheet, &ua_guard);
|
self.add_stylesheet(&stylesheet, guards.ua_or_user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.quirks_mode {
|
if self.quirks_mode {
|
||||||
self.add_stylesheet(&ua_stylesheets.quirks_mode_stylesheet, &ua_guard);
|
self.add_stylesheet(&ua_stylesheets.quirks_mode_stylesheet, guards.ua_or_user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ref stylesheet in doc_stylesheets.iter() {
|
for ref stylesheet in doc_stylesheets.iter() {
|
||||||
self.add_stylesheet(stylesheet, doc_guard);
|
self.add_stylesheet(stylesheet, guards.author);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Stylist stats:");
|
debug!("Stylist stats:");
|
||||||
|
@ -221,8 +220,9 @@ impl Stylist {
|
||||||
SelectorImpl::each_precomputed_pseudo_element(|pseudo| {
|
SelectorImpl::each_precomputed_pseudo_element(|pseudo| {
|
||||||
if let Some(map) = self.pseudos_map.remove(&pseudo) {
|
if let Some(map) = self.pseudos_map.remove(&pseudo) {
|
||||||
let declarations =
|
let declarations =
|
||||||
map.user_agent.get_universal_rules(CascadeLevel::UANormal,
|
map.user_agent.get_universal_rules(
|
||||||
CascadeLevel::UAImportant);
|
guards.ua_or_user, CascadeLevel::UANormal, CascadeLevel::UAImportant
|
||||||
|
);
|
||||||
self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
|
self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -241,9 +241,9 @@ impl Stylist {
|
||||||
|
|
||||||
stylesheet.effective_rules(&device, guard, |rule| {
|
stylesheet.effective_rules(&device, guard, |rule| {
|
||||||
match *rule {
|
match *rule {
|
||||||
CssRule::Style(ref style_rule) => {
|
CssRule::Style(ref locked) => {
|
||||||
let guard = style_rule.read();
|
let style_rule = locked.read_with(&guard);
|
||||||
for selector in &guard.selectors.0 {
|
for selector in &style_rule.selectors.0 {
|
||||||
let map = if let Some(ref pseudo) = selector.pseudo_element {
|
let map = if let Some(ref pseudo) = selector.pseudo_element {
|
||||||
self.pseudos_map
|
self.pseudos_map
|
||||||
.entry(pseudo.clone())
|
.entry(pseudo.clone())
|
||||||
|
@ -255,14 +255,14 @@ impl Stylist {
|
||||||
|
|
||||||
map.insert(Rule {
|
map.insert(Rule {
|
||||||
selector: selector.complex_selector.clone(),
|
selector: selector.complex_selector.clone(),
|
||||||
style_rule: style_rule.clone(),
|
style_rule: locked.clone(),
|
||||||
specificity: selector.specificity,
|
specificity: selector.specificity,
|
||||||
source_order: self.rules_source_order,
|
source_order: self.rules_source_order,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.rules_source_order += 1;
|
self.rules_source_order += 1;
|
||||||
|
|
||||||
for selector in &guard.selectors.0 {
|
for selector in &style_rule.selectors.0 {
|
||||||
self.state_deps.note_selector(&selector.complex_selector);
|
self.state_deps.note_selector(&selector.complex_selector);
|
||||||
if selector.affects_siblings() {
|
if selector.affects_siblings() {
|
||||||
self.sibling_affecting_selectors.push(selector.clone());
|
self.sibling_affecting_selectors.push(selector.clone());
|
||||||
|
@ -300,6 +300,7 @@ impl Stylist {
|
||||||
/// values. The flow constructor uses this flag when constructing anonymous
|
/// values. The flow constructor uses this flag when constructing anonymous
|
||||||
/// flows.
|
/// flows.
|
||||||
pub fn precomputed_values_for_pseudo(&self,
|
pub fn precomputed_values_for_pseudo(&self,
|
||||||
|
guards: &ReadGuards,
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent: Option<&Arc<ComputedValues>>,
|
parent: Option<&Arc<ComputedValues>>,
|
||||||
cascade_flags: CascadeFlags)
|
cascade_flags: CascadeFlags)
|
||||||
|
@ -333,6 +334,7 @@ impl Stylist {
|
||||||
let computed =
|
let computed =
|
||||||
properties::cascade(&self.device,
|
properties::cascade(&self.device,
|
||||||
&rule_node,
|
&rule_node,
|
||||||
|
guards,
|
||||||
parent.map(|p| &**p),
|
parent.map(|p| &**p),
|
||||||
parent.map(|p| &**p),
|
parent.map(|p| &**p),
|
||||||
None,
|
None,
|
||||||
|
@ -344,6 +346,7 @@ impl Stylist {
|
||||||
/// Returns the style for an anonymous box of the given type.
|
/// Returns the style for an anonymous box of the given type.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn style_for_anonymous_box(&self,
|
pub fn style_for_anonymous_box(&self,
|
||||||
|
guards: &ReadGuards,
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent_style: &Arc<ComputedValues>)
|
parent_style: &Arc<ComputedValues>)
|
||||||
-> Arc<ComputedValues> {
|
-> Arc<ComputedValues> {
|
||||||
|
@ -368,7 +371,7 @@ impl Stylist {
|
||||||
if inherit_all {
|
if inherit_all {
|
||||||
cascade_flags.insert(INHERIT_ALL);
|
cascade_flags.insert(INHERIT_ALL);
|
||||||
}
|
}
|
||||||
self.precomputed_values_for_pseudo(&pseudo, Some(parent_style), cascade_flags)
|
self.precomputed_values_for_pseudo(guards, &pseudo, Some(parent_style), cascade_flags)
|
||||||
.values.unwrap()
|
.values.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +383,7 @@ impl Stylist {
|
||||||
/// Check the documentation on lazy pseudo-elements in
|
/// Check the documentation on lazy pseudo-elements in
|
||||||
/// docs/components/style.md
|
/// docs/components/style.md
|
||||||
pub fn lazily_compute_pseudo_element_style<E>(&self,
|
pub fn lazily_compute_pseudo_element_style<E>(&self,
|
||||||
|
guards: &ReadGuards,
|
||||||
element: &E,
|
element: &E,
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent: &Arc<ComputedValues>)
|
parent: &Arc<ComputedValues>)
|
||||||
|
@ -401,6 +405,7 @@ impl Stylist {
|
||||||
None,
|
None,
|
||||||
AnimationRules(None, None),
|
AnimationRules(None, None),
|
||||||
Some(pseudo),
|
Some(pseudo),
|
||||||
|
guards,
|
||||||
&mut declarations,
|
&mut declarations,
|
||||||
&mut flags);
|
&mut flags);
|
||||||
|
|
||||||
|
@ -415,6 +420,7 @@ impl Stylist {
|
||||||
let computed =
|
let computed =
|
||||||
properties::cascade(&self.device,
|
properties::cascade(&self.device,
|
||||||
&rule_node,
|
&rule_node,
|
||||||
|
guards,
|
||||||
Some(&**parent),
|
Some(&**parent),
|
||||||
Some(&**parent),
|
Some(&**parent),
|
||||||
None,
|
None,
|
||||||
|
@ -539,6 +545,7 @@ impl Stylist {
|
||||||
style_attribute: Option<&Arc<RwLock<PropertyDeclarationBlock>>>,
|
style_attribute: Option<&Arc<RwLock<PropertyDeclarationBlock>>>,
|
||||||
animation_rules: AnimationRules,
|
animation_rules: AnimationRules,
|
||||||
pseudo_element: Option<&PseudoElement>,
|
pseudo_element: Option<&PseudoElement>,
|
||||||
|
guards: &ReadGuards,
|
||||||
applicable_declarations: &mut V,
|
applicable_declarations: &mut V,
|
||||||
flags: &mut ElementSelectorFlags) -> StyleRelations
|
flags: &mut ElementSelectorFlags) -> StyleRelations
|
||||||
where E: TElement +
|
where E: TElement +
|
||||||
|
@ -564,6 +571,7 @@ impl Stylist {
|
||||||
// Step 1: Normal user-agent rules.
|
// Step 1: Normal user-agent rules.
|
||||||
map.user_agent.get_all_matching_rules(element,
|
map.user_agent.get_all_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -588,6 +596,7 @@ impl Stylist {
|
||||||
// Step 3: User and author normal rules.
|
// Step 3: User and author normal rules.
|
||||||
map.user.get_all_matching_rules(element,
|
map.user.get_all_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -595,6 +604,7 @@ impl Stylist {
|
||||||
debug!("user normal: {:?}", relations);
|
debug!("user normal: {:?}", relations);
|
||||||
map.author.get_all_matching_rules(element,
|
map.author.get_all_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
|
guards.author,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -629,6 +639,7 @@ impl Stylist {
|
||||||
// Step 6: Author-supplied `!important` rules.
|
// Step 6: Author-supplied `!important` rules.
|
||||||
map.author.get_all_matching_rules(element,
|
map.author.get_all_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
|
guards.author,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -652,6 +663,7 @@ impl Stylist {
|
||||||
// Step 8: User `!important` rules.
|
// Step 8: User `!important` rules.
|
||||||
map.user.get_all_matching_rules(element,
|
map.user.get_all_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -665,6 +677,7 @@ impl Stylist {
|
||||||
// Step 9: UA `!important` rules.
|
// Step 9: UA `!important` rules.
|
||||||
map.user_agent.get_all_matching_rules(element,
|
map.user_agent.get_all_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -903,6 +916,7 @@ impl SelectorMap {
|
||||||
pub fn get_all_matching_rules<E, V>(&self,
|
pub fn get_all_matching_rules<E, V>(&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
matching_rules_list: &mut V,
|
matching_rules_list: &mut V,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags,
|
flags: &mut ElementSelectorFlags,
|
||||||
|
@ -921,6 +935,7 @@ impl SelectorMap {
|
||||||
parent_bf,
|
parent_bf,
|
||||||
&self.id_hash,
|
&self.id_hash,
|
||||||
&id,
|
&id,
|
||||||
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -932,6 +947,7 @@ impl SelectorMap {
|
||||||
parent_bf,
|
parent_bf,
|
||||||
&self.class_hash,
|
&self.class_hash,
|
||||||
class,
|
class,
|
||||||
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -947,6 +963,7 @@ impl SelectorMap {
|
||||||
parent_bf,
|
parent_bf,
|
||||||
local_name_hash,
|
local_name_hash,
|
||||||
element.get_local_name(),
|
element.get_local_name(),
|
||||||
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -955,6 +972,7 @@ impl SelectorMap {
|
||||||
SelectorMap::get_matching_rules(element,
|
SelectorMap::get_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
&self.other_rules,
|
&self.other_rules,
|
||||||
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -968,6 +986,7 @@ impl SelectorMap {
|
||||||
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
|
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
|
||||||
/// `self` sorted by specificity and source order.
|
/// `self` sorted by specificity and source order.
|
||||||
pub fn get_universal_rules(&self,
|
pub fn get_universal_rules(&self,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
cascade_level: CascadeLevel,
|
cascade_level: CascadeLevel,
|
||||||
important_cascade_level: CascadeLevel)
|
important_cascade_level: CascadeLevel)
|
||||||
-> Vec<ApplicableDeclarationBlock> {
|
-> Vec<ApplicableDeclarationBlock> {
|
||||||
|
@ -985,8 +1004,8 @@ impl SelectorMap {
|
||||||
for rule in self.other_rules.iter() {
|
for rule in self.other_rules.iter() {
|
||||||
if rule.selector.compound_selector.is_empty() &&
|
if rule.selector.compound_selector.is_empty() &&
|
||||||
rule.selector.next.is_none() {
|
rule.selector.next.is_none() {
|
||||||
let guard = rule.style_rule.read();
|
let style_rule = rule.style_rule.read_with(guard);
|
||||||
let block = guard.block.read();
|
let block = style_rule.block.read();
|
||||||
if block.any_normal() {
|
if block.any_normal() {
|
||||||
matching_rules_list.push(
|
matching_rules_list.push(
|
||||||
rule.to_applicable_declaration_block(cascade_level));
|
rule.to_applicable_declaration_block(cascade_level));
|
||||||
|
@ -1014,6 +1033,7 @@ impl SelectorMap {
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
hash: &FnvHashMap<Str, Vec<Rule>>,
|
hash: &FnvHashMap<Str, Vec<Rule>>,
|
||||||
key: &BorrowedStr,
|
key: &BorrowedStr,
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
matching_rules: &mut Vector,
|
matching_rules: &mut Vector,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags,
|
flags: &mut ElementSelectorFlags,
|
||||||
|
@ -1027,6 +1047,7 @@ impl SelectorMap {
|
||||||
SelectorMap::get_matching_rules(element,
|
SelectorMap::get_matching_rules(element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
rules,
|
rules,
|
||||||
|
guard,
|
||||||
matching_rules,
|
matching_rules,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags,
|
||||||
|
@ -1038,6 +1059,7 @@ impl SelectorMap {
|
||||||
fn get_matching_rules<E, V>(element: &E,
|
fn get_matching_rules<E, V>(element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
rules: &[Rule],
|
rules: &[Rule],
|
||||||
|
guard: &SharedRwLockReadGuard,
|
||||||
matching_rules: &mut V,
|
matching_rules: &mut V,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags,
|
flags: &mut ElementSelectorFlags,
|
||||||
|
@ -1046,8 +1068,8 @@ impl SelectorMap {
|
||||||
V: VecLike<ApplicableDeclarationBlock>
|
V: VecLike<ApplicableDeclarationBlock>
|
||||||
{
|
{
|
||||||
for rule in rules.iter() {
|
for rule in rules.iter() {
|
||||||
let guard = rule.style_rule.read();
|
let style_rule = rule.style_rule.read_with(guard);
|
||||||
let block = guard.block.read();
|
let block = style_rule.block.read();
|
||||||
let any_declaration_for_importance = if cascade_level.is_important() {
|
let any_declaration_for_importance = if cascade_level.is_important() {
|
||||||
block.any_important()
|
block.any_important()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1145,7 +1167,7 @@ pub struct Rule {
|
||||||
pub selector: Arc<ComplexSelector<SelectorImpl>>,
|
pub selector: Arc<ComplexSelector<SelectorImpl>>,
|
||||||
/// The actual style rule.
|
/// The actual style rule.
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||||
pub style_rule: Arc<RwLock<StyleRule>>,
|
pub style_rule: Arc<Locked<StyleRule>>,
|
||||||
/// The source order this style rule appears in.
|
/// The source order this style rule appears in.
|
||||||
pub source_order: usize,
|
pub source_order: usize,
|
||||||
/// The specificity of the rule this selector represents.
|
/// The specificity of the rule this selector represents.
|
||||||
|
|
|
@ -312,7 +312,8 @@ pub trait DomTraversal<E: TElement> : Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for the function below.
|
/// Helper for the function below.
|
||||||
fn resolve_style_internal<E, F>(context: &mut StyleContext<E>, element: E, ensure_data: &F)
|
fn resolve_style_internal<E, F>(context: &mut StyleContext<E>,
|
||||||
|
element: E, ensure_data: &F)
|
||||||
-> Option<E>
|
-> Option<E>
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
F: Fn(E),
|
F: Fn(E),
|
||||||
|
|
|
@ -23,7 +23,6 @@ use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInf
|
||||||
use style::data::{ElementData, ElementStyles, RestyleData};
|
use style::data::{ElementData, ElementStyles, RestyleData};
|
||||||
use style::dom::{ShowSubtreeData, TElement, TNode};
|
use style::dom::{ShowSubtreeData, TElement, TNode};
|
||||||
use style::error_reporting::StdoutErrorReporter;
|
use style::error_reporting::StdoutErrorReporter;
|
||||||
use style::gecko::arc_types::HackHackHack;
|
|
||||||
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||||
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
||||||
|
@ -77,12 +76,11 @@ use style::properties::parse_one_declaration;
|
||||||
use style::restyle_hints::{self, RestyleHint};
|
use style::restyle_hints::{self, RestyleHint};
|
||||||
use style::selector_parser::PseudoElementCascadeType;
|
use style::selector_parser::PseudoElementCascadeType;
|
||||||
use style::sequential;
|
use style::sequential;
|
||||||
use style::shared_lock::{SharedRwLock, ToCssWithGuard, Locked};
|
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ReadGuards, ToCssWithGuard, Locked};
|
||||||
use style::string_cache::Atom;
|
use style::string_cache::Atom;
|
||||||
use style::stylesheets::{CssRule, CssRules, ImportRule, MediaRule, NamespaceRule};
|
use style::stylesheets::{CssRule, CssRules, ImportRule, MediaRule, NamespaceRule};
|
||||||
use style::stylesheets::{Origin, Stylesheet, StyleRule};
|
use style::stylesheets::{Origin, Stylesheet, StyleRule};
|
||||||
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
||||||
use style::stylesheets::RwLockStyleRulePretendLockedStyleRule;
|
|
||||||
use style::supports::parse_condition_or_declaration;
|
use style::supports::parse_condition_or_declaration;
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
use style::timer::Timer;
|
use style::timer::Timer;
|
||||||
|
@ -167,12 +165,14 @@ pub extern "C" fn Servo_Shutdown() {
|
||||||
gecko_properties::shutdown();
|
gecko_properties::shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_shared_context(per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext {
|
fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
|
||||||
|
per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext<'a> {
|
||||||
let local_context_data =
|
let local_context_data =
|
||||||
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
|
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
|
||||||
|
|
||||||
SharedStyleContext {
|
SharedStyleContext {
|
||||||
stylist: per_doc_data.stylist.clone(),
|
stylist: per_doc_data.stylist.clone(),
|
||||||
|
guards: ReadGuards::same(guard),
|
||||||
running_animations: per_doc_data.running_animations.clone(),
|
running_animations: per_doc_data.running_animations.clone(),
|
||||||
expired_animations: per_doc_data.expired_animations.clone(),
|
expired_animations: per_doc_data.expired_animations.clone(),
|
||||||
// FIXME(emilio): Stop boxing here.
|
// FIXME(emilio): Stop boxing here.
|
||||||
|
@ -205,8 +205,9 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
||||||
debug!("Traversing subtree:");
|
debug!("Traversing subtree:");
|
||||||
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
||||||
|
|
||||||
let shared_style_context = create_shared_context(&per_doc_data);
|
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
let shared_style_context = create_shared_context(&guard, &per_doc_data);
|
||||||
|
|
||||||
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
|
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
|
||||||
TraversalDriver::Sequential
|
TraversalDriver::Sequential
|
||||||
|
@ -625,22 +626,28 @@ impl_basic_rule_funcs! { (Namespace, NamespaceRule, RawServoNamespaceRule),
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
||||||
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
rule.read().block.clone().into_strong()
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
let rule = Locked::<StyleRule>::as_arc(&rule);
|
||||||
|
rule.read_with(&guard).block.clone().into_strong()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
|
pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
|
||||||
declarations: RawServoDeclarationBlockBorrowed) {
|
declarations: RawServoDeclarationBlockBorrowed) {
|
||||||
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
let mut guard = global_style_data.shared_lock.write();
|
||||||
|
let rule = Locked::<StyleRule>::as_arc(&rule);
|
||||||
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
||||||
rule.write().block = declarations.clone();
|
rule.write_with(&mut guard).block = declarations.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) {
|
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) {
|
||||||
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
rule.read().selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
let rule = Locked::<StyleRule>::as_arc(&rule);
|
||||||
|
rule.read_with(&guard).selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -681,6 +688,9 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
||||||
skip_display_fixup: bool,
|
skip_display_fixup: bool,
|
||||||
raw_data: RawServoStyleSetBorrowed)
|
raw_data: RawServoStyleSetBorrowed)
|
||||||
-> ServoComputedValuesStrong {
|
-> ServoComputedValuesStrong {
|
||||||
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
let guards = ReadGuards::same(&guard);
|
||||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||||
let atom = Atom::from(pseudo_tag);
|
let atom = Atom::from(pseudo_tag);
|
||||||
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
|
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
|
||||||
|
@ -691,7 +701,7 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
||||||
if skip_display_fixup {
|
if skip_display_fixup {
|
||||||
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
|
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
|
||||||
}
|
}
|
||||||
data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent,
|
data.stylist.precomputed_values_for_pseudo(&guards, &pseudo, maybe_parent,
|
||||||
cascade_flags)
|
cascade_flags)
|
||||||
.values.unwrap()
|
.values.unwrap()
|
||||||
.into_strong()
|
.into_strong()
|
||||||
|
@ -717,14 +727,16 @@ pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
match get_pseudo_style(element, pseudo_tag, data.styles(), doc_data) {
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
let guard = global_style_data.shared_lock.read();
|
||||||
|
match get_pseudo_style(&guard, element, pseudo_tag, data.styles(), doc_data) {
|
||||||
Some(values) => values.into_strong(),
|
Some(values) => values.into_strong(),
|
||||||
None if !is_probe => data.styles().primary.values().clone().into_strong(),
|
None if !is_probe => data.styles().primary.values().clone().into_strong(),
|
||||||
None => Strong::null(),
|
None => Strong::null(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pseudo_style(element: GeckoElement, pseudo_tag: *mut nsIAtom,
|
fn get_pseudo_style(guard: &SharedRwLockReadGuard, element: GeckoElement, pseudo_tag: *mut nsIAtom,
|
||||||
styles: &ElementStyles, doc_data: &PerDocumentStyleData)
|
styles: &ElementStyles, doc_data: &PerDocumentStyleData)
|
||||||
-> Option<Arc<ComputedValues>>
|
-> Option<Arc<ComputedValues>>
|
||||||
{
|
{
|
||||||
|
@ -735,7 +747,9 @@ fn get_pseudo_style(element: GeckoElement, pseudo_tag: *mut nsIAtom,
|
||||||
PseudoElementCascadeType::Lazy => {
|
PseudoElementCascadeType::Lazy => {
|
||||||
let d = doc_data.borrow_mut();
|
let d = doc_data.borrow_mut();
|
||||||
let base = styles.primary.values();
|
let base = styles.primary.values();
|
||||||
d.stylist.lazily_compute_pseudo_element_style(&element,
|
let guards = ReadGuards::same(guard);
|
||||||
|
d.stylist.lazily_compute_pseudo_element_style(&guards,
|
||||||
|
&element,
|
||||||
&pseudo,
|
&pseudo,
|
||||||
base)
|
base)
|
||||||
.map(|s| s.values().clone())
|
.map(|s| s.values().clone())
|
||||||
|
@ -1463,11 +1477,13 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
|
||||||
raw_data: RawServoStyleSetBorrowed)
|
raw_data: RawServoStyleSetBorrowed)
|
||||||
-> ServoComputedValuesStrong
|
-> ServoComputedValuesStrong
|
||||||
{
|
{
|
||||||
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
|
let guard = global_style_data.shared_lock.read();
|
||||||
let element = GeckoElement(element);
|
let element = GeckoElement(element);
|
||||||
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
||||||
let finish = |styles: &ElementStyles| -> Arc<ComputedValues> {
|
let finish = |styles: &ElementStyles| -> Arc<ComputedValues> {
|
||||||
let maybe_pseudo = if !pseudo_tag.is_null() {
|
let maybe_pseudo = if !pseudo_tag.is_null() {
|
||||||
get_pseudo_style(element, pseudo_tag, styles, doc_data)
|
get_pseudo_style(&guard, element, pseudo_tag, styles, doc_data)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -1483,7 +1499,7 @@ 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 shared = create_shared_context(&mut doc_data.borrow_mut());
|
let shared = create_shared_context(&guard, &mut doc_data.borrow_mut());
|
||||||
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
||||||
let mut context = StyleContext {
|
let mut context = StyleContext {
|
||||||
shared: &shared,
|
shared: &shared,
|
||||||
|
|
|
@ -17,7 +17,6 @@ app_units = "0.4"
|
||||||
cssparser = "0.12"
|
cssparser = "0.12"
|
||||||
euclid = "0.11"
|
euclid = "0.11"
|
||||||
html5ever-atoms = "0.2"
|
html5ever-atoms = "0.2"
|
||||||
owning_ref = "0.2.2"
|
|
||||||
parking_lot = "0.3"
|
parking_lot = "0.3"
|
||||||
rayon = "0.6"
|
rayon = "0.6"
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
|
|
|
@ -9,7 +9,6 @@ extern crate app_units;
|
||||||
extern crate cssparser;
|
extern crate cssparser;
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
#[macro_use] extern crate html5ever_atoms;
|
#[macro_use] extern crate html5ever_atoms;
|
||||||
extern crate owning_ref;
|
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate rayon;
|
extern crate rayon;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
|
@ -26,7 +25,6 @@ mod attr;
|
||||||
mod keyframes;
|
mod keyframes;
|
||||||
mod logical_geometry;
|
mod logical_geometry;
|
||||||
mod media_queries;
|
mod media_queries;
|
||||||
mod owning_handle;
|
|
||||||
mod parsing;
|
mod parsing;
|
||||||
mod properties;
|
mod properties;
|
||||||
mod rule_tree;
|
mod rule_tree;
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
use owning_ref::RcRef;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use style::owning_handle::OwningHandle;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn owning_handle() {
|
|
||||||
use std::cell::RefCell;
|
|
||||||
let cell = Rc::new(RefCell::new(2));
|
|
||||||
let cell_ref = RcRef::new(cell);
|
|
||||||
let mut handle = OwningHandle::new(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
|
||||||
assert_eq!(*handle, 2);
|
|
||||||
*handle = 3;
|
|
||||||
assert_eq!(*handle, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn nested() {
|
|
||||||
let result = {
|
|
||||||
let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
|
|
||||||
let curr = RcRef::new(complex);
|
|
||||||
let curr = OwningHandle::new(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
|
||||||
let mut curr = OwningHandle::new(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
|
|
||||||
assert_eq!(*curr, "someString");
|
|
||||||
*curr = "someOtherString";
|
|
||||||
curr
|
|
||||||
};
|
|
||||||
assert_eq!(*result, "someOtherString");
|
|
||||||
}
|
|
|
@ -81,7 +81,7 @@ fn test_parse_stylesheet() {
|
||||||
prefix: None,
|
prefix: None,
|
||||||
url: NsAtom::from("http://www.w3.org/1999/xhtml")
|
url: NsAtom::from("http://www.w3.org/1999/xhtml")
|
||||||
}))),
|
}))),
|
||||||
CssRule::Style(Arc::new(RwLock::new(StyleRule {
|
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||||
selectors: SelectorList(vec![
|
selectors: SelectorList(vec![
|
||||||
Selector {
|
Selector {
|
||||||
complex_selector: Arc::new(ComplexSelector {
|
complex_selector: Arc::new(ComplexSelector {
|
||||||
|
@ -117,7 +117,7 @@ fn test_parse_stylesheet() {
|
||||||
Importance::Important),
|
Importance::Important),
|
||||||
]))),
|
]))),
|
||||||
}))),
|
}))),
|
||||||
CssRule::Style(Arc::new(RwLock::new(StyleRule {
|
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||||
selectors: SelectorList(vec![
|
selectors: SelectorList(vec![
|
||||||
Selector {
|
Selector {
|
||||||
complex_selector: Arc::new(ComplexSelector {
|
complex_selector: Arc::new(ComplexSelector {
|
||||||
|
@ -159,7 +159,7 @@ fn test_parse_stylesheet() {
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
]))),
|
]))),
|
||||||
}))),
|
}))),
|
||||||
CssRule::Style(Arc::new(RwLock::new(StyleRule {
|
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
|
||||||
selectors: SelectorList(vec![
|
selectors: SelectorList(vec![
|
||||||
Selector {
|
Selector {
|
||||||
complex_selector: Arc::new(ComplexSelector {
|
complex_selector: Arc::new(ComplexSelector {
|
||||||
|
|
|
@ -11,17 +11,19 @@ use style::properties::{PropertyDeclarationBlock, PropertyDeclaration};
|
||||||
use style::properties::{longhands, Importance};
|
use style::properties::{longhands, Importance};
|
||||||
use style::rule_tree::CascadeLevel;
|
use style::rule_tree::CascadeLevel;
|
||||||
use style::selector_parser::SelectorParser;
|
use style::selector_parser::SelectorParser;
|
||||||
|
use style::shared_lock::SharedRwLock;
|
||||||
use style::stylesheets::StyleRule;
|
use style::stylesheets::StyleRule;
|
||||||
use style::stylist::{Rule, SelectorMap};
|
use style::stylist::{Rule, SelectorMap};
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
|
|
||||||
/// Helper method to get some Rules from selector strings.
|
/// Helper method to get some Rules from selector strings.
|
||||||
/// Each sublist of the result contains the Rules for one StyleRule.
|
/// Each sublist of the result contains the Rules for one StyleRule.
|
||||||
fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
|
fn get_mock_rules(css_selectors: &[&str]) -> (Vec<Vec<Rule>>, SharedRwLock) {
|
||||||
css_selectors.iter().enumerate().map(|(i, selectors)| {
|
let shared_lock = SharedRwLock::new();
|
||||||
|
(css_selectors.iter().enumerate().map(|(i, selectors)| {
|
||||||
let selectors = SelectorParser::parse_author_origin_no_namespace(selectors).unwrap();
|
let selectors = SelectorParser::parse_author_origin_no_namespace(selectors).unwrap();
|
||||||
|
|
||||||
let rule = Arc::new(RwLock::new(StyleRule {
|
let locked = Arc::new(shared_lock.wrap(StyleRule {
|
||||||
selectors: selectors,
|
selectors: selectors,
|
||||||
block: Arc::new(RwLock::new(PropertyDeclarationBlock::with_one(
|
block: Arc::new(RwLock::new(PropertyDeclarationBlock::with_one(
|
||||||
PropertyDeclaration::Display(
|
PropertyDeclaration::Display(
|
||||||
|
@ -30,21 +32,22 @@ fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
|
||||||
))),
|
))),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let guard = rule.read();
|
let guard = shared_lock.read();
|
||||||
guard.selectors.0.iter().map(|s| {
|
let rule = locked.read_with(&guard);
|
||||||
|
rule.selectors.0.iter().map(|s| {
|
||||||
Rule {
|
Rule {
|
||||||
selector: s.complex_selector.clone(),
|
selector: s.complex_selector.clone(),
|
||||||
style_rule: rule.clone(),
|
style_rule: locked.clone(),
|
||||||
specificity: s.specificity,
|
specificity: s.specificity,
|
||||||
source_order: i,
|
source_order: i,
|
||||||
}
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
}).collect()
|
}).collect(), shared_lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mock_map(selectors: &[&str]) -> SelectorMap {
|
fn get_mock_map(selectors: &[&str]) -> (SelectorMap, SharedRwLock) {
|
||||||
let mut map = SelectorMap::new();
|
let mut map = SelectorMap::new();
|
||||||
let selector_rules = get_mock_rules(selectors);
|
let (selector_rules, shared_lock) = get_mock_rules(selectors);
|
||||||
|
|
||||||
for rules in selector_rules.into_iter() {
|
for rules in selector_rules.into_iter() {
|
||||||
for rule in rules.into_iter() {
|
for rule in rules.into_iter() {
|
||||||
|
@ -52,12 +55,12 @@ fn get_mock_map(selectors: &[&str]) -> SelectorMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map
|
(map, shared_lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rule_ordering_same_specificity() {
|
fn test_rule_ordering_same_specificity() {
|
||||||
let rules_list = get_mock_rules(&["a.intro", "img.sidebar"]);
|
let (rules_list, _) = get_mock_rules(&["a.intro", "img.sidebar"]);
|
||||||
let a = &rules_list[0][0];
|
let a = &rules_list[0][0];
|
||||||
let b = &rules_list[1][0];
|
let b = &rules_list[1][0];
|
||||||
assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)),
|
assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)),
|
||||||
|
@ -67,21 +70,21 @@ fn test_rule_ordering_same_specificity() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_id_name() {
|
fn test_get_id_name() {
|
||||||
let rules_list = get_mock_rules(&[".intro", "#top"]);
|
let (rules_list, _) = get_mock_rules(&[".intro", "#top"]);
|
||||||
assert_eq!(SelectorMap::get_id_name(&rules_list[0][0]), None);
|
assert_eq!(SelectorMap::get_id_name(&rules_list[0][0]), None);
|
||||||
assert_eq!(SelectorMap::get_id_name(&rules_list[1][0]), Some(Atom::from("top")));
|
assert_eq!(SelectorMap::get_id_name(&rules_list[1][0]), Some(Atom::from("top")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_class_name() {
|
fn test_get_class_name() {
|
||||||
let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
|
let (rules_list, _) = get_mock_rules(&[".intro.foo", "#top"]);
|
||||||
assert_eq!(SelectorMap::get_class_name(&rules_list[0][0]), Some(Atom::from("intro")));
|
assert_eq!(SelectorMap::get_class_name(&rules_list[0][0]), Some(Atom::from("intro")));
|
||||||
assert_eq!(SelectorMap::get_class_name(&rules_list[1][0]), None);
|
assert_eq!(SelectorMap::get_class_name(&rules_list[1][0]), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_local_name() {
|
fn test_get_local_name() {
|
||||||
let rules_list = get_mock_rules(&["img.foo", "#top", "IMG", "ImG"]);
|
let (rules_list, _) = get_mock_rules(&["img.foo", "#top", "IMG", "ImG"]);
|
||||||
let check = |i: usize, names: Option<(&str, &str)>| {
|
let check = |i: usize, names: Option<(&str, &str)>| {
|
||||||
assert!(SelectorMap::get_local_name(&rules_list[i][0])
|
assert!(SelectorMap::get_local_name(&rules_list[i][0])
|
||||||
== names.map(|(name, lower_name)| LocalNameSelector {
|
== names.map(|(name, lower_name)| LocalNameSelector {
|
||||||
|
@ -96,7 +99,7 @@ fn test_get_local_name() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert() {
|
fn test_insert() {
|
||||||
let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
|
let (rules_list, _) = get_mock_rules(&[".intro.foo", "#top"]);
|
||||||
let mut selector_map = SelectorMap::new();
|
let mut selector_map = SelectorMap::new();
|
||||||
selector_map.insert(rules_list[1][0].clone());
|
selector_map.insert(rules_list[1][0].clone());
|
||||||
assert_eq!(1, selector_map.id_hash.get(&Atom::from("top")).unwrap()[0].source_order);
|
assert_eq!(1, selector_map.id_hash.get(&Atom::from("top")).unwrap()[0].source_order);
|
||||||
|
@ -108,10 +111,11 @@ fn test_insert() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_universal_rules() {
|
fn test_get_universal_rules() {
|
||||||
thread_state::initialize(thread_state::LAYOUT);
|
thread_state::initialize(thread_state::LAYOUT);
|
||||||
let map = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
|
let (map, shared_lock) = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
|
||||||
|
|
||||||
let decls = map.get_universal_rules(CascadeLevel::UserNormal,
|
let guard = shared_lock.read();
|
||||||
CascadeLevel::UserImportant);
|
let decls = map.get_universal_rules(
|
||||||
|
&guard, CascadeLevel::UserNormal, CascadeLevel::UserImportant);
|
||||||
|
|
||||||
assert_eq!(decls.len(), 1);
|
assert_eq!(decls.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue