summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarter Snook <cartersnook04@gmail.com>2022-06-27 07:41:58 -0500
committerGitHub <noreply@github.com>2022-06-27 18:11:58 +0530
commit89fc24086142d019c9fad75fad31f97b21e0de73 (patch)
treec800c5cadd5bc4d9280769eff4b69d5130ce90e4
parent2d1c48ce171b32eb24a8438d9056ff46c44c1be8 (diff)
fix(dts/ffi): non-exact types break FFI inference (#14968)
-rw-r--r--cli/dts/lib.deno.unstable.d.ts71
-rw-r--r--test_ffi/tests/ffi_types.ts102
2 files changed, 143 insertions, 30 deletions
diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts
index 643386ced..ab6f8634f 100644
--- a/cli/dts/lib.deno.unstable.d.ts
+++ b/cli/dts/lib.deno.unstable.d.ts
@@ -362,49 +362,60 @@ declare namespace Deno {
export type NativeResultType = NativeType | NativeVoidType;
+ type ToNativeTypeMap =
+ & Record<NativeNumberType, number>
+ & Record<NativeBigIntType, bigint | number>
+ & Record<NativePointerType, TypedArray | bigint | null>
+ & Record<NativeFunctionType, bigint | null>;
+
/** Type conversion for foreign symbol parameters and unsafe callback return types */
- type ToNativeType<T extends NativeType = NativeType> = T extends
- NativeNumberType ? number
- : T extends NativeBigIntType ? bigint | number
- : T extends NativePointerType ? TypedArray | bigint | null
- : T extends NativeFunctionType ? bigint | null
- : never;
+ type ToNativeType<T extends NativeType = NativeType> = ToNativeTypeMap[T];
+
+ type ToNativeResultTypeMap = ToNativeTypeMap & Record<NativeVoidType, void>;
/** Type conversion for unsafe callback return types */
type ToNativeResultType<T extends NativeResultType = NativeResultType> =
- T extends NativeType ? ToNativeType<T>
- : T extends NativeVoidType ? void
+ ToNativeResultTypeMap[T];
+
+ type ToNativeParameterTypes<T extends readonly NativeType[]> =
+ //
+ [(T[number])[]] extends [T] ? ToNativeType<T[number]>[]
+ : [readonly (T[number])[]] extends [T]
+ ? readonly ToNativeType<T[number]>[]
+ : T extends readonly [...NativeType[]] ? {
+ [K in keyof T]: ToNativeType<T[K]>;
+ }
: never;
- type ToNativeParameterTypes<T extends readonly NativeType[]> = T extends
- readonly [] ? []
- : T extends readonly [
- infer U extends NativeType,
- ...(infer V extends NativeType[]),
- ] ? [ToNativeType<U>, ...ToNativeParameterTypes<V>]
- : never;
+ type FromNativeTypeMap =
+ & Record<NativeNumberType, number>
+ & Record<NativeBigIntType, bigint>
+ & Record<NativePointerType, bigint>
+ & Record<NativeFunctionType, bigint>;
/** Type conversion for foreign symbol return types and unsafe callback parameters */
- type FromNativeType<T extends NativeType = NativeType> = T extends
- NativeNumberType ? number
- : T extends NativeBigIntType | NativePointerType | NativeFunctionType
- ? bigint
- : never;
+ type FromNativeType<T extends NativeType = NativeType> = FromNativeTypeMap[T];
+
+ type FromNativeResultTypeMap =
+ & FromNativeTypeMap
+ & Record<NativeVoidType, void>;
/** Type conversion for foregin symbol return types */
type FromNativeResultType<T extends NativeResultType = NativeResultType> =
- T extends NativeType ? FromNativeType<T>
- : T extends NativeVoidType ? void
+ FromNativeResultTypeMap[T];
+
+ type FromNativeParameterTypes<
+ T extends readonly NativeType[],
+ > =
+ //
+ [(T[number])[]] extends [T] ? FromNativeType<T[number]>[]
+ : [readonly (T[number])[]] extends [T]
+ ? readonly FromNativeType<T[number]>[]
+ : T extends readonly [...NativeType[]] ? {
+ [K in keyof T]: FromNativeType<T[K]>;
+ }
: never;
- type FromNativeParameterTypes<T extends readonly NativeType[]> = T extends
- readonly [] ? []
- : T extends readonly [
- infer U extends NativeType,
- ...(infer V extends NativeType[]),
- ] ? [FromNativeType<U>, ...FromNativeParameterTypes<V>]
- : never;
-
/** A foreign function as defined by its parameter and result types */
export interface ForeignFunction<
Parameters extends readonly NativeType[] = readonly NativeType[],
diff --git a/test_ffi/tests/ffi_types.ts b/test_ffi/tests/ffi_types.ts
index 742f92748..dde08155d 100644
--- a/test_ffi/tests/ffi_types.ts
+++ b/test_ffi/tests/ffi_types.ts
@@ -285,3 +285,105 @@ const static13_right: number = remote.symbols.static13;
// @ts-expect-error: Invalid member type
const static14_wrong: null = remote.symbols.static14;
const static14_right: number = remote.symbols.static14;
+
+// Adapted from https://stackoverflow.com/a/53808212/10873797
+type Equal<T, U> = (<G>() => G extends T ? 1 : 2) extends
+ (<G>() => G extends U ? 1 : 2) ? true
+ : false;
+
+type AssertEqual<
+ Expected extends $,
+ Got extends $$,
+ $ = [Equal<Got, Expected>] extends [true] ? Expected
+ : ([Expected] extends [Got] ? never : Got),
+ $$ = [Equal<Expected, Got>] extends [true] ? Got
+ : ([Got] extends [Expected] ? never : Got),
+> = never;
+
+type AssertNotEqual<
+ Expected extends $,
+ Got,
+ $ = [Equal<Expected, Got>] extends [true] ? never : Expected,
+> = never;
+
+type TypedArray =
+ | Int8Array
+ | Uint8Array
+ | Int16Array
+ | Uint16Array
+ | Int32Array
+ | Uint32Array
+ | Uint8ClampedArray
+ | Float32Array
+ | Float64Array
+ | BigInt64Array
+ | BigUint64Array;
+
+type __Tests__ = [
+ empty: AssertEqual<
+ { symbols: Record<never, never>; close(): void },
+ Deno.DynamicLibrary<Record<never, never>>
+ >,
+ basic: AssertEqual<
+ { symbols: { add: (n1: number, n2: number) => number }; close(): void },
+ Deno.DynamicLibrary<{ add: { parameters: ["i32", "u8"]; result: "i32" } }>
+ >,
+ higher_order_params: AssertEqual<
+ {
+ symbols: {
+ pushBuf: (ptr: bigint | TypedArray | null, func: bigint | null) => void;
+ };
+ close(): void;
+ },
+ Deno.DynamicLibrary<
+ { pushBuf: { parameters: ["pointer", "function"]; result: "void" } }
+ >
+ >,
+ higher_order_returns: AssertEqual<
+ {
+ symbols: {
+ pushBuf: (
+ ptr: bigint | TypedArray | null,
+ func: bigint | null,
+ ) => bigint;
+ };
+ close(): void;
+ },
+ Deno.DynamicLibrary<
+ { pushBuf: { parameters: ["pointer", "function"]; result: "pointer" } }
+ >
+ >,
+ non_exact_params: AssertEqual<
+ {
+ symbols: {
+ foo: (...args: (number | bigint | TypedArray | null)[]) => bigint;
+ };
+ close(): void;
+ },
+ Deno.DynamicLibrary<
+ { foo: { parameters: ("i32" | "pointer")[]; result: "u64" } }
+ >
+ >,
+ non_exact_params_empty: AssertEqual<
+ {
+ symbols: {
+ foo: () => number;
+ };
+ close(): void;
+ },
+ Deno.DynamicLibrary<
+ { foo: { parameters: []; result: "i32" } }
+ >
+ >,
+ non_exact_params_empty: AssertNotEqual<
+ {
+ symbols: {
+ foo: (a: number) => number;
+ };
+ close(): void;
+ },
+ Deno.DynamicLibrary<
+ { foo: { parameters: []; result: "i32" } }
+ >
+ >,
+];