use alloc::boxed::Box;
use crate::runtime::with_backend;
pub struct LazyCell<T: 'static> {
init: fn() -> T,
}
impl<T> LazyCell<T> {
#[doc(hidden)]
pub const fn new(init: fn() -> T) -> Self {
Self { init }
}
pub fn force(&'static self) -> &'static T {
let init = self.init;
let value = match with_backend(|runtime| runtime.take_thread_local_box(self)) {
Some(value) => *value.downcast::<&'static T>().expect("type mismatch"),
None => Box::leak(Box::new(init())) as &'static T,
};
with_backend(|runtime| {
runtime.insert_thread_local_box(self, Box::new(value));
});
value
}
}
pub struct JsThreadLocal<T: 'static> {
inner: LazyCell<T>,
}
impl<T> JsThreadLocal<T> {
#[doc(hidden)]
pub const fn new(init: fn() -> T) -> Self {
Self {
inner: LazyCell::new(init),
}
}
pub fn with<F, R>(&'static self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
f(LazyCell::force(&self.inner))
}
}