summaryrefslogtreecommitdiff
path: root/ext/ffi/call.rs
diff options
context:
space:
mode:
authorAapo Alasuutari <aapo.alasuutari@gmail.com>2023-02-22 19:32:38 +0200
committerGitHub <noreply@github.com>2023-02-22 19:32:38 +0200
commitb56b8c8a753442036ace3bb0f4403c952f18d408 (patch)
tree675c47da4847a754cf2cc3cb664dc8047944246d /ext/ffi/call.rs
parent2bd7482295daae4edfd367d84505bb43735cd410 (diff)
feat(ext/ffi): Replace pointer integers with v8::External objects (#16889)
Diffstat (limited to 'ext/ffi/call.rs')
-rw-r--r--ext/ffi/call.rs140
1 files changed, 75 insertions, 65 deletions
diff --git a/ext/ffi/call.rs b/ext/ffi/call.rs
index 731460af9..8a9b393c3 100644
--- a/ext/ffi/call.rs
+++ b/ext/ffi/call.rs
@@ -14,9 +14,11 @@ use deno_core::error::AnyError;
use deno_core::op;
use deno_core::serde_json::Value;
use deno_core::serde_v8;
+use deno_core::serde_v8::ExternalPointer;
use deno_core::v8;
use deno_core::ResourceId;
use libffi::middle::Arg;
+use serde::Serialize;
use std::cell::RefCell;
use std::ffi::c_void;
use std::future::Future;
@@ -28,14 +30,13 @@ unsafe fn ffi_call_rtype_struct(
fn_ptr: &libffi::middle::CodePtr,
call_args: Vec<Arg>,
out_buffer: *mut u8,
-) -> NativeValue {
+) {
libffi::raw::ffi_call(
cif.as_raw_ptr(),
Some(*fn_ptr.as_safe_fun()),
out_buffer as *mut c_void,
call_args.as_ptr() as *mut *mut c_void,
);
- NativeValue { void_value: () }
}
// A one-off synchronous FFI call.
@@ -174,16 +175,25 @@ where
pointer: cif.call::<*mut c_void>(*fun_ptr, &call_args),
}
}
- NativeType::Struct(_) => ffi_call_rtype_struct(
- &symbol.cif,
- &symbol.ptr,
- call_args,
- out_buffer.unwrap().0,
- ),
+ NativeType::Struct(_) => NativeValue {
+ void_value: ffi_call_rtype_struct(
+ &symbol.cif,
+ &symbol.ptr,
+ call_args,
+ out_buffer.unwrap().0,
+ ),
+ },
})
}
}
+#[derive(Serialize)]
+#[serde(untagged)]
+pub enum FfiValue {
+ Value(Value),
+ External(ExternalPointer),
+}
+
fn ffi_call(
call_args: Vec<NativeValue>,
cif: &libffi::middle::Cif,
@@ -191,7 +201,7 @@ fn ffi_call(
parameter_types: &[NativeType],
result_type: NativeType,
out_buffer: Option<OutBuffer>,
-) -> Result<NativeValue, AnyError> {
+) -> Result<FfiValue, AnyError> {
let call_args: Vec<Arg> = call_args
.iter()
.enumerate()
@@ -205,55 +215,57 @@ fn ffi_call(
// types of symbol.
unsafe {
Ok(match result_type {
- NativeType::Void => NativeValue {
- void_value: cif.call::<()>(fun_ptr, &call_args),
- },
- NativeType::Bool => NativeValue {
- bool_value: cif.call::<bool>(fun_ptr, &call_args),
- },
- NativeType::U8 => NativeValue {
- u8_value: cif.call::<u8>(fun_ptr, &call_args),
- },
- NativeType::I8 => NativeValue {
- i8_value: cif.call::<i8>(fun_ptr, &call_args),
- },
- NativeType::U16 => NativeValue {
- u16_value: cif.call::<u16>(fun_ptr, &call_args),
- },
- NativeType::I16 => NativeValue {
- i16_value: cif.call::<i16>(fun_ptr, &call_args),
- },
- NativeType::U32 => NativeValue {
- u32_value: cif.call::<u32>(fun_ptr, &call_args),
- },
- NativeType::I32 => NativeValue {
- i32_value: cif.call::<i32>(fun_ptr, &call_args),
- },
- NativeType::U64 => NativeValue {
- u64_value: cif.call::<u64>(fun_ptr, &call_args),
- },
- NativeType::I64 => NativeValue {
- i64_value: cif.call::<i64>(fun_ptr, &call_args),
- },
- NativeType::USize => NativeValue {
- usize_value: cif.call::<usize>(fun_ptr, &call_args),
- },
- NativeType::ISize => NativeValue {
- isize_value: cif.call::<isize>(fun_ptr, &call_args),
- },
- NativeType::F32 => NativeValue {
- f32_value: cif.call::<f32>(fun_ptr, &call_args),
- },
- NativeType::F64 => NativeValue {
- f64_value: cif.call::<f64>(fun_ptr, &call_args),
- },
+ NativeType::Void => {
+ cif.call::<()>(fun_ptr, &call_args);
+ FfiValue::Value(Value::from(()))
+ }
+ NativeType::Bool => {
+ FfiValue::Value(Value::from(cif.call::<bool>(fun_ptr, &call_args)))
+ }
+ NativeType::U8 => {
+ FfiValue::Value(Value::from(cif.call::<u8>(fun_ptr, &call_args)))
+ }
+ NativeType::I8 => {
+ FfiValue::Value(Value::from(cif.call::<i8>(fun_ptr, &call_args)))
+ }
+ NativeType::U16 => {
+ FfiValue::Value(Value::from(cif.call::<u16>(fun_ptr, &call_args)))
+ }
+ NativeType::I16 => {
+ FfiValue::Value(Value::from(cif.call::<i16>(fun_ptr, &call_args)))
+ }
+ NativeType::U32 => {
+ FfiValue::Value(Value::from(cif.call::<u32>(fun_ptr, &call_args)))
+ }
+ NativeType::I32 => {
+ FfiValue::Value(Value::from(cif.call::<i32>(fun_ptr, &call_args)))
+ }
+ NativeType::U64 => {
+ FfiValue::Value(Value::from(cif.call::<u64>(fun_ptr, &call_args)))
+ }
+ NativeType::I64 => {
+ FfiValue::Value(Value::from(cif.call::<i64>(fun_ptr, &call_args)))
+ }
+ NativeType::USize => {
+ FfiValue::Value(Value::from(cif.call::<usize>(fun_ptr, &call_args)))
+ }
+ NativeType::ISize => {
+ FfiValue::Value(Value::from(cif.call::<isize>(fun_ptr, &call_args)))
+ }
+ NativeType::F32 => {
+ FfiValue::Value(Value::from(cif.call::<f32>(fun_ptr, &call_args)))
+ }
+ NativeType::F64 => {
+ FfiValue::Value(Value::from(cif.call::<f64>(fun_ptr, &call_args)))
+ }
NativeType::Pointer | NativeType::Function | NativeType::Buffer => {
- NativeValue {
- pointer: cif.call::<*mut c_void>(fun_ptr, &call_args),
- }
+ FfiValue::External(ExternalPointer::from(
+ cif.call::<*mut c_void>(fun_ptr, &call_args),
+ ))
}
NativeType::Struct(_) => {
- ffi_call_rtype_struct(cif, &fun_ptr, call_args, out_buffer.unwrap().0)
+ ffi_call_rtype_struct(cif, &fun_ptr, call_args, out_buffer.unwrap().0);
+ FfiValue::Value(Value::Null)
}
})
}
@@ -263,11 +275,11 @@ fn ffi_call(
pub fn op_ffi_call_ptr_nonblocking<'scope, FP>(
scope: &mut v8::HandleScope<'scope>,
state: Rc<RefCell<deno_core::OpState>>,
- pointer: usize,
+ pointer: *mut c_void,
def: ForeignFunction,
parameters: serde_v8::Value<'scope>,
out_buffer: Option<serde_v8::Value<'scope>>,
-) -> Result<impl Future<Output = Result<Value, AnyError>>, AnyError>
+) -> Result<impl Future<Output = Result<FfiValue, AnyError>>, AnyError>
where
FP: FfiPermissions + 'static,
{
@@ -280,7 +292,6 @@ where
let symbol = PtrSymbol::new(pointer, &def)?;
let call_args = ffi_parse_args(scope, parameters, &def.parameters)?;
- let def_result = def.result.clone();
let out_buffer = out_buffer
.map(|v| v8::Local::<v8::TypedArray>::try_from(v.v8_value).unwrap());
@@ -303,7 +314,7 @@ where
.await
.map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??;
// SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
- Ok(unsafe { result.to_value(def_result) })
+ Ok(result)
})
}
@@ -316,7 +327,8 @@ pub fn op_ffi_call_nonblocking<'scope>(
symbol: String,
parameters: serde_v8::Value<'scope>,
out_buffer: Option<serde_v8::Value<'scope>>,
-) -> Result<impl Future<Output = Result<Value, AnyError>> + 'static, AnyError> {
+) -> Result<impl Future<Output = Result<FfiValue, AnyError>> + 'static, AnyError>
+{
let symbol = {
let state = state.borrow();
let resource = state.resource_table.get::<DynamicLibraryResource>(rid)?;
@@ -332,7 +344,6 @@ pub fn op_ffi_call_nonblocking<'scope>(
.map(|v| v8::Local::<v8::TypedArray>::try_from(v.v8_value).unwrap());
let out_buffer_ptr = out_buffer_as_ptr(scope, out_buffer);
- let result_type = symbol.result_type.clone();
let join_handle = tokio::task::spawn_blocking(move || {
let Symbol {
cif,
@@ -356,7 +367,7 @@ pub fn op_ffi_call_nonblocking<'scope>(
.await
.map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??;
// SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
- Ok(unsafe { result.to_value(result_type) })
+ Ok(result)
})
}
@@ -364,11 +375,11 @@ pub fn op_ffi_call_nonblocking<'scope>(
pub fn op_ffi_call_ptr<FP, 'scope>(
scope: &mut v8::HandleScope<'scope>,
state: Rc<RefCell<deno_core::OpState>>,
- pointer: usize,
+ pointer: *mut c_void,
def: ForeignFunction,
parameters: serde_v8::Value<'scope>,
out_buffer: Option<serde_v8::Value<'scope>>,
-) -> Result<serde_v8::Value<'scope>, AnyError>
+) -> Result<FfiValue, AnyError>
where
FP: FfiPermissions + 'static,
{
@@ -395,6 +406,5 @@ where
out_buffer_ptr,
)?;
// SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
- let result = unsafe { result.to_v8(scope, def.result) };
Ok(result)
}