style/rule_tree/source.rs
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#![deny(unsafe_code)]
6
7use crate::properties::PropertyDeclarationBlock;
8use crate::shared_lock::{Locked, SharedRwLockReadGuard};
9use servo_arc::Arc;
10use std::io::Write;
11use std::ptr;
12
13/// A style source for the rule node. It is a declaration block that may come from either a style
14/// rule or a standalone block like animations / transitions / smil / preshints / style attr...
15///
16/// Keeping the style rule around would provide more debugability, but also causes more
17/// pointer-chasing in the common code-path, which is undesired. If needed, we could keep it around
18/// in debug builds or something along those lines.
19#[derive(Clone, Debug)]
20pub struct StyleSource(Arc<Locked<PropertyDeclarationBlock>>);
21
22impl PartialEq for StyleSource {
23 fn eq(&self, other: &Self) -> bool {
24 Arc::ptr_eq(&self.0, &other.0)
25 }
26}
27
28impl StyleSource {
29 #[inline]
30 pub(super) fn key(&self) -> ptr::NonNull<()> {
31 self.0.raw_ptr()
32 }
33
34 /// Creates a StyleSource from a PropertyDeclarationBlock.
35 #[inline]
36 pub fn from_declarations(decls: Arc<Locked<PropertyDeclarationBlock>>) -> Self {
37 Self(decls)
38 }
39
40 pub(super) fn dump<W: Write>(&self, guard: &SharedRwLockReadGuard, writer: &mut W) {
41 let _ = write!(writer, " -> {:?}", self.read(guard).declarations());
42 }
43
44 /// Read the style source guard, and obtain thus read access to the
45 /// underlying property declaration block.
46 #[inline]
47 pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a PropertyDeclarationBlock {
48 self.0.read_with(guard)
49 }
50
51 /// Returns the declaration block if applicable, otherwise None.
52 #[inline]
53 pub fn get(&self) -> &Arc<Locked<PropertyDeclarationBlock>> {
54 &self.0
55 }
56
57 /// Marks this block as part of the rule tree.
58 #[inline]
59 pub fn mark_in_rule_tree(&self) {
60 use std::sync::atomic::Ordering;
61 if self.0.is_static() {
62 // For static pointers, it doesn't matter whether we might be in the rule tree or not,
63 // because those are not mutable.
64 return;
65 }
66 // SAFETY: We're only accessing a relaxed atomic inside the locked object, which we know
67 // is alive. In theory, we could/should track that boolean outside of the
68 // Locked<PropertyDeclarationBlock>, but that is kind of a PITA.
69 #[allow(unsafe_code)]
70 unsafe {
71 self.0
72 .read_unchecked()
73 .immutable
74 .store(true, Ordering::Relaxed);
75 }
76 }
77}