Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
Rust
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091//! Interior-mutable storage for Stylo's per-element style slot. Adapted from Blitz's//! `blitz-dom/src/node/stylo_data.rs` (Apache-2.0): hand-directed scaffolding, not//! generated code.//!//! An `UnsafeCell` rather than a `RefCell`: the `ElementDataRef`/`ElementDataMut`//! wrappers Stylo hands back do not carry the borrow guard that would keep a//! `RefCell`'s runtime check honest across the call, so wrapping them in one would//! either leak the borrow count or need the same unsafe code one layer further in.//! Safety instead rests on the traversal invariant this project takes from Stylo//! (`roadmap.md` -> "DOM layer, shaped by Stylo"): a style traversal has exclusive//! access to the tree, and `ensure_init`/`clear` are only ever called from inside one.
use std::cell::UnsafeCell;use std::fmt;use std::ops::{Deref, DerefMut};
use style::data::{ElementDataMut, ElementDataRef, ElementDataWrapper};use style::selector_parser::RestyleDamage;
pub struct StyloData { inner: UnsafeCell<Option<ElementDataWrapper>>,}
impl Default for StyloData { fn default() -> Self { Self { inner: UnsafeCell::new(None) } }}
impl fmt::Debug for StyloData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("StyloData").finish_non_exhaustive() }}
impl Deref for StyloData { type Target = Option<ElementDataWrapper>; fn deref(&self) -> &Self::Target { // SAFETY: `&self` here borrows the `StyloData`, and every other access in // this file requires at least that same borrow, so this cannot alias a `&mut`. unsafe { &*self.inner.get() } }}
impl DerefMut for StyloData { fn deref_mut(&mut self) -> &mut Self::Target { self.inner.get_mut() }}
impl StyloData { pub fn has_data(&self) -> bool { self.deref().is_some() }
pub fn get(&self) -> Option<ElementDataRef<'_>> { self.deref().as_ref().map(|w| w.borrow()) }
/// Get a mutable reference to the data. /// /// SAFETY: there must be no outstanding borrow of this container, or of anything /// borrowed from it via [`get`](Self::get), when this is called. pub unsafe fn get_mut_unchecked(&self) -> Option<ElementDataMut<'_>> { let opt = unsafe { &mut *self.inner.get() }; opt.as_mut().map(|w| w.borrow_mut()) }
/// Initialize the element data if it is not already initialized, and return a /// mutable borrow either way. /// /// SAFETY: same as [`get_mut_unchecked`](Self::get_mut_unchecked). pub unsafe fn ensure_init(&self) -> ElementDataMut<'_> { if !self.has_data() { unsafe { *self.inner.get() = Some(ElementDataWrapper::default()) }; let mut data = unsafe { self.get_mut_unchecked() }.expect("just initialized"); data.damage = RestyleDamage::reconstruct(); data } else { unsafe { self.get_mut_unchecked() }.expect("has_data() just returned true") } }
/// Clear the element data, returning to the uninitialized state. /// /// SAFETY: same as [`get_mut_unchecked`](Self::get_mut_unchecked). pub unsafe fn clear(&self) { unsafe { *self.inner.get() = None }; }}