diff options
author | 阿豪 <504595380@qq.com> | 2022-12-03 20:15:35 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-03 17:45:35 +0530 |
commit | 8b5b327b18b1cc6b0519e632d0e9b709af18820e (patch) | |
tree | 8f38b23887fc9b62bd4358e659ebd98ef6c13c53 | |
parent | 0169949c299f05c62e5964973361217af1432171 (diff) |
feat(ext/ffi): better type hints for Deno.dlopen (#16874)
-rw-r--r-- | cli/tsc/dts/lib.deno.unstable.d.ts | 17 | ||||
-rw-r--r-- | test_ffi/tests/ffi_types.ts | 36 |
2 files changed, 34 insertions, 19 deletions
diff --git a/cli/tsc/dts/lib.deno.unstable.d.ts b/cli/tsc/dts/lib.deno.unstable.d.ts index ce609736b..9e91c8800 100644 --- a/cli/tsc/dts/lib.deno.unstable.d.ts +++ b/cli/tsc/dts/lib.deno.unstable.d.ts @@ -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. diff --git a/test_ffi/tests/ffi_types.ts b/test_ffi/tests/ffi_types.ts index e2054cfe1..a49224cfd 100644 --- a/test_ffi/tests/ffi_types.ts +++ b/test_ffi/tests/ffi_types.ts @@ -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) => {}, ); |