mirror of
https://github.com/denoland/deno.git
synced 2025-03-05 18:37:20 -05:00

Now that ArrayBuffer/ArrayBufferView is a generic Value type, we have to handle it being passed any value. To do this, thread FastApiCallbackOptions through the function, and add error raising logic. If we run conversion and the value is not valid, we return `isize::MAX`, and then in cranelift we use this value to know that we should branch to the error logic. An example compilation looks like this: ```rust extern "C" fn print_buffer(ptr: *const u8, len: usize); ``` ```clif function %print_buffer_wrapper(i64, i64, i64, i64) system_v { sig0 = (i64, i64) system_v sig1 = (i64) -> i64 system_v sig2 = (i64) system_v block0(v0: i64, v1: i64, v2: i64, v3: i64): v4 = iconst.i64 0x6525_9198_2d00 ; turbocall_ab_contents v5 = call_indirect sig1, v4(v1) v6 = iconst.i64 0x7fff_ffff_ffff_ffff v7 = icmp eq v5, v6 brif v7, block1, block2 block2: v8 = iconst.i64 0x7558_4c0c_0700 ; sym.ptr call_indirect sig0, v8(v5, v2) return block1 cold: v9 = iconst.i64 0x6525_9198_2d70 ; turbocall_raise call_indirect sig2, v9(v3) return } ``` Also cleaned up all the `unwrap`s and added some logging.
81 lines
2.3 KiB
Rust
81 lines
2.3 KiB
Rust
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
|
|
use deno_error::JsErrorBox;
|
|
|
|
/// Defines the accepted types that can be used as
|
|
/// parameters and return values in FFI.
|
|
#[derive(Clone, Debug, serde::Deserialize, Eq, PartialEq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum NativeType {
|
|
Void,
|
|
Bool,
|
|
U8,
|
|
I8,
|
|
U16,
|
|
I16,
|
|
U32,
|
|
I32,
|
|
U64,
|
|
I64,
|
|
USize,
|
|
ISize,
|
|
F32,
|
|
F64,
|
|
Pointer,
|
|
Buffer,
|
|
Function,
|
|
Struct(Box<[NativeType]>),
|
|
}
|
|
|
|
impl TryFrom<NativeType> for libffi::middle::Type {
|
|
type Error = JsErrorBox;
|
|
|
|
fn try_from(native_type: NativeType) -> Result<Self, Self::Error> {
|
|
Ok(match native_type {
|
|
NativeType::Void => libffi::middle::Type::void(),
|
|
NativeType::U8 | NativeType::Bool => libffi::middle::Type::u8(),
|
|
NativeType::I8 => libffi::middle::Type::i8(),
|
|
NativeType::U16 => libffi::middle::Type::u16(),
|
|
NativeType::I16 => libffi::middle::Type::i16(),
|
|
NativeType::U32 => libffi::middle::Type::u32(),
|
|
NativeType::I32 => libffi::middle::Type::i32(),
|
|
NativeType::U64 => libffi::middle::Type::u64(),
|
|
NativeType::I64 => libffi::middle::Type::i64(),
|
|
NativeType::USize => libffi::middle::Type::usize(),
|
|
NativeType::ISize => libffi::middle::Type::isize(),
|
|
NativeType::F32 => libffi::middle::Type::f32(),
|
|
NativeType::F64 => libffi::middle::Type::f64(),
|
|
NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
|
|
libffi::middle::Type::pointer()
|
|
}
|
|
NativeType::Struct(fields) => {
|
|
libffi::middle::Type::structure(match fields.len() > 0 {
|
|
true => fields
|
|
.iter()
|
|
.map(|field| field.clone().try_into())
|
|
.collect::<Result<Vec<_>, _>>()?,
|
|
false => {
|
|
return Err(JsErrorBox::type_error(
|
|
"Struct must have at least one field",
|
|
))
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Symbol {
|
|
pub name: String,
|
|
pub cif: libffi::middle::Cif,
|
|
pub ptr: libffi::middle::CodePtr,
|
|
pub parameter_types: Vec<NativeType>,
|
|
pub result_type: NativeType,
|
|
}
|
|
|
|
#[allow(clippy::non_send_fields_in_send_ty)]
|
|
// SAFETY: unsafe trait must have unsafe implementation
|
|
unsafe impl Send for Symbol {}
|
|
// SAFETY: unsafe trait must have unsafe implementation
|
|
unsafe impl Sync for Symbol {}
|