diff --git a/components/layout/query.rs b/components/layout/query.rs index a71bc246113..b491f08632d 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -631,14 +631,14 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N, where N: LayoutNode, C: StyleContext<'a> { - use style::traversal::ensure_node_styled; + use style::traversal::ensure_element_styled; // This node might have display: none, or it's style might be not up to // date, so we might need to do style recalc. // // FIXME(emilio): Is a bit shame we have to do this instead of in style. ensure_node_data_initialized(&requested_node); - ensure_node_styled(requested_node, style_context); + ensure_element_styled(requested_node.as_element().unwrap(), style_context); let layout_node = requested_node.to_threadsafe(); let layout_node = match *pseudo { diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 36130aba4c4..2ab1e21cebe 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -99,8 +99,7 @@ impl<'lc, N> DomTraversalContext for RecalcStyleAndConstructFlows<'lc> // // The bloom filter stuff is all going to be rewritten, so we just hackily duplicate // the bloom filter manipulation from recalc_style_at to maintain invariants. - let parent = node.parent_node(); - debug_assert!(parent.unwrap().is_element()); + let parent = node.parent_node().unwrap().as_element(); let bf = take_thread_local_bloom_filter(parent, self.root, self.context.shared_context()); put_thread_local_bloom_filter(bf, &node.to_unsafe(), self.context.shared_context()); diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index b5e1c5a4f60..75bdd55aedc 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -133,7 +133,6 @@ impl<'ln> NodeInfo for ServoLayoutNode<'ln> { impl<'ln> TNode for ServoLayoutNode<'ln> { type ConcreteElement = ServoLayoutElement<'ln>; type ConcreteDocument = ServoLayoutDocument<'ln>; - type ConcreteRestyleDamage = RestyleDamage; type ConcreteChildrenIterator = ServoChildrenIterator<'ln>; fn to_unsafe(&self) -> UnsafeNode { @@ -470,6 +469,7 @@ impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> { impl<'le> TElement for ServoLayoutElement<'le> { type ConcreteNode = ServoLayoutNode<'le>; type ConcreteDocument = ServoLayoutDocument<'le>; + type ConcreteRestyleDamage = RestyleDamage; fn as_node(&self) -> ServoLayoutNode<'le> { ServoLayoutNode::from_layout_js(self.element.upcast()) diff --git a/components/style/dom.rs b/components/style/dom.rs index aa5d0829001..7ead2605416 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -106,7 +106,6 @@ impl Iterator for LayoutIterator where T: Iterator, I: NodeInfo pub trait TNode : Sized + Copy + Clone + NodeInfo { type ConcreteElement: TElement; type ConcreteDocument: TDocument; - type ConcreteRestyleDamage: TRestyleDamage; type ConcreteChildrenIterator: Iterator; fn to_unsafe(&self) -> UnsafeNode; @@ -249,6 +248,7 @@ pub trait PresentationalHintsSynthetizer { pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer { type ConcreteNode: TNode; type ConcreteDocument: TDocument; + type ConcreteRestyleDamage: TRestyleDamage; fn as_node(&self) -> Self::ConcreteNode; @@ -260,7 +260,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre fn attr_equals(&self, namespace: &Namespace, attr: &Atom, value: &Atom) -> bool; /// Set the restyle damage field. - fn set_restyle_damage(self, damage: ::ConcreteRestyleDamage); + fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage); /// XXX: It's a bit unfortunate we need to pass the current computed values /// as an argument here, but otherwise Servo would crash due to double @@ -268,8 +268,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre fn existing_style_for_restyle_damage<'a>(&'a self, current_computed_values: Option<&'a Arc>, pseudo: Option<&PseudoElement>) - -> Option<&'a <::ConcreteRestyleDamage as TRestyleDamage> - ::PreExistingComputedValues>; + -> Option<&'a ::PreExistingComputedValues>; /// Properly marks nodes as dirty in response to restyle hints. fn note_restyle_hint>(&self, hint: RestyleHint) { diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index a1128768d1b..e1ca9ab6723 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -160,7 +160,6 @@ impl<'ln> NodeInfo for GeckoNode<'ln> { impl<'ln> TNode for GeckoNode<'ln> { type ConcreteDocument = GeckoDocument<'ln>; type ConcreteElement = GeckoElement<'ln>; - type ConcreteRestyleDamage = GeckoRestyleDamage; type ConcreteChildrenIterator = GeckoChildrenIterator<'ln>; fn to_unsafe(&self) -> UnsafeNode { @@ -399,6 +398,7 @@ lazy_static! { impl<'le> TElement for GeckoElement<'le> { type ConcreteNode = GeckoNode<'le>; type ConcreteDocument = GeckoDocument<'le>; + type ConcreteRestyleDamage = GeckoRestyleDamage; fn as_node(&self) -> Self::ConcreteNode { unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) } diff --git a/components/style/matching.rs b/components/style/matching.rs index 82add15f335..794e18e2c7b 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -12,12 +12,12 @@ use cache::{LRUCache, SimpleHashCache}; use cascade_info::CascadeInfo; use context::{SharedStyleContext, StyleContext}; use data::{NodeStyles, PseudoStyles}; -use dom::{NodeInfo, TElement, TNode, TRestyleDamage, UnsafeNode}; +use dom::{TElement, TNode, TRestyleDamage, UnsafeNode}; use properties::{CascadeFlags, ComputedValues, SHAREABLE, cascade}; use properties::longhands::display::computed_value as display; use selector_impl::{PseudoElement, TheSelectorImpl}; use selector_matching::{ApplicableDeclarationBlock, Stylist}; -use selectors::{Element, MatchAttr}; +use selectors::MatchAttr; use selectors::bloom::BloomFilter; use selectors::matching::{AFFECTED_BY_PSEUDO_ELEMENTS, MatchingReason, StyleRelations}; use sink::ForgetfulSink; @@ -497,7 +497,7 @@ struct CascadeBooleans { animate: bool, } -trait PrivateMatchMethods: TNode { +trait PrivateMatchMethods: TElement { /// Actually cascades style for a node or a pseudo-element of a node. /// /// Note that animations only apply to nodes or ::before or ::after @@ -521,7 +521,7 @@ trait PrivateMatchMethods: TNode { // and the cache would not be effective anyway. // This also works around the test failures at // https://github.com/servo/servo/pull/13459#issuecomment-250717584 - let has_style_attribute = self.as_element().map_or(false, |e| e.style_attribute().is_some()); + let has_style_attribute = self.style_attribute().is_some(); cacheable = cacheable && !has_style_attribute; let mut cascade_info = CascadeInfo::new(); @@ -556,7 +556,7 @@ trait PrivateMatchMethods: TNode { cascade_flags) } }; - cascade_info.finish(self); + cascade_info.finish(&self.as_node()); cacheable = cacheable && is_cacheable; @@ -564,7 +564,7 @@ trait PrivateMatchMethods: TNode { if booleans.animate { let new_animations_sender = &context.local_context().new_animations_sender; - let this_opaque = self.opaque(); + let this_opaque = self.as_node().opaque(); // Trigger any present animations if necessary. let mut animations_started = animation::maybe_start_animations( &shared_context, @@ -579,7 +579,7 @@ trait PrivateMatchMethods: TNode { animation::start_transitions_if_applicable( new_animations_sender, this_opaque, - self.to_unsafe(), + self.as_node().to_unsafe(), &**style, &mut this_style, &shared_context.timer); @@ -601,7 +601,7 @@ trait PrivateMatchMethods: TNode { context: &SharedStyleContext, style: &mut Arc) -> bool { // Finish any expired transitions. - let this_opaque = self.opaque(); + let this_opaque = self.as_node().opaque(); let had_animations_to_expire = animation::complete_expired_transitions(this_opaque, style, context); @@ -636,18 +636,11 @@ trait PrivateMatchMethods: TNode { had_animations_to_expire || had_running_animations } -} -impl PrivateMatchMethods for N {} - -trait PrivateElementMatchMethods: TElement { fn share_style_with_candidate_if_possible(&self, - parent_node: Self::ConcreteNode, shared_context: &SharedStyleContext, candidate: &mut StyleSharingCandidate) -> Result, CacheMiss> { - debug_assert!(parent_node.is_element()); - let candidate_element = unsafe { Self::ConcreteNode::from_unsafe(&candidate.node).as_element().unwrap() }; @@ -657,9 +650,9 @@ trait PrivateElementMatchMethods: TElement { } } -impl PrivateElementMatchMethods for E {} +impl PrivateMatchMethods for E {} -pub trait ElementMatchMethods : TElement { +pub trait MatchMethods : TElement { fn match_element(&self, stylist: &Stylist, parent_bf: Option<&BloomFilter>, @@ -703,9 +696,8 @@ pub trait ElementMatchMethods : TElement { unsafe fn share_style_if_possible(&self, style_sharing_candidate_cache: &mut StyleSharingCandidateCache, - shared_context: &SharedStyleContext, - parent: Option) - -> StyleSharingResult<::ConcreteRestyleDamage> { + shared_context: &SharedStyleContext) + -> StyleSharingResult { if opts::get().disable_share_style_cache { return StyleSharingResult::CannotShare } @@ -718,16 +710,9 @@ pub trait ElementMatchMethods : TElement { return StyleSharingResult::CannotShare } - let parent = match parent { - Some(parent) if parent.is_element() => parent, - _ => return StyleSharingResult::CannotShare, - }; - let mut should_clear_cache = false; for (i, &mut (ref mut candidate, ())) in style_sharing_candidate_cache.iter_mut().enumerate() { - let sharing_result = self.share_style_with_candidate_if_possible(parent, - shared_context, - candidate); + let sharing_result = self.share_style_with_candidate_if_possible(shared_context, candidate); match sharing_result { Ok(shared_style) => { // Yay, cache hit. Share the style. @@ -741,12 +726,10 @@ pub trait ElementMatchMethods : TElement { let damage = match self.existing_style_for_restyle_damage(data.previous_styles().map(|x| &x.primary), None) { Some(ref source) => { - <::ConcreteNode as TNode> - ::ConcreteRestyleDamage::compute(source, &shared_style) + Self::ConcreteRestyleDamage::compute(source, &shared_style) } None => { - <::ConcreteNode as TNode> - ::ConcreteRestyleDamage::rebuild_and_reflow() + Self::ConcreteRestyleDamage::rebuild_and_reflow() } }; @@ -788,11 +771,7 @@ pub trait ElementMatchMethods : TElement { StyleSharingResult::CannotShare } -} -impl ElementMatchMethods for E {} - -pub trait MatchMethods : TNode { // The below two functions are copy+paste because I can't figure out how to // write a function which takes a generic function. I don't think it can // be done. @@ -816,29 +795,23 @@ pub trait MatchMethods : TNode { /// Therefore, each node must have its matching selectors inserted _after_ /// its own selector matching and _before_ its children start. fn insert_into_bloom_filter(&self, bf: &mut BloomFilter) { - // Only elements are interesting. - if let Some(element) = self.as_element() { - bf.insert(&*element.get_local_name()); - bf.insert(&*element.get_namespace()); - element.get_id().map(|id| bf.insert(&id)); + bf.insert(&*self.get_local_name()); + bf.insert(&*self.get_namespace()); + self.get_id().map(|id| bf.insert(&id)); - // TODO: case-sensitivity depends on the document type and quirks mode - element.each_class(|class| bf.insert(class)); - } + // TODO: case-sensitivity depends on the document type and quirks mode + self.each_class(|class| bf.insert(class)); } /// After all the children are done css selector matching, this must be /// called to reset the bloom filter after an `insert`. fn remove_from_bloom_filter(&self, bf: &mut BloomFilter) { - // Only elements are interesting. - if let Some(element) = self.as_element() { - bf.remove(&*element.get_local_name()); - bf.remove(&*element.get_namespace()); - element.get_id().map(|id| bf.remove(&id)); + bf.remove(&*self.get_local_name()); + bf.remove(&*self.get_namespace()); + self.get_id().map(|id| bf.remove(&id)); - // TODO: case-sensitivity depends on the document type and quirks mode - element.each_class(|class| bf.remove(class)); - } + // TODO: case-sensitivity depends on the document type and quirks mode + self.each_class(|class| bf.remove(class)); } fn compute_restyle_damage(&self, @@ -847,7 +820,7 @@ pub trait MatchMethods : TNode { pseudo: Option<&PseudoElement>) -> Self::ConcreteRestyleDamage { - match self.as_element().unwrap().existing_style_for_restyle_damage(old_style, pseudo) { + match self.existing_style_for_restyle_damage(old_style, pseudo) { Some(ref source) => { Self::ConcreteRestyleDamage::compute(source, new_style) @@ -890,23 +863,12 @@ pub trait MatchMethods : TNode { where Ctx: StyleContext<'a> { // Get our parent's style. - let parent_data = parent.as_ref().map(|x| x.borrow_data().unwrap()); + let parent_as_node = parent.map(|x| x.as_node()); + let parent_data = parent_as_node.as_ref().map(|x| x.borrow_data().unwrap()); let parent_style = parent_data.as_ref().map(|x| &x.current_styles().primary); - // In the case we're styling a text node, we don't need to compute the - // restyle damage, since it's a subset of the restyle damage of the - // parent. - // - // In Gecko, we're done, we don't need anything else from text nodes. - // - // In Servo, this is also true, since text nodes generate UnscannedText - // fragments, which aren't repairable by incremental layout. - if self.is_text_node() { - self.style_text_node(ComputedValues::style_for_child_text_node(parent_style.clone().unwrap())); - return RestyleResult::Continue; - } - - let mut data = self.begin_styling(); + let node = self.as_node(); + let mut data = node.begin_styling(); let mut new_styles; let mut applicable_declarations_cache = @@ -944,8 +906,8 @@ pub trait MatchMethods : TNode { context, applicable_declarations, &mut applicable_declarations_cache); - self.set_can_be_fragmented(parent.map_or(false, |p| { - p.can_be_fragmented() || + self.as_node().set_can_be_fragmented(parent.map_or(false, |p| { + p.as_node().can_be_fragmented() || parent_style.unwrap().is_multicol() })); @@ -955,7 +917,7 @@ pub trait MatchMethods : TNode { data.finish_styling(new_styles); // Drop the mutable borrow early, since Servo's set_restyle_damage also borrows. mem::drop(data); - self.as_element().unwrap().set_restyle_damage(damage); + self.set_restyle_damage(damage); restyle_result } @@ -1006,7 +968,7 @@ pub trait MatchMethods : TNode { let no_damage = Self::ConcreteRestyleDamage::empty(); debug_assert!(new_pseudos.is_empty()); - ::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| { + ::Impl::each_eagerly_cascaded_pseudo_element(|pseudo| { let applicable_declarations_for_this_pseudo = applicable_declarations.per_pseudo.get(&pseudo).unwrap(); @@ -1018,8 +980,7 @@ pub trait MatchMethods : TNode { if has_declarations { // We have declarations, so we need to cascade. Compute parameters. - let animate = ::Impl - ::pseudo_is_before_or_after(&pseudo); + let animate = ::Impl::pseudo_is_before_or_after(&pseudo); let cacheable = if animate && old_pseudo_style.is_some() { // Update animations before the cascade. This may modify // the value of old_pseudo_style. @@ -1064,4 +1025,4 @@ pub trait MatchMethods : TNode { } } -impl MatchMethods for N {} +impl MatchMethods for E {} diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 03405e59360..48b598ba93a 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -8,7 +8,7 @@ use atomic_refcell::AtomicRefCell; use context::{LocalStyleContext, SharedStyleContext, StyleContext}; use data::NodeData; use dom::{NodeInfo, OpaqueNode, StylingMode, TElement, TNode, UnsafeNode}; -use matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult}; +use matching::{ApplicableDeclarations, MatchMethods, StyleSharingResult}; use selectors::bloom::BloomFilter; use selectors::matching::StyleRelations; use std::cell::RefCell; @@ -62,13 +62,13 @@ thread_local!( /// /// If one does not exist, a new one will be made for you. If it is out of date, /// it will be cleared and reused. -pub fn take_thread_local_bloom_filter(parent_node: Option, +pub fn take_thread_local_bloom_filter(parent_element: Option, root: OpaqueNode, context: &SharedStyleContext) -> Box - where N: TNode { + where E: TElement { STYLE_BLOOM.with(|style_bloom| { - match (parent_node, style_bloom.borrow_mut().take()) { + match (parent_element, style_bloom.borrow_mut().take()) { // Root node. Needs new bloom filter. (None, _ ) => { debug!("[{}] No parent, but new bloom filter!", tid()); @@ -82,7 +82,7 @@ pub fn take_thread_local_bloom_filter(parent_node: Option, } // Found cached bloom filter. (Some(parent), Some((mut bloom_filter, old_node, old_generation))) => { - if old_node == parent.to_unsafe() && + if old_node == parent.as_node().to_unsafe() && old_generation == context.generation { // Hey, the cached parent is our parent! We can reuse the bloom filter. debug!("[{}] Parent matches (={}). Reusing bloom filter.", tid(), old_node.0); @@ -108,17 +108,17 @@ pub fn put_thread_local_bloom_filter(bf: Box, unsafe_node: &UnsafeN } /// "Ancestors" in this context is inclusive of ourselves. -fn insert_ancestors_into_bloom_filter(bf: &mut Box, - mut n: N, +fn insert_ancestors_into_bloom_filter(bf: &mut Box, + mut el: E, root: OpaqueNode) - where N: TNode { + where E: TElement { debug!("[{}] Inserting ancestors.", tid()); let mut ancestors = 0; loop { ancestors += 1; - n.insert_into_bloom_filter(&mut **bf); - n = match n.layout_parent_node(root) { + el.insert_into_bloom_filter(&mut **bf); + el = match el.as_node().layout_parent_node(root).and_then(|x| x.as_element()) { None => break, Some(p) => p, }; @@ -149,7 +149,7 @@ pub fn remove_from_bloom_filter<'a, N, C>(context: &C, root: OpaqueNode, node: N } Some(parent) => { // Otherwise, put it back, but remove this node. - node.remove_from_bloom_filter(&mut *bf); + node.as_element().map(|x| x.remove_from_bloom_filter(&mut *bf)); let unsafe_parent = parent.to_unsafe(); put_thread_local_bloom_filter(bf, &unsafe_parent, &context.shared_context()); }, @@ -213,20 +213,20 @@ pub fn relations_are_shareable(relations: &StyleRelations) -> bool { AFFECTED_BY_PRESENTATIONAL_HINTS) } -pub fn ensure_node_styled<'a, N, C>(node: N, - context: &'a C) - where N: TNode, +pub fn ensure_element_styled<'a, E, C>(element: E, + context: &'a C) + where E: TElement, C: StyleContext<'a> { let mut display_none = false; - ensure_node_styled_internal(node, context, &mut display_none); + ensure_element_styled_internal(element, context, &mut display_none); } #[allow(unsafe_code)] -fn ensure_node_styled_internal<'a, N, C>(node: N, - context: &'a C, - parents_had_display_none: &mut bool) - where N: TNode, +fn ensure_element_styled_internal<'a, E, C>(element: E, + context: &'a C, + parents_had_display_none: &mut bool) + where E: TElement, C: StyleContext<'a> { use properties::longhands::display::computed_value as display; @@ -238,13 +238,9 @@ fn ensure_node_styled_internal<'a, N, C>(node: N, // This means potentially a bit of wasted work (usually not much). We could // add a flag at the node at which point we stopped the traversal to know // where should we stop, but let's not add that complication unless needed. - let parent = match node.parent_node() { - Some(parent) if parent.is_element() => Some(parent), - _ => None, - }; - + let parent = element.parent_element(); if let Some(parent) = parent { - ensure_node_styled_internal(parent, context, parents_had_display_none); + ensure_element_styled_internal(parent, context, parents_had_display_none); } // Common case: our style is already resolved and none of our ancestors had @@ -252,6 +248,7 @@ fn ensure_node_styled_internal<'a, N, C>(node: N, // // We only need to mark whether we have display none, and forget about it, // our style is up to date. + let node = element.as_node(); if let Some(data) = node.borrow_data() { if let Some(style) = data.get_current_styles().map(|x| &x.primary) { if !*parents_had_display_none { @@ -268,16 +265,14 @@ fn ensure_node_styled_internal<'a, N, C>(node: N, // probably not necessary since we're likely to be matching only a few // nodes, at best. let mut applicable_declarations = ApplicableDeclarations::new(); - if let Some(element) = node.as_element() { - let stylist = &context.shared_context().stylist; + let stylist = &context.shared_context().stylist; - element.match_element(&**stylist, - None, - &mut applicable_declarations); - } + element.match_element(&**stylist, + None, + &mut applicable_declarations); unsafe { - node.cascade_node(context, parent, &applicable_declarations); + element.cascade_node(context, parent, &applicable_declarations); } } @@ -291,34 +286,21 @@ pub fn recalc_style_at<'a, E, C, D>(context: &'a C, C: StyleContext<'a>, D: DomTraversalContext { - let node = element.as_node(); - - // Get the parent node. - let parent_opt = match node.parent_node() { - Some(parent) if parent.is_element() => Some(parent), - _ => None, - }; - // Get the style bloom filter. - let mut bf = take_thread_local_bloom_filter(parent_opt, root, context.shared_context()); + let mut bf = take_thread_local_bloom_filter(element.parent_element(), root, context.shared_context()); let mut restyle_result = RestyleResult::Continue; - let mode = node.styling_mode(); + let mode = element.as_node().styling_mode(); debug_assert!(mode != StylingMode::Stop, "Parent should not have enqueued us"); if mode != StylingMode::Traverse { // Check to see whether we can share a style with someone. let style_sharing_candidate_cache = &mut context.local_context().style_sharing_candidate_cache.borrow_mut(); - let sharing_result = match node.as_element() { - Some(element) => { - unsafe { - element.share_style_if_possible(style_sharing_candidate_cache, - context.shared_context(), - parent_opt.clone()) - } - }, - None => StyleSharingResult::CannotShare, + let sharing_result = if element.parent_element().is_none() { + StyleSharingResult::CannotShare + } else { + unsafe { element.share_style_if_possible(style_sharing_candidate_cache, context.shared_context()) } }; // Otherwise, match and cascade selectors. @@ -327,38 +309,32 @@ pub fn recalc_style_at<'a, E, C, D>(context: &'a C, let mut applicable_declarations = ApplicableDeclarations::new(); let relations; - let shareable_element = match node.as_element() { - Some(element) => { - if opts::get().style_sharing_stats { - STYLE_SHARING_CACHE_MISSES.fetch_add(1, Ordering::Relaxed); - } + let shareable_element = { + if opts::get().style_sharing_stats { + STYLE_SHARING_CACHE_MISSES.fetch_add(1, Ordering::Relaxed); + } - // Perform the CSS selector matching. - let stylist = &context.shared_context().stylist; + // Perform the CSS selector matching. + let stylist = &context.shared_context().stylist; - relations = element.match_element(&**stylist, - Some(&*bf), - &mut applicable_declarations); + relations = element.match_element(&**stylist, + Some(&*bf), + &mut applicable_declarations); - debug!("Result of selector matching: {:?}", relations); + debug!("Result of selector matching: {:?}", relations); - if relations_are_shareable(&relations) { - Some(element) - } else { - None - } - }, - None => { - relations = StyleRelations::empty(); + if relations_are_shareable(&relations) { + Some(element) + } else { None - }, + } }; // Perform the CSS cascade. unsafe { - restyle_result = node.cascade_node(context, - parent_opt, - &applicable_declarations); + restyle_result = element.cascade_node(context, + element.parent_element(), + &applicable_declarations); } // Add ourselves to the LRU cache. @@ -372,7 +348,7 @@ pub fn recalc_style_at<'a, E, C, D>(context: &'a C, STYLE_SHARING_CACHE_HITS.fetch_add(1, Ordering::Relaxed); } style_sharing_candidate_cache.touch(index); - node.as_element().unwrap().set_restyle_damage(damage); + element.set_restyle_damage(damage); } } } @@ -381,7 +357,7 @@ pub fn recalc_style_at<'a, E, C, D>(context: &'a C, // processing. The eventual algorithm we're designing does this in a more granular // fashion. if mode == StylingMode::Restyle && restyle_result == RestyleResult::Continue { - for kid in node.children() { + for kid in element.as_node().children() { let mut data = D::ensure_node_data(&kid).borrow_mut(); if kid.is_text_node() { data.ensure_restyle_data(); @@ -394,12 +370,12 @@ pub fn recalc_style_at<'a, E, C, D>(context: &'a C, } } - let unsafe_layout_node = node.to_unsafe(); + let unsafe_layout_node = element.as_node().to_unsafe(); // Before running the children, we need to insert our nodes into the bloom // filter. debug!("[{}] + {:X}", tid(), unsafe_layout_node.0); - node.insert_into_bloom_filter(&mut *bf); + element.insert_into_bloom_filter(&mut *bf); // NB: flow construction updates the bloom filter on the way up. put_thread_local_bloom_filter(bf, &unsafe_layout_node, context.shared_context());