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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,40 @@ Supported type names:
6363

6464
*`void`
6565
*`char`
66-
*`i8`, `int8`
67-
*`u8`, `uint8`, `bool`
68-
*`i16`, `int16`
69-
*`u16`, `uint16`
70-
*`i32`, `int32`
71-
*`u32`, `uint32`
72-
*`i64`, `int64`
73-
*`u64`, `uint64`
74-
*`f32`, `float`, `float32`
75-
*`f64`, `double`, `float64`
76-
*`pointer`, `ptr`
77-
*`string`, `str`
66+
*`int8`
67+
*`uint8`
68+
*`int16`
69+
*`uint16`
70+
*`int32`
71+
*`uint32`
72+
*`int64`
73+
*`uint64`
74+
*`float32`
75+
*`float64`
76+
*`pointer`
77+
*`string`
7878
*`buffer`
7979
*`arraybuffer`
8080
*`function`
8181

82+
<details>
83+
<summary>Alternative spellings</summary>
84+
85+
*`i8` for `int8`
86+
*`u8` and `bool` for `uint8`
87+
*`i16` for `int16`
88+
*`u16` for `uint16`
89+
*`i32` for `int32`
90+
*`u32` for `uint32`
91+
*`i64` for `int64`
92+
*`u64` for `uint64`
93+
*`f32` and `float` for `float32`
94+
*`f64` and `double` for `float64`
95+
*`ptr` for `pointer`
96+
*`str` for `string`
97+
98+
</details>
99+
82100
These type names are also exposed as constants on `ffi.types`:
83101

