dom.rs (36181B)
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/. */ 4 5 //! Types and traits used to access the DOM from style calculation. 6 7 #![allow(unsafe_code)] 8 #![deny(missing_docs)] 9 10 use crate::applicable_declarations::ApplicableDeclarationBlock; 11 use crate::context::SharedStyleContext; 12 #[cfg(feature = "gecko")] 13 use crate::context::UpdateAnimationsTasks; 14 use crate::data::ElementData; 15 use crate::media_queries::Device; 16 use crate::properties::{AnimationDeclarations, ComputedValues, PropertyDeclarationBlock}; 17 use crate::selector_parser::{AttrValue, Lang, PseudoElement, RestyleDamage, SelectorImpl}; 18 use crate::shared_lock::{Locked, SharedRwLock}; 19 use crate::stylesheets::scope_rule::ImplicitScopeRoot; 20 use crate::stylist::CascadeData; 21 use crate::values::computed::Display; 22 use crate::values::AtomIdent; 23 use crate::{LocalName, WeakAtom}; 24 use atomic_refcell::{AtomicRef, AtomicRefMut}; 25 use dom::ElementState; 26 use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode}; 27 use selectors::sink::Push; 28 use selectors::{Element as SelectorsElement, OpaqueElement}; 29 use servo_arc::{Arc, ArcBorrow}; 30 use std::fmt; 31 use std::fmt::Debug; 32 use std::hash::Hash; 33 use std::ops::Deref; 34 35 pub use style_traits::dom::OpaqueNode; 36 37 /// Simple trait to provide basic information about the type of an element. 38 /// 39 /// We avoid exposing the full type id, since computing it in the general case 40 /// would be difficult for Gecko nodes. 41 pub trait NodeInfo { 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; 46 } 47 48 /// A node iterator that only returns node that don't need layout. 49 pub struct LayoutIterator<T>(pub T); 50 51 impl<T, N> Iterator for LayoutIterator<T> 52 where 53 T: Iterator<Item = N>, 54 N: NodeInfo, 55 { 56 type Item = N; 57 58 fn next(&mut self) -> Option<N> { 59 loop { 60 let n = self.0.next()?; 61 // Filter out nodes that layout should ignore. 62 if n.is_text_node() || n.is_element() { 63 return Some(n); 64 } 65 } 66 } 67 } 68 69 /// An iterator over the DOM children of a node. 70 pub struct DomChildren<N>(Option<N>); 71 impl<N> Iterator for DomChildren<N> 72 where 73 N: TNode, 74 { 75 type Item = N; 76 77 fn next(&mut self) -> Option<N> { 78 let n = self.0.take()?; 79 self.0 = n.next_sibling(); 80 Some(n) 81 } 82 } 83 84 /// An iterator over the DOM descendants of a node in pre-order. 85 pub struct DomDescendants<N> { 86 previous: Option<N>, 87 scope: N, 88 } 89 90 impl<N> DomDescendants<N> 91 where 92 N: TNode, 93 { 94 /// Returns the next element ignoring all of our subtree. 95 #[inline] 96 pub fn next_skipping_children(&mut self) -> Option<N> { 97 let prev = self.previous.take()?; 98 self.previous = prev.next_in_preorder_skipping_children(self.scope); 99 self.previous 100 } 101 } 102 103 impl<N> Iterator for DomDescendants<N> 104 where 105 N: TNode, 106 { 107 type Item = N; 108 109 #[inline] 110 fn next(&mut self) -> Option<N> { 111 let prev = self.previous.take()?; 112 self.previous = prev.next_in_preorder(self.scope); 113 self.previous 114 } 115 } 116 117 /// The `TDocument` trait, to represent a document node. 118 pub trait TDocument: Sized + Copy + Clone { 119 /// The concrete `TNode` type. 120 type ConcreteNode: TNode<ConcreteDocument = Self>; 121 122 /// Get this document as a `TNode`. 123 fn as_node(&self) -> Self::ConcreteNode; 124 125 /// Returns whether this document is an HTML document. 126 fn is_html_document(&self) -> bool; 127 128 /// Returns the quirks mode of this document. 129 fn quirks_mode(&self) -> QuirksMode; 130 131 /// Get a list of elements with a given ID in this document, sorted by 132 /// tree position. 133 /// 134 /// Can return an error to signal that this list is not available, or also 135 /// return an empty slice. 136 fn elements_with_id<'a>( 137 &self, 138 _id: &AtomIdent, 139 ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()> 140 where 141 Self: 'a, 142 { 143 Err(()) 144 } 145 146 /// This document's shared lock. 147 fn shared_lock(&self) -> &SharedRwLock; 148 } 149 150 /// The `TNode` trait. This is the main generic trait over which the style 151 /// system can be implemented. 152 pub trait TNode: Sized + Copy + Clone + Debug + NodeInfo + PartialEq { 153 /// The concrete `TElement` type. 154 type ConcreteElement: TElement<ConcreteNode = Self>; 155 156 /// The concrete `TDocument` type. 157 type ConcreteDocument: TDocument<ConcreteNode = Self>; 158 159 /// The concrete `TShadowRoot` type. 160 type ConcreteShadowRoot: TShadowRoot<ConcreteNode = Self>; 161 162 /// Get this node's parent node. 163 fn parent_node(&self) -> Option<Self>; 164 165 /// Get this node's first child. 166 fn first_child(&self) -> Option<Self>; 167 168 /// Get this node's last child. 169 fn last_child(&self) -> Option<Self>; 170 171 /// Get this node's previous sibling. 172 fn prev_sibling(&self) -> Option<Self>; 173 174 /// Get this node's next sibling. 175 fn next_sibling(&self) -> Option<Self>; 176 177 /// Get the owner document of this node. 178 fn owner_doc(&self) -> Self::ConcreteDocument; 179 180 /// Iterate over the DOM children of a node. 181 #[inline(always)] 182 fn dom_children(&self) -> DomChildren<Self> { 183 DomChildren(self.first_child()) 184 } 185 186 /// Returns whether the node is attached to a document. 187 fn is_in_document(&self) -> bool; 188 189 /// Iterate over the DOM children of a node, in preorder. 190 #[inline(always)] 191 fn dom_descendants(&self) -> DomDescendants<Self> { 192 DomDescendants { 193 previous: Some(*self), 194 scope: *self, 195 } 196 } 197 198 /// Returns the next node after this one, in a pre-order tree-traversal of 199 /// the subtree rooted at scoped_to. 200 #[inline] 201 fn next_in_preorder(&self, scoped_to: Self) -> Option<Self> { 202 if let Some(c) = self.first_child() { 203 return Some(c); 204 } 205 self.next_in_preorder_skipping_children(scoped_to) 206 } 207 208 /// Returns the next node in tree order, skipping the children of the current node. 209 /// 210 /// This is useful when we know that a subtree cannot contain matches, allowing us 211 /// to skip entire subtrees during traversal. 212 #[inline] 213 fn next_in_preorder_skipping_children(&self, scoped_to: Self) -> Option<Self> { 214 let mut current = *self; 215 loop { 216 if current == scoped_to { 217 return None; 218 } 219 220 if let Some(s) = current.next_sibling() { 221 return Some(s); 222 } 223 224 debug_assert!( 225 current.parent_node().is_some(), 226 "Not a descendant of the scope?" 227 ); 228 current = current.parent_node()?; 229 } 230 } 231 232 /// Returns the depth of this node in the DOM. 233 fn depth(&self) -> usize { 234 let mut depth = 0; 235 let mut curr = *self; 236 while let Some(parent) = curr.traversal_parent() { 237 depth += 1; 238 curr = parent.as_node(); 239 } 240 depth 241 } 242 243 /// Get this node's parent element from the perspective of a restyle 244 /// traversal. 245 fn traversal_parent(&self) -> Option<Self::ConcreteElement>; 246 247 /// Get this node's parent element if present. 248 fn parent_element(&self) -> Option<Self::ConcreteElement> { 249 self.parent_node().and_then(|n| n.as_element()) 250 } 251 252 /// Get this node's parent element, or shadow host if it's a shadow root. 253 fn parent_element_or_host(&self) -> Option<Self::ConcreteElement> { 254 let parent = self.parent_node()?; 255 if let Some(e) = parent.as_element() { 256 return Some(e); 257 } 258 if let Some(root) = parent.as_shadow_root() { 259 return Some(root.host()); 260 } 261 None 262 } 263 264 /// Converts self into an `OpaqueNode`. 265 fn opaque(&self) -> OpaqueNode; 266 267 /// A debug id, only useful, mm... for debugging. 268 fn debug_id(self) -> usize; 269 270 /// Get this node as an element, if it's one. 271 fn as_element(&self) -> Option<Self::ConcreteElement>; 272 273 /// Get this node as a document, if it's one. 274 fn as_document(&self) -> Option<Self::ConcreteDocument>; 275 276 /// Get this node as a ShadowRoot, if it's one. 277 fn as_shadow_root(&self) -> Option<Self::ConcreteShadowRoot>; 278 } 279 280 /// Wrapper to output the subtree rather than the single node when formatting 281 /// for Debug. 282 pub struct ShowSubtree<N: TNode>(pub N); 283 impl<N: TNode> Debug for ShowSubtree<N> { 284 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 285 writeln!(f, "DOM Subtree:")?; 286 fmt_subtree(f, &|f, n| write!(f, "{:?}", n), self.0, 1) 287 } 288 } 289 290 /// Wrapper to output the subtree along with the ElementData when formatting 291 /// for Debug. 292 pub struct ShowSubtreeData<N: TNode>(pub N); 293 impl<N: TNode> Debug for ShowSubtreeData<N> { 294 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 295 writeln!(f, "DOM Subtree:")?; 296 fmt_subtree(f, &|f, n| fmt_with_data(f, n), self.0, 1) 297 } 298 } 299 300 /// Wrapper to output the subtree along with the ElementData and primary 301 /// ComputedValues when formatting for Debug. This is extremely verbose. 302 #[cfg(feature = "servo")] 303 pub struct ShowSubtreeDataAndPrimaryValues<N: TNode>(pub N); 304 #[cfg(feature = "servo")] 305 impl<N: TNode> Debug for ShowSubtreeDataAndPrimaryValues<N> { 306 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 307 writeln!(f, "DOM Subtree:")?; 308 fmt_subtree(f, &|f, n| fmt_with_data_and_primary_values(f, n), self.0, 1) 309 } 310 } 311 312 fn fmt_with_data<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result { 313 if let Some(el) = n.as_element() { 314 write!( 315 f, 316 "{:?} dd={} aodd={} data={:?}", 317 el, 318 el.has_dirty_descendants(), 319 el.has_animation_only_dirty_descendants(), 320 el.borrow_data(), 321 ) 322 } else { 323 write!(f, "{:?}", n) 324 } 325 } 326 327 #[cfg(feature = "servo")] 328 fn fmt_with_data_and_primary_values<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result { 329 if let Some(el) = n.as_element() { 330 let dd = el.has_dirty_descendants(); 331 let aodd = el.has_animation_only_dirty_descendants(); 332 let data = el.borrow_data(); 333 let values = data.as_ref().and_then(|d| d.styles.get_primary()); 334 write!( 335 f, 336 "{:?} dd={} aodd={} data={:?} values={:?}", 337 el, dd, aodd, &data, values 338 ) 339 } else { 340 write!(f, "{:?}", n) 341 } 342 } 343 344 fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N, indent: u32) -> fmt::Result 345 where 346 F: Fn(&mut fmt::Formatter, N) -> fmt::Result, 347 { 348 for _ in 0..indent { 349 write!(f, " ")?; 350 } 351 stringify(f, n)?; 352 if let Some(e) = n.as_element() { 353 for kid in e.traversal_children() { 354 writeln!(f, "")?; 355 fmt_subtree(f, stringify, kid, indent + 1)?; 356 } 357 } 358 359 Ok(()) 360 } 361 362 /// The ShadowRoot trait. 363 pub trait TShadowRoot: Sized + Copy + Clone + Debug + PartialEq { 364 /// The concrete node type. 365 type ConcreteNode: TNode<ConcreteShadowRoot = Self>; 366 367 /// Get this ShadowRoot as a node. 368 fn as_node(&self) -> Self::ConcreteNode; 369 370 /// Get the shadow host that hosts this ShadowRoot. 371 fn host(&self) -> <Self::ConcreteNode as TNode>::ConcreteElement; 372 373 /// Get the style data for this ShadowRoot. 374 fn style_data<'a>(&self) -> Option<&'a CascadeData> 375 where 376 Self: 'a; 377 378 /// Get the list of shadow parts for this shadow root. 379 fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::ConcreteElement] 380 where 381 Self: 'a, 382 { 383 &[] 384 } 385 386 /// Get a list of elements with a given ID in this shadow root, sorted by 387 /// tree position. 388 /// 389 /// Can return an error to signal that this list is not available, or also 390 /// return an empty slice. 391 fn elements_with_id<'a>( 392 &self, 393 _id: &AtomIdent, 394 ) -> Result<&'a [<Self::ConcreteNode as TNode>::ConcreteElement], ()> 395 where 396 Self: 'a, 397 { 398 Err(()) 399 } 400 401 /// Get the implicit scope for a stylesheet in given index. 402 fn implicit_scope_for_sheet(&self, _sheet_index: usize) -> Option<ImplicitScopeRoot> { 403 None 404 } 405 } 406 407 /// The element trait, the main abstraction the style crate acts over. 408 pub trait TElement: 409 Eq 410 + PartialEq 411 + Debug 412 + Hash 413 + Sized 414 + Copy 415 + Clone 416 + SelectorsElement<Impl = SelectorImpl> 417 + AttributeProvider 418 { 419 /// The concrete node type. 420 type ConcreteNode: TNode<ConcreteElement = Self>; 421 422 /// A concrete children iterator type in order to iterate over the `Node`s. 423 /// 424 /// TODO(emilio): We should eventually replace this with the `impl Trait` 425 /// syntax. 426 type TraversalChildrenIterator: Iterator<Item = Self::ConcreteNode>; 427 428 /// Get this element as a node. 429 fn as_node(&self) -> Self::ConcreteNode; 430 431 /// A debug-only check that the device's owner doc matches the actual doc 432 /// we're the root of. 433 /// 434 /// Otherwise we may set document-level state incorrectly, like the root 435 /// font-size used for rem units. 436 fn owner_doc_matches_for_testing(&self, _: &Device) -> bool { 437 true 438 } 439 440 /// Whether this element should match user and content rules. 441 /// 442 /// We use this for Native Anonymous Content in Gecko. 443 fn matches_user_and_content_rules(&self) -> bool { 444 true 445 } 446 447 /// Get this node's parent element from the perspective of a restyle 448 /// traversal. 449 fn traversal_parent(&self) -> Option<Self> { 450 self.as_node().traversal_parent() 451 } 452 453 /// Get this node's children from the perspective of a restyle traversal. 454 fn traversal_children(&self) -> LayoutIterator<Self::TraversalChildrenIterator>; 455 456 /// Returns the parent element we should inherit from. 457 /// 458 /// This is pretty much always the parent element itself, except in the case 459 /// of Gecko's Native Anonymous Content, which uses the traversal parent 460 /// (i.e. the flattened tree parent) and which also may need to find the 461 /// closest non-NAC ancestor. 462 fn inheritance_parent(&self) -> Option<Self> { 463 self.parent_element() 464 } 465 466 /// Execute `f` for each anonymous content child (apart from ::before and 467 /// ::after) whose originating element is `self`. 468 fn each_anonymous_content_child<F>(&self, _f: F) 469 where 470 F: FnMut(Self), 471 { 472 } 473 474 /// Return whether this element is an element in the HTML namespace. 475 fn is_html_element(&self) -> bool; 476 477 /// Return whether this element is an element in the MathML namespace. 478 fn is_mathml_element(&self) -> bool; 479 480 /// Return whether this element is an element in the SVG namespace. 481 fn is_svg_element(&self) -> bool; 482 483 /// Return whether this element is an element in the XUL namespace. 484 fn is_xul_element(&self) -> bool { 485 false 486 } 487 488 /// Returns the bloom filter for this element's subtree, used for fast 489 /// querySelector optimization by allowing subtrees to be skipped. 490 /// Each element's filter includes hashes for all of it's class names and 491 /// attribute names (not values), along with the names for all descendent 492 /// elements. 493 /// 494 /// The default implementation returns all bits set, meaning the bloom filter 495 /// never filters anything. 496 fn subtree_bloom_filter(&self) -> u64 { 497 u64::MAX 498 } 499 500 /// Check if this element's subtree may contain elements with the given bloom hash. 501 fn bloom_may_have_hash(&self, bloom_hash: u64) -> bool { 502 let bloom = self.subtree_bloom_filter(); 503 (bloom & bloom_hash) == bloom_hash 504 } 505 506 /// Convert a 32-bit atom hash to a bloom filter value using k=2 hash functions. 507 /// This must match the C++ implementation of HashForBloomFilter in Element.cpp 508 fn hash_for_bloom_filter(hash: u32) -> u64 { 509 // On 32-bit platforms, we have 31 bits available + 1 tag bit. 510 // On 64-bit platforms, we have 63 bits available + 1 tag bit. 511 #[cfg(target_pointer_width = "32")] 512 const BLOOM_BITS: u32 = 31; 513 514 #[cfg(target_pointer_width = "64")] 515 const BLOOM_BITS: u32 = 63; 516 517 let mut filter = 1u64; 518 filter |= 1u64 << (1 + (hash % BLOOM_BITS)); 519 filter |= 1u64 << (1 + ((hash >> 6) % BLOOM_BITS)); 520 filter 521 } 522 523 /// Return the list of slotted nodes of this node. 524 fn slotted_nodes(&self) -> &[Self::ConcreteNode] { 525 &[] 526 } 527 528 /// Get this element's style attribute. 529 fn style_attribute(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarationBlock>>>; 530 531 /// Unset the style attribute's dirty bit. 532 /// Servo doesn't need to manage ditry bit for style attribute. 533 fn unset_dirty_style_attribute(&self) {} 534 535 /// Get this element's SMIL override declarations. 536 fn smil_override(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarationBlock>>> { 537 None 538 } 539 540 /// Get the combined animation and transition rules. 541 /// 542 /// FIXME(emilio): Is this really useful? 543 fn animation_declarations(&self, context: &SharedStyleContext) -> AnimationDeclarations { 544 if !self.may_have_animations() { 545 return Default::default(); 546 } 547 548 AnimationDeclarations { 549 animations: self.animation_rule(context), 550 transitions: self.transition_rule(context), 551 } 552 } 553 554 /// Get this element's animation rule. 555 fn animation_rule( 556 &self, 557 _: &SharedStyleContext, 558 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>>; 559 560 /// Get this element's transition rule. 561 fn transition_rule( 562 &self, 563 context: &SharedStyleContext, 564 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>>; 565 566 /// Get this element's state, for non-tree-structural pseudos. 567 fn state(&self) -> ElementState; 568 569 /// Returns whether this element has a `part` attribute. 570 fn has_part_attr(&self) -> bool; 571 572 /// Returns whether this element exports any part from its shadow tree. 573 fn exports_any_part(&self) -> bool; 574 575 /// The ID for this element. 576 fn id(&self) -> Option<&WeakAtom>; 577 578 /// Internal iterator for the classes of this element. 579 fn each_class<F>(&self, callback: F) 580 where 581 F: FnMut(&AtomIdent); 582 583 /// Internal iterator for the classes of this element. 584 fn each_custom_state<F>(&self, callback: F) 585 where 586 F: FnMut(&AtomIdent); 587 588 /// Internal iterator for the part names of this element. 589 fn each_part<F>(&self, _callback: F) 590 where 591 F: FnMut(&AtomIdent), 592 { 593 } 594 595 /// Internal iterator for the attribute names of this element. 596 fn each_attr_name<F>(&self, callback: F) 597 where 598 F: FnMut(&LocalName); 599 600 /// Internal iterator for the part names that this element exports for a 601 /// given part name. 602 fn each_exported_part<F>(&self, _name: &AtomIdent, _callback: F) 603 where 604 F: FnMut(&AtomIdent), 605 { 606 } 607 608 /// Whether a given element may generate a pseudo-element. 609 /// 610 /// This is useful to avoid computing, for example, pseudo styles for 611 /// `::-first-line` or `::-first-letter`, when we know it won't affect us. 612 /// 613 /// TODO(emilio, bz): actually implement the logic for it. 614 fn may_generate_pseudo(&self, pseudo: &PseudoElement, _primary_style: &ComputedValues) -> bool { 615 // ::before/::after are always supported for now, though we could try to 616 // optimize out leaf elements. 617 618 // ::first-letter and ::first-line are only supported for block-inside 619 // things, and only in Gecko, not Servo. Unfortunately, Gecko has 620 // block-inside things that might have any computed display value due to 621 // things like fieldsets, legends, etc. Need to figure out how this 622 // should work. 623 debug_assert!( 624 pseudo.is_eager(), 625 "Someone called may_generate_pseudo with a non-eager pseudo." 626 ); 627 true 628 } 629 630 /// Returns true if this element may have a descendant needing style processing. 631 /// 632 /// Note that we cannot guarantee the existence of such an element, because 633 /// it may have been removed from the DOM between marking it for restyle and 634 /// the actual restyle traversal. 635 fn has_dirty_descendants(&self) -> bool; 636 637 /// Returns whether state or attributes that may change style have changed 638 /// on the element, and thus whether the element has been snapshotted to do 639 /// restyle hint computation. 640 fn has_snapshot(&self) -> bool; 641 642 /// Returns whether the current snapshot if present has been handled. 643 fn handled_snapshot(&self) -> bool; 644 645 /// Flags this element as having handled already its snapshot. 646 unsafe fn set_handled_snapshot(&self); 647 648 /// Returns whether the element's styles are up-to-date after traversal 649 /// (i.e. in post traversal). 650 fn has_current_styles(&self, data: &ElementData) -> bool { 651 if self.has_snapshot() && !self.handled_snapshot() { 652 return false; 653 } 654 655 data.has_styles() && 656 // TODO(hiro): When an animating element moved into subtree of 657 // contenteditable element, there remains animation restyle hints in 658 // post traversal. It's generally harmless since the hints will be 659 // processed in a next styling but ideally it should be processed soon. 660 // 661 // Without this, we get failures in: 662 // layout/style/crashtests/1383319.html 663 // layout/style/crashtests/1383001.html 664 // 665 // https://bugzilla.mozilla.org/show_bug.cgi?id=1389675 tracks fixing 666 // this. 667 !data.hint.has_non_animation_invalidations() 668 } 669 670 /// Flag that this element has a descendant for style processing. 671 /// 672 /// Only safe to call with exclusive access to the element. 673 unsafe fn set_dirty_descendants(&self); 674 675 /// Flag that this element has no descendant for style processing. 676 /// 677 /// Only safe to call with exclusive access to the element. 678 unsafe fn unset_dirty_descendants(&self); 679 680 /// Similar to the dirty_descendants but for representing a descendant of 681 /// the element needs to be updated in animation-only traversal. 682 fn has_animation_only_dirty_descendants(&self) -> bool { 683 false 684 } 685 686 /// Flag that this element has a descendant for animation-only restyle 687 /// processing. 688 /// 689 /// Only safe to call with exclusive access to the element. 690 unsafe fn set_animation_only_dirty_descendants(&self) {} 691 692 /// Flag that this element has no descendant for animation-only restyle processing. 693 /// 694 /// Only safe to call with exclusive access to the element. 695 unsafe fn unset_animation_only_dirty_descendants(&self) {} 696 697 /// Clear all bits related describing the dirtiness of descendants. 698 /// 699 /// In Gecko, this corresponds to the regular dirty descendants bit, the 700 /// animation-only dirty descendants bit, and the lazy frame construction 701 /// descendants bit. 702 unsafe fn clear_descendant_bits(&self) { 703 self.unset_dirty_descendants(); 704 } 705 706 /// Returns true if this element is a visited link. 707 /// 708 /// Servo doesn't support visited styles yet. 709 fn is_visited_link(&self) -> bool { 710 false 711 } 712 713 /// Returns the pseudo-element implemented by this element, if any. 714 /// 715 /// Gecko traverses pseudo-elements during the style traversal, and we need 716 /// to know this so we can properly grab the pseudo-element style from the 717 /// parent element. 718 /// 719 /// Note that we still need to compute the pseudo-elements before-hand, 720 /// given otherwise we don't know if we need to create an element or not. 721 fn implemented_pseudo_element(&self) -> Option<PseudoElement> { 722 None 723 } 724 725 /// Atomically stores the number of children of this node that we will 726 /// need to process during bottom-up traversal. 727 fn store_children_to_process(&self, n: isize); 728 729 /// Atomically notes that a child has been processed during bottom-up 730 /// traversal. Returns the number of children left to process. 731 fn did_process_child(&self) -> isize; 732 733 /// Gets a reference to the ElementData container, or creates one. 734 /// 735 /// Unsafe because it can race to allocate and leak if not used with 736 /// exclusive access to the element. 737 unsafe fn ensure_data(&self) -> AtomicRefMut<'_, ElementData>; 738 739 /// Clears the element data reference, if any. 740 /// 741 /// Unsafe following the same reasoning as ensure_data. 742 unsafe fn clear_data(&self); 743 744 /// Whether there is an ElementData container. 745 fn has_data(&self) -> bool; 746 747 /// Immutably borrows the ElementData. 748 fn borrow_data(&self) -> Option<AtomicRef<'_, ElementData>>; 749 750 /// Mutably borrows the ElementData. 751 fn mutate_data(&self) -> Option<AtomicRefMut<'_, ElementData>>; 752 753 /// Whether we should skip any root- or item-based display property 754 /// blockification on this element. (This function exists so that Gecko 755 /// native anonymous content can opt out of this style fixup.) 756 fn skip_item_display_fixup(&self) -> bool; 757 758 /// In Gecko, element has a flag that represents the element may have 759 /// any type of animations or not to bail out animation stuff early. 760 /// Whereas Servo doesn't have such flag. 761 fn may_have_animations(&self) -> bool; 762 763 /// Creates a task to update various animation state on a given (pseudo-)element. 764 #[cfg(feature = "gecko")] 765 fn update_animations( 766 &self, 767 before_change_style: Option<Arc<ComputedValues>>, 768 tasks: UpdateAnimationsTasks, 769 ); 770 771 /// Returns true if the element has relevant animations. Relevant 772 /// animations are those animations that are affecting the element's style 773 /// or are scheduled to do so in the future. 774 fn has_animations(&self, context: &SharedStyleContext) -> bool; 775 776 /// Returns true if the element has a CSS animation. The `context` and `pseudo_element` 777 /// arguments are only used by Servo, since it stores animations globally and pseudo-elements 778 /// are not in the DOM. 779 fn has_css_animations( 780 &self, 781 context: &SharedStyleContext, 782 pseudo_element: Option<PseudoElement>, 783 ) -> bool; 784 785 /// Returns true if the element has a CSS transition (including running transitions and 786 /// completed transitions). The `context` and `pseudo_element` arguments are only used 787 /// by Servo, since it stores animations globally and pseudo-elements are not in the DOM. 788 fn has_css_transitions( 789 &self, 790 context: &SharedStyleContext, 791 pseudo_element: Option<PseudoElement>, 792 ) -> bool; 793 794 /// Returns true if the element has animation restyle hints. 795 fn has_animation_restyle_hints(&self) -> bool { 796 let data = match self.borrow_data() { 797 Some(d) => d, 798 None => return false, 799 }; 800 return data.hint.has_animation_hint(); 801 } 802 803 /// The shadow root this element is a host of. 804 fn shadow_root(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>; 805 806 /// The shadow root which roots the subtree this element is contained in. 807 fn containing_shadow(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>; 808 809 /// Return the element which we can use to look up rules in the selector 810 /// maps. 811 /// 812 /// This is always the element itself, except in the case where we are an 813 /// element-backed pseudo-element, in which case we return the originating 814 /// element. 815 fn rule_hash_target(&self) -> Self { 816 let mut cur = *self; 817 while cur.is_pseudo_element() { 818 cur = cur 819 .pseudo_element_originating_element() 820 .expect("Trying to collect rules for a detached pseudo-element") 821 } 822 cur 823 } 824 825 /// Executes the callback for each applicable style rule data which isn't 826 /// the main document's data (which stores UA / author rules). 827 /// 828 /// The element passed to the callback is the containing shadow host for the 829 /// data if it comes from Shadow DOM. 830 /// 831 /// Returns whether normal document author rules should apply. 832 /// 833 /// TODO(emilio): We could separate the invalidation data for elements 834 /// matching in other scopes to avoid over-invalidation. 835 fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool 836 where 837 Self: 'a, 838 F: FnMut(&'a CascadeData, Self), 839 { 840 use crate::rule_collector::containing_shadow_ignoring_svg_use; 841 842 let target = self.rule_hash_target(); 843 let matches_user_and_content_rules = target.matches_user_and_content_rules(); 844 let mut doc_rules_apply = matches_user_and_content_rules; 845 846 // Use the same rules to look for the containing host as we do for rule 847 // collection. 848 if let Some(shadow) = containing_shadow_ignoring_svg_use(target) { 849 doc_rules_apply = false; 850 if let Some(data) = shadow.style_data() { 851 f(data, shadow.host()); 852 } 853 } 854 855 if let Some(shadow) = target.shadow_root() { 856 if let Some(data) = shadow.style_data() { 857 f(data, shadow.host()); 858 } 859 } 860 861 let mut current = target.assigned_slot(); 862 while let Some(slot) = current { 863 // Slots can only have assigned nodes when in a shadow tree. 864 let shadow = slot.containing_shadow().unwrap(); 865 if let Some(data) = shadow.style_data() { 866 if data.any_slotted_rule() { 867 f(data, shadow.host()); 868 } 869 } 870 current = slot.assigned_slot(); 871 } 872 873 if target.has_part_attr() { 874 if let Some(mut inner_shadow) = target.containing_shadow() { 875 loop { 876 let inner_shadow_host = inner_shadow.host(); 877 match inner_shadow_host.containing_shadow() { 878 Some(shadow) => { 879 if let Some(data) = shadow.style_data() { 880 if data.any_part_rule() { 881 f(data, shadow.host()) 882 } 883 } 884 // TODO: Could be more granular. 885 if !inner_shadow_host.exports_any_part() { 886 break; 887 } 888 inner_shadow = shadow; 889 }, 890 None => { 891 // TODO(emilio): Should probably distinguish with 892 // MatchesDocumentRules::{No,Yes,IfPart} or something so that we could 893 // skip some work. 894 doc_rules_apply = matches_user_and_content_rules; 895 break; 896 }, 897 } 898 } 899 } 900 } 901 902 doc_rules_apply 903 } 904 905 /// Returns true if one of the transitions needs to be updated on this element. We check all 906 /// the transition properties to make sure that updating transitions is necessary. 907 /// This method should only be called if might_needs_transitions_update returns true when 908 /// passed the same parameters. 909 #[cfg(feature = "gecko")] 910 fn needs_transitions_update( 911 &self, 912 before_change_style: &ComputedValues, 913 after_change_style: &ComputedValues, 914 ) -> bool; 915 916 /// Returns the value of the `xml:lang=""` attribute (or, if appropriate, 917 /// the `lang=""` attribute) on this element. 918 fn lang_attr(&self) -> Option<AttrValue>; 919 920 /// Returns whether this element's language matches the language tag 921 /// `value`. If `override_lang` is not `None`, it specifies the value 922 /// of the `xml:lang=""` or `lang=""` attribute to use in place of 923 /// looking at the element and its ancestors. (This argument is used 924 /// to implement matching of `:lang()` against snapshots.) 925 fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, value: &Lang) -> bool; 926 927 /// Returns whether this element is the main body element of the HTML 928 /// document it is on. 929 fn is_html_document_body_element(&self) -> bool; 930 931 /// Generate the proper applicable declarations due to presentational hints, 932 /// and insert them into `hints`. 933 fn synthesize_presentational_hints_for_legacy_attributes<V>( 934 &self, 935 visited_handling: VisitedHandlingMode, 936 hints: &mut V, 937 ) where 938 V: Push<ApplicableDeclarationBlock>; 939 940 /// Generate the proper applicable declarations due to view transition dynamic rules, and 941 /// insert them into `rules`. 942 /// https://drafts.csswg.org/css-view-transitions-1/#document-dynamic-view-transition-style-sheet 943 fn synthesize_view_transition_dynamic_rules<V>(&self, _rules: &mut V) 944 where 945 V: Push<ApplicableDeclarationBlock>, 946 { 947 } 948 949 /// Returns element's local name. 950 fn local_name(&self) -> &<SelectorImpl as selectors::parser::SelectorImpl>::BorrowedLocalName; 951 952 /// Returns element's namespace. 953 fn namespace(&self) 954 -> &<SelectorImpl as selectors::parser::SelectorImpl>::BorrowedNamespaceUrl; 955 956 /// Returns the size of the element to be used in container size queries. 957 /// This will usually be the size of the content area of the primary box, 958 /// but can be None if there is no box or if some axis lacks size containment. 959 fn query_container_size( 960 &self, 961 display: &Display, 962 ) -> euclid::default::Size2D<Option<app_units::Au>>; 963 964 /// Returns true if the element has all of specified selector flags. 965 fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool; 966 967 /// Returns the search direction for relative selector invalidation, if it is on the search path. 968 fn relative_selector_search_direction(&self) -> ElementSelectorFlags; 969 970 /// Returns the implicit scope root for given sheet index and host. 971 fn implicit_scope_for_sheet_in_shadow_root( 972 _opaque_host: OpaqueElement, 973 _sheet_index: usize, 974 ) -> Option<ImplicitScopeRoot> { 975 None 976 } 977 978 /// Compute the damage incurred by the change from the `_old` to `_new`. 979 fn compute_layout_damage(_old: &ComputedValues, _new: &ComputedValues) -> RestyleDamage { 980 Default::default() 981 } 982 } 983 984 /// The attribute provider trait 985 pub trait AttributeProvider { 986 /// Return the value of the given custom attibute if it exists. 987 fn get_attr(&self, attr: &LocalName) -> Option<String>; 988 } 989 990 /// A dummy AttributeProvider that returns none to any attribute query. 991 #[derive(Clone, Debug, PartialEq)] 992 pub struct DummyAttributeProvider; 993 994 impl AttributeProvider for DummyAttributeProvider { 995 fn get_attr(&self, _attr: &LocalName) -> Option<String> { 996 None 997 } 998 } 999 1000 /// TNode and TElement aren't Send because we want to be careful and explicit 1001 /// about our parallel traversal. However, there are certain situations 1002 /// (including but not limited to the traversal) where we need to send DOM 1003 /// objects to other threads. 1004 /// 1005 /// That's the reason why `SendNode` exists. 1006 #[derive(Clone, Debug, PartialEq)] 1007 pub struct SendNode<N: TNode>(N); 1008 unsafe impl<N: TNode> Send for SendNode<N> {} 1009 impl<N: TNode> SendNode<N> { 1010 /// Unsafely construct a SendNode. 1011 pub unsafe fn new(node: N) -> Self { 1012 SendNode(node) 1013 } 1014 } 1015 impl<N: TNode> Deref for SendNode<N> { 1016 type Target = N; 1017 fn deref(&self) -> &N { 1018 &self.0 1019 } 1020 } 1021 1022 /// Same reason as for the existence of SendNode, SendElement does the proper 1023 /// things for a given `TElement`. 1024 #[derive(Debug, Eq, Hash, PartialEq)] 1025 pub struct SendElement<E: TElement>(E); 1026 unsafe impl<E: TElement> Send for SendElement<E> {} 1027 impl<E: TElement> SendElement<E> { 1028 /// Unsafely construct a SendElement. 1029 pub unsafe fn new(el: E) -> Self { 1030 SendElement(el) 1031 } 1032 } 1033 impl<E: TElement> Deref for SendElement<E> { 1034 type Target = E; 1035 fn deref(&self) -> &E { 1036 &self.0 1037 } 1038 }