diff --git a/doc/api/ffi.md b/doc/api/ffi.md
index 54de34da7a1..fcb39d223f0 100644
--- a/doc/api/ffi.md
+++ b/doc/api/ffi.md
@@ -63,22 +63,40 @@ Supported type names:
* `void`
* `char`
-* `i8`, `int8`
-* `u8`, `uint8`, `bool`
-* `i16`, `int16`
-* `u16`, `uint16`
-* `i32`, `int32`
-* `u32`, `uint32`
-* `i64`, `int64`
-* `u64`, `uint64`
-* `f32`, `float`, `float32`
-* `f64`, `double`, `float64`
-* `pointer`, `ptr`
-* `string`, `str`
+* `int8`
+* `uint8`
+* `int16`
+* `uint16`
+* `int32`
+* `uint32`
+* `int64`
+* `uint64`
+* `float32`
+* `float64`
+* `pointer`
+* `string`
* `buffer`
* `arraybuffer`
* `function`
+
+Alternative spellings
+
+* `i8` for `int8`
+* `u8` and `bool` for `uint8`
+* `i16` for `int16`
+* `u16` for `uint16`
+* `i32` for `int32`
+* `u32` for `uint32`
+* `i64` for `int64`
+* `u64` for `uint64`
+* `f32` and `float` for `float32`
+* `f64` and `double` for `float64`
+* `ptr` for `pointer`
+* `str` for `string`
+
+
+
These type names are also exposed as constants on `ffi.types`:
* `ffi.types.VOID` = `'void'`
@@ -116,15 +134,15 @@ through reentrant JavaScript such as FFI callbacks. Doing so may crash the
process, produce incorrect output, or corrupt memory.
The `char` type follows the platform C ABI. On platforms where plain C `char`
-is signed it behaves like `i8`; otherwise it behaves like `u8`.
+is signed it behaves like `int8`; otherwise it behaves like `uint8`.
The `bool` type is marshaled as an 8-bit unsigned integer. Pass numeric values
such as `0` and `1`; JavaScript `true` and `false` are not accepted.
-On optimized Fast FFI calls, `pointer`, `ptr`, and `function` parameters accept
-raw pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
-strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are
-converted on the JavaScript side before calling the optimized native wrapper.
+On optimized Fast FFI calls, `pointer` and `function` parameters accept raw
+pointer `bigint` values. For pointer-like parameters, `null`, `undefined`,
+strings, `Buffer`, typed array, `DataView`, and `ArrayBuffer` values are converted
+on the JavaScript side before calling the optimized native wrapper.
Optimized Fast FFI calls fall back to the generic FFI call path when a
function's arguments or return type do not fit the platform-specific fast
@@ -161,8 +179,8 @@ optional:
```js
const signature = {
- return: 'i32',
- arguments: ['i32', 'i32'],
+ return: 'int32',
+ arguments: ['int32', 'int32'],
};
```
@@ -220,7 +238,7 @@ import { dlopen, suffix } from 'node:ffi';
{
using handle = dlopen(`./mylib.${suffix}`, {
- add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
+ add_i32: { arguments: ['int32', 'int32'], return: 'int32' },
});
console.log(handle.functions.add_i32(20, 22));
} // handle.lib.close() is invoked automatically here.
@@ -230,8 +248,8 @@ import { dlopen, suffix } from 'node:ffi';
import { dlopen, suffix } from 'node:ffi';
const { lib, functions } = dlopen(`./mylib.${suffix}`, {
- add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
- string_length: { arguments: ['pointer'], return: 'u64' },
+ add_i32: { arguments: ['int32', 'int32'], return: 'int32' },
+ string_length: { arguments: ['pointer'], return: 'uint64' },
});
console.log(functions.add_i32(20, 22));
@@ -241,8 +259,8 @@ console.log(functions.add_i32(20, 22));
const { dlopen, suffix } = require('node:ffi');
const { lib, functions } = dlopen(`./mylib.${suffix}`, {
- add_i32: { arguments: ['i32', 'i32'], return: 'i32' },
- string_length: { arguments: ['pointer'], return: 'u64' },
+ add_i32: { arguments: ['int32', 'int32'], return: 'int32' },
+ string_length: { arguments: ['pointer'], return: 'uint64' },
});
console.log(functions.add_i32(20, 22));
@@ -384,8 +402,8 @@ const { DynamicLibrary, suffix } = require('node:ffi');
const lib = new DynamicLibrary(`./mylib.${suffix}`);
const add = lib.getFunction('add_i32', {
- arguments: ['i32', 'i32'],
- return: 'i32',
+ arguments: ['int32', 'int32'],
+ return: 'int32',
});
console.log(add(20, 22));
@@ -435,7 +453,7 @@ const { DynamicLibrary, suffix } = require('node:ffi');
const lib = new DynamicLibrary(`./mylib.${suffix}`);
const callback = lib.registerCallback(
- { arguments: ['i32'], return: 'i32' },
+ { arguments: ['int32'], return: 'int32' },
(value) => value * 2,
);
```
@@ -498,7 +516,8 @@ Argument conversion depends on the declared FFI type.
For 8-, 16-, and 32-bit integer types and for floating-point types, pass
JavaScript `number` values that match the declared type.
-For 64-bit integer types (`i64` and `u64`), pass JavaScript `bigint` values.
+For 64-bit integer types (`int64` and `uint64`), pass JavaScript `bigint`
+values.
For pointer-like arguments:
diff --git a/lib/internal/ffi-shared-buffer.js b/lib/internal/ffi-shared-buffer.js
index 94764bdf0db..13002193cd9 100644
--- a/lib/internal/ffi-shared-buffer.js
+++ b/lib/internal/ffi-shared-buffer.js
@@ -64,38 +64,40 @@ const gF64 = DataViewPrototypeGetFloat64;
const sbTypeInfo = {
__proto__: null,
- i8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
- int8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
char: charIsSigned ?
{ set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' } :
{ set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
- u8: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
+ int8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
uint8: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
+ int16: { set: sI16, get: gI16, kind: 'int', min: -32768, max: 32767, label: 'an int16' },
+ uint16: { set: sU16, get: gU16, kind: 'int', min: 0, max: 65535, label: 'a uint16' },
+ int32: { set: sI32, get: gI32, kind: 'int', min: -2147483648, max: 2147483647, label: 'an int32' },
+ uint32: { set: sU32, get: gU32, kind: 'int', min: 0, max: 4294967295, label: 'a uint32' },
+ int64: { set: sI64, get: gI64, kind: 'i64', label: 'an int64' },
+ uint64: { set: sU64, get: gU64, kind: 'u64', label: 'a uint64' },
+ float32: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
+ float64: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
+ pointer: { set: sU64, get: gU64, kind: 'pointer' },
+ string: { set: sU64, get: gU64, kind: 'pointer' },
+ buffer: { set: sU64, get: gU64, kind: 'pointer' },
+ arraybuffer: { set: sU64, get: gU64, kind: 'pointer' },
+ function: { set: sU64, get: gU64, kind: 'pointer' },
+
+ // Alternative spellings.
+ i8: { set: sI8, get: gI8, kind: 'int', min: -128, max: 127, label: 'an int8' },
+ u8: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
bool: { set: sU8, get: gU8, kind: 'int', min: 0, max: 255, label: 'a uint8' },
i16: { set: sI16, get: gI16, kind: 'int', min: -32768, max: 32767, label: 'an int16' },
- int16: { set: sI16, get: gI16, kind: 'int', min: -32768, max: 32767, label: 'an int16' },
u16: { set: sU16, get: gU16, kind: 'int', min: 0, max: 65535, label: 'a uint16' },
- uint16: { set: sU16, get: gU16, kind: 'int', min: 0, max: 65535, label: 'a uint16' },
i32: { set: sI32, get: gI32, kind: 'int', min: -2147483648, max: 2147483647, label: 'an int32' },
- int32: { set: sI32, get: gI32, kind: 'int', min: -2147483648, max: 2147483647, label: 'an int32' },
u32: { set: sU32, get: gU32, kind: 'int', min: 0, max: 4294967295, label: 'a uint32' },
- uint32: { set: sU32, get: gU32, kind: 'int', min: 0, max: 4294967295, label: 'a uint32' },
i64: { set: sI64, get: gI64, kind: 'i64', label: 'an int64' },
- int64: { set: sI64, get: gI64, kind: 'i64', label: 'an int64' },
u64: { set: sU64, get: gU64, kind: 'u64', label: 'a uint64' },
- uint64: { set: sU64, get: gU64, kind: 'u64', label: 'a uint64' },
f32: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
float: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
- float32: { set: sF32, get: gF32, kind: 'float', label: 'a float' },
f64: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
double: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
- float64: { set: sF64, get: gF64, kind: 'float', label: 'a double' },
- pointer: { set: sU64, get: gU64, kind: 'pointer' },
ptr: { set: sU64, get: gU64, kind: 'pointer' },
- function: { set: sU64, get: gU64, kind: 'pointer' },
- buffer: { set: sU64, get: gU64, kind: 'pointer' },
- arraybuffer: { set: sU64, get: gU64, kind: 'pointer' },
- string: { set: sU64, get: gU64, kind: 'pointer' },
str: { set: sU64, get: gU64, kind: 'pointer' },
};
diff --git a/lib/internal/ffi/fast-api.js b/lib/internal/ffi/fast-api.js
index 4b531dfe039..38f4f4e3437 100644
--- a/lib/internal/ffi/fast-api.js
+++ b/lib/internal/ffi/fast-api.js
@@ -47,26 +47,28 @@ const fastLibraryStates = new SafeWeakMap();
// conversions, so the public FFI ranges must be checked before the raw call.
const fastIntegerTypeInfo = {
__proto__: null,
- i8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
- int8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
char: charIsSigned ?
{ kind: 'number', min: -128, max: 127, label: 'an int8' } :
{ kind: 'number', min: 0, max: 255, label: 'a uint8' },
- u8: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
+ int8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
uint8: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
+ int16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' },
+ uint16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' },
+ int32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' },
+ uint32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' },
+ int64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' },
+ uint64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' },
+
+ // Alternative spellings.
+ i8: { kind: 'number', min: -128, max: 127, label: 'an int8' },
+ u8: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
bool: { kind: 'number', min: 0, max: 255, label: 'a uint8' },
i16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' },
- int16: { kind: 'number', min: -32768, max: 32767, label: 'an int16' },
u16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' },
- uint16: { kind: 'number', min: 0, max: 65535, label: 'a uint16' },
i32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' },
- int32: { kind: 'number', min: -2147483648, max: 2147483647, label: 'an int32' },
u32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' },
- uint32: { kind: 'number', min: 0, max: 4294967295, label: 'a uint32' },
i64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' },
- int64: { kind: 'bigint', min: I64_MIN, max: I64_MAX, label: 'an int64' },
u64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' },
- uint64: { kind: 'bigint', min: 0n, max: U64_MAX, label: 'a uint64' },
};
function throwFFIArgError(msg) {
@@ -97,8 +99,8 @@ function needsRawPointerConversion(type) {
}
function needsPointerLikeConversion(type) {
- return type === 'pointer' || type === 'ptr' || type === 'function' ||
- type === 'buffer' || type === 'arraybuffer';
+ return type === 'pointer' || type === 'function' || type === 'buffer' ||
+ type === 'arraybuffer' || type === 'ptr';
}
function needsStringPointerConversion(type) {
diff --git a/src/ffi/fast.cc b/src/ffi/fast.cc
index 8e92c56aebb..24809e744a2 100644
--- a/src/ffi/fast.cc
+++ b/src/ffi/fast.cc
@@ -36,34 +36,32 @@ bool FastScalarTypeFromName(std::string_view type, FastFFIType* out) {
// JavaScript wrappers handle strings and object-to-pointer conversions.
if (type == "void") {
*out = FastFFIType::kVoid;
- } else if (type == "bool") {
- *out = FastFFIType::kUint8;
- } else if (IsTypeName(type, {"i8", "int8"})) {
- *out = FastFFIType::kInt8;
- } else if (IsTypeName(type, {"u8", "uint8"})) {
- *out = FastFFIType::kUint8;
} else if (type == "char") {
*out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8;
- } else if (IsTypeName(type, {"i16", "int16"})) {
+ } else if (IsTypeName(type, {"int8", "i8"})) {
+ *out = FastFFIType::kInt8;
+ } else if (IsTypeName(type, {"uint8", "u8", "bool"})) {
+ *out = FastFFIType::kUint8;
+ } else if (IsTypeName(type, {"int16", "i16"})) {
*out = FastFFIType::kInt16;
- } else if (IsTypeName(type, {"u16", "uint16"})) {
+ } else if (IsTypeName(type, {"uint16", "u16"})) {
*out = FastFFIType::kUint16;
- } else if (IsTypeName(type, {"i32", "int32"})) {
+ } else if (IsTypeName(type, {"int32", "i32"})) {
*out = FastFFIType::kInt32;
- } else if (IsTypeName(type, {"u32", "uint32"})) {
+ } else if (IsTypeName(type, {"uint32", "u32"})) {
*out = FastFFIType::kUint32;
- } else if (IsTypeName(type, {"i64", "int64"})) {
+ } else if (IsTypeName(type, {"int64", "i64"})) {
*out = FastFFIType::kInt64;
- } else if (IsTypeName(type, {"u64", "uint64"})) {
+ } else if (IsTypeName(type, {"uint64", "u64"})) {
*out = FastFFIType::kUint64;
- } else if (IsTypeName(type, {"f32", "float", "float32"})) {
+ } else if (IsTypeName(type, {"float32", "f32", "float"})) {
*out = FastFFIType::kFloat32;
- } else if (IsTypeName(type, {"f64", "double", "float64"})) {
+ } else if (IsTypeName(type, {"float64", "f64", "double"})) {
*out = FastFFIType::kFloat64;
} else if (IsTypeName(type, {"buffer", "arraybuffer"})) {
*out = FastFFIType::kPointer;
} else if (IsTypeName(type,
- {"pointer", "ptr", "string", "str", "function"})) {
+ {"pointer", "string", "function", "ptr", "str"})) {
*out = FastFFIType::kPointer;
} else {
return false;
@@ -162,11 +160,12 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
// V8 widens narrow integers to 32 bits and truncates BigInts to 64 bits for
// Fast API calls. These types need a JS range check before the trampoline.
for (const std::string& name : fn.arg_type_names) {
- if (name == "bool" || name == "char" || name == "i8" || name == "int8" ||
- name == "u8" || name == "uint8" || name == "i16" || name == "int16" ||
- name == "u16" || name == "uint16" || name == "i32" || name == "int32" ||
- name == "u32" || name == "uint32" || name == "i64" || name == "int64" ||
- name == "u64" || name == "uint64") {
+ if (name == "char" || name == "int8" || name == "uint8" ||
+ name == "int16" || name == "uint16" || name == "int32" ||
+ name == "uint32" || name == "int64" || name == "uint64" ||
+ name == "i8" || name == "u8" || name == "bool" || name == "i16" ||
+ name == "u16" || name == "i32" || name == "u32" || name == "i64" ||
+ name == "u64") {
return true;
}
}
@@ -176,7 +175,7 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) {
bool IsPointerTypeName(const std::string& name) {
// `pointer`, `ptr`, and `function` all use the same uintptr ABI slot; only
// the public type spelling differs.
- return name == "pointer" || name == "ptr" || name == "function";
+ return name == "pointer" || name == "function" || name == "ptr";
}
bool IsBufferTypeName(const std::string& name) {
diff --git a/src/ffi/types.cc b/src/ffi/types.cc
index db0c913c547..83be0f48ecc 100644
--- a/src/ffi/types.cc
+++ b/src/ffi/types.cc
@@ -552,34 +552,33 @@ void WriteFFIReturnToBuffer(ffi_type* type,
v8::Maybe ToFFIType(Environment* env, std::string_view type_str) {
if (type_str == "void") {
return Just(&ffi_type_void);
- } else if (type_str == "i8" || type_str == "int8") {
- return Just(&ffi_type_sint8);
- } else if (type_str == "u8" || type_str == "uint8" || type_str == "bool") {
- return Just(&ffi_type_uint8);
} else if (type_str == "char") {
return Just(CHAR_MIN < 0 ? &ffi_type_sint8 : &ffi_type_uint8);
- } else if (type_str == "i16" || type_str == "int16") {
+ } else if (type_str == "int8" || type_str == "i8") {
+ return Just(&ffi_type_sint8);
+ } else if (type_str == "uint8" || type_str == "u8" || type_str == "bool") {
+ return Just(&ffi_type_uint8);
+ } else if (type_str == "int16" || type_str == "i16") {
return Just(&ffi_type_sint16);
- } else if (type_str == "u16" || type_str == "uint16") {
+ } else if (type_str == "uint16" || type_str == "u16") {
return Just(&ffi_type_uint16);
- } else if (type_str == "i32" || type_str == "int32") {
+ } else if (type_str == "int32" || type_str == "i32") {
return Just(&ffi_type_sint32);
- } else if (type_str == "u32" || type_str == "uint32") {
+ } else if (type_str == "uint32" || type_str == "u32") {
return Just(&ffi_type_uint32);
- } else if (type_str == "i64" || type_str == "int64") {
+ } else if (type_str == "int64" || type_str == "i64") {
return Just(&ffi_type_sint64);
- } else if (type_str == "u64" || type_str == "uint64") {
+ } else if (type_str == "uint64" || type_str == "u64") {
return Just(&ffi_type_uint64);
- } else if (type_str == "f32" || type_str == "float" ||
- type_str == "float32") {
+ } else if (type_str == "float32" || type_str == "f32" ||
+ type_str == "float") {
return Just(&ffi_type_float);
- } else if (type_str == "f64" || type_str == "double" ||
- type_str == "float64") {
+ } else if (type_str == "float64" || type_str == "f64" ||
+ type_str == "double") {
return Just(&ffi_type_double);
- } else if (type_str == "buffer" || type_str == "arraybuffer" ||
- type_str == "string" || type_str == "str" ||
- type_str == "pointer" || type_str == "ptr" ||
- type_str == "function") {
+ } else if (type_str == "pointer" || type_str == "string" ||
+ type_str == "buffer" || type_str == "arraybuffer" ||
+ type_str == "function" || type_str == "ptr" || type_str == "str") {
return Just(&ffi_type_pointer);
} else {
THROW_ERR_INVALID_ARG_VALUE(env, "Unsupported FFI type: %s", type_str);