Skip to content

Commit d44e83d

Browse files
committed
Add path from v8 values to js_value variants
1 parent 63856e5 commit d44e83d

1 file changed

Lines changed: 58 additions & 3 deletions

File tree

src/js_value.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,48 @@ macro_rules! impl_v8 {
1212
($name:ident$(<$generic:ident>)?, $checker:ident $(,)?) => {
1313
impl $(<$generic>)? $name $(<$generic>)? where
1414
$( $generic: serde::de::DeserializeOwned, )? {
15+
/// Consume this struct and return the underlying `V8Value`
16+
#[allow(dead_code)]
17+
pub(crate) fn into_inner(self) -> V8Value<$checker> {
18+
self.0
19+
}
20+
1521
/// Returns the underlying [`crate::deno_core::v8::Global`]
1622
/// This is useful if you want to pass the value to a [`crate::deno_core::JsRuntime`] function directly
1723
#[must_use]
1824
pub fn into_v8(self) -> v8::Global<v8::Value> {
1925
self.0 .0
2026
}
27+
28+
/// Creates a new instance of this struct from a global value
29+
///
30+
/// # Errors
31+
/// Will return an error if the value is the wrong type
32+
/// For `Value`, this check cannot fail
33+
pub fn try_from_v8<'a, H>(
34+
scope: &mut v8::HandleScope<'a>,
35+
value: v8::Global<H>,
36+
) -> Result<Self, crate::Error>
37+
where
38+
v8::Local<'a, v8::Value>: From<v8::Local<'a, H>>,
39+
{
40+
let local: v8::Local<v8::Value> = v8::Local::new(scope, value).into();
41+
v8::Global::new(scope, local).try_into()
42+
}
43+
44+
/// Creates a new instance of this struct from a global value
45+
/// Makes no attempt to check the type of the value
46+
/// This can result in a panic if the value is not of the correct type
47+
///
48+
/// # Safety
49+
/// This function is unsafe because it does not check the type of the value
50+
/// If the value is not of the correct type, a panic will occur
51+
/// It is recommended to use [`Self::try_from_v8`] instead
52+
#[must_use]
53+
pub unsafe fn from_v8_unchecked(value: v8::Global<v8::Value>) -> Self {
54+
let inner = V8Value::<$checker>(value, std::marker::PhantomData);
55+
Self(inner $(, std::marker::PhantomData::<$generic>)?)
56+
}
2157
}
2258
impl<'de$(, $generic)?> serde::Deserialize<'de> for $name $(<$generic>)?
2359
$(where $generic: serde::de::DeserializeOwned,)?
@@ -37,6 +73,15 @@ macro_rules! impl_v8 {
3773
self.0 .0
3874
}
3975
}
76+
77+
impl $(<$generic>)? TryFrom<v8::Global<v8::Value>> for $name $(<$generic>)? $(where $generic: serde::de::DeserializeOwned)? {
78+
type Error = crate::Error;
79+
fn try_from(value: v8::Global<v8::Value>) -> Result<Self, Self::Error> {
80+
<$checker as $crate::js_value::V8TypeChecker>::validate(value.clone())?;
81+
let inner = V8Value::<$checker>(value, std::marker::PhantomData);
82+
Ok(Self(inner $(, std::marker::PhantomData::<$generic>)?))
83+
}
84+
}
4085
};
4186
}
4287

@@ -46,7 +91,7 @@ macro_rules! impl_checker {
4691
#[doc = "Implementations of `V8TypeChecker`"]
4792
#[doc = concat!("Guards for `v8::", stringify!($v8_name), "` values")]
4893
#[derive(Eq, Hash, PartialEq, Debug, Clone, Deserialize)]
49-
struct $name;
94+
pub(crate) struct $name;
5095
impl $crate::js_value::V8TypeChecker for $name {
5196
type Output = v8::$v8_name;
5297
fn validate(value: v8::Global<v8::Value>) -> Result<(), crate::Error> {
@@ -65,7 +110,7 @@ macro_rules! impl_checker {
65110
#[doc = "Implementation of `V8TypeChecker`"]
66111
#[doc = concat!("Guards for `v8::", stringify!($v8_name), "` values")]
67112
#[derive(Eq, Hash, PartialEq, Debug, Clone, Deserialize)]
68-
struct $name;
113+
pub(crate) struct $name;
69114
impl V8TypeChecker for $name {
70115
type Output = v8::$v8_name;
71116
fn validate(_: v8::Global<v8::Value>) -> Result<(), crate::Error> {
@@ -100,7 +145,7 @@ impl_checker!(DefaultTypeChecker, Value);
100145
/// A Deserializable javascript object, that can be stored and used later
101146
/// Must live as long as the runtime it was birthed from
102147
#[derive(Eq, Hash, PartialEq, Debug, Clone)]
103-
struct V8Value<V8TypeChecker>(
148+
pub(crate) struct V8Value<V8TypeChecker>(
104149
v8::Global<v8::Value>,
105150
std::marker::PhantomData<V8TypeChecker>,
106151
);
@@ -192,6 +237,7 @@ mod test {
192237
"test.js",
193238
"
194239
export const f = 42;
240+
export const g = () => 42;
195241
",
196242
);
197243

@@ -201,5 +247,14 @@ mod test {
201247
let f: Value = runtime.get_value(Some(&handle), "f").unwrap();
202248
let value: usize = f.try_into(&mut runtime).unwrap();
203249
assert_eq!(value, 42);
250+
251+
let g: Value = runtime.get_value(Some(&handle), "g").unwrap();
252+
let global = g.into_v8();
253+
let _f = Function::try_from_v8(&mut runtime.deno_runtime().handle_scope(), global.clone())
254+
.unwrap();
255+
let f = unsafe { Function::from_v8_unchecked(global) };
256+
let _f = f
257+
.into_inner()
258+
.as_local(&mut runtime.deno_runtime().handle_scope());
204259
}
205260
}

0 commit comments

Comments
 (0)