1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-21 23:04:45 -05:00

feat(ext/ffi): better type hints for Deno.dlopen (#16874)

This commit is contained in:
阿豪 2022-12-03 20:15:35 +08:00 committed by GitHub
parent 0169949c29
commit 8b5b327b18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 19 deletions

View file

@ -443,7 +443,7 @@ declare namespace Deno {
/** The definition of the function. */
definition: Fn;
constructor(pointer: PointerValue, definition: Fn);
constructor(pointer: PointerValue, definition: Const<Fn>);
/** Call the foreign function. */
call: FromForeignFunction<Fn>;
@ -494,7 +494,7 @@ declare namespace Deno {
Definition extends UnsafeCallbackDefinition = UnsafeCallbackDefinition,
> {
constructor(
definition: Definition,
definition: Const<Definition>,
callback: UnsafeCallbackFunction<
Definition["parameters"],
Definition["result"]
@ -562,6 +562,17 @@ declare namespace Deno {
close(): void;
}
/**
* This magic code used to implement better type hints for {@linkcode Deno.dlopen}
*/
type Cast<A, B> = A extends B ? A : B;
type Const<T> = Cast<
T,
| (T extends string | number | bigint | boolean ? T : never)
| { [K in keyof T]: Const<T[K]> }
| []
>;
/** **UNSTABLE**: New API, yet to be vetted.
*
* Opens an external dynamic library and registers symbols, making foreign
@ -611,7 +622,7 @@ declare namespace Deno {
*/
export function dlopen<S extends ForeignLibraryInterface>(
filename: string | URL,
symbols: S,
symbols: Const<S>,
): DynamicLibrary<S>;
/** **UNSTABLE**: New API, yet to be vetted.

View file

@ -5,7 +5,7 @@
const remote = Deno.dlopen(
"dummy_lib.so",
{
method1: { parameters: ["usize", "usize"], result: "void", callback: true },
method1: { parameters: ["usize", "bool"], result: "void", callback: true },
method2: { parameters: [], result: "void" },
method3: { parameters: ["usize"], result: "void" },
method4: { parameters: ["isize"], result: "void" },
@ -61,16 +61,16 @@ const remote = Deno.dlopen(
static13: { type: "f32" },
static14: { type: "f64" },
static15: { type: "bool" },
} as const,
},
);
Deno.dlopen(
"dummy_lib_2.so",
// @ts-expect-error: Returning a function pointer
// is declared using "pointer" or "function" + UnsafeFnPointer
{
wrong_method1: {
parameters: [],
// @ts-expect-error not assignable to type 'NativeResultType'
result: {
function: {
parameters: [],
@ -78,14 +78,18 @@ Deno.dlopen(
},
},
},
} as const,
},
);
// @ts-expect-error: Invalid argument
remote.symbols.method1(0);
// @ts-expect-error: Invalid argument
remote.symbols.method1(0, 0);
// @ts-expect-error: Invalid argument
remote.symbols.method1(true, true);
// @ts-expect-error: Invalid return type
<number> remote.symbols.method1(0, 0);
<void> remote.symbols.method1(0n, 0n);
<number> remote.symbols.method1(0, true);
<void> remote.symbols.method1(0n, true);
// @ts-expect-error: Expected 0 arguments, but got 1.
remote.symbols.method2(null);
@ -170,7 +174,7 @@ const fnptr = new Deno.UnsafeFnPointer(
{
parameters: ["u32", "pointer"],
result: "void",
} as const,
},
);
// @ts-expect-error: Invalid argument
fnptr.call(null, null);
@ -180,7 +184,7 @@ const unsafe_callback_wrong1 = new Deno.UnsafeCallback(
{
parameters: ["i8"],
result: "void",
} as const,
},
// @ts-expect-error: i8 is not a pointer
(_: bigint) => {},
);
@ -188,7 +192,7 @@ const unsafe_callback_wrong2 = new Deno.UnsafeCallback(
{
parameters: ["pointer"],
result: "u64",
} as const,
},
// @ts-expect-error: must return a number or bigint
(_: Deno.UnsafePointer) => {},
);
@ -196,7 +200,7 @@ const unsafe_callback_wrong3 = new Deno.UnsafeCallback(
{
parameters: [],
result: "void",
} as const,
},
// @ts-expect-error: no parameters
(_: Deno.UnsafePointer) => {},
);
@ -204,7 +208,7 @@ const unsafe_callback_wrong4 = new Deno.UnsafeCallback(
{
parameters: ["u64"],
result: "void",
} as const,
},
// @ts-expect-error: Callback's 64bit parameters are either number or bigint
(_: number) => {},
);
@ -212,21 +216,21 @@ const unsafe_callback_right1 = new Deno.UnsafeCallback(
{
parameters: ["u8", "u32", "pointer"],
result: "void",
} as const,
},
(_1: number, _2: number, _3: Deno.PointerValue) => {},
);
const unsafe_callback_right2 = new Deno.UnsafeCallback(
{
parameters: [],
result: "u8",
} as const,
},
() => 3,
);
const unsafe_callback_right3 = new Deno.UnsafeCallback(
{
parameters: [],
result: "function",
} as const,
},
// Callbacks can return other callbacks' pointers, if really wanted.
() => unsafe_callback_right2.pointer,
);
@ -234,14 +238,14 @@ const unsafe_callback_right4 = new Deno.UnsafeCallback(
{
parameters: ["u8", "u32", "pointer"],
result: "u8",
} as const,
},
(_1: number, _2: number, _3: Deno.PointerValue) => 3,
);
const unsafe_callback_right5 = new Deno.UnsafeCallback(
{
parameters: ["u8", "i32", "pointer"],
result: "void",
} as const,
},
(_1: number, _2: number, _3: Deno.PointerValue) => {},
);