From 6e6c683dc8e17bb8cc9273384d0a2328e7098ab1 Mon Sep 17 00:00:00 2001 From: David Alsh Date: Tue, 25 Jun 2024 14:03:19 +1000 Subject: [PATCH] Global root is a little better, still weird though --- crates/neon/src/handle/root_global.rs | 108 +++++++++++++------------- crates/neon/src/sys/tag.rs | 5 ++ crates/neon/src/types_impl/mod.rs | 3 +- 3 files changed, 61 insertions(+), 55 deletions(-) diff --git a/crates/neon/src/handle/root_global.rs b/crates/neon/src/handle/root_global.rs index 8213ce2c1..6c8e25ac6 100644 --- a/crates/neon/src/handle/root_global.rs +++ b/crates/neon/src/handle/root_global.rs @@ -1,35 +1,30 @@ -use once_cell::unsync::Lazy; use once_cell::unsync::OnceCell; use std::cell::RefCell; use std::marker::PhantomData; use std::rc::Rc; -use super::TransparentNoCopyWrapper; +use super::Root; use super::Value; use crate::context::Context; use crate::object::Object; use crate::prelude::Handle; use crate::result::JsResult; use crate::result::NeonResult; -use crate::sys::Value__; -use crate::types::private::ValueInternal; -use crate::types::JsError; use crate::types::JsFunction; -use crate::types::JsNumber; use crate::types::JsObject; -use crate::types::JsValue; +use crate::types::JsSymbol; static KEY_NEON_CACHE: &str = "__neon_cache"; thread_local! { // Symbol("__neon_cache") - static CACHE_SYMBOL: OnceCell<*mut Value__> = OnceCell::default(); + static CACHE_SYMBOL: OnceCell> = OnceCell::default(); } /// Reference counted JavaScript value with a static lifetime for use in async closures pub struct RootGlobal { pub(crate) count: Rc>, - pub(crate) inner: Rc<*mut Value__>, + pub(crate) inner: Rc, _p: PhantomData, } @@ -45,19 +40,31 @@ impl RootGlobal { }) } - pub fn clone<'a>(&self, cx: impl Context<'a>) -> Result, ()> { - todo!(); + pub fn clone<'a>(&self) -> RootGlobal { + let mut count = self.count.borrow_mut(); + *count += 1; + drop(count); + + Self { + count: self.count.clone(), + inner: self.inner.clone(), + _p: self._p.clone(), + } } - pub fn deref<'a>(&self, cx: &mut impl Context<'a>) -> JsResult<'a, T> { - // TODO error handling - let env_raw = cx.env(); - let hydrated = unsafe { T::from_local(env_raw, *self.inner) }; - Ok(Handle::new_internal(hydrated)) + pub fn into_inner<'a>(&self, cx: &mut impl Context<'a>) -> JsResult<'a, T> { + get_ref(cx, &*self.inner) } - pub fn drop<'a>(&self, cx: impl Context<'a>) -> Result<(), ()> { - todo!(); + pub fn drop<'a>(&self, cx: &mut impl Context<'a>) -> NeonResult<()> { + let mut count = self.count.borrow_mut(); + *count -= 1; + + if *count == 0 { + delete_ref(cx, &*self.inner)? + } + + Ok(()) } } @@ -72,74 +79,69 @@ fn get_cache<'a>(cx: &mut impl Context<'a>) -> JsResult<'a, JsObject> { let neon_cache_symbol = CACHE_SYMBOL.with({ |raw_value| { raw_value - .get_or_try_init(|| -> NeonResult<*mut Value__> { - let symbol_ctor = global_this.get::(cx, "Symbol")?; - let set_ctor = global_this.get::(cx, "Set")?; - + .get_or_try_init(|| -> NeonResult> { + let set_ctor = global_this.get::(cx, "Map")?; let neon_cache = set_ctor.construct(cx, &[])?; - let key = cx.string(KEY_NEON_CACHE); - let symbol: Handle = symbol_ctor.call_with(cx).arg(key).apply(cx)?; - let symbol_raw = symbol.to_local(); + let symbol = cx.symbol(KEY_NEON_CACHE); + let symbol = symbol.root(cx); - global_this.set(cx, symbol, neon_cache)?; + { + let symbol = symbol.clone(cx); + let symbol = symbol.into_inner(cx); + global_this.set(cx, symbol, neon_cache)?; + } - Ok(symbol_raw) + Ok(symbol) }) - .cloned() + .and_then(|e| Ok(e.clone(cx))) } })?; - let neon_cache_symbol = - Handle::new_internal(unsafe { JsValue::from_local(cx.env(), neon_cache_symbol) }); + let neon_cache_symbol = neon_cache_symbol.into_inner(cx); let Some(neon_cache) = global_this.get_opt::(cx, neon_cache_symbol)? else { return Err(cx.throw_error("Unable to find cache")?); }; - console_log(cx, &neon_cache); - console_log(cx, &neon_cache_symbol); - Ok(neon_cache) } -fn set_ref<'a, V: Value>( - cx: &mut impl Context<'a>, - value: Handle<'a, V>, -) -> NeonResult<*mut Value__> { +fn set_ref<'a, V: Value>(cx: &mut impl Context<'a>, value: Handle<'a, V>) -> NeonResult { let neon_cache = get_cache(cx)?; - let value_raw = value.to_local(); + let key = format!("{:?}", value.to_local()); get_cache(cx)? - .get::(cx, "add")? + .get::(cx, "set")? .call_with(cx) .this(neon_cache) + .arg(cx.string(&key)) .arg(value) .exec(cx)?; - Ok(value_raw) + Ok(key) +} + +fn get_ref<'a, V: Value>(cx: &mut impl Context<'a>, key: &str) -> JsResult<'a, V> { + let neon_cache = get_cache(cx)?; + + get_cache(cx)? + .get::(cx, "get")? + .call_with(cx) + .this(neon_cache) + .arg(cx.string(&key)) + .apply(cx) } -fn delete_ref<'a, V: Value>(cx: &mut impl Context<'a>, value: Handle<'a, V>) -> NeonResult<()> { +fn delete_ref<'a>(cx: &mut impl Context<'a>, key: &str) -> NeonResult<()> { let neon_cache = get_cache(cx)?; get_cache(cx)? .get::(cx, "delete")? .call_with(cx) .this(neon_cache) - .arg(value) + .arg(cx.string(&key)) .exec(cx)?; Ok(()) } - -fn console_log<'a, V: Value>(cx: &mut impl Context<'a>, v: &Handle<'a, V>) { - cx.global::("console") - .unwrap() - .get::(cx, "log") - .unwrap() - .call_with(cx) - .arg(*v) - .exec(cx) - .unwrap(); -} diff --git a/crates/neon/src/sys/tag.rs b/crates/neon/src/sys/tag.rs index 91b2266a6..b918611b6 100644 --- a/crates/neon/src/sys/tag.rs +++ b/crates/neon/src/sys/tag.rs @@ -31,6 +31,11 @@ pub unsafe fn is_boolean(env: Env, val: Local) -> bool { is_type(env, val, napi::ValueType::Boolean) } +/// Is `val` a JavaScript symbol? +pub unsafe fn is_symbol(env: Env, val: Local) -> bool { + is_type(env, val, napi::ValueType::Symbol) +} + /// Is `val` a JavaScript string? pub unsafe fn is_string(env: Env, val: Local) -> bool { is_type(env, val, napi::ValueType::String) diff --git a/crates/neon/src/types_impl/mod.rs b/crates/neon/src/types_impl/mod.rs index efc0e837e..167c09bd8 100644 --- a/crates/neon/src/types_impl/mod.rs +++ b/crates/neon/src/types_impl/mod.rs @@ -434,8 +434,7 @@ impl ValueInternal for JsSymbol { } fn is_typeof(env: Env, other: &Other) -> bool { - true - // unsafe { sys::tag::is_string(env.to_raw(), other.to_local()) } + unsafe { sys::tag::is_symbol(env.to_raw(), other.to_local()) } } fn to_local(&self) -> raw::Local {