84102
*`ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
116134
process, produce incorrect output, or corrupt memory.
117135

118136
The `char` type follows the platform C ABI. On platforms where plain C `char`
119-
is signed it behaves like `i8`; otherwise it behaves like `u8`.
137+
is signed it behaves like `int8`; otherwise it behaves like `uint8`.
120138

121139
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
122140
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
123141

124-
On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
125-
raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
126-
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
127-
converted on the JavaScript side before calling the optimized native wrapper.
142+
On optimized Fast FFI calls, `pointer`and `function` parameters accept raw
143+
pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
144+
strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
145+
on the JavaScript side before calling the optimized native wrapper.
128146

129147
Optimized Fast FFI calls fall back to the generic FFI call path when a
130148
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
161179

162180
```js
163181
constsignature= {
164-
return:'i32',
165-
arguments: ['i32', 'i32'],
182+
return:'int32',
183+
arguments: ['int32', 'int32'],
166184
};
167185
```
168186

@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
220238

221239
{
222240
using handle =dlopen(`./mylib.${suffix}`, {
223-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
241+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
224242
});
225243
console.log(handle.functions.add_i32(20, 22));
226244
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
230248
import { dlopen, suffix } from'node:ffi';
231249

232250
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
233-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
234-
string_length: { arguments: ['pointer'], return:'u64' },
251+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
252+
string_length: { arguments: ['pointer'], return:'uint64' },
235253
});
236254

237255
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
241259
const { dlopen, suffix } =require('node:ffi');
242260

243261
const { lib, functions } =dlopen(`./mylib.${suffix}`, {
244-
add_i32: { arguments: ['i32', 'i32'], return:'i32' },
245-
string_length: { arguments: ['pointer'], return:'u64' },
262+
add_i32: { arguments: ['int32', 'int32'], return:'int32' },
263+
string_length: { arguments: ['pointer'], return:'uint64' },
246264
});
247265

248266
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
384402

385403
constlib=newDynamicLibrary(`./mylib.${suffix}`);
386404
constadd=lib.getFunction('add_i32', {
387-
arguments: ['i32', 'i32'],
388-
return:'i32',
405+
arguments: ['int32', 'int32'],
406+
return:'int32',
389407
});
390408

391409
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
435453
constlib=newDynamicLibrary(`./mylib.${suffix}`);
436454

437455
constcallback=lib.registerCallback(
438-
{ arguments: ['i32'], return:'i32' },
456+
{ arguments: ['int32'], return:'int32' },
439457
(value) => value *2,
440458
);
441459
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
498516
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
499517
JavaScript `number` values that match the declared type.
500518

501-
For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
519+
For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
520+
values.
502521

503522
For pointer-like arguments:
504523

β€Ž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
constsbTypeInfo={
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
constfastIntegerTypeInfo={
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
functionthrowFFIArgError(msg){
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
9799
}
98100

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

104106
functionneedsStringPointerConversion(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-
} elseif (type == "bool") {
40-
*out = FastFFIType::kUint8;
41-
} elseif (IsTypeName(type, {"i8", "int8"})) {
42-
*out = FastFFIType::kInt8;
43-
} elseif (IsTypeName(type, {"u8", "uint8"})) {
44-
*out = FastFFIType::kUint8;
4539
} elseif (type == "char") {
4640
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
47-
} elseif (IsTypeName(type, {"i16", "int16"})) {
41+
} elseif (IsTypeName(type, {"int8", "i8"})) {
42+
*out = FastFFIType::kInt8;
43+
} elseif (IsTypeName(type, {"uint8", "u8", "bool"})) {
44+
*out = FastFFIType::kUint8;
45+
} elseif (IsTypeName(type, {"int16", "i16"})) {
4846
*out = FastFFIType::kInt16;
49-
} elseif (IsTypeName(type, {"u16", "uint16"})) {
47+
} elseif (IsTypeName(type, {"uint16", "u16"})) {
5048
*out = FastFFIType::kUint16;
51-
} elseif (IsTypeName(type, {"i32", "int32"})) {
49+
} elseif (IsTypeName(type, {"int32", "i32"})) {
5250
*out = FastFFIType::kInt32;
53-
} elseif (IsTypeName(type, {"u32", "uint32"})) {
51+
} elseif (IsTypeName(type, {"uint32", "u32"})) {
5452
*out = FastFFIType::kUint32;
55-
} elseif (IsTypeName(type, {"i64", "int64"})) {
53+
} elseif (IsTypeName(type, {"int64", "i64"})) {
5654
*out = FastFFIType::kInt64;
57-
} elseif (IsTypeName(type, {"u64", "uint64"})) {
55+
} elseif (IsTypeName(type, {"uint64", "u64"})) {
5856
*out = FastFFIType::kUint64;
59-
} elseif (IsTypeName(type, {"f32", "float", "float32"})) {
57+
} elseif (IsTypeName(type, {"float32", "f32", "float"})) {
6058
*out = FastFFIType::kFloat32;
61-
} elseif (IsTypeName(type, {"f64", "double", "float64"})) {
59+
} elseif (IsTypeName(type, {"float64", "f64", "double"})) {
6260
*out = FastFFIType::kFloat64;
6361
} elseif (IsTypeName(type, {"buffer", "arraybuffer"})) {
6462
*out = FastFFIType::kPointer;
6563
} elseif (IsTypeName(type,
66-
{"pointer", "ptr", "string", "str", "function"})) {
64+
{"pointer", "string", "function", "ptr", "str"})) {
6765
*out = FastFFIType::kPointer;
6866
} else {
6967
returnfalse;
@@ -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
returntrue;
171170
}
172171
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
176175
boolIsPointerTypeName(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
boolIsBufferTypeName(const std::string& name) {

β€Žsrc/ffi/types.ccβ€Ž

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
552552
v8::Maybe<ffi_type*> ToFFIType(Environment* env, std::string_view type_str) {
553553
if (type_str == "void") {
554554
returnJust(&ffi_type_void);
555-
} elseif (type_str == "i8" || type_str == "int8") {
556-
returnJust(&ffi_type_sint8);
557-
} elseif (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
558-
returnJust(&ffi_type_uint8);
559555
} elseif (type_str == "char") {
560556
returnJust(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
561-
} elseif (type_str == "i16" || type_str == "int16") {
557+
} elseif (type_str == "int8" || type_str == "i8") {
558+
returnJust(&ffi_type_sint8);
559+
} elseif (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
560+
returnJust(&ffi_type_uint8);
561+
} elseif (type_str == "int16" || type_str == "i16") {
562562
returnJust(&ffi_type_sint16);
563-
} elseif (type_str == "u16" || type_str == "uint16") {
563+
} elseif (type_str == "uint16" || type_str == "u16") {
564564
returnJust(&ffi_type_uint16);
565-
} elseif (type_str == "i32" || type_str == "int32") {
565+
} elseif (type_str == "int32" || type_str == "i32") {
566566
returnJust(&ffi_type_sint32);
567-
} elseif (type_str == "u32" || type_str == "uint32") {
567+
} elseif (type_str == "uint32" || type_str == "u32") {
568568
returnJust(&ffi_type_uint32);
569-
} elseif (type_str == "i64" || type_str == "int64") {
569+
} elseif (type_str == "int64" || type_str == "i64") {
570570
returnJust(&ffi_type_sint64);
571-
} elseif (type_str == "u64" || type_str == "uint64") {
571+
} elseif (type_str == "uint64" || type_str == "u64") {
572572
returnJust(&ffi_type_uint64);
573-
} elseif (type_str == "f32" || type_str == "float" ||
574-
type_str == "float32") {
573+
} elseif (type_str == "float32" || type_str == "f32" ||
574+
type_str == "float") {
575575
returnJust(&ffi_type_float);
576-
} elseif (type_str == "f64" || type_str == "double" ||
577-
type_str == "float64") {
576+
} elseif (type_str == "float64" || type_str == "f64" ||
577+
type_str == "double") {
578578
returnJust(&ffi_type_double);
579-
} elseif (type_str == "buffer" || type_str == "arraybuffer" ||
580-
type_str == "string" || type_str == "str" ||
581-
type_str == "pointer" || type_str == "ptr" ||
582-
type_str == "function") {
579+
} elseif (type_str == "pointer" || type_str == "string" ||
580+
type_str == "buffer" || type_str == "arraybuffer" ||
581+
type_str == "function" || type_str == "ptr" || type_str == "str") {
583582
returnJust(&ffi_type_pointer);
584583
} else {
585584
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);

0 commit comments

Comments
Β (0)