summaryrefslogtreecommitdiff
path: root/ext/ffi/call.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi/call.rs')
-rw-r--r--ext/ffi/call.rs75
1 files changed, 46 insertions, 29 deletions
diff --git a/ext/ffi/call.rs b/ext/ffi/call.rs
index 3572b9e81..bbff0ee48 100644
--- a/ext/ffi/call.rs
+++ b/ext/ffi/call.rs
@@ -7,23 +7,38 @@ use crate::symbol::NativeType;
use crate::symbol::Symbol;
use crate::FfiPermissions;
use crate::ForeignFunction;
-use deno_core::anyhow::anyhow;
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::serde_json::Value;
+use deno_core::serde_v8::BigInt as V8BigInt;
use deno_core::serde_v8::ExternalPointer;
use deno_core::unsync::spawn_blocking;
use deno_core::v8;
use deno_core::OpState;
use deno_core::ResourceId;
use libffi::middle::Arg;
+use num_bigint::BigInt;
use serde::Serialize;
use std::cell::RefCell;
use std::ffi::c_void;
use std::future::Future;
use std::rc::Rc;
+#[derive(Debug, thiserror::Error)]
+pub enum CallError {
+ #[error(transparent)]
+ IR(#[from] IRError),
+ #[error("Nonblocking FFI call failed: {0}")]
+ NonblockingCallFailure(#[source] tokio::task::JoinError),
+ #[error("Invalid FFI symbol name: '{0}'")]
+ InvalidSymbol(String),
+ #[error(transparent)]
+ Permission(#[from] deno_permissions::PermissionCheckError),
+ #[error(transparent)]
+ Resource(deno_core::error::AnyError),
+ #[error(transparent)]
+ Callback(#[from] super::CallbackError),
+}
+
// SAFETY: Makes an FFI call
unsafe fn ffi_call_rtype_struct(
cif: &libffi::middle::Cif,
@@ -45,7 +60,7 @@ pub(crate) fn ffi_call_sync<'scope>(
args: v8::FunctionCallbackArguments,
symbol: &Symbol,
out_buffer: Option<OutBuffer>,
-) -> Result<NativeValue, AnyError>
+) -> Result<NativeValue, CallError>
where
'scope: 'scope,
{
@@ -191,6 +206,7 @@ where
#[serde(untagged)]
pub enum FfiValue {
Value(Value),
+ BigInt(V8BigInt),
External(ExternalPointer),
}
@@ -201,7 +217,7 @@ fn ffi_call(
parameter_types: &[NativeType],
result_type: NativeType,
out_buffer: Option<OutBuffer>,
-) -> Result<FfiValue, AnyError> {
+) -> FfiValue {
let call_args: Vec<Arg> = call_args
.iter()
.enumerate()
@@ -214,7 +230,7 @@ fn ffi_call(
// SAFETY: types in the `Cif` match the actual calling convention and
// types of symbol.
unsafe {
- Ok(match result_type {
+ match result_type {
NativeType::Void => {
cif.call::<()>(fun_ptr, &call_args);
FfiValue::Value(Value::from(()))
@@ -240,18 +256,18 @@ fn ffi_call(
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::U64 => FfiValue::BigInt(V8BigInt::from(BigInt::from(
+ cif.call::<u64>(fun_ptr, &call_args),
+ ))),
+ NativeType::I64 => FfiValue::BigInt(V8BigInt::from(BigInt::from(
+ cif.call::<i64>(fun_ptr, &call_args),
+ ))),
+ NativeType::USize => FfiValue::BigInt(V8BigInt::from(BigInt::from(
+ cif.call::<usize>(fun_ptr, &call_args),
+ ))),
+ NativeType::ISize => FfiValue::BigInt(V8BigInt::from(BigInt::from(
+ cif.call::<isize>(fun_ptr, &call_args),
+ ))),
NativeType::F32 => {
FfiValue::Value(Value::from(cif.call::<f32>(fun_ptr, &call_args)))
}
@@ -267,7 +283,7 @@ fn ffi_call(
ffi_call_rtype_struct(cif, &fun_ptr, call_args, out_buffer.unwrap().0);
FfiValue::Value(Value::Null)
}
- })
+ }
}
}
@@ -280,7 +296,7 @@ pub fn op_ffi_call_ptr_nonblocking<FP>(
#[serde] def: ForeignFunction,
parameters: v8::Local<v8::Array>,
out_buffer: Option<v8::Local<v8::TypedArray>>,
-) -> Result<impl Future<Output = Result<FfiValue, AnyError>>, AnyError>
+) -> Result<impl Future<Output = Result<FfiValue, CallError>>, CallError>
where
FP: FfiPermissions + 'static,
{
@@ -309,7 +325,7 @@ where
Ok(async move {
let result = join_handle
.await
- .map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??;
+ .map_err(CallError::NonblockingCallFailure)?;
// SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
Ok(result)
})
@@ -325,16 +341,17 @@ pub fn op_ffi_call_nonblocking(
#[string] symbol: String,
parameters: v8::Local<v8::Array>,
out_buffer: Option<v8::Local<v8::TypedArray>>,
-) -> Result<impl Future<Output = Result<FfiValue, AnyError>>, AnyError> {
+) -> Result<impl Future<Output = Result<FfiValue, CallError>>, CallError> {
let symbol = {
let state = state.borrow();
- let resource = state.resource_table.get::<DynamicLibraryResource>(rid)?;
+ let resource = state
+ .resource_table
+ .get::<DynamicLibraryResource>(rid)
+ .map_err(CallError::Resource)?;
let symbols = &resource.symbols;
*symbols
.get(&symbol)
- .ok_or_else(|| {
- type_error(format!("Invalid FFI symbol name: '{symbol}'"))
- })?
+ .ok_or_else(|| CallError::InvalidSymbol(symbol))?
.clone()
};
@@ -362,7 +379,7 @@ pub fn op_ffi_call_nonblocking(
Ok(async move {
let result = join_handle
.await
- .map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??;
+ .map_err(CallError::NonblockingCallFailure)?;
// SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
Ok(result)
})
@@ -377,7 +394,7 @@ pub fn op_ffi_call_ptr<FP>(
#[serde] def: ForeignFunction,
parameters: v8::Local<v8::Array>,
out_buffer: Option<v8::Local<v8::TypedArray>>,
-) -> Result<FfiValue, AnyError>
+) -> Result<FfiValue, CallError>
where
FP: FfiPermissions + 'static,
{
@@ -399,7 +416,7 @@ where
&def.parameters,
def.result.clone(),
out_buffer_ptr,
- )?;
+ );
// SAFETY: Same return type declared to libffi; trust user to have it right beyond that.
Ok(result)
}