ffi: prefer canonical type names · nodejs/node@7670c81 · GitHub
Skip to content

Commit 7670c81

Browse files
trivikraduh95
authored andcommitted
ffi: prefer canonical type names
Document long type names as canonical and use them in examples. Group alternative spellings separately in the documentation and internal type maps while retaining support for every existing alias. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: #65417 Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Aviv Keller <me@aviv.sh> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
1 parent eb1ebbb commit 7670c81

5 files changed

Lines changed: 115 additions & 94 deletions

File tree

doc/api/ffi.md

Lines changed: 47 additions & 28 deletions

lib/internal/ffi-shared-buffer.js

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,38 +64,40 @@ const gF64 = DataViewPrototypeGetFloat64;
6464

6565
const sbTypeInfo = {
6666
__proto__: null,
67-
i8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
68-
int8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
6967
char: charIsSigned ?
7068
{ set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' } :
7169
{ set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
72-
u8: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
70+
int8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
7371
uint8: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
72+
int16: { set: sI16, get: gI16, kind: 'int', min: -32768, max: 32767, label: 'an int16' },
73+
uint16: { set: sU16, get: gU16, kind: 'int', min: 0, max: 65535, label: 'a uint16' },
74+
int32: { set: sI32, get: gI32, kind: 'int', min: -2147483648, max: 2147483647, label: 'an int32' },
75+
uint32: { set: sU32, get: gU32, kind: 'int', min: 0, max: 4294967295, label: 'a uint32' },
76+
int64: { set: sI64, get: gI64, kind: 'i64', label: 'an int64' },
77+
uint64: { set: sU64, get: gU64, kind: 'u64', label: 'a uint64' },
78+
float32: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
79+
float64: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
80+
pointer: { set: sU64, get: gU64, kind: 'pointer' },
81+
string: { set: sU64, get: gU64, kind: 'pointer' },
82+
buffer: { set: sU64, get: gU64, kind: 'pointer' },
83+
arraybuffer: { set: sU64, get: gU64, kind: 'pointer' },
84+
function: { set: sU64, get: gU64, kind: 'pointer' },
85+
86+
// Alternative spellings.
87+
i8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
88+
u8: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
7489
bool: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
7590
i16: { set: sI16, get: gI16, kind: 'int', min: -32768, max: 32767, label: 'an int16' },
76-
int16: { set: sI16, get: gI16, kind: 'int', min: -32768, max: 32767, label: 'an int16' },
7791
u16: { set: sU16, get: gU16, kind: 'int', min: 0, max: 65535, label: 'a uint16' },
78-
uint16: { set: sU16, get: gU16, kind: 'int', min: 0, max: 65535, label: 'a uint16' },
7992
i32: { set: sI32, get: gI32, kind: 'int', min: -2147483648, max: 2147483647, label: 'an int32' },
80-
int32: { set: sI32, get: gI32, kind: 'int', min: -2147483648, max: 2147483647, label: 'an int32' },
8193
u32: { set: sU32, get: gU32, kind: 'int', min: 0, max: 4294967295, label: 'a uint32' },
82-
uint32: { set: sU32, get: gU32, kind: 'int', min: 0, max: 4294967295, label: 'a uint32' },
8394
i64: { set: sI64, get: gI64, kind: 'i64', label: 'an int64' },
84-
int64: { set: sI64, get: gI64, kind: 'i64', label: 'an int64' },
8595
u64: { set: sU64, get: gU64, kind: 'u64', label: 'a uint64' },
86-
uint64: { set: sU64, get: gU64, kind: 'u64', label: 'a uint64' },
8796
f32: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
8897
float: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
89-
float32: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
9098
f64: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
9199
double: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
92-
float64: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
93-
pointer: { set: sU64, get: gU64, kind: 'pointer' },
94100
ptr: { set: sU64, get: gU64, kind: 'pointer' },
95-
function: { set: sU64, get: gU64, kind: 'pointer' },
96-
buffer: { set: sU64, get: gU64, kind: 'pointer' },
97-
arraybuffer: { set: sU64, get: gU64, kind: 'pointer' },
98-
string: { set: sU64, get: gU64, kind: 'pointer' },
99101
str: { set: sU64, get: gU64, kind: 'pointer' },
100102
};
101103

lib/internal/ffi/fast-api.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,28 @@ const fastLibraryStates = new SafeWeakMap();
4747
// conversions, so the public FFI ranges must be checked before the raw call.
4848
const fastIntegerTypeInfo = {
4949
__proto__: null,
50-
i8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
51-
int8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
5250
char: charIsSigned ?
5351
{ kind: 'number', min: -128, max: 127, label: 'an int8' } :
5452
{ kind: 'number', min: 0, max: 255, label: 'a uint8' },
55-
u8: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
53+
int8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
5654
uint8: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
55+
int16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' },
56+
uint16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' },
57+
int32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' },
58+
uint32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' },
59+
int64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' },
60+
uint64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' },
61+
62+
// Alternative spellings.
63+
i8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
64+
u8: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
5765
bool: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
5866
i16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' },
59-
int16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' },
6067
u16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' },
61-
uint16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' },
6268
i32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' },
63-
int32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' },
6469
u32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' },
65-
uint32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' },
6670
i64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' },
67-
int64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' },
6871
u64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' },
69-
uint64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' },
7072
};
7173

7274
function throwFFIArgError(msg) {
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

99101
function needsPointerLikeConversion(type) {
100-
return type === 'pointer' || type === 'ptr' || type === 'function' ||
101-
type === 'buffer' || type === 'arraybuffer';
102+
return type === 'pointer' || type === 'function' || type === 'buffer' ||
103+
type === 'arraybuffer' || type === 'ptr';
102104
}
103105

104106
function needsStringPointerConversion(type) {

src/ffi/fast.cc

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,32 @@ bool FastScalarTypeFromName(std::string_view type, FastFFIType* out) {
3636
// JavaScript wrappers handle strings and object-to-pointer conversions.
3737
if (type == "void") {
3838
*out = FastFFIType::kVoid;
39-
} else if (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} else if (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} else if (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} else if (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} else if (IsTypeName(type, {"i16", "int16"})) {
41+
} else if (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} else if (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} else if (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} else if (IsTypeName(type, {"u16", "uint16"})) {
47+
} else if (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} else if (IsTypeName(type, {"i32", "int32"})) {
49+
} else if (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} else if (IsTypeName(type, {"u32", "uint32"})) {
51+
} else if (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} else if (IsTypeName(type, {"i64", "int64"})) {
53+
} else if (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} else if (IsTypeName(type, {"u64", "uint64"})) {
55+
} else if (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} else if (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} else if (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} else if (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} else if (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} else if (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} else if (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
return false;
@@ -162,11 +160,12 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
162160
// V8 widens narrow integers to 32 bits and truncates BigInts to 64 bits for
163161
// Fast API calls. These types need a JS range check before the trampoline.
164162
for (const std::string& name : fn.arg_type_names) {
165-
if (name == "bool" || name == "char" || name == "i8" || name == "int8" ||
166-
name == "u8" || name == "uint8" || name == "i16" || name == "int16" ||
167-
name == "u16" || name == "uint16" || name == "i32" || name == "int32" ||
168-
name == "u32" || name == "uint32" || name == "i64" || name == "int64" ||
169-
name == "u64" || name == "uint64") {
163+
if (name == "char" || name == "int8" || name == "uint8" ||
164+
name == "int16" || name == "uint16" || name == "int32" ||
165+
name == "uint32" || name == "int64" || name == "uint64" ||
166+
name == "i8" || name == "u8" || name == "bool" || name == "i16" ||
167+
name == "u16" || name == "i32" || name == "u32" || name == "i64" ||
168+
name == "u64") {
170169
return true;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
bool IsPointerTypeName(const std::string& name) {
177176
// `pointer`, `ptr`, and `function` all use the same uintptr ABI slot; only
178177
// the public type spelling differs.
179-
return name == "pointer" || name == "ptr" || name == "function";
178+
return name == "pointer" || name == "function" || name == "ptr";
180179
}
181180

182181
bool IsBufferTypeName(const std::string& name) {

src/ffi/types.cc

Lines changed: 17 additions & 18 deletions

0 commit comments

Comments
 (0)