Skip to content

Commit

Permalink
Global root is a little better, still weird though
Browse files Browse the repository at this point in the history
  • Loading branch information
alshdavid committed Jun 25, 2024
1 parent ae96111 commit 6e6c683
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 55 deletions.
108 changes: 55 additions & 53 deletions crates/neon/src/handle/root_global.rs
Original file line number Diff line number Diff line change
@@ -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<Root<JsSymbol>> = OnceCell::default();
}

/// Reference counted JavaScript value with a static lifetime for use in async closures
pub struct RootGlobal<T> {
pub(crate) count: Rc<RefCell<u32>>,
pub(crate) inner: Rc<*mut Value__>,
pub(crate) inner: Rc<String>,
_p: PhantomData<T>,
}

Expand All @@ -45,19 +40,31 @@ impl<T: Value> RootGlobal<T> {
})
}

pub fn clone<'a>(&self, cx: impl Context<'a>) -> Result<RootGlobal<T>, ()> {
todo!();
pub fn clone<'a>(&self) -> RootGlobal<T> {
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(())
}
}

Expand All @@ -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::<JsFunction, _, _>(cx, "Symbol")?;
let set_ctor = global_this.get::<JsFunction, _, _>(cx, "Set")?;

.get_or_try_init(|| -> NeonResult<Root<JsSymbol>> {
let set_ctor = global_this.get::<JsFunction, _, _>(cx, "Map")?;
let neon_cache = set_ctor.construct(cx, &[])?;

let key = cx.string(KEY_NEON_CACHE);
let symbol: Handle<JsValue> = 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::<JsObject, _, _>(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<String> {
let neon_cache = get_cache(cx)?;
let value_raw = value.to_local();
let key = format!("{:?}", value.to_local());

get_cache(cx)?
.get::<JsFunction, _, _>(cx, "add")?
.get::<JsFunction, _, _>(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::<JsFunction, _, _>(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::<JsFunction, _, _>(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::<JsObject>("console")
.unwrap()
.get::<JsFunction, _, _>(cx, "log")
.unwrap()
.call_with(cx)
.arg(*v)
.exec(cx)
.unwrap();
}
5 changes: 5 additions & 0 deletions crates/neon/src/sys/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions crates/neon/src/types_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,7 @@ impl ValueInternal for JsSymbol {
}

fn is_typeof<Other: Value>(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 {
Expand Down

0 comments on commit 6e6c683

Please sign in to comment.