mirror of
https://github.com/denoland/deno.git
synced 2025-01-06 22:35:51 -05:00
feat(ext/ffi): Support bool FFI type (#15754)
This commit is contained in:
parent
9d127a71b0
commit
d908032dbb
10 changed files with 227 additions and 66 deletions
7
cli/dts/lib.deno.unstable.d.ts
vendored
7
cli/dts/lib.deno.unstable.d.ts
vendored
|
@ -393,6 +393,8 @@ declare namespace Deno {
|
||||||
| "usize"
|
| "usize"
|
||||||
| "isize";
|
| "isize";
|
||||||
|
|
||||||
|
type NativeBooleanType = "bool";
|
||||||
|
|
||||||
type NativePointerType = "pointer";
|
type NativePointerType = "pointer";
|
||||||
|
|
||||||
type NativeBufferType = "buffer";
|
type NativeBufferType = "buffer";
|
||||||
|
@ -408,6 +410,7 @@ declare namespace Deno {
|
||||||
export type NativeType =
|
export type NativeType =
|
||||||
| NativeNumberType
|
| NativeNumberType
|
||||||
| NativeBigIntType
|
| NativeBigIntType
|
||||||
|
| NativeBooleanType
|
||||||
| NativePointerType
|
| NativePointerType
|
||||||
| NativeBufferType
|
| NativeBufferType
|
||||||
| NativeFunctionType;
|
| NativeFunctionType;
|
||||||
|
@ -419,6 +422,7 @@ declare namespace Deno {
|
||||||
type ToNativeTypeMap =
|
type ToNativeTypeMap =
|
||||||
& Record<NativeNumberType, number>
|
& Record<NativeNumberType, number>
|
||||||
& Record<NativeBigIntType, PointerValue>
|
& Record<NativeBigIntType, PointerValue>
|
||||||
|
& Record<NativeBooleanType, boolean>
|
||||||
& Record<NativePointerType, PointerValue | null>
|
& Record<NativePointerType, PointerValue | null>
|
||||||
& Record<NativeFunctionType, PointerValue | null>
|
& Record<NativeFunctionType, PointerValue | null>
|
||||||
& Record<NativeBufferType, TypedArray | null>;
|
& Record<NativeBufferType, TypedArray | null>;
|
||||||
|
@ -455,6 +459,7 @@ declare namespace Deno {
|
||||||
type FromNativeTypeMap =
|
type FromNativeTypeMap =
|
||||||
& Record<NativeNumberType, number>
|
& Record<NativeNumberType, number>
|
||||||
& Record<NativeBigIntType, PointerValue>
|
& Record<NativeBigIntType, PointerValue>
|
||||||
|
& Record<NativeBooleanType, boolean>
|
||||||
& Record<NativePointerType, PointerValue>
|
& Record<NativePointerType, PointerValue>
|
||||||
& Record<NativeBufferType, PointerValue>
|
& Record<NativeBufferType, PointerValue>
|
||||||
& Record<NativeFunctionType, PointerValue>;
|
& Record<NativeFunctionType, PointerValue>;
|
||||||
|
@ -610,6 +615,8 @@ declare namespace Deno {
|
||||||
|
|
||||||
pointer: bigint;
|
pointer: bigint;
|
||||||
|
|
||||||
|
/** Gets a boolean at the specified byte offset from the pointer. */
|
||||||
|
getBool(offset?: number): boolean;
|
||||||
/** Gets an unsigned 8-bit integer at the specified byte offset from the pointer. */
|
/** Gets an unsigned 8-bit integer at the specified byte offset from the pointer. */
|
||||||
getUint8(offset?: number): number;
|
getUint8(offset?: number): number;
|
||||||
/** Gets a signed 8-bit integer at the specified byte offset from the pointer. */
|
/** Gets a signed 8-bit integer at the specified byte offset from the pointer. */
|
||||||
|
|
|
@ -45,6 +45,12 @@
|
||||||
this.pointer = pointer;
|
this.pointer = pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBool(offset = 0) {
|
||||||
|
return ops.op_ffi_read_bool(
|
||||||
|
offset ? BigInt(this.pointer) + BigInt(offset) : this.pointer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getUint8(offset = 0) {
|
getUint8(offset = 0) {
|
||||||
return ops.op_ffi_read_u8(
|
return ops.op_ffi_read_u8(
|
||||||
offset ? BigInt(this.pointer) + BigInt(offset) : this.pointer,
|
offset ? BigInt(this.pointer) + BigInt(offset) : this.pointer,
|
||||||
|
|
|
@ -23,6 +23,7 @@ macro_rules! cstr {
|
||||||
|
|
||||||
fn native_arg_to_c(ty: &NativeType) -> &'static str {
|
fn native_arg_to_c(ty: &NativeType) -> &'static str {
|
||||||
match ty {
|
match ty {
|
||||||
|
NativeType::Bool => "bool",
|
||||||
NativeType::U8 | NativeType::U16 | NativeType::U32 => "uint32_t",
|
NativeType::U8 | NativeType::U16 | NativeType::U32 => "uint32_t",
|
||||||
NativeType::I8 | NativeType::I16 | NativeType::I32 => "int32_t",
|
NativeType::I8 | NativeType::I16 | NativeType::I32 => "int32_t",
|
||||||
NativeType::Void => "void",
|
NativeType::Void => "void",
|
||||||
|
@ -39,6 +40,7 @@ fn native_arg_to_c(ty: &NativeType) -> &'static str {
|
||||||
|
|
||||||
fn native_to_c(ty: &NativeType) -> &'static str {
|
fn native_to_c(ty: &NativeType) -> &'static str {
|
||||||
match ty {
|
match ty {
|
||||||
|
NativeType::Bool => "bool",
|
||||||
NativeType::U8 => "uint8_t",
|
NativeType::U8 => "uint8_t",
|
||||||
NativeType::U16 => "uint16_t",
|
NativeType::U16 => "uint16_t",
|
||||||
NativeType::U32 => "uint32_t",
|
NativeType::U32 => "uint32_t",
|
||||||
|
|
192
ext/ffi/lib.rs
192
ext/ffi/lib.rs
|
@ -23,7 +23,6 @@ use deno_core::ZeroCopyBuf;
|
||||||
use dlopen::raw::Library;
|
use dlopen::raw::Library;
|
||||||
use libffi::middle::Arg;
|
use libffi::middle::Arg;
|
||||||
use libffi::middle::Cif;
|
use libffi::middle::Cif;
|
||||||
use libffi::raw::*;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -186,6 +185,7 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
|
||||||
op_ffi_get_buf::decl::<P>(),
|
op_ffi_get_buf::decl::<P>(),
|
||||||
op_ffi_buf_copy_into::decl::<P>(),
|
op_ffi_buf_copy_into::decl::<P>(),
|
||||||
op_ffi_cstr_read::decl::<P>(),
|
op_ffi_cstr_read::decl::<P>(),
|
||||||
|
op_ffi_read_bool::decl::<P>(),
|
||||||
op_ffi_read_u8::decl::<P>(),
|
op_ffi_read_u8::decl::<P>(),
|
||||||
op_ffi_read_i8::decl::<P>(),
|
op_ffi_read_i8::decl::<P>(),
|
||||||
op_ffi_read_u16::decl::<P>(),
|
op_ffi_read_u16::decl::<P>(),
|
||||||
|
@ -253,6 +253,7 @@ pub fn init<P: FfiPermissions + 'static>(unstable: bool) -> Extension {
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
enum NativeType {
|
enum NativeType {
|
||||||
Void,
|
Void,
|
||||||
|
Bool,
|
||||||
U8,
|
U8,
|
||||||
I8,
|
I8,
|
||||||
U16,
|
U16,
|
||||||
|
@ -274,7 +275,7 @@ impl From<NativeType> for libffi::middle::Type {
|
||||||
fn from(native_type: NativeType) -> Self {
|
fn from(native_type: NativeType) -> Self {
|
||||||
match native_type {
|
match native_type {
|
||||||
NativeType::Void => libffi::middle::Type::void(),
|
NativeType::Void => libffi::middle::Type::void(),
|
||||||
NativeType::U8 => libffi::middle::Type::u8(),
|
NativeType::U8 | NativeType::Bool => libffi::middle::Type::u8(),
|
||||||
NativeType::I8 => libffi::middle::Type::i8(),
|
NativeType::I8 => libffi::middle::Type::i8(),
|
||||||
NativeType::U16 => libffi::middle::Type::u16(),
|
NativeType::U16 => libffi::middle::Type::u16(),
|
||||||
NativeType::I16 => libffi::middle::Type::i16(),
|
NativeType::I16 => libffi::middle::Type::i16(),
|
||||||
|
@ -298,6 +299,7 @@ impl From<NativeType> for libffi::middle::Type {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
union NativeValue {
|
union NativeValue {
|
||||||
void_value: (),
|
void_value: (),
|
||||||
|
bool_value: bool,
|
||||||
u8_value: u8,
|
u8_value: u8,
|
||||||
i8_value: i8,
|
i8_value: i8,
|
||||||
u16_value: u16,
|
u16_value: u16,
|
||||||
|
@ -317,6 +319,7 @@ impl NativeValue {
|
||||||
unsafe fn as_arg(&self, native_type: NativeType) -> Arg {
|
unsafe fn as_arg(&self, native_type: NativeType) -> Arg {
|
||||||
match native_type {
|
match native_type {
|
||||||
NativeType::Void => unreachable!(),
|
NativeType::Void => unreachable!(),
|
||||||
|
NativeType::Bool => Arg::new(&self.bool_value),
|
||||||
NativeType::U8 => Arg::new(&self.u8_value),
|
NativeType::U8 => Arg::new(&self.u8_value),
|
||||||
NativeType::I8 => Arg::new(&self.i8_value),
|
NativeType::I8 => Arg::new(&self.i8_value),
|
||||||
NativeType::U16 => Arg::new(&self.u16_value),
|
NativeType::U16 => Arg::new(&self.u16_value),
|
||||||
|
@ -339,6 +342,7 @@ impl NativeValue {
|
||||||
unsafe fn to_value(&self, native_type: NativeType) -> Value {
|
unsafe fn to_value(&self, native_type: NativeType) -> Value {
|
||||||
match native_type {
|
match native_type {
|
||||||
NativeType::Void => Value::Null,
|
NativeType::Void => Value::Null,
|
||||||
|
NativeType::Bool => Value::from(self.bool_value),
|
||||||
NativeType::U8 => Value::from(self.u8_value),
|
NativeType::U8 => Value::from(self.u8_value),
|
||||||
NativeType::I8 => Value::from(self.i8_value),
|
NativeType::I8 => Value::from(self.i8_value),
|
||||||
NativeType::U16 => Value::from(self.u16_value),
|
NativeType::U16 => Value::from(self.u16_value),
|
||||||
|
@ -402,6 +406,11 @@ impl NativeValue {
|
||||||
let local_value: v8::Local<v8::Value> = v8::undefined(scope).into();
|
let local_value: v8::Local<v8::Value> = v8::undefined(scope).into();
|
||||||
local_value.into()
|
local_value.into()
|
||||||
}
|
}
|
||||||
|
NativeType::Bool => {
|
||||||
|
let local_value: v8::Local<v8::Value> =
|
||||||
|
v8::Boolean::new(scope, self.bool_value).into();
|
||||||
|
local_value.into()
|
||||||
|
}
|
||||||
NativeType::U8 => {
|
NativeType::U8 => {
|
||||||
let local_value: v8::Local<v8::Value> =
|
let local_value: v8::Local<v8::Value> =
|
||||||
v8::Integer::new_from_unsigned(scope, self.u8_value as u32).into();
|
v8::Integer::new_from_unsigned(scope, self.u8_value as u32).into();
|
||||||
|
@ -743,6 +752,7 @@ impl fast_api::FastFunction for FfiFastCallTemplate {
|
||||||
impl From<&NativeType> for fast_api::Type {
|
impl From<&NativeType> for fast_api::Type {
|
||||||
fn from(native_type: &NativeType) -> Self {
|
fn from(native_type: &NativeType) -> Self {
|
||||||
match native_type {
|
match native_type {
|
||||||
|
NativeType::Bool => fast_api::Type::Bool,
|
||||||
NativeType::U8 | NativeType::U16 | NativeType::U32 => {
|
NativeType::U8 | NativeType::U16 | NativeType::U32 => {
|
||||||
fast_api::Type::Uint32
|
fast_api::Type::Uint32
|
||||||
}
|
}
|
||||||
|
@ -907,6 +917,16 @@ fn make_sync_fn<'s>(
|
||||||
weak.to_local(scope).unwrap()
|
weak.to_local(scope).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn ffi_parse_bool_arg(
|
||||||
|
arg: v8::Local<v8::Value>,
|
||||||
|
) -> Result<NativeValue, AnyError> {
|
||||||
|
let bool_value = v8::Local::<v8::Boolean>::try_from(arg)
|
||||||
|
.map_err(|_| type_error("Invalid FFI u8 type, expected boolean"))?
|
||||||
|
.is_true();
|
||||||
|
Ok(NativeValue { bool_value })
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ffi_parse_u8_arg(
|
fn ffi_parse_u8_arg(
|
||||||
arg: v8::Local<v8::Value>,
|
arg: v8::Local<v8::Value>,
|
||||||
|
@ -1163,6 +1183,9 @@ where
|
||||||
for (index, native_type) in parameter_types.iter().enumerate() {
|
for (index, native_type) in parameter_types.iter().enumerate() {
|
||||||
let value = args.get_index(scope, index as u32).unwrap();
|
let value = args.get_index(scope, index as u32).unwrap();
|
||||||
match native_type {
|
match native_type {
|
||||||
|
NativeType::Bool => {
|
||||||
|
ffi_args.push(ffi_parse_bool_arg(value)?);
|
||||||
|
}
|
||||||
NativeType::U8 => {
|
NativeType::U8 => {
|
||||||
ffi_args.push(ffi_parse_u8_arg(value)?);
|
ffi_args.push(ffi_parse_u8_arg(value)?);
|
||||||
}
|
}
|
||||||
|
@ -1239,6 +1262,9 @@ where
|
||||||
for (index, native_type) in parameter_types.iter().enumerate() {
|
for (index, native_type) in parameter_types.iter().enumerate() {
|
||||||
let value = args.get(index as i32);
|
let value = args.get(index as i32);
|
||||||
match native_type {
|
match native_type {
|
||||||
|
NativeType::Bool => {
|
||||||
|
ffi_args.push(ffi_parse_bool_arg(value)?);
|
||||||
|
}
|
||||||
NativeType::U8 => {
|
NativeType::U8 => {
|
||||||
ffi_args.push(ffi_parse_u8_arg(value)?);
|
ffi_args.push(ffi_parse_u8_arg(value)?);
|
||||||
}
|
}
|
||||||
|
@ -1297,6 +1323,9 @@ where
|
||||||
NativeType::Void => NativeValue {
|
NativeType::Void => NativeValue {
|
||||||
void_value: cif.call::<()>(*fun_ptr, &call_args),
|
void_value: cif.call::<()>(*fun_ptr, &call_args),
|
||||||
},
|
},
|
||||||
|
NativeType::Bool => NativeValue {
|
||||||
|
bool_value: cif.call::<bool>(*fun_ptr, &call_args),
|
||||||
|
},
|
||||||
NativeType::U8 => NativeValue {
|
NativeType::U8 => NativeValue {
|
||||||
u8_value: cif.call::<u8>(*fun_ptr, &call_args),
|
u8_value: cif.call::<u8>(*fun_ptr, &call_args),
|
||||||
},
|
},
|
||||||
|
@ -1365,6 +1394,9 @@ fn ffi_call(
|
||||||
NativeType::Void => NativeValue {
|
NativeType::Void => NativeValue {
|
||||||
void_value: cif.call::<()>(fun_ptr, &call_args),
|
void_value: cif.call::<()>(fun_ptr, &call_args),
|
||||||
},
|
},
|
||||||
|
NativeType::Bool => NativeValue {
|
||||||
|
bool_value: cif.call::<bool>(fun_ptr, &call_args),
|
||||||
|
},
|
||||||
NativeType::U8 => NativeValue {
|
NativeType::U8 => NativeValue {
|
||||||
u8_value: cif.call::<u8>(fun_ptr, &call_args),
|
u8_value: cif.call::<u8>(fun_ptr, &call_args),
|
||||||
},
|
},
|
||||||
|
@ -1438,6 +1470,8 @@ impl Resource for UnsafeCallbackResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CallbackInfo {
|
struct CallbackInfo {
|
||||||
|
pub parameters: Vec<NativeType>,
|
||||||
|
pub result: NativeType,
|
||||||
pub async_work_sender: mpsc::UnboundedSender<PendingFfiAsyncWork>,
|
pub async_work_sender: mpsc::UnboundedSender<PendingFfiAsyncWork>,
|
||||||
pub callback: NonNull<v8::Function>,
|
pub callback: NonNull<v8::Function>,
|
||||||
pub context: NonNull<v8::Context>,
|
pub context: NonNull<v8::Context>,
|
||||||
|
@ -1445,7 +1479,7 @@ struct CallbackInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn deno_ffi_callback(
|
unsafe extern "C" fn deno_ffi_callback(
|
||||||
cif: &libffi::low::ffi_cif,
|
_cif: &libffi::low::ffi_cif,
|
||||||
result: &mut c_void,
|
result: &mut c_void,
|
||||||
args: *const *const c_void,
|
args: *const *const c_void,
|
||||||
info: &CallbackInfo,
|
info: &CallbackInfo,
|
||||||
|
@ -1453,30 +1487,15 @@ unsafe extern "C" fn deno_ffi_callback(
|
||||||
LOCAL_ISOLATE_POINTER.with(|s| {
|
LOCAL_ISOLATE_POINTER.with(|s| {
|
||||||
if ptr::eq(*s.borrow(), info.isolate) {
|
if ptr::eq(*s.borrow(), info.isolate) {
|
||||||
// Own isolate thread, okay to call directly
|
// Own isolate thread, okay to call directly
|
||||||
do_ffi_callback(
|
do_ffi_callback(info, result, args);
|
||||||
cif,
|
|
||||||
result,
|
|
||||||
args,
|
|
||||||
info.callback,
|
|
||||||
info.context,
|
|
||||||
info.isolate,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
let async_work_sender = &info.async_work_sender;
|
let async_work_sender = &info.async_work_sender;
|
||||||
// SAFETY: Safe as this function blocks until `do_ffi_callback` completes and a response message is received.
|
// SAFETY: Safe as this function blocks until `do_ffi_callback` completes and a response message is received.
|
||||||
let cif: &'static libffi::low::ffi_cif = std::mem::transmute(cif);
|
|
||||||
let result: &'static mut c_void = std::mem::transmute(result);
|
let result: &'static mut c_void = std::mem::transmute(result);
|
||||||
let info: &'static CallbackInfo = std::mem::transmute(info);
|
let info: &'static CallbackInfo = std::mem::transmute(info);
|
||||||
let (response_sender, response_receiver) = sync_channel::<()>(0);
|
let (response_sender, response_receiver) = sync_channel::<()>(0);
|
||||||
let fut = Box::new(move || {
|
let fut = Box::new(move || {
|
||||||
do_ffi_callback(
|
do_ffi_callback(info, result, args);
|
||||||
cif,
|
|
||||||
result,
|
|
||||||
args,
|
|
||||||
info.callback,
|
|
||||||
info.context,
|
|
||||||
info.isolate,
|
|
||||||
);
|
|
||||||
response_sender.send(()).unwrap();
|
response_sender.send(()).unwrap();
|
||||||
});
|
});
|
||||||
async_work_sender.unbounded_send(fut).unwrap();
|
async_work_sender.unbounded_send(fut).unwrap();
|
||||||
|
@ -1486,13 +1505,13 @@ unsafe extern "C" fn deno_ffi_callback(
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn do_ffi_callback(
|
unsafe fn do_ffi_callback(
|
||||||
cif: &libffi::low::ffi_cif,
|
info: &CallbackInfo,
|
||||||
result: &mut c_void,
|
result: &mut c_void,
|
||||||
args: *const *const c_void,
|
args: *const *const c_void,
|
||||||
callback: NonNull<v8::Function>,
|
|
||||||
context: NonNull<v8::Context>,
|
|
||||||
isolate: *mut v8::Isolate,
|
|
||||||
) {
|
) {
|
||||||
|
let callback: NonNull<v8::Function> = info.callback;
|
||||||
|
let context: NonNull<v8::Context> = info.context;
|
||||||
|
let isolate: *mut v8::Isolate = info.isolate;
|
||||||
let isolate = &mut *isolate;
|
let isolate = &mut *isolate;
|
||||||
let callback = v8::Global::from_raw(isolate, callback);
|
let callback = v8::Global::from_raw(isolate, callback);
|
||||||
let context = std::mem::transmute::<
|
let context = std::mem::transmute::<
|
||||||
|
@ -1513,47 +1532,49 @@ unsafe fn do_ffi_callback(
|
||||||
let scope = &mut v8::HandleScope::new(&mut cb_scope);
|
let scope = &mut v8::HandleScope::new(&mut cb_scope);
|
||||||
let func = callback.open(scope);
|
let func = callback.open(scope);
|
||||||
let result = result as *mut c_void;
|
let result = result as *mut c_void;
|
||||||
let repr: &[*mut ffi_type] =
|
|
||||||
std::slice::from_raw_parts(cif.arg_types, cif.nargs as usize);
|
|
||||||
let vals: &[*const c_void] =
|
let vals: &[*const c_void] =
|
||||||
std::slice::from_raw_parts(args, cif.nargs as usize);
|
std::slice::from_raw_parts(args, info.parameters.len() as usize);
|
||||||
|
|
||||||
let mut params: Vec<v8::Local<v8::Value>> = vec![];
|
let mut params: Vec<v8::Local<v8::Value>> = vec![];
|
||||||
for (repr, val) in repr.iter().zip(vals) {
|
for (native_type, val) in info.parameters.iter().zip(vals) {
|
||||||
let value: v8::Local<v8::Value> = match (*(*repr)).type_ as _ {
|
let value: v8::Local<v8::Value> = match native_type {
|
||||||
FFI_TYPE_FLOAT => {
|
NativeType::Bool => {
|
||||||
|
let value = *((*val) as *const bool);
|
||||||
|
v8::Boolean::new(scope, value).into()
|
||||||
|
}
|
||||||
|
NativeType::F32 => {
|
||||||
let value = *((*val) as *const f32);
|
let value = *((*val) as *const f32);
|
||||||
v8::Number::new(scope, value as f64).into()
|
v8::Number::new(scope, value as f64).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_DOUBLE => {
|
NativeType::F64 => {
|
||||||
let value = *((*val) as *const f64);
|
let value = *((*val) as *const f64);
|
||||||
v8::Number::new(scope, value).into()
|
v8::Number::new(scope, value).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT8 => {
|
NativeType::I8 => {
|
||||||
let value = *((*val) as *const i8);
|
let value = *((*val) as *const i8);
|
||||||
v8::Integer::new(scope, value as i32).into()
|
v8::Integer::new(scope, value as i32).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT8 => {
|
NativeType::U8 => {
|
||||||
let value = *((*val) as *const u8);
|
let value = *((*val) as *const u8);
|
||||||
v8::Integer::new_from_unsigned(scope, value as u32).into()
|
v8::Integer::new_from_unsigned(scope, value as u32).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT16 => {
|
NativeType::I16 => {
|
||||||
let value = *((*val) as *const i16);
|
let value = *((*val) as *const i16);
|
||||||
v8::Integer::new(scope, value as i32).into()
|
v8::Integer::new(scope, value as i32).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT16 => {
|
NativeType::U16 => {
|
||||||
let value = *((*val) as *const u16);
|
let value = *((*val) as *const u16);
|
||||||
v8::Integer::new_from_unsigned(scope, value as u32).into()
|
v8::Integer::new_from_unsigned(scope, value as u32).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_INT | FFI_TYPE_SINT32 => {
|
NativeType::I32 => {
|
||||||
let value = *((*val) as *const i32);
|
let value = *((*val) as *const i32);
|
||||||
v8::Integer::new(scope, value).into()
|
v8::Integer::new(scope, value).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT32 => {
|
NativeType::U32 => {
|
||||||
let value = *((*val) as *const u32);
|
let value = *((*val) as *const u32);
|
||||||
v8::Integer::new_from_unsigned(scope, value).into()
|
v8::Integer::new_from_unsigned(scope, value).into()
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT64 => {
|
NativeType::I64 => {
|
||||||
let result = *((*val) as *const i64);
|
let result = *((*val) as *const i64);
|
||||||
if result > MAX_SAFE_INTEGER as i64 || result < MIN_SAFE_INTEGER as i64
|
if result > MAX_SAFE_INTEGER as i64 || result < MIN_SAFE_INTEGER as i64
|
||||||
{
|
{
|
||||||
|
@ -1562,7 +1583,7 @@ unsafe fn do_ffi_callback(
|
||||||
v8::Number::new(scope, result as f64).into()
|
v8::Number::new(scope, result as f64).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT64 => {
|
NativeType::U64 => {
|
||||||
let result = *((*val) as *const u64);
|
let result = *((*val) as *const u64);
|
||||||
if result > MAX_SAFE_INTEGER as u64 {
|
if result > MAX_SAFE_INTEGER as u64 {
|
||||||
v8::BigInt::new_from_u64(scope, result).into()
|
v8::BigInt::new_from_u64(scope, result).into()
|
||||||
|
@ -1570,15 +1591,14 @@ unsafe fn do_ffi_callback(
|
||||||
v8::Number::new(scope, result as f64).into()
|
v8::Number::new(scope, result as f64).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FFI_TYPE_POINTER | FFI_TYPE_STRUCT => {
|
NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
|
||||||
let result = *((*val) as *const u64);
|
let result = *((*val) as *const usize);
|
||||||
if result > MAX_SAFE_INTEGER as u64 {
|
if result > MAX_SAFE_INTEGER as usize {
|
||||||
v8::BigInt::new_from_u64(scope, result).into()
|
v8::BigInt::new_from_u64(scope, result as u64).into()
|
||||||
} else {
|
} else {
|
||||||
v8::Number::new(scope, result as f64).into()
|
v8::Number::new(scope, result as f64).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FFI_TYPE_VOID => v8::undefined(scope).into(),
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1594,30 +1614,36 @@ unsafe fn do_ffi_callback(
|
||||||
// JS function threw an exception. Set the return value to zero and return.
|
// JS function threw an exception. Set the return value to zero and return.
|
||||||
// The exception continue propagating up the call chain when the event loop
|
// The exception continue propagating up the call chain when the event loop
|
||||||
// resumes.
|
// resumes.
|
||||||
match (*cif.rtype).type_ as _ {
|
match info.result {
|
||||||
FFI_TYPE_INT | FFI_TYPE_SINT32 | FFI_TYPE_UINT32 => {
|
NativeType::Bool => {
|
||||||
|
*(result as *mut bool) = false;
|
||||||
|
}
|
||||||
|
NativeType::U32 | NativeType::I32 => {
|
||||||
// zero is equal for signed and unsigned alike
|
// zero is equal for signed and unsigned alike
|
||||||
*(result as *mut u32) = 0;
|
*(result as *mut u32) = 0;
|
||||||
}
|
}
|
||||||
FFI_TYPE_FLOAT => {
|
NativeType::F32 => {
|
||||||
*(result as *mut f32) = 0.0;
|
*(result as *mut f32) = 0.0;
|
||||||
}
|
}
|
||||||
FFI_TYPE_DOUBLE => {
|
NativeType::F64 => {
|
||||||
*(result as *mut f64) = 0.0;
|
*(result as *mut f64) = 0.0;
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT8 | FFI_TYPE_UINT8 => {
|
NativeType::U8 | NativeType::I8 => {
|
||||||
// zero is equal for signed and unsigned alike
|
// zero is equal for signed and unsigned alike
|
||||||
*(result as *mut u8) = 0;
|
*(result as *mut u8) = 0;
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT16 | FFI_TYPE_UINT16 => {
|
NativeType::U16 | NativeType::I16 => {
|
||||||
// zero is equal for signed and unsigned alike
|
// zero is equal for signed and unsigned alike
|
||||||
*(result as *mut u16) = 0;
|
*(result as *mut u16) = 0;
|
||||||
}
|
}
|
||||||
FFI_TYPE_POINTER | FFI_TYPE_STRUCT | FFI_TYPE_UINT64
|
NativeType::Pointer
|
||||||
| FFI_TYPE_SINT64 => {
|
| NativeType::Buffer
|
||||||
|
| NativeType::Function
|
||||||
|
| NativeType::U64
|
||||||
|
| NativeType::I64 => {
|
||||||
*(result as *mut usize) = 0;
|
*(result as *mut usize) = 0;
|
||||||
}
|
}
|
||||||
FFI_TYPE_VOID => {
|
NativeType::Void => {
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1629,8 +1655,16 @@ unsafe fn do_ffi_callback(
|
||||||
}
|
}
|
||||||
let value = call_result.unwrap();
|
let value = call_result.unwrap();
|
||||||
|
|
||||||
match (*cif.rtype).type_ as _ {
|
match info.result {
|
||||||
FFI_TYPE_INT | FFI_TYPE_SINT32 => {
|
NativeType::Bool => {
|
||||||
|
let value = if let Ok(value) = v8::Local::<v8::Boolean>::try_from(value) {
|
||||||
|
value.is_true()
|
||||||
|
} else {
|
||||||
|
value.boolean_value(scope)
|
||||||
|
};
|
||||||
|
*(result as *mut bool) = value;
|
||||||
|
}
|
||||||
|
NativeType::I32 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
value.value() as i32
|
value.value() as i32
|
||||||
} else {
|
} else {
|
||||||
|
@ -1641,7 +1675,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut i32) = value;
|
*(result as *mut i32) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_FLOAT => {
|
NativeType::F32 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Number>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Number>::try_from(value) {
|
||||||
value.value() as f32
|
value.value() as f32
|
||||||
} else {
|
} else {
|
||||||
|
@ -1652,7 +1686,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut f32) = value;
|
*(result as *mut f32) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_DOUBLE => {
|
NativeType::F64 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Number>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Number>::try_from(value) {
|
||||||
value.value()
|
value.value()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1663,7 +1697,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut f64) = value;
|
*(result as *mut f64) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_POINTER | FFI_TYPE_STRUCT => {
|
NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
|
||||||
let pointer = if let Ok(value) =
|
let pointer = if let Ok(value) =
|
||||||
v8::Local::<v8::ArrayBufferView>::try_from(value)
|
v8::Local::<v8::ArrayBufferView>::try_from(value)
|
||||||
{
|
{
|
||||||
|
@ -1692,7 +1726,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut *const u8) = pointer;
|
*(result as *mut *const u8) = pointer;
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT8 => {
|
NativeType::I8 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
value.value() as i8
|
value.value() as i8
|
||||||
} else {
|
} else {
|
||||||
|
@ -1703,7 +1737,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut i8) = value;
|
*(result as *mut i8) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT8 => {
|
NativeType::U8 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
value.value() as u8
|
value.value() as u8
|
||||||
} else {
|
} else {
|
||||||
|
@ -1714,7 +1748,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut u8) = value;
|
*(result as *mut u8) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT16 => {
|
NativeType::I16 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
value.value() as i16
|
value.value() as i16
|
||||||
} else {
|
} else {
|
||||||
|
@ -1725,7 +1759,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut i16) = value;
|
*(result as *mut i16) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT16 => {
|
NativeType::U16 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
value.value() as u16
|
value.value() as u16
|
||||||
} else {
|
} else {
|
||||||
|
@ -1736,7 +1770,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut u16) = value;
|
*(result as *mut u16) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT32 => {
|
NativeType::U32 => {
|
||||||
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
let value = if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
value.value() as u32
|
value.value() as u32
|
||||||
} else {
|
} else {
|
||||||
|
@ -1747,7 +1781,7 @@ unsafe fn do_ffi_callback(
|
||||||
};
|
};
|
||||||
*(result as *mut u32) = value;
|
*(result as *mut u32) = value;
|
||||||
}
|
}
|
||||||
FFI_TYPE_SINT64 => {
|
NativeType::I64 => {
|
||||||
if let Ok(value) = v8::Local::<v8::BigInt>::try_from(value) {
|
if let Ok(value) = v8::Local::<v8::BigInt>::try_from(value) {
|
||||||
*(result as *mut i64) = value.i64_value().0;
|
*(result as *mut i64) = value.i64_value().0;
|
||||||
} else if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
} else if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
|
@ -1759,7 +1793,7 @@ unsafe fn do_ffi_callback(
|
||||||
as i64;
|
as i64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FFI_TYPE_UINT64 => {
|
NativeType::U64 => {
|
||||||
if let Ok(value) = v8::Local::<v8::BigInt>::try_from(value) {
|
if let Ok(value) = v8::Local::<v8::BigInt>::try_from(value) {
|
||||||
*(result as *mut u64) = value.u64_value().0;
|
*(result as *mut u64) = value.u64_value().0;
|
||||||
} else if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
} else if let Ok(value) = v8::Local::<v8::Integer>::try_from(value) {
|
||||||
|
@ -1771,7 +1805,7 @@ unsafe fn do_ffi_callback(
|
||||||
as u64;
|
as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FFI_TYPE_VOID => {
|
NativeType::Void => {
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1817,6 +1851,8 @@ where
|
||||||
let context = v8::Global::new(scope, current_context).into_raw();
|
let context = v8::Global::new(scope, current_context).into_raw();
|
||||||
|
|
||||||
let info = Box::leak(Box::new(CallbackInfo {
|
let info = Box::leak(Box::new(CallbackInfo {
|
||||||
|
parameters: args.parameters.clone(),
|
||||||
|
result: args.result,
|
||||||
async_work_sender,
|
async_work_sender,
|
||||||
callback,
|
callback,
|
||||||
context,
|
context,
|
||||||
|
@ -1941,6 +1977,13 @@ fn op_ffi_get_static<'scope>(
|
||||||
NativeType::Void => {
|
NativeType::Void => {
|
||||||
return Err(type_error("Invalid FFI static type 'void'"));
|
return Err(type_error("Invalid FFI static type 'void'"));
|
||||||
}
|
}
|
||||||
|
NativeType::Bool => {
|
||||||
|
// SAFETY: ptr is user provided
|
||||||
|
let result = unsafe { ptr::read_unaligned(data_ptr as *const bool) };
|
||||||
|
let boolean: v8::Local<v8::Value> =
|
||||||
|
v8::Boolean::new(scope, result).into();
|
||||||
|
boolean.into()
|
||||||
|
}
|
||||||
NativeType::U8 => {
|
NativeType::U8 => {
|
||||||
// SAFETY: ptr is user provided
|
// SAFETY: ptr is user provided
|
||||||
let result = unsafe { ptr::read_unaligned(data_ptr as *const u8) };
|
let result = unsafe { ptr::read_unaligned(data_ptr as *const u8) };
|
||||||
|
@ -2239,6 +2282,23 @@ where
|
||||||
Ok(value.into())
|
Ok(value.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_ffi_read_bool<FP>(
|
||||||
|
state: &mut deno_core::OpState,
|
||||||
|
ptr: usize,
|
||||||
|
) -> Result<bool, AnyError>
|
||||||
|
where
|
||||||
|
FP: FfiPermissions + 'static,
|
||||||
|
{
|
||||||
|
check_unstable(state, "Deno.UnsafePointerView#getBool");
|
||||||
|
|
||||||
|
let permissions = state.borrow_mut::<FP>();
|
||||||
|
permissions.check(None)?;
|
||||||
|
|
||||||
|
// SAFETY: ptr is user provided.
|
||||||
|
Ok(unsafe { ptr::read_unaligned(ptr as *const bool) })
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_ffi_read_u8<FP>(
|
fn op_ffi_read_u8<FP>(
|
||||||
state: &mut deno_core::OpState,
|
state: &mut deno_core::OpState,
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
/* Boolean type */
|
||||||
|
|
||||||
|
#ifndef _STDBOOL_H
|
||||||
|
#define _STDBOOL_H
|
||||||
|
|
||||||
|
#define bool _Bool
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Exact integral types. */
|
/* Exact integral types. */
|
||||||
|
|
||||||
/* Signed. */
|
/* Signed. */
|
||||||
|
|
|
@ -94,6 +94,11 @@ pub extern "C" fn add_f64(a: f64, b: f64) -> f64 {
|
||||||
a + b
|
a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn and(a: bool, b: bool) -> bool {
|
||||||
|
a && b
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn hash(ptr: *const u8, length: u32) -> u32 {
|
unsafe extern "C" fn hash(ptr: *const u8, length: u32) -> u32 {
|
||||||
let buf = std::slice::from_raw_parts(ptr, length as usize);
|
let buf = std::slice::from_raw_parts(ptr, length as usize);
|
||||||
|
@ -257,6 +262,9 @@ pub extern "C" fn call_stored_function_thread_safe_and_log() {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn nop() {}
|
pub extern "C" fn nop() {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn nop_bool(_a: bool) {}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn nop_u8(_a: u8) {}
|
pub extern "C" fn nop_u8(_a: u8) {}
|
||||||
|
|
||||||
|
@ -296,6 +304,11 @@ pub extern "C" fn nop_f64(_a: f64) {}
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn nop_buffer(_buffer: *mut [u8; 8]) {}
|
pub extern "C" fn nop_buffer(_buffer: *mut [u8; 8]) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn return_bool() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn return_u8() -> u8 {
|
pub extern "C" fn return_u8() -> u8 {
|
||||||
255
|
255
|
||||||
|
|
|
@ -15,6 +15,7 @@ const dylib = Deno.dlopen(libPath, {
|
||||||
"add_u64": { parameters: ["u64", "u64"], result: "u64" },
|
"add_u64": { parameters: ["u64", "u64"], result: "u64" },
|
||||||
"ffi_string": { parameters: [], result: "pointer" },
|
"ffi_string": { parameters: [], result: "pointer" },
|
||||||
"hash": { parameters: ["buffer", "u32"], result: "u32" },
|
"hash": { parameters: ["buffer", "u32"], result: "u32" },
|
||||||
|
"nop_bool": { parameters: ["bool"], result: "void" },
|
||||||
"nop_u8": { parameters: ["u8"], result: "void" },
|
"nop_u8": { parameters: ["u8"], result: "void" },
|
||||||
"nop_i8": { parameters: ["i8"], result: "void" },
|
"nop_i8": { parameters: ["i8"], result: "void" },
|
||||||
"nop_u16": { parameters: ["u16"], result: "void" },
|
"nop_u16": { parameters: ["u16"], result: "void" },
|
||||||
|
@ -28,6 +29,7 @@ const dylib = Deno.dlopen(libPath, {
|
||||||
"nop_f32": { parameters: ["f32"], result: "void" },
|
"nop_f32": { parameters: ["f32"], result: "void" },
|
||||||
"nop_f64": { parameters: ["f64"], result: "void" },
|
"nop_f64": { parameters: ["f64"], result: "void" },
|
||||||
"nop_buffer": { parameters: ["buffer"], result: "void" },
|
"nop_buffer": { parameters: ["buffer"], result: "void" },
|
||||||
|
"return_bool": { parameters: [], result: "bool" },
|
||||||
"return_u8": { parameters: [], result: "u8" },
|
"return_u8": { parameters: [], result: "u8" },
|
||||||
"return_i8": { parameters: [], result: "i8" },
|
"return_i8": { parameters: [], result: "i8" },
|
||||||
"return_u16": { parameters: [], result: "u16" },
|
"return_u16": { parameters: [], result: "u16" },
|
||||||
|
@ -43,6 +45,11 @@ const dylib = Deno.dlopen(libPath, {
|
||||||
"return_buffer": { parameters: [], result: "buffer" },
|
"return_buffer": { parameters: [], result: "buffer" },
|
||||||
// Nonblocking calls
|
// Nonblocking calls
|
||||||
"nop_nonblocking": { name: "nop", parameters: [], result: "void" },
|
"nop_nonblocking": { name: "nop", parameters: [], result: "void" },
|
||||||
|
"nop_bool_nonblocking": {
|
||||||
|
name: "nop_bool",
|
||||||
|
parameters: ["bool"],
|
||||||
|
result: "void",
|
||||||
|
},
|
||||||
"nop_u8_nonblocking": { name: "nop_u8", parameters: ["u8"], result: "void" },
|
"nop_u8_nonblocking": { name: "nop_u8", parameters: ["u8"], result: "void" },
|
||||||
"nop_i8_nonblocking": { name: "nop_i8", parameters: ["i8"], result: "void" },
|
"nop_i8_nonblocking": { name: "nop_i8", parameters: ["i8"], result: "void" },
|
||||||
"nop_u16_nonblocking": {
|
"nop_u16_nonblocking": {
|
||||||
|
@ -100,6 +107,11 @@ const dylib = Deno.dlopen(libPath, {
|
||||||
parameters: ["buffer"],
|
parameters: ["buffer"],
|
||||||
result: "void",
|
result: "void",
|
||||||
},
|
},
|
||||||
|
"return_bool_nonblocking": {
|
||||||
|
name: "return_bool",
|
||||||
|
parameters: [],
|
||||||
|
result: "bool",
|
||||||
|
},
|
||||||
"return_u8_nonblocking": { name: "return_u8", parameters: [], result: "u8" },
|
"return_u8_nonblocking": { name: "return_u8", parameters: [], result: "u8" },
|
||||||
"return_i8_nonblocking": { name: "return_i8", parameters: [], result: "i8" },
|
"return_i8_nonblocking": { name: "return_i8", parameters: [], result: "i8" },
|
||||||
"return_u16_nonblocking": {
|
"return_u16_nonblocking": {
|
||||||
|
@ -267,6 +279,11 @@ Deno.bench("return_i64()", () => {
|
||||||
return_i64();
|
return_i64();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { nop_bool } = dylib.symbols;
|
||||||
|
Deno.bench("nop_bool()", () => {
|
||||||
|
nop_bool(true);
|
||||||
|
});
|
||||||
|
|
||||||
const { nop_u8 } = dylib.symbols;
|
const { nop_u8 } = dylib.symbols;
|
||||||
Deno.bench("nop_u8()", () => {
|
Deno.bench("nop_u8()", () => {
|
||||||
nop_u8(100);
|
nop_u8(100);
|
||||||
|
@ -343,6 +360,11 @@ Deno.bench("nop_buffer()", () => {
|
||||||
nop_buffer(buffer);
|
nop_buffer(buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { return_bool } = dylib.symbols;
|
||||||
|
Deno.bench("return_bool()", () => {
|
||||||
|
return_bool();
|
||||||
|
});
|
||||||
|
|
||||||
const { return_u8 } = dylib.symbols;
|
const { return_u8 } = dylib.symbols;
|
||||||
Deno.bench("return_u8()", () => {
|
Deno.bench("return_u8()", () => {
|
||||||
return_u8();
|
return_u8();
|
||||||
|
@ -400,6 +422,11 @@ Deno.bench("nop_nonblocking()", async () => {
|
||||||
await nop_nonblocking();
|
await nop_nonblocking();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { nop_bool_nonblocking } = dylib.symbols;
|
||||||
|
Deno.bench("nop_bool_nonblocking()", async () => {
|
||||||
|
await nop_bool_nonblocking(true);
|
||||||
|
});
|
||||||
|
|
||||||
const { nop_u8_nonblocking } = dylib.symbols;
|
const { nop_u8_nonblocking } = dylib.symbols;
|
||||||
Deno.bench("nop_u8_nonblocking()", async () => {
|
Deno.bench("nop_u8_nonblocking()", async () => {
|
||||||
await nop_u8_nonblocking(100);
|
await nop_u8_nonblocking(100);
|
||||||
|
@ -465,6 +492,12 @@ const { nop_buffer_nonblocking } = dylib.symbols;
|
||||||
Deno.bench("nop_buffer_nonblocking()", async () => {
|
Deno.bench("nop_buffer_nonblocking()", async () => {
|
||||||
await nop_buffer_nonblocking(buffer);
|
await nop_buffer_nonblocking(buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { return_bool_nonblocking } = dylib.symbols;
|
||||||
|
Deno.bench("return_bool_nonblocking()", async () => {
|
||||||
|
await return_bool_nonblocking();
|
||||||
|
});
|
||||||
|
|
||||||
const { return_u8_nonblocking } = dylib.symbols;
|
const { return_u8_nonblocking } = dylib.symbols;
|
||||||
Deno.bench("return_u8_nonblocking()", async () => {
|
Deno.bench("return_u8_nonblocking()", async () => {
|
||||||
await return_u8_nonblocking();
|
await return_u8_nonblocking();
|
||||||
|
|
|
@ -42,6 +42,10 @@ const remote = Deno.dlopen(
|
||||||
parameters: ["buffer"],
|
parameters: ["buffer"],
|
||||||
result: "void",
|
result: "void",
|
||||||
},
|
},
|
||||||
|
method24: {
|
||||||
|
parameters: ["bool"],
|
||||||
|
result: "bool",
|
||||||
|
},
|
||||||
static1: { type: "usize" },
|
static1: { type: "usize" },
|
||||||
static2: { type: "pointer" },
|
static2: { type: "pointer" },
|
||||||
static3: { type: "usize" },
|
static3: { type: "usize" },
|
||||||
|
@ -56,6 +60,7 @@ const remote = Deno.dlopen(
|
||||||
static12: { type: "i64" },
|
static12: { type: "i64" },
|
||||||
static13: { type: "f32" },
|
static13: { type: "f32" },
|
||||||
static14: { type: "f64" },
|
static14: { type: "f64" },
|
||||||
|
static15: { type: "bool" },
|
||||||
} as const,
|
} as const,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -258,6 +263,22 @@ remote.symbols.method23(0);
|
||||||
remote.symbols.method23(0n);
|
remote.symbols.method23(0n);
|
||||||
remote.symbols.method23(null);
|
remote.symbols.method23(null);
|
||||||
|
|
||||||
|
// @ts-expect-error: Cannot pass number as bool.
|
||||||
|
remote.symbols.method24(0);
|
||||||
|
// @ts-expect-error: Cannot pass number as bool.
|
||||||
|
remote.symbols.method24(1);
|
||||||
|
// @ts-expect-error: Cannot pass null as bool.
|
||||||
|
remote.symbols.method24(null);
|
||||||
|
remote.symbols.method24(true);
|
||||||
|
remote.symbols.method24(false);
|
||||||
|
// @ts-expect-error: Cannot assert return type as a number.
|
||||||
|
<number> remote.symbols.method24(true);
|
||||||
|
// @ts-expect-error: Cannot assert return type truthiness.
|
||||||
|
let r24_0: true = remote.symbols.method24(true);
|
||||||
|
// @ts-expect-error: Cannot assert return type as a number.
|
||||||
|
let r42_1: number = remote.symbols.method24(true);
|
||||||
|
<boolean> remote.symbols.method24(Math.random() > 0.5);
|
||||||
|
|
||||||
// @ts-expect-error: Invalid member type
|
// @ts-expect-error: Invalid member type
|
||||||
const static1_wrong: null = remote.symbols.static1;
|
const static1_wrong: null = remote.symbols.static1;
|
||||||
const static1_right: Deno.PointerValue = remote.symbols.static1;
|
const static1_right: Deno.PointerValue = remote.symbols.static1;
|
||||||
|
@ -300,6 +321,9 @@ const static13_right: number = remote.symbols.static13;
|
||||||
// @ts-expect-error: Invalid member type
|
// @ts-expect-error: Invalid member type
|
||||||
const static14_wrong: null = remote.symbols.static14;
|
const static14_wrong: null = remote.symbols.static14;
|
||||||
const static14_right: number = remote.symbols.static14;
|
const static14_right: number = remote.symbols.static14;
|
||||||
|
// @ts-expect-error: Invalid member type
|
||||||
|
const static15_wrong: number = remote.symbols.static15;
|
||||||
|
const static15_right: boolean = remote.symbols.static15;
|
||||||
|
|
||||||
// Adapted from https://stackoverflow.com/a/53808212/10873797
|
// Adapted from https://stackoverflow.com/a/53808212/10873797
|
||||||
type Equal<T, U> = (<G>() => G extends T ? 1 : 2) extends
|
type Equal<T, U> = (<G>() => G extends T ? 1 : 2) extends
|
||||||
|
|
|
@ -78,6 +78,8 @@ fn basic() {
|
||||||
-9007199254740992n\n\
|
-9007199254740992n\n\
|
||||||
579.9119873046875\n\
|
579.9119873046875\n\
|
||||||
579.912\n\
|
579.912\n\
|
||||||
|
true\n\
|
||||||
|
false\n\
|
||||||
579\n\
|
579\n\
|
||||||
8589934590\n\
|
8589934590\n\
|
||||||
-8589934590\n\
|
-8589934590\n\
|
||||||
|
|
|
@ -59,6 +59,7 @@ const dylib = Deno.dlopen(libPath, {
|
||||||
"add_isize": { parameters: ["isize", "isize"], result: "isize" },
|
"add_isize": { parameters: ["isize", "isize"], result: "isize" },
|
||||||
"add_f32": { parameters: ["f32", "f32"], result: "f32" },
|
"add_f32": { parameters: ["f32", "f32"], result: "f32" },
|
||||||
"add_f64": { parameters: ["f64", "f64"], result: "f64" },
|
"add_f64": { parameters: ["f64", "f64"], result: "f64" },
|
||||||
|
"and": { parameters: ["bool", "bool"], result: "bool" },
|
||||||
"add_u32_nonblocking": {
|
"add_u32_nonblocking": {
|
||||||
name: "add_u32",
|
name: "add_u32",
|
||||||
parameters: ["u32", "u32"],
|
parameters: ["u32", "u32"],
|
||||||
|
@ -290,6 +291,8 @@ console.log(dylib.symbols.add_isize(Number.MAX_SAFE_INTEGER, 1));
|
||||||
console.log(dylib.symbols.add_isize(Number.MIN_SAFE_INTEGER, -1));
|
console.log(dylib.symbols.add_isize(Number.MIN_SAFE_INTEGER, -1));
|
||||||
console.log(dylib.symbols.add_f32(123.123, 456.789));
|
console.log(dylib.symbols.add_f32(123.123, 456.789));
|
||||||
console.log(dylib.symbols.add_f64(123.123, 456.789));
|
console.log(dylib.symbols.add_f64(123.123, 456.789));
|
||||||
|
console.log(dylib.symbols.and(true, true));
|
||||||
|
console.log(dylib.symbols.and(true, false));
|
||||||
|
|
||||||
// Test adders as nonblocking calls
|
// Test adders as nonblocking calls
|
||||||
console.log(await dylib.symbols.add_i32_nonblocking(123, 456));
|
console.log(await dylib.symbols.add_i32_nonblocking(123, 456));
|
||||||
|
|
Loading…
Reference in a new issue