1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
5 //! Types and traits used to access the DOM from style calculation.
10 use crate::applicable_declarations::ApplicableDeclarationBlock;
11 use crate::context::SharedStyleContext;
12 #[cfg(feature = "gecko")]
13 use crate::context::{PostAnimationTasks, UpdateAnimationsTasks};
14 use crate::data::ElementData;
15 use crate::element_state::ElementState;
16 use crate::font_metrics::FontMetricsProvider;
17 use crate::media_queries::Device;
18 use crate::properties::{AnimationDeclarations, ComputedValues, PropertyDeclarationBlock};
19 use crate::selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl};
20 use crate::shared_lock::{Locked, SharedRwLock};
21 use crate::stylist::CascadeData;
22 use crate::traversal_flags::TraversalFlags;
23 use crate::values::AtomIdent;
24 use crate::{LocalName, Namespace, WeakAtom};
25 use atomic_refcell::{AtomicRef, AtomicRefMut};
26 use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode};
27 use selectors::sink::Push;
28 use selectors::Element as SelectorsElement;
29 use servo_arc::{Arc, ArcBorrow};
35 pub use style_traits::dom::OpaqueNode;
37 /// Simple trait to provide basic information about the type of an element.
39 /// We avoid exposing the full type id, since computing it in the general case
40 /// would be difficult for Gecko nodes.
42 /// Whether this node is an element.
43 fn is_element(&self) -> bool;
44 /// Whether this node is a text node.
45 fn is_text_node(&self) -> bool;
48 /// A node iterator that only returns node that don't need layout.
49 pub struct LayoutIterator<T>(pub T);
51 impl<T, N> Iterator for LayoutIterator<T>
53 T: Iterator<Item = N>,
58 fn next(&mut self) -> Option<N> {
60 let n = self.0.next()?;
61 // Filter out nodes that layout should ignore.
62 if n.is_text_node() || n.is_element() {
69 /// An iterator over the DOM children of a node.
70 pub struct DomChildren<N>(Option<N>);
71 impl<N> Iterator for DomChildren<N>
77 fn next(&mut self) -> Option<N> {
78 let n = self.0.take()?;
79 self.0 = n.next_sibling();
84 /// An iterator over the DOM descendants of a node in pre-order.
85 pub struct DomDescendants<N> {
90 impl<N> Iterator for DomDescendants<N>
97 fn next(&mut self) -> Option<N> {
98 let prev = self.previous.take()?;
99 self.previous = prev.next_in_preorder(Some(self.scope));
104 /// The `TDocument` trait, to represent a document node.
105 pub trait TDocument: Sized + Copy + Clone {
106 /// The concrete `TNode` type.
107 type ConcreteNode: TNode<ConcreteDocument = Self>;
109 /// Get this document as a `TNode`.
110 fn as_node(&self) -> Self::ConcreteNode;
112 /// Returns whether this document is an HTML document.
113 fn is_html_document(&self) -> bool;
115 /// Returns the quirks mode of this document.
116 fn quirks_mode(&self) -> QuirksMode;
118 /// Get a list of elements with a given ID in this document, sorted by
121 /// Can return an error to signal that this list is not available, or also
122 /// return an empty slice.
123 fn elements_with_id<'a>(
126 ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()>
133 /// This document's shared lock.
134 fn shared_lock(&self) -> &SharedRwLock;
137 /// The `TNode` trait. This is the main generic trait over which the style
138 /// system can be implemented.
139 pub trait TNode: Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
140 /// The concrete `TElement` type.
141 type ConcreteElement: TElement<ConcreteNode = Self>;
143 /// The concrete `TDocument` type.
144 type ConcreteDocument: TDocument<ConcreteNode = Self>;
146 /// The concrete `TShadowRoot` type.
147 type ConcreteShadowRoot: TShadowRoot<ConcreteNode = Self>;
149 /// Get this node's parent node.
150 fn parent_node(&self) -> Option<Self>;
152 /// Get this node's first child.
153 fn first_child(&self) -> Option<Self>;
155 /// Get this node's last child.
156 fn last_child(&self) -> Option<Self>;
158 /// Get this node's previous sibling.
159 fn prev_sibling(&self) -> Option<Self>;
161 /// Get this node's next sibling.
162 fn next_sibling(&self) -> Option<Self>;
164 /// Get the owner document of this node.
165 fn owner_doc(&self) -> Self::ConcreteDocument;
167 /// Iterate over the DOM children of a node.
168 fn dom_children(&self) -> DomChildren<Self> {
169 DomChildren(self.first_child())
172 /// Returns whether the node is attached to a document.
173 fn is_in_document(&self) -> bool;
175 /// Iterate over the DOM children of a node, in preorder.
176 fn dom_descendants(&self) -> DomDescendants<Self> {
178 previous: Some(*self),
183 /// Returns the next children in pre-order, optionally scoped to a subtree
186 fn next_in_preorder(&self, scoped_to: Option<Self>) -> Option<Self> {
187 if let Some(c) = self.first_child() {
191 let mut current = Some(*self);
193 if current == scoped_to {
197 debug_assert!(current.is_some(), "not a descendant of the scope?");
198 if let Some(s) = current?.next_sibling() {
202 current = current?.parent_node();
206 /// Get this node's parent element from the perspective of a restyle
208 fn traversal_parent(&self) -> Option<Self::ConcreteElement>;
210 /// Get this node's parent element if present.
211 fn parent_element(&self) -> Option<Self::ConcreteElement> {
212 self.parent_node().and_then(|n| n.as_element())
215 /// Converts self into an `OpaqueNode`.
216 fn opaque(&self) -> OpaqueNode;
218 /// A debug id, only useful, mm... for debugging.
219 fn debug_id(self) -> usize;
221 /// Get this node as an element, if it's one.
222 fn as_element(&self) -> Option<Self::ConcreteElement>;
224 /// Get this node as a document, if it's one.
225 fn as_document(&self) -> Option<Self::ConcreteDocument>;
227 /// Get this node as a ShadowRoot, if it's one.
228 fn as_shadow_root(&self) -> Option<Self::ConcreteShadowRoot>;
231 /// Wrapper to output the subtree rather than the single node when formatting
233 pub struct ShowSubtree<N: TNode>(pub N);
234 impl<N: TNode> Debug for ShowSubtree<N> {
235 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236 writeln!(f, "DOM Subtree:")?;
237 fmt_subtree(f, &|f, n| write!(f, "{:?}", n), self.0, 1)
241 /// Wrapper to output the subtree along with the ElementData when formatting
243 pub struct ShowSubtreeData<N: TNode>(pub N);
244 impl<N: TNode> Debug for ShowSubtreeData<N> {
245 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246 writeln!(f, "DOM Subtree:")?;
247 fmt_subtree(f, &|f, n| fmt_with_data(f, n), self.0, 1)
251 /// Wrapper to output the subtree along with the ElementData and primary
252 /// ComputedValues when formatting for Debug. This is extremely verbose.
253 #[cfg(feature = "servo")]
254 pub struct ShowSubtreeDataAndPrimaryValues<N: TNode>(pub N);
255 #[cfg(feature = "servo")]
256 impl<N: TNode> Debug for ShowSubtreeDataAndPrimaryValues<N> {
257 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258 writeln!(f, "DOM Subtree:")?;
259 fmt_subtree(f, &|f, n| fmt_with_data_and_primary_values(f, n), self.0, 1)
263 fn fmt_with_data<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
264 if let Some(el) = n.as_element() {
267 "{:?} dd={} aodd={} data={:?}",
269 el.has_dirty_descendants(),
270 el.has_animation_only_dirty_descendants(),
278 #[cfg(feature = "servo")]
279 fn fmt_with_data_and_primary_values<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
280 if let Some(el) = n.as_element() {
281 let dd = el.has_dirty_descendants();
282 let aodd = el.has_animation_only_dirty_descendants();
283 let data = el.borrow_data();
284 let values = data.as_ref().and_then(|d| d.styles.get_primary());
287 "{:?} dd={} aodd={} data={:?} values={:?}",
288 el, dd, aodd, &data, values
295 fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N, indent: u32) -> fmt::Result
297 F: Fn(&mut fmt::Formatter, N) -> fmt::Result,
303 if let Some(e) = n.as_element() {
304 for kid in e.traversal_children() {
306 fmt_subtree(f, stringify, kid, indent + 1)?;
313 /// The ShadowRoot trait.
314 pub trait TShadowRoot: Sized + Copy + Clone + Debug + PartialEq {
315 /// The concrete node type.
316 type ConcreteNode: TNode<ConcreteShadowRoot = Self>;
318 /// Get this ShadowRoot as a node.
319 fn as_node(&self) -> Self::ConcreteNode;
321 /// Get the shadow host that hosts this ShadowRoot.
322 fn host(&self) -> <Self::ConcreteNode as TNode>::ConcreteElement;
324 /// Get the style data for this ShadowRoot.
325 fn style_data<'a>(&self) -> Option<&'a CascadeData>
329 /// Get the list of shadow parts for this shadow root.
330 fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::ConcreteElement]
337 /// Get a list of elements with a given ID in this shadow root, sorted by
340 /// Can return an error to signal that this list is not available, or also
341 /// return an empty slice.
342 fn elements_with_id<'a>(
345 ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()>
353 /// The element trait, the main abstraction the style crate acts over.
355 Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + SelectorsElement<Impl = SelectorImpl>
357 /// The concrete node type.
358 type ConcreteNode: TNode<ConcreteElement = Self>;
360 /// A concrete children iterator type in order to iterate over the `Node`s.
362 /// TODO(emilio): We should eventually replace this with the `impl Trait`
364 type TraversalChildrenIterator: Iterator<Item = Self::ConcreteNode>;
366 /// Type of the font metrics provider
368 /// XXXManishearth It would be better to make this a type parameter on
369 /// ThreadLocalStyleContext and StyleContext
370 type FontMetricsProvider: FontMetricsProvider + Send;
372 /// Get this element as a node.
373 fn as_node(&self) -> Self::ConcreteNode;
375 /// A debug-only check that the device's owner doc matches the actual doc
376 /// we're the root of.
378 /// Otherwise we may set document-level state incorrectly, like the root
379 /// font-size used for rem units.
380 fn owner_doc_matches_for_testing(&self, _: &Device) -> bool {
384 /// Whether this element should match user and author rules.
386 /// We use this for Native Anonymous Content in Gecko.
387 fn matches_user_and_author_rules(&self) -> bool {
391 /// Returns the depth of this element in the DOM.
392 fn depth(&self) -> usize {
394 let mut curr = *self;
395 while let Some(parent) = curr.traversal_parent() {
403 /// Get this node's parent element from the perspective of a restyle
405 fn traversal_parent(&self) -> Option<Self> {
406 self.as_node().traversal_parent()
409 /// Get this node's children from the perspective of a restyle traversal.
410 fn traversal_children(&self) -> LayoutIterator<Self::TraversalChildrenIterator>;
412 /// Returns the parent element we should inherit from.
414 /// This is pretty much always the parent element itself, except in the case
415 /// of Gecko's Native Anonymous Content, which uses the traversal parent
416 /// (i.e. the flattened tree parent) and which also may need to find the
417 /// closest non-NAC ancestor.
418 fn inheritance_parent(&self) -> Option<Self> {
419 self.parent_element()
422 /// The ::before pseudo-element of this element, if it exists.
423 fn before_pseudo_element(&self) -> Option<Self> {
427 /// The ::after pseudo-element of this element, if it exists.
428 fn after_pseudo_element(&self) -> Option<Self> {
432 /// The ::marker pseudo-element of this element, if it exists.
433 fn marker_pseudo_element(&self) -> Option<Self> {
437 /// Execute `f` for each anonymous content child (apart from ::before and
438 /// ::after) whose originating element is `self`.
439 fn each_anonymous_content_child<F>(&self, _f: F)
445 /// Return whether this element is an element in the HTML namespace.
446 fn is_html_element(&self) -> bool;
448 /// Return whether this element is an element in the MathML namespace.
449 fn is_mathml_element(&self) -> bool;
451 /// Return whether this element is an element in the SVG namespace.
452 fn is_svg_element(&self) -> bool;
454 /// Return whether this element is an element in the XUL namespace.
455 fn is_xul_element(&self) -> bool {
459 /// Return the list of slotted nodes of this node.
460 fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
464 /// Get this element's style attribute.
465 fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>;
467 /// Unset the style attribute's dirty bit.
468 /// Servo doesn't need to manage ditry bit for style attribute.
469 fn unset_dirty_style_attribute(&self) {}
471 /// Get this element's SMIL override declarations.
472 fn smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
476 /// Get the combined animation and transition rules.
478 /// FIXME(emilio): Is this really useful?
479 fn animation_declarations(&self, context: &SharedStyleContext) -> AnimationDeclarations {
480 if !self.may_have_animations() {
481 return Default::default();
484 AnimationDeclarations {
485 animations: self.animation_rule(context),
486 transitions: self.transition_rule(context),
490 /// Get this element's animation rule.
493 _: &SharedStyleContext,
494 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>>;
496 /// Get this element's transition rule.
499 context: &SharedStyleContext,
500 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>>;
502 /// Get this element's state, for non-tree-structural pseudos.
503 fn state(&self) -> ElementState;
505 /// Whether this element has an attribute with a given namespace.
506 fn has_attr(&self, namespace: &Namespace, attr: &LocalName) -> bool;
508 /// Returns whether this element has a `part` attribute.
509 fn has_part_attr(&self) -> bool;
511 /// Returns whether this element exports any part from its shadow tree.
512 fn exports_any_part(&self) -> bool;
514 /// The ID for this element.
515 fn id(&self) -> Option<&WeakAtom>;
517 /// Internal iterator for the classes of this element.
518 fn each_class<F>(&self, callback: F)
520 F: FnMut(&AtomIdent);
522 /// Internal iterator for the part names of this element.
523 fn each_part<F>(&self, _callback: F)
525 F: FnMut(&AtomIdent),
529 /// Internal iterator for the attribute names of this element.
530 fn each_attr_name<F>(&self, callback: F)
532 F: FnMut(&AtomIdent);
534 /// Internal iterator for the part names that this element exports for a
536 fn each_exported_part<F>(&self, _name: &AtomIdent, _callback: F)
538 F: FnMut(&AtomIdent),
542 /// Whether a given element may generate a pseudo-element.
544 /// This is useful to avoid computing, for example, pseudo styles for
545 /// `::-first-line` or `::-first-letter`, when we know it won't affect us.
547 /// TODO(emilio, bz): actually implement the logic for it.
548 fn may_generate_pseudo(&self, pseudo: &PseudoElement, _primary_style: &ComputedValues) -> bool {
549 // ::before/::after are always supported for now, though we could try to
550 // optimize out leaf elements.
552 // ::first-letter and ::first-line are only supported for block-inside
553 // things, and only in Gecko, not Servo. Unfortunately, Gecko has
554 // block-inside things that might have any computed display value due to
555 // things like fieldsets, legends, etc. Need to figure out how this
559 "Someone called may_generate_pseudo with a non-eager pseudo."
564 /// Returns true if this element may have a descendant needing style processing.
566 /// Note that we cannot guarantee the existence of such an element, because
567 /// it may have been removed from the DOM between marking it for restyle and
568 /// the actual restyle traversal.
569 fn has_dirty_descendants(&self) -> bool;
571 /// Returns whether state or attributes that may change style have changed
572 /// on the element, and thus whether the element has been snapshotted to do
573 /// restyle hint computation.
574 fn has_snapshot(&self) -> bool;
576 /// Returns whether the current snapshot if present has been handled.
577 fn handled_snapshot(&self) -> bool;
579 /// Flags this element as having handled already its snapshot.
580 unsafe fn set_handled_snapshot(&self);
582 /// Returns whether the element's styles are up-to-date for |traversal_flags|.
583 fn has_current_styles_for_traversal(
586 traversal_flags: TraversalFlags,
588 if traversal_flags.for_animation_only() {
589 // In animation-only restyle we never touch snapshots and don't care
590 // about them. But we can't assert '!self.handled_snapshot()'
591 // here since there are some cases that a second animation-only
592 // restyle which is a result of normal restyle (e.g. setting
593 // animation-name in normal restyle and creating a new CSS
594 // animation in a SequentialTask) is processed after the normal
595 // traversal in that we had elements that handled snapshot.
596 if !data.has_styles() {
600 if !data.hint.has_animation_hint_or_recascade() {
604 // FIXME: This should ideally always return false, but it is a hack
605 // to work around our weird animation-only traversal
606 // stuff: If we're display: none and the rules we could match could
607 // change, we consider our style up-to-date. This is because
608 // re-cascading with and old style doesn't guarantee returning the
609 // correct animation style (that's bug 1393323). So if our display
610 // changed, and it changed from display: none, we would incorrectly
611 // forget about it and wouldn't be able to correctly style our
612 // descendants later.
613 if data.styles.is_display_none() && data.hint.match_self() {
620 if self.has_snapshot() && !self.handled_snapshot() {
624 data.has_styles() && !data.hint.has_non_animation_invalidations()
627 /// Returns whether the element's styles are up-to-date after traversal
628 /// (i.e. in post traversal).
629 fn has_current_styles(&self, data: &ElementData) -> bool {
630 if self.has_snapshot() && !self.handled_snapshot() {
635 // TODO(hiro): When an animating element moved into subtree of
636 // contenteditable element, there remains animation restyle hints in
637 // post traversal. It's generally harmless since the hints will be
638 // processed in a next styling but ideally it should be processed soon.
640 // Without this, we get failures in:
641 // layout/style/crashtests/1383319.html
642 // layout/style/crashtests/1383001.html
644 // https://bugzilla.mozilla.org/show_bug.cgi?id=1389675 tracks fixing
646 !data.hint.has_non_animation_invalidations()
649 /// Flag that this element has a descendant for style processing.
651 /// Only safe to call with exclusive access to the element.
652 unsafe fn set_dirty_descendants(&self);
654 /// Flag that this element has no descendant for style processing.
656 /// Only safe to call with exclusive access to the element.
657 unsafe fn unset_dirty_descendants(&self);
659 /// Similar to the dirty_descendants but for representing a descendant of
660 /// the element needs to be updated in animation-only traversal.
661 fn has_animation_only_dirty_descendants(&self) -> bool {
665 /// Flag that this element has a descendant for animation-only restyle
668 /// Only safe to call with exclusive access to the element.
669 unsafe fn set_animation_only_dirty_descendants(&self) {}
671 /// Flag that this element has no descendant for animation-only restyle processing.
673 /// Only safe to call with exclusive access to the element.
674 unsafe fn unset_animation_only_dirty_descendants(&self) {}
676 /// Clear all bits related describing the dirtiness of descendants.
678 /// In Gecko, this corresponds to the regular dirty descendants bit, the
679 /// animation-only dirty descendants bit, and the lazy frame construction
681 unsafe fn clear_descendant_bits(&self) {
682 self.unset_dirty_descendants();
685 /// Returns true if this element is a visited link.
687 /// Servo doesn't support visited styles yet.
688 fn is_visited_link(&self) -> bool {
692 /// Returns true if this element is in a native anonymous subtree.
693 fn is_in_native_anonymous_subtree(&self) -> bool {
697 /// Returns the pseudo-element implemented by this element, if any.
699 /// Gecko traverses pseudo-elements during the style traversal, and we need
700 /// to know this so we can properly grab the pseudo-element style from the
703 /// Note that we still need to compute the pseudo-elements before-hand,
704 /// given otherwise we don't know if we need to create an element or not.
706 /// Servo doesn't have to deal with this.
707 fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
711 /// Atomically stores the number of children of this node that we will
712 /// need to process during bottom-up traversal.
713 fn store_children_to_process(&self, n: isize);
715 /// Atomically notes that a child has been processed during bottom-up
716 /// traversal. Returns the number of children left to process.
717 fn did_process_child(&self) -> isize;
719 /// Gets a reference to the ElementData container, or creates one.
721 /// Unsafe because it can race to allocate and leak if not used with
722 /// exclusive access to the element.
723 unsafe fn ensure_data(&self) -> AtomicRefMut<ElementData>;
725 /// Clears the element data reference, if any.
727 /// Unsafe following the same reasoning as ensure_data.
728 unsafe fn clear_data(&self);
730 /// Whether there is an ElementData container.
731 fn has_data(&self) -> bool;
733 /// Immutably borrows the ElementData.
734 fn borrow_data(&self) -> Option<AtomicRef<ElementData>>;
736 /// Mutably borrows the ElementData.
737 fn mutate_data(&self) -> Option<AtomicRefMut<ElementData>>;
739 /// Whether we should skip any root- or item-based display property
740 /// blockification on this element. (This function exists so that Gecko
741 /// native anonymous content can opt out of this style fixup.)
742 fn skip_item_display_fixup(&self) -> bool;
744 /// Sets selector flags, which indicate what kinds of selectors may have
745 /// matched on this element and therefore what kind of work may need to
746 /// be performed when DOM state changes.
748 /// This is unsafe, like all the flag-setting methods, because it's only safe
749 /// to call with exclusive access to the element. When setting flags on the
750 /// parent during parallel traversal, we use SequentialTask to queue up the
751 /// set to run after the threads join.
752 unsafe fn set_selector_flags(&self, flags: ElementSelectorFlags);
754 /// Returns true if the element has all the specified selector flags.
755 fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
757 /// In Gecko, element has a flag that represents the element may have
758 /// any type of animations or not to bail out animation stuff early.
759 /// Whereas Servo doesn't have such flag.
760 fn may_have_animations(&self) -> bool;
762 /// Creates a task to update various animation state on a given (pseudo-)element.
763 #[cfg(feature = "gecko")]
764 fn update_animations(
766 before_change_style: Option<Arc<ComputedValues>>,
767 tasks: UpdateAnimationsTasks,
770 /// Creates a task to process post animation on a given element.
771 #[cfg(feature = "gecko")]
772 fn process_post_animation(&self, tasks: PostAnimationTasks);
774 /// Returns true if the element has relevant animations. Relevant
775 /// animations are those animations that are affecting the element's style
776 /// or are scheduled to do so in the future.
777 fn has_animations(&self, context: &SharedStyleContext) -> bool;
779 /// Returns true if the element has a CSS animation. The `context` and `pseudo_element`
780 /// arguments are only used by Servo, since it stores animations globally and pseudo-elements
781 /// are not in the DOM.
782 fn has_css_animations(
784 context: &SharedStyleContext,
785 pseudo_element: Option<PseudoElement>,
788 /// Returns true if the element has a CSS transition (including running transitions and
789 /// completed transitions). The `context` and `pseudo_element` arguments are only used
790 /// by Servo, since it stores animations globally and pseudo-elements are not in the DOM.
791 fn has_css_transitions(
793 context: &SharedStyleContext,
794 pseudo_element: Option<PseudoElement>,
797 /// Returns true if the element has animation restyle hints.
798 fn has_animation_restyle_hints(&self) -> bool {
799 let data = match self.borrow_data() {
801 None => return false,
803 return data.hint.has_animation_hint();
806 /// The shadow root this element is a host of.
807 fn shadow_root(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>;
809 /// The shadow root which roots the subtree this element is contained in.
810 fn containing_shadow(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>;
812 /// Return the element which we can use to look up rules in the selector
815 /// This is always the element itself, except in the case where we are an
816 /// element-backed pseudo-element, in which case we return the originating
818 fn rule_hash_target(&self) -> Self {
819 if self.is_pseudo_element() {
820 self.pseudo_element_originating_element()
821 .expect("Trying to collect rules for a detached pseudo-element")
827 /// Executes the callback for each applicable style rule data which isn't
828 /// the main document's data (which stores UA / author rules).
830 /// The element passed to the callback is the containing shadow host for the
831 /// data if it comes from Shadow DOM.
833 /// Returns whether normal document author rules should apply.
835 /// TODO(emilio): We could separate the invalidation data for elements
836 /// matching in other scopes to avoid over-invalidation.
837 fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
840 F: FnMut(&'a CascadeData, Self),
842 use crate::rule_collector::containing_shadow_ignoring_svg_use;
844 let target = self.rule_hash_target();
845 if !target.matches_user_and_author_rules() {
849 let mut doc_rules_apply = true;
851 // Use the same rules to look for the containing host as we do for rule
853 if let Some(shadow) = containing_shadow_ignoring_svg_use(target) {
854 doc_rules_apply = false;
855 if let Some(data) = shadow.style_data() {
856 f(data, shadow.host());
860 if let Some(shadow) = target.shadow_root() {
861 if let Some(data) = shadow.style_data() {
862 f(data, shadow.host());
866 let mut current = target.assigned_slot();
867 while let Some(slot) = current {
868 // Slots can only have assigned nodes when in a shadow tree.
869 let shadow = slot.containing_shadow().unwrap();
870 if let Some(data) = shadow.style_data() {
871 if data.any_slotted_rule() {
872 f(data, shadow.host());
875 current = slot.assigned_slot();
878 if target.has_part_attr() {
879 if let Some(mut inner_shadow) = target.containing_shadow() {
881 let inner_shadow_host = inner_shadow.host();
882 match inner_shadow_host.containing_shadow() {
884 if let Some(data) = shadow.style_data() {
885 if data.any_part_rule() {
886 f(data, shadow.host())
889 // TODO: Could be more granular.
890 if !inner_shadow_host.exports_any_part() {
893 inner_shadow = shadow;
896 // TODO(emilio): Should probably distinguish with
897 // MatchesDocumentRules::{No,Yes,IfPart} or
898 // something so that we could skip some work.
899 doc_rules_apply = true;
910 /// Returns true if one of the transitions needs to be updated on this element. We check all
911 /// the transition properties to make sure that updating transitions is necessary.
912 /// This method should only be called if might_needs_transitions_update returns true when
913 /// passed the same parameters.
914 #[cfg(feature = "gecko")]
915 fn needs_transitions_update(
917 before_change_style: &ComputedValues,
918 after_change_style: &ComputedValues,
921 /// Returns the value of the `xml:lang=""` attribute (or, if appropriate,
922 /// the `lang=""` attribute) on this element.
923 fn lang_attr(&self) -> Option<AttrValue>;
925 /// Returns whether this element's language matches the language tag
926 /// `value`. If `override_lang` is not `None`, it specifies the value
927 /// of the `xml:lang=""` or `lang=""` attribute to use in place of
928 /// looking at the element and its ancestors. (This argument is used
929 /// to implement matching of `:lang()` against snapshots.)
930 fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, value: &Lang) -> bool;
932 /// Returns whether this element is the main body element of the HTML
933 /// document it is on.
934 fn is_html_document_body_element(&self) -> bool;
936 /// Generate the proper applicable declarations due to presentational hints,
937 /// and insert them into `hints`.
938 fn synthesize_presentational_hints_for_legacy_attributes<V>(
940 visited_handling: VisitedHandlingMode,
943 V: Push<ApplicableDeclarationBlock>;
945 /// Returns element's local name.
946 fn local_name(&self) -> &<SelectorImpl as selectors::parser::SelectorImpl>::BorrowedLocalName;
948 /// Returns element's namespace.
950 -> &<SelectorImpl as selectors::parser::SelectorImpl>::BorrowedNamespaceUrl;
953 /// TNode and TElement aren't Send because we want to be careful and explicit
954 /// about our parallel traversal. However, there are certain situations
955 /// (including but not limited to the traversal) where we need to send DOM
956 /// objects to other threads.
958 /// That's the reason why `SendNode` exists.
959 #[derive(Clone, Debug, PartialEq)]
960 pub struct SendNode<N: TNode>(N);
961 unsafe impl<N: TNode> Send for SendNode<N> {}
962 impl<N: TNode> SendNode<N> {
963 /// Unsafely construct a SendNode.
964 pub unsafe fn new(node: N) -> Self {
968 impl<N: TNode> Deref for SendNode<N> {
970 fn deref(&self) -> &N {
975 /// Same reason as for the existence of SendNode, SendElement does the proper
976 /// things for a given `TElement`.
977 #[derive(Debug, Eq, Hash, PartialEq)]
978 pub struct SendElement<E: TElement>(E);
979 unsafe impl<E: TElement> Send for SendElement<E> {}
980 impl<E: TElement> SendElement<E> {
981 /// Unsafely construct a SendElement.
982 pub unsafe fn new(el: E) -> Self {
986 impl<E: TElement> Deref for SendElement<E> {
988 fn deref(&self) -> &E {