0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-08 07:16:56 -05:00

BREAKING(ext/ffi): specialized buffer type (#15518)

This commit is contained in:
Divy Srivastava 2022-08-23 09:16:43 +05:30 committed by GitHub
parent d0c5477731
commit e34260c5b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 137 additions and 101 deletions

View file

@ -395,6 +395,8 @@ declare namespace Deno {
type NativePointerType = "pointer"; type NativePointerType = "pointer";
type NativeBufferType = "buffer";
type NativeFunctionType = "function"; type NativeFunctionType = "function";
type NativeVoidType = "void"; type NativeVoidType = "void";
@ -407,6 +409,7 @@ declare namespace Deno {
| NativeNumberType | NativeNumberType
| NativeBigIntType | NativeBigIntType
| NativePointerType | NativePointerType
| NativeBufferType
| NativeFunctionType; | NativeFunctionType;
/** @category FFI */ /** @category FFI */
@ -416,8 +419,9 @@ declare namespace Deno {
type ToNativeTypeMap = type ToNativeTypeMap =
& Record<NativeNumberType, number> & Record<NativeNumberType, number>
& Record<NativeBigIntType, PointerValue> & Record<NativeBigIntType, PointerValue>
& Record<NativePointerType, TypedArray | PointerValue | null> & Record<NativePointerType, PointerValue | null>
& Record<NativeFunctionType, PointerValue | null>; & Record<NativeFunctionType, PointerValue | null>
& Record<NativeBufferType, TypedArray>;
/** Type conversion for foreign symbol parameters and unsafe callback return /** Type conversion for foreign symbol parameters and unsafe callback return
* types. * types.
@ -452,6 +456,7 @@ declare namespace Deno {
& Record<NativeNumberType, number> & Record<NativeNumberType, number>
& Record<NativeBigIntType, PointerValue> & Record<NativeBigIntType, PointerValue>
& Record<NativePointerType, PointerValue> & Record<NativePointerType, PointerValue>
& Record<NativeBufferType, PointerValue>
& Record<NativeFunctionType, PointerValue>; & Record<NativeFunctionType, PointerValue>;
/** Type conversion for foreign symbol return types and unsafe callback /** Type conversion for foreign symbol return types and unsafe callback

View file

@ -216,7 +216,7 @@
} }
function isPointerType(type) { function isPointerType(type) {
return type === "pointer" || return type === "buffer" || type === "pointer" ||
typeof type === "object" && type !== null && "function" in type; typeof type === "object" && type !== null && "function" in type;
} }

View file

@ -32,8 +32,8 @@ fn native_arg_to_c(ty: &NativeType) -> &'static str {
NativeType::I64 => "int64_t", NativeType::I64 => "int64_t",
NativeType::ISize => "intptr_t", NativeType::ISize => "intptr_t",
NativeType::USize => "uintptr_t", NativeType::USize => "uintptr_t",
NativeType::Pointer => "struct FastApiTypedArray*", NativeType::Buffer => "struct FastApiTypedArray*",
NativeType::Function => "void*", NativeType::Function | NativeType::Pointer => "void*",
} }
} }
@ -52,7 +52,7 @@ fn native_to_c(ty: &NativeType) -> &'static str {
NativeType::I64 => "int64_t", NativeType::I64 => "int64_t",
NativeType::ISize => "intptr_t", NativeType::ISize => "intptr_t",
NativeType::USize => "uintptr_t", NativeType::USize => "uintptr_t",
NativeType::Pointer | NativeType::Function => "void*", NativeType::Pointer | NativeType::Buffer | NativeType::Function => "void*",
} }
} }
@ -97,7 +97,7 @@ pub(crate) fn codegen(sym: &crate::Symbol) -> String {
if i > 0 { if i > 0 {
call_s += ", "; call_s += ", ";
} }
if matches!(ty, NativeType::Pointer) { if matches!(ty, NativeType::Buffer) {
let _ = write!(call_s, "p{i}->data"); let _ = write!(call_s, "p{i}->data");
} else { } else {
let _ = write!(call_s, "p{i}"); let _ = write!(call_s, "p{i}");
@ -195,14 +195,14 @@ mod tests {
}\n\n", }\n\n",
); );
assert_codegen( assert_codegen(
codegen(vec![NativeType::Pointer, NativeType::U32], NativeType::U32), codegen(vec![NativeType::Buffer, NativeType::U32], NativeType::U32),
"extern uint32_t func(void* p0, uint32_t p1);\n\n\ "extern uint32_t func(void* p0, uint32_t p1);\n\n\
uint32_t func_trampoline(void* recv, struct FastApiTypedArray* p0, uint32_t p1) {\ uint32_t func_trampoline(void* recv, struct FastApiTypedArray* p0, uint32_t p1) {\
\n return func(p0->data, p1);\n\ \n return func(p0->data, p1);\n\
}\n\n", }\n\n",
); );
assert_codegen( assert_codegen(
codegen(vec![NativeType::Pointer, NativeType::Pointer], NativeType::U32), codegen(vec![NativeType::Buffer, NativeType::Buffer], NativeType::U32),
"extern uint32_t func(void* p0, void* p1);\n\n\ "extern uint32_t func(void* p0, void* p1);\n\n\
uint32_t func_trampoline(void* recv, struct FastApiTypedArray* p0, struct FastApiTypedArray* p1) {\ uint32_t func_trampoline(void* recv, struct FastApiTypedArray* p0, struct FastApiTypedArray* p1) {\
\n return func(p0->data, p1->data);\n\ \n return func(p0->data, p1->data);\n\
@ -217,13 +217,21 @@ mod tests {
}\n\n", }\n\n",
); );
assert_codegen( assert_codegen(
codegen(vec![NativeType::Pointer, NativeType::Pointer], NativeType::U64), codegen(vec![NativeType::Buffer, NativeType::Buffer], NativeType::U64),
"extern uint64_t func(void* p0, void* p1);\n\n\ "extern uint64_t func(void* p0, void* p1);\n\n\
void func_trampoline(void* recv, struct FastApiTypedArray* p0, struct FastApiTypedArray* p1, struct FastApiTypedArray* const p_ret) {\ void func_trampoline(void* recv, struct FastApiTypedArray* p0, struct FastApiTypedArray* p1, struct FastApiTypedArray* const p_ret) {\
\n uint64_t r = func(p0->data, p1->data);\ \n uint64_t r = func(p0->data, p1->data);\
\n ((uint64_t*)p_ret->data)[0] = r;\n\ \n ((uint64_t*)p_ret->data)[0] = r;\n\
}\n\n", }\n\n",
); );
assert_codegen(
codegen(vec![NativeType::Pointer, NativeType::Pointer], NativeType::U64),
"extern uint64_t func(void* p0, void* p1);\n\n\
void func_trampoline(void* recv, void* p0, void* p1, struct FastApiTypedArray* const p_ret) {\
\n uint64_t r = func(p0, p1);\
\n ((uint64_t*)p_ret->data)[0] = r;\n\
}\n\n",
);
} }
#[test] #[test]

View file

@ -266,6 +266,7 @@ enum NativeType {
F32, F32,
F64, F64,
Pointer, Pointer,
Buffer,
Function, Function,
} }
@ -285,8 +286,9 @@ impl From<NativeType> for libffi::middle::Type {
NativeType::ISize => libffi::middle::Type::isize(), NativeType::ISize => libffi::middle::Type::isize(),
NativeType::F32 => libffi::middle::Type::f32(), NativeType::F32 => libffi::middle::Type::f32(),
NativeType::F64 => libffi::middle::Type::f64(), NativeType::F64 => libffi::middle::Type::f64(),
NativeType::Pointer => libffi::middle::Type::pointer(), NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
NativeType::Function => libffi::middle::Type::pointer(), libffi::middle::Type::pointer()
}
} }
} }
} }
@ -327,7 +329,9 @@ impl NativeValue {
NativeType::ISize => Arg::new(&self.isize_value), NativeType::ISize => Arg::new(&self.isize_value),
NativeType::F32 => Arg::new(&self.f32_value), NativeType::F32 => Arg::new(&self.f32_value),
NativeType::F64 => Arg::new(&self.f64_value), NativeType::F64 => Arg::new(&self.f64_value),
NativeType::Pointer | NativeType::Function => Arg::new(&self.pointer), NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
Arg::new(&self.pointer)
}
} }
} }
@ -375,7 +379,7 @@ impl NativeValue {
} }
NativeType::F32 => Value::from(self.f32_value), NativeType::F32 => Value::from(self.f32_value),
NativeType::F64 => Value::from(self.f64_value), NativeType::F64 => Value::from(self.f64_value),
NativeType::Pointer | NativeType::Function => { NativeType::Pointer | NativeType::Function | NativeType::Buffer => {
let value = self.pointer as usize; let value = self.pointer as usize;
if value > MAX_SAFE_INTEGER as usize { if value > MAX_SAFE_INTEGER as usize {
json!(U32x2::from(value as u64)) json!(U32x2::from(value as u64))
@ -479,7 +483,7 @@ impl NativeValue {
v8::Number::new(scope, self.f64_value).into(); v8::Number::new(scope, self.f64_value).into();
local_value.into() local_value.into()
} }
NativeType::Pointer | NativeType::Function => { NativeType::Pointer | NativeType::Buffer | NativeType::Function => {
let value = self.pointer as u64; let value = self.pointer as u64;
let local_value: v8::Local<v8::Value> = let local_value: v8::Local<v8::Value> =
if value > MAX_SAFE_INTEGER as u64 { if value > MAX_SAFE_INTEGER as u64 {
@ -751,8 +755,10 @@ impl From<&NativeType> for fast_api::Type {
NativeType::I64 => fast_api::Type::Int64, NativeType::I64 => fast_api::Type::Int64,
NativeType::U64 => fast_api::Type::Uint64, NativeType::U64 => fast_api::Type::Uint64,
NativeType::ISize => fast_api::Type::Int64, NativeType::ISize => fast_api::Type::Int64,
NativeType::USize | NativeType::Function => fast_api::Type::Uint64, NativeType::USize | NativeType::Pointer | NativeType::Function => {
NativeType::Pointer => fast_api::Type::TypedArray(fast_api::CType::Uint8), fast_api::Type::Uint64
}
NativeType::Buffer => fast_api::Type::TypedArray(fast_api::CType::Uint8),
} }
} }
} }
@ -762,6 +768,7 @@ fn needs_unwrap(rv: NativeType) -> bool {
rv, rv,
NativeType::Function NativeType::Function
| NativeType::Pointer | NativeType::Pointer
| NativeType::Buffer
| NativeType::I64 | NativeType::I64
| NativeType::ISize | NativeType::ISize
| NativeType::U64 | NativeType::U64
@ -1064,14 +1071,37 @@ fn ffi_parse_pointer_arg(
arg: v8::Local<v8::Value>, arg: v8::Local<v8::Value>,
) -> Result<NativeValue, AnyError> { ) -> Result<NativeValue, AnyError> {
// Order of checking: // Order of checking:
// 1. ArrayBufferView: Common and not supported by Fast API, optimise this case. // 1. BigInt: Uncommon and not supported by Fast API, optimise this case.
// 2. BigInt: Uncommon and not supported by Fast API, optimise this case as second. // 2. Number: Common and supported by Fast API.
// 3. Number: Common and supported by Fast API, optimise the common case third. // 3. Null: Very uncommon / can be represented by a 0.
// 4. ArrayBuffer: Fairly common and not supported by Fast API. let pointer = if let Ok(value) = v8::Local::<v8::BigInt>::try_from(arg) {
value.u64_value().0 as usize as *const u8
} else if let Ok(value) = v8::Local::<v8::Number>::try_from(arg) {
value.integer_value(scope).unwrap() as usize as *const u8
} else if arg.is_null() {
ptr::null()
} else {
return Err(type_error(
"Invalid FFI pointer type, expected null, integer or BigInt",
));
};
Ok(NativeValue { pointer })
}
#[inline]
fn ffi_parse_buffer_arg(
scope: &mut v8::HandleScope,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, AnyError> {
// Order of checking:
// 1. ArrayBuffer: Fairly common and not supported by Fast API, optimise this case.
// 2. ArrayBufferView: Common and supported by Fast API
// 5. Null: Very uncommon / can be represented by a 0. // 5. Null: Very uncommon / can be represented by a 0.
let pointer = if let Ok(value) =
v8::Local::<v8::ArrayBufferView>::try_from(arg) let pointer = if let Ok(value) = v8::Local::<v8::ArrayBuffer>::try_from(arg) {
{ let backing_store = value.get_backing_store();
&backing_store[..] as *const _ as *const u8
} else if let Ok(value) = v8::Local::<v8::ArrayBufferView>::try_from(arg) {
let byte_offset = value.byte_offset(); let byte_offset = value.byte_offset();
let backing_store = value let backing_store = value
.buffer(scope) .buffer(scope)
@ -1080,17 +1110,12 @@ fn ffi_parse_pointer_arg(
})? })?
.get_backing_store(); .get_backing_store();
&backing_store[byte_offset..] as *const _ as *const u8 &backing_store[byte_offset..] as *const _ as *const u8
} else if let Ok(value) = v8::Local::<v8::BigInt>::try_from(arg) {
value.u64_value().0 as usize as *const u8
} else if let Ok(value) = v8::Local::<v8::Number>::try_from(arg) {
value.integer_value(scope).unwrap() as usize as *const u8
} else if let Ok(value) = v8::Local::<v8::ArrayBuffer>::try_from(arg) {
let backing_store = value.get_backing_store();
&backing_store[..] as *const _ as *const u8
} else if arg.is_null() { } else if arg.is_null() {
ptr::null() ptr::null()
} else { } else {
return Err(type_error("Invalid FFI pointer type, expected null, integer, BigInt, ArrayBuffer, or ArrayBufferView")); return Err(type_error(
"Invalid FFI buffer type, expected null, ArrayBuffer, or ArrayBufferView",
));
}; };
Ok(NativeValue { pointer }) Ok(NativeValue { pointer })
} }
@ -1174,6 +1199,9 @@ where
NativeType::F64 => { NativeType::F64 => {
ffi_args.push(ffi_parse_f64_arg(value)?); ffi_args.push(ffi_parse_f64_arg(value)?);
} }
NativeType::Buffer => {
ffi_args.push(ffi_parse_buffer_arg(scope, value)?);
}
NativeType::Pointer => { NativeType::Pointer => {
ffi_args.push(ffi_parse_pointer_arg(scope, value)?); ffi_args.push(ffi_parse_pointer_arg(scope, value)?);
} }
@ -1247,6 +1275,9 @@ where
NativeType::F64 => { NativeType::F64 => {
ffi_args.push(ffi_parse_f64_arg(value)?); ffi_args.push(ffi_parse_f64_arg(value)?);
} }
NativeType::Buffer => {
ffi_args.push(ffi_parse_buffer_arg(scope, value)?);
}
NativeType::Pointer => { NativeType::Pointer => {
ffi_args.push(ffi_parse_pointer_arg(scope, value)?); ffi_args.push(ffi_parse_pointer_arg(scope, value)?);
} }
@ -1302,9 +1333,11 @@ where
NativeType::F64 => NativeValue { NativeType::F64 => NativeValue {
f64_value: cif.call::<f64>(*fun_ptr, &call_args), f64_value: cif.call::<f64>(*fun_ptr, &call_args),
}, },
NativeType::Pointer | NativeType::Function => NativeValue { NativeType::Pointer | NativeType::Function | NativeType::Buffer => {
pointer: cif.call::<*const u8>(*fun_ptr, &call_args), NativeValue {
}, pointer: cif.call::<*const u8>(*fun_ptr, &call_args),
}
}
}) })
} }
} }
@ -1368,9 +1401,11 @@ fn ffi_call(
NativeType::F64 => NativeValue { NativeType::F64 => NativeValue {
f64_value: cif.call::<f64>(fun_ptr, &call_args), f64_value: cif.call::<f64>(fun_ptr, &call_args),
}, },
NativeType::Pointer | NativeType::Function => NativeValue { NativeType::Pointer | NativeType::Function | NativeType::Buffer => {
pointer: cif.call::<*const u8>(fun_ptr, &call_args), NativeValue {
}, pointer: cif.call::<*const u8>(fun_ptr, &call_args),
}
}
}) })
} }
} }
@ -2004,7 +2039,7 @@ fn op_ffi_get_static<'scope>(
let number: v8::Local<v8::Value> = v8::Number::new(scope, result).into(); let number: v8::Local<v8::Value> = v8::Number::new(scope, result).into();
number.into() number.into()
} }
NativeType::Pointer | NativeType::Function => { NativeType::Pointer | NativeType::Function | NativeType::Buffer => {
let result = data_ptr as u64; let result = data_ptr as u64;
let integer: v8::Local<v8::Value> = if result > MAX_SAFE_INTEGER as u64 { let integer: v8::Local<v8::Value> = if result > MAX_SAFE_INTEGER as u64 {
v8::BigInt::new_from_u64(scope, result).into() v8::BigInt::new_from_u64(scope, result).into()

View file

@ -14,7 +14,7 @@ const dylib = Deno.dlopen(libPath, {
"add_u32": { parameters: ["u32", "u32"], result: "u32" }, "add_u32": { parameters: ["u32", "u32"], result: "u32" },
"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: ["pointer", "u32"], result: "u32" }, "hash": { parameters: ["buffer", "u32"], result: "u32" },
"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" },
@ -27,7 +27,7 @@ const dylib = Deno.dlopen(libPath, {
"nop_isize": { parameters: ["isize"], result: "void" }, "nop_isize": { parameters: ["isize"], result: "void" },
"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: ["pointer"], result: "void" }, "nop_buffer": { parameters: ["buffer"], result: "void" },
"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" },
@ -40,7 +40,7 @@ const dylib = Deno.dlopen(libPath, {
"return_isize": { parameters: [], result: "isize" }, "return_isize": { parameters: [], result: "isize" },
"return_f32": { parameters: [], result: "f32" }, "return_f32": { parameters: [], result: "f32" },
"return_f64": { parameters: [], result: "f64" }, "return_f64": { parameters: [], result: "f64" },
"return_buffer": { parameters: [], result: "pointer" }, "return_buffer": { parameters: [], result: "buffer" },
// Nonblocking calls // Nonblocking calls
"nop_nonblocking": { name: "nop", parameters: [], result: "void" }, "nop_nonblocking": { name: "nop", parameters: [], result: "void" },
"nop_u8_nonblocking": { name: "nop_u8", parameters: ["u8"], result: "void" }, "nop_u8_nonblocking": { name: "nop_u8", parameters: ["u8"], result: "void" },
@ -97,7 +97,7 @@ const dylib = Deno.dlopen(libPath, {
}, },
"nop_buffer_nonblocking": { "nop_buffer_nonblocking": {
name: "nop_buffer", name: "nop_buffer",
parameters: ["pointer"], parameters: ["buffer"],
result: "void", result: "void",
}, },
"return_u8_nonblocking": { name: "return_u8", parameters: [], result: "u8" }, "return_u8_nonblocking": { name: "return_u8", parameters: [], result: "u8" },
@ -155,7 +155,7 @@ const dylib = Deno.dlopen(libPath, {
"return_buffer_nonblocking": { "return_buffer_nonblocking": {
name: "return_buffer", name: "return_buffer",
parameters: [], parameters: [],
result: "pointer", result: "buffer",
}, },
// Parameter checking // Parameter checking
"nop_many_parameters": { "nop_many_parameters": {
@ -172,7 +172,7 @@ const dylib = Deno.dlopen(libPath, {
"isize", "isize",
"f32", "f32",
"f64", "f64",
"pointer", "buffer",
"u8", "u8",
"i8", "i8",
"u16", "u16",
@ -185,7 +185,7 @@ const dylib = Deno.dlopen(libPath, {
"isize", "isize",
"f32", "f32",
"f64", "f64",
"pointer", "buffer",
], ],
result: "void", result: "void",
}, },
@ -343,11 +343,6 @@ Deno.bench("nop_buffer()", () => {
nop_buffer(buffer); nop_buffer(buffer);
}); });
const buffer_ptr = Deno.UnsafePointer.of(buffer);
Deno.bench("nop_buffer() number", () => {
nop_buffer(buffer_ptr);
});
const { return_u8 } = dylib.symbols; const { return_u8 } = dylib.symbols;
Deno.bench("return_u8()", () => { Deno.bench("return_u8()", () => {
return_u8(); return_u8();
@ -431,6 +426,7 @@ Deno.bench("nop_u32_nonblocking()", async () => {
}); });
const { nop_i32_nonblocking } = dylib.symbols; const { nop_i32_nonblocking } = dylib.symbols;
Deno.bench("nop_i32_nonblocking()", async () => { Deno.bench("nop_i32_nonblocking()", async () => {
await nop_i32_nonblocking(100); await nop_i32_nonblocking(100);
}); });
@ -469,11 +465,6 @@ 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);
}); });
Deno.bench("nop_buffer_nonblocking() number", async () => {
await nop_buffer_nonblocking(buffer_ptr);
});
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();
@ -574,38 +565,6 @@ Deno.bench("nop_many_parameters()", () => {
); );
}); });
const buffer2_ptr = Deno.UnsafePointer.of(buffer2);
Deno.bench("nop_many_parameters() number", () => {
nop_many_parameters(
135,
47,
356,
-236,
7457,
-1356,
16471468,
-1334748136,
132658769535,
-42745856824,
13567.26437,
7.686234e-3,
buffer_ptr,
64,
-42,
83,
-136,
3657,
-2376,
3277918,
-474628146,
344657895,
-2436732,
135.26437e3,
264.3576468623546834,
buffer2_ptr,
);
});
const { nop_many_parameters_nonblocking } = dylib.symbols; const { nop_many_parameters_nonblocking } = dylib.symbols;
Deno.bench("nop_many_parameters_nonblocking()", () => { Deno.bench("nop_many_parameters_nonblocking()", () => {
nop_many_parameters_nonblocking( nop_many_parameters_nonblocking(

View file

@ -38,6 +38,10 @@ const remote = Deno.dlopen(
parameters: ["pointer"], parameters: ["pointer"],
result: "void", result: "void",
}, },
method23: {
parameters: ["buffer"],
result: "void",
},
static1: { type: "usize" }, static1: { type: "usize" },
static2: { type: "pointer" }, static2: { type: "pointer" },
static3: { type: "usize" }, static3: { type: "usize" },
@ -132,6 +136,7 @@ remote.symbols.method14(0);
// @ts-expect-error: Invalid argument // @ts-expect-error: Invalid argument
remote.symbols.method15("foo"); remote.symbols.method15("foo");
// @ts-expect-error: Invalid argument
remote.symbols.method15(new Uint16Array(1)); remote.symbols.method15(new Uint16Array(1));
remote.symbols.method15(0n); remote.symbols.method15(0n);
@ -243,6 +248,17 @@ remote.symbols.method20(null);
remote.symbols.method20(unsafe_callback_right2); remote.symbols.method20(unsafe_callback_right2);
remote.symbols.method20(unsafe_callback_right1.pointer); remote.symbols.method20(unsafe_callback_right1.pointer);
remote.symbols.method23(new Uint8Array(1));
remote.symbols.method23(new Uint32Array(1));
remote.symbols.method23(new Uint8Array(1));
// @ts-expect-error: Cannot pass pointer values as buffer.
remote.symbols.method23(0);
// @ts-expect-error: Cannot pass pointer values as buffer.
remote.symbols.method23(0n);
// @ts-expect-error: Cannot pass pointer values as buffer.
remote.symbols.method23(null);
// @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;
@ -332,35 +348,47 @@ type __Tests__ = [
{ {
symbols: { symbols: {
pushBuf: ( pushBuf: (
ptr: number | bigint | TypedArray | null, buf: TypedArray,
ptr: number | bigint | null,
func: number | bigint | null, func: number | bigint | null,
) => void; ) => void;
}; };
close(): void; close(): void;
}, },
Deno.DynamicLibrary< Deno.DynamicLibrary<
{ pushBuf: { parameters: ["pointer", "function"]; result: "void" } } {
pushBuf: {
parameters: ["buffer", "pointer", "function"];
result: "void";
};
}
> >
>, >,
higher_order_returns: AssertEqual< higher_order_returns: AssertEqual<
{ {
symbols: { symbols: {
pushBuf: ( pushBuf: (
ptr: number | bigint | TypedArray | null, buf: TypedArray,
ptr: number | bigint | null,
func: number | bigint | null, func: number | bigint | null,
) => number | bigint; ) => number | bigint;
}; };
close(): void; close(): void;
}, },
Deno.DynamicLibrary< Deno.DynamicLibrary<
{ pushBuf: { parameters: ["pointer", "function"]; result: "pointer" } } {
pushBuf: {
parameters: ["buffer", "pointer", "function"];
result: "pointer";
};
}
> >
>, >,
non_exact_params: AssertEqual< non_exact_params: AssertEqual<
{ {
symbols: { symbols: {
foo: ( foo: (
...args: (number | bigint | TypedArray | null)[] ...args: (number | bigint | null)[]
) => number | bigint; ) => number | bigint;
}; };
close(): void; close(): void;

View file

@ -42,12 +42,13 @@ const dylib = Deno.dlopen(libPath, {
parameters: [], parameters: [],
result: "void", result: "void",
}, },
"print_buffer": { parameters: ["pointer", "usize"], result: "void" }, "print_buffer": { parameters: ["buffer", "usize"], result: "void" },
"print_pointer": { name: "print_buffer", parameters: ["pointer", "usize"], result: "void" },
"print_buffer2": { "print_buffer2": {
parameters: ["pointer", "usize", "pointer", "usize"], parameters: ["buffer", "usize", "buffer", "usize"],
result: "void", result: "void",
}, },
"return_buffer": { parameters: [], result: "pointer" }, "return_buffer": { parameters: [], result: "buffer" },
"is_null_ptr": { parameters: ["pointer"], result: "u8" }, "is_null_ptr": { parameters: ["pointer"], result: "u8" },
"add_u32": { parameters: ["u32", "u32"], result: "u32" }, "add_u32": { parameters: ["u32", "u32"], result: "u32" },
"add_i32": { parameters: ["i32", "i32"], result: "i32" }, "add_i32": { parameters: ["i32", "i32"], result: "i32" },
@ -106,7 +107,7 @@ const dylib = Deno.dlopen(libPath, {
result: "f64", result: "f64",
nonblocking: true, nonblocking: true,
}, },
"fill_buffer": { parameters: ["u8", "pointer", "usize"], result: "void" }, "fill_buffer": { parameters: ["u8", "buffer", "usize"], result: "void" },
"sleep_nonblocking": { "sleep_nonblocking": {
name: "sleep_blocking", name: "sleep_blocking",
parameters: ["u64"], parameters: ["u64"],
@ -115,7 +116,7 @@ const dylib = Deno.dlopen(libPath, {
}, },
"sleep_blocking": { parameters: ["u64"], result: "void" }, "sleep_blocking": { parameters: ["u64"], result: "void" },
"nonblocking_buffer": { "nonblocking_buffer": {
parameters: ["pointer", "usize"], parameters: ["buffer", "usize"],
result: "void", result: "void",
nonblocking: true, nonblocking: true,
}, },
@ -214,7 +215,7 @@ if (!(status & (1 << 4))) {
throw new Error("returnBuffer is not optimized"); throw new Error("returnBuffer is not optimized");
} }
dylib.symbols.print_buffer(ptr0, 8); dylib.symbols.print_pointer(ptr0, 8);
const ptrView = new Deno.UnsafePointerView(ptr0); const ptrView = new Deno.UnsafePointerView(ptr0);
const into = new Uint8Array(6); const into = new Uint8Array(6);
const into2 = new Uint8Array(3); const into2 = new Uint8Array(3);
@ -239,9 +240,9 @@ console.log(Boolean(dylib.symbols.is_null_ptr(ptr0)));
console.log(Boolean(dylib.symbols.is_null_ptr(null))); console.log(Boolean(dylib.symbols.is_null_ptr(null)));
console.log(Boolean(dylib.symbols.is_null_ptr(Deno.UnsafePointer.of(into)))); console.log(Boolean(dylib.symbols.is_null_ptr(Deno.UnsafePointer.of(into))));
const emptyBuffer = new BigUint64Array(0); const emptyBuffer = new BigUint64Array(0);
console.log(Boolean(dylib.symbols.is_null_ptr(emptyBuffer))); console.log(Boolean(dylib.symbols.is_null_ptr(Deno.UnsafePointer.of(emptyBuffer))));
const emptySlice = into.subarray(6); const emptySlice = into.subarray(6);
console.log(Boolean(dylib.symbols.is_null_ptr(emptySlice))); console.log(Boolean(dylib.symbols.is_null_ptr(Deno.UnsafePointer.of(emptySlice))));
const addU32Ptr = dylib.symbols.get_add_u32_ptr(); const addU32Ptr = dylib.symbols.get_add_u32_ptr();
const addU32 = new Deno.UnsafeFnPointer(addU32Ptr, { const addU32 = new Deno.UnsafeFnPointer(addU32Ptr, {