use std::cell::Cell;
thread_local! {
static CSSOM_REENTRY: Cell<bool> = const { Cell::new(false) };
}
pub(crate) struct ReentryGuard {
prev: bool,
}
impl ReentryGuard {
#[inline]
pub(crate) fn enter() -> Self {
let prev = CSSOM_REENTRY.with(|f| f.replace(true));
Self { prev }
}
}
impl Drop for ReentryGuard {
#[inline]
fn drop(&mut self) {
CSSOM_REENTRY.with(|f| f.set(self.prev));
}
}
#[inline]
pub(crate) fn is_in_cssom_write() -> bool {
CSSOM_REENTRY.with(|f| f.get())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_false() {
assert!(!is_in_cssom_write());
}
#[test]
fn guard_sets_flag_inside_scope() {
assert!(!is_in_cssom_write());
{
let _g = ReentryGuard::enter();
assert!(is_in_cssom_write());
}
assert!(!is_in_cssom_write(), "flag must be restored after Drop");
}
#[test]
fn guard_nests_correctly() {
{
let _outer = ReentryGuard::enter();
assert!(is_in_cssom_write());
{
let _inner = ReentryGuard::enter();
assert!(is_in_cssom_write());
}
assert!(is_in_cssom_write());
}
assert!(!is_in_cssom_write());
}
#[test]
fn guard_restores_flag_on_panic() {
let outcome = std::panic::catch_unwind(|| {
let _g = ReentryGuard::enter();
assert!(is_in_cssom_write());
panic!("simulated panic inside CSSOM write");
});
assert!(outcome.is_err(), "expected panic to propagate");
assert!(
!is_in_cssom_write(),
"guard's Drop must clear the flag even on panic"
);
}
}