diff --git a/benches/function.rs b/benches/function.rs index b1b9f8d9..5b2ba9d7 100644 --- a/benches/function.rs +++ b/benches/function.rs @@ -87,7 +87,7 @@ fn main() { rv.set(v8::Integer::new(scope, 42).into()); }, ) - .build_fast(scope, &FastCall, None); + .build_fast(scope, &FastCall, None, None, None); let name = v8::String::new(scope, "new_fast").unwrap(); let value = template.get_function(scope).unwrap(); diff --git a/src/fast_api.rs b/src/fast_api.rs index e2558de3..80c265a2 100644 --- a/src/fast_api.rs +++ b/src/fast_api.rs @@ -30,7 +30,7 @@ pub struct CFunction(Opaque); impl CFunctionInfo { #[inline(always)] - pub(crate) unsafe fn new( + pub unsafe fn new( args: *const CTypeInfo, args_len: usize, return_type: *const CTypeInfo, @@ -45,11 +45,11 @@ pub struct CTypeInfo(Opaque); impl CTypeInfo { #[inline(always)] - pub(crate) fn new(ty: CType) -> NonNull { + pub fn new(ty: CType) -> NonNull { unsafe { NonNull::new_unchecked(v8__CTypeInfo__New(ty)) } } - pub(crate) fn new_from_slice(types: &[Type]) -> NonNull { + pub fn new_from_slice(types: &[Type]) -> NonNull { let mut structs = vec![]; for type_ in types.iter() { diff --git a/src/template.rs b/src/template.rs index 2b037b11..e1197b07 100644 --- a/src/template.rs +++ b/src/template.rs @@ -372,27 +372,50 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> { .unwrap() } + /// It's not required to provide `CFunctionInfo` for the overloads - if they + /// are omitted, then they will be automatically created. In some cases it is + /// useful to pass them explicitly - eg. when you are snapshotting you'd provide + /// the overloads and `CFunctionInfo` that would be placed in the external + /// references array. pub fn build_fast( self, scope: &mut HandleScope<'s, ()>, overload1: &dyn FastFunction, + c_fn_info1: Option<*const CFunctionInfo>, overload2: Option<&dyn FastFunction>, + c_fn_info2: Option<*const CFunctionInfo>, ) -> Local<'s, FunctionTemplate> { - unsafe { + let c_fn1 = if let Some(fn_info) = c_fn_info1 { + fn_info + } else { let args = CTypeInfo::new_from_slice(overload1.args()); let ret = CTypeInfo::new(overload1.return_type()); - let c_fn1 = - CFunctionInfo::new(args.as_ptr(), overload1.args().len(), ret.as_ptr()); - - let c_fn2 = match overload2 { - Some(overload) => { - let args = CTypeInfo::new_from_slice(overload.args()); - let ret = CTypeInfo::new(overload.return_type()); - CFunctionInfo::new(args.as_ptr(), overload.args().len(), ret.as_ptr()) - .as_ptr() - } - None => null(), + let fn_info = unsafe { + CFunctionInfo::new(args.as_ptr(), overload1.args().len(), ret.as_ptr()) }; + fn_info.as_ptr() + }; + + let c_fn2 = if let Some(overload2) = overload2 { + if let Some(fn_info) = c_fn_info2 { + fn_info + } else { + let args = CTypeInfo::new_from_slice(overload2.args()); + let ret = CTypeInfo::new(overload2.return_type()); + let fn_info = unsafe { + CFunctionInfo::new( + args.as_ptr(), + overload2.args().len(), + ret.as_ptr(), + ) + }; + fn_info.as_ptr() + } + } else { + null() + }; + + unsafe { scope.cast_local(|sd| { v8__FunctionTemplate__New( sd.get_isolate_ptr(), @@ -403,7 +426,7 @@ impl<'s> FunctionBuilder<'s, FunctionTemplate> { ConstructorBehavior::Throw, self.side_effect_type, overload1.function(), - c_fn1.as_ptr(), + c_fn1, overload2.map_or(null(), |f| f.function()), c_fn2, ) diff --git a/tests/test_api.rs b/tests/test_api.rs index 9639f9c3..f1b3d8e3 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -8268,8 +8268,8 @@ fn test_fast_calls() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8341,8 +8341,8 @@ fn test_fast_calls_sequence() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8414,8 +8414,8 @@ fn test_fast_calls_arraybuffer() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8490,8 +8490,8 @@ fn test_fast_calls_typedarray() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8580,8 +8580,8 @@ fn test_fast_calls_reciever() { embedder_obj as _, ); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "method").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8674,7 +8674,9 @@ fn test_fast_calls_overload() { let template = v8::FunctionTemplate::builder(slow_fn).build_fast( scope, &FastTest, + None, Some(&FastTest2), + None, ); let name = v8::String::new(scope, "func").unwrap(); @@ -8748,8 +8750,8 @@ fn test_fast_calls_callback_options_fallback() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8824,7 +8826,7 @@ fn test_fast_calls_callback_options_data() { let template = v8::FunctionTemplate::builder(slow_fn) .data(external.into()) - .build_fast(scope, &FastTest, None); + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -8936,8 +8938,8 @@ fn test_fast_calls_onebytestring() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap(); @@ -9076,8 +9078,8 @@ fn test_fast_calls_pointer() { let global = context.global(scope); - let template = - v8::FunctionTemplate::builder(slow_fn).build_fast(scope, &FastTest, None); + let template = v8::FunctionTemplate::builder(slow_fn) + .build_fast(scope, &FastTest, None, None, None); let name = v8::String::new(scope, "func").unwrap(); let value = template.get_function(scope).unwrap();