From fe447c88df5d123621040bdca383ebfa15b46988 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sat, 19 Feb 2022 05:38:54 +0530 Subject: [PATCH] feat: support adding raw pointers to ExternalReferences (#901) --- src/external_references.rs | 4 ++- tests/test_api.rs | 53 ++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/external_references.rs b/src/external_references.rs index 90364bcf..646690f4 100644 --- a/src/external_references.rs +++ b/src/external_references.rs @@ -3,15 +3,17 @@ use crate::support::intptr_t; use crate::AccessorNameGetterCallback; use crate::FunctionCallback; use crate::MessageCallback; +use std::os::raw::c_void; #[derive(Clone, Copy)] pub union ExternalReference<'s> { pub function: FunctionCallback, pub getter: AccessorNameGetterCallback<'s>, pub message: MessageCallback, + pub pointer: *mut c_void, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternalReferences { null_terminated: Vec, } diff --git a/tests/test_api.rs b/tests/test_api.rs index 135f4589..a5c3e405 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1946,6 +1946,22 @@ fn proxy() { } } +fn fn_callback_external( + scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut rv: v8::ReturnValue, +) { + assert_eq!(args.length(), 0); + let data = args.data().unwrap(); + let external = v8::Local::::try_from(data).unwrap(); + let data = + unsafe { std::slice::from_raw_parts(external.value() as *mut u8, 5) }; + assert_eq!(&[0, 1, 2, 3, 4], data); + let s = v8::String::new(scope, "Hello callback!").unwrap(); + assert!(rv.get(scope).is_undefined()); + rv.set(s.into()); +} + fn fn_callback( scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, @@ -2934,21 +2950,33 @@ fn snapshot_creator() { } } -lazy_static! { - static ref EXTERNAL_REFERENCES: v8::ExternalReferences = - v8::ExternalReferences::new(&[v8::ExternalReference { - function: fn_callback.map_fn_to() - }]); -} - #[test] fn external_references() { let _setup_guard = setup(); + // Allocate externals for the test. + let external_ptr = Box::into_raw(vec![0_u8, 1, 2, 3, 4].into_boxed_slice()) + as *mut [u8] as *mut c_void; + // Push them to the external reference table. + let refs = v8::ExternalReferences::new(&[ + v8::ExternalReference { + function: fn_callback.map_fn_to(), + }, + v8::ExternalReference { + function: fn_callback_external.map_fn_to(), + }, + v8::ExternalReference { + pointer: external_ptr, + }, + ]); + // TODO(piscisaureus): leaking the `ExternalReferences` collection shouldn't + // be necessary. The reference needs to remain valid for the lifetime of the + // `SnapshotCreator` or `Isolate` that uses it, which would be the case here + // even without leaking. + let refs: &'static v8::ExternalReferences = Box::leak(Box::new(refs)); // First we create the snapshot, there is a single global variable 'a' set to // the value 3. let startup_data = { - let mut snapshot_creator = - v8::SnapshotCreator::new(Some(&EXTERNAL_REFERENCES)); + let mut snapshot_creator = v8::SnapshotCreator::new(Some(refs)); // TODO(ry) this shouldn't be necessary. workaround unfinished business in // the scope type system. let mut isolate = unsafe { snapshot_creator.get_owned_isolate() }; @@ -2958,7 +2986,10 @@ fn external_references() { let scope = &mut v8::ContextScope::new(scope, context); // create function using template - let fn_template = v8::FunctionTemplate::new(scope, fn_callback); + let external = v8::External::new(scope, external_ptr); + let fn_template = v8::FunctionTemplate::builder(fn_callback_external) + .data(external.into()) + .build(scope); let function = fn_template .get_function(scope) .expect("Unable to create function"); @@ -2980,7 +3011,7 @@ fn external_references() { { let params = v8::Isolate::create_params() .snapshot_blob(startup_data) - .external_references(&**EXTERNAL_REFERENCES); + .external_references(&**refs); let isolate = &mut v8::Isolate::new(params); { let scope = &mut v8::HandleScope::new(isolate);