@@ -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