diff --git a/doc/api/ffi.md b/doc/api/ffi.md index 54de34da7a1..7de1266e9ba 100644 --- a/doc/api/ffi.md +++ b/doc/api/ffi.md @@ -63,18 +63,18 @@ 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` @@ -86,11 +86,8 @@ These type names are also exposed as constants on `ffi.types`: * `ffi.types.BUFFER` = `'buffer'` * `ffi.types.ARRAY_BUFFER` = `'arraybuffer'` * `ffi.types.FUNCTION` = `'function'` -* `ffi.types.BOOL` = `'bool'` * `ffi.types.CHAR` = `'char'` * `ffi.types.STRING` = `'string'` -* `ffi.types.FLOAT` = `'float'` -* `ffi.types.DOUBLE` = `'double'` * `ffi.types.INT_8` = `'int8'` * `ffi.types.UINT_8` = `'uint8'` * `ffi.types.INT_16` = `'int16'` @@ -116,12 +113,9 @@ 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 +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. @@ -161,8 +155,8 @@ optional: ```js const signature = { - return: 'i32', - arguments: ['i32', 'i32'], + return: 'int32', + arguments: ['int32', 'int32'], }; ``` @@ -220,7 +214,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 +224,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 +235,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 +378,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 +429,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 +492,7 @@ 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/ffi.js b/lib/ffi.js index cbd18879320..738dce787be 100644 --- a/lib/ffi.js +++ b/lib/ffi.js @@ -326,11 +326,8 @@ const types = ObjectFreeze({ BUFFER: 'buffer', ARRAY_BUFFER: 'arraybuffer', FUNCTION: 'function', - BOOL: 'bool', CHAR: 'char', STRING: 'string', - FLOAT: 'float', - DOUBLE: 'double', INT_8: 'int8', UINT_8: 'uint8', INT_16: 'int16', diff --git a/lib/internal/ffi-shared-buffer.js b/lib/internal/ffi-shared-buffer.js index 94764bdf0db..2a9405dac4b 100644 --- a/lib/internal/ffi-shared-buffer.js +++ b/lib/internal/ffi-shared-buffer.js @@ -64,39 +64,24 @@ 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' }, uint8: { 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' }, }; const U64_MAX = 0xFFFFFFFFFFFFFFFFn; diff --git a/lib/internal/ffi/fast-api.js b/lib/internal/ffi/fast-api.js index 4b531dfe039..2b46634aeff 100644 --- a/lib/internal/ffi/fast-api.js +++ b/lib/internal/ffi/fast-api.js @@ -47,25 +47,16 @@ 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' }, uint8: { 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' }, }; @@ -97,16 +88,16 @@ function needsRawPointerConversion(type) { } function needsPointerLikeConversion(type) { - return type === 'pointer' || type === 'ptr' || type === 'function' || + return type === 'pointer' || type === 'function' || type === 'buffer' || type === 'arraybuffer'; } function needsStringPointerConversion(type) { - return type === 'string' || type === 'str' || needsPointerLikeConversion(type); + return type === 'string' || needsPointerLikeConversion(type); } function needsNullPointerConversion(type) { - return needsPointerLikeConversion(type) || type === 'string' || type === 'str' || + return needsPointerLikeConversion(type) || type === 'string' || needsRawPointerConversion(type); } diff --git a/src/ffi/fast.cc b/src/ffi/fast.cc index 8e92c56aebb..d3297f00780 100644 --- a/src/ffi/fast.cc +++ b/src/ffi/fast.cc @@ -19,9 +19,6 @@ using v8::FastApiCallbackOptions; bool IsTypeName(std::string_view type, std::initializer_list names) { - // Signature parsing accepts several public aliases for the same ABI type. - // The fast path normalizes them by checking the original type name against - // each alias set before selecting a FastFFIType. for (std::string_view name : names) { if (type == name) { return true; @@ -36,34 +33,31 @@ 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"})) { + } else if (type == "int8") { *out = FastFFIType::kInt8; - } else if (IsTypeName(type, {"u8", "uint8"})) { + } else if (type == "uint8") { *out = FastFFIType::kUint8; } else if (type == "char") { *out = CHAR_MIN < 0 ? FastFFIType::kInt8 : FastFFIType::kUint8; - } else if (IsTypeName(type, {"i16", "int16"})) { + } else if (type == "int16") { *out = FastFFIType::kInt16; - } else if (IsTypeName(type, {"u16", "uint16"})) { + } else if (type == "uint16") { *out = FastFFIType::kUint16; - } else if (IsTypeName(type, {"i32", "int32"})) { + } else if (type == "int32") { *out = FastFFIType::kInt32; - } else if (IsTypeName(type, {"u32", "uint32"})) { + } else if (type == "uint32") { *out = FastFFIType::kUint32; - } else if (IsTypeName(type, {"i64", "int64"})) { + } else if (type == "int64") { *out = FastFFIType::kInt64; - } else if (IsTypeName(type, {"u64", "uint64"})) { + } else if (type == "uint64") { *out = FastFFIType::kUint64; - } else if (IsTypeName(type, {"f32", "float", "float32"})) { + } else if (type == "float32") { *out = FastFFIType::kFloat32; - } else if (IsTypeName(type, {"f64", "double", "float64"})) { + } else if (type == "float64") { *out = FastFFIType::kFloat64; } else if (IsTypeName(type, {"buffer", "arraybuffer"})) { *out = FastFFIType::kPointer; - } else if (IsTypeName(type, - {"pointer", "ptr", "string", "str", "function"})) { + } else if (IsTypeName(type, {"pointer", "string", "function"})) { *out = FastFFIType::kPointer; } else { return false; @@ -150,8 +144,7 @@ bool SignatureNeedsRawPointerConversions(const FFIFunction& fn) { // a signature contains them, JS wraps the fast function to perform the // conversion before V8 enters the CFunction trampoline. for (const std::string& name : fn.arg_type_names) { - if (name == "buffer" || name == "arraybuffer" || name == "string" || - name == "str") { + if (name == "buffer" || name == "arraybuffer" || name == "string") { return true; } } @@ -162,11 +155,9 @@ 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") { return true; } } @@ -174,9 +165,9 @@ bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn) { } bool IsPointerTypeName(const std::string& name) { - // `pointer`, `ptr`, and `function` all use the same uintptr ABI slot; only + // `pointer` and `function` use the same uintptr ABI slot; only // the public type spelling differs. - return name == "pointer" || name == "ptr" || name == "function"; + return name == "pointer" || name == "function"; } bool IsBufferTypeName(const std::string& name) { diff --git a/src/ffi/types.cc b/src/ffi/types.cc index db0c913c547..8c34bb24c5c 100644 --- a/src/ffi/types.cc +++ b/src/ffi/types.cc @@ -552,33 +552,30 @@ 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") { + } else if (type_str == "int8") { return Just(&ffi_type_sint8); - } else if (type_str == "u8" || type_str == "uint8" || type_str == "bool") { + } else if (type_str == "uint8") { 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 == "int16") { return Just(&ffi_type_sint16); - } else if (type_str == "u16" || type_str == "uint16") { + } else if (type_str == "uint16") { return Just(&ffi_type_uint16); - } else if (type_str == "i32" || type_str == "int32") { + } else if (type_str == "int32") { return Just(&ffi_type_sint32); - } else if (type_str == "u32" || type_str == "uint32") { + } else if (type_str == "uint32") { return Just(&ffi_type_uint32); - } else if (type_str == "i64" || type_str == "int64") { + } else if (type_str == "int64") { return Just(&ffi_type_sint64); - } else if (type_str == "u64" || type_str == "uint64") { + } else if (type_str == "uint64") { return Just(&ffi_type_uint64); - } else if (type_str == "f32" || type_str == "float" || - type_str == "float32") { + } else if (type_str == "float32") { return Just(&ffi_type_float); - } else if (type_str == "f64" || type_str == "double" || - type_str == "float64") { + } else if (type_str == "float64") { 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 == "string" || type_str == "pointer" || type_str == "function") { return Just(&ffi_type_pointer); } else { diff --git a/test/ffi/ffi-test-common.js b/test/ffi/ffi-test-common.js index fa54ca2cfd3..75e0fc1fd79 100644 --- a/test/ffi/ffi-test-common.js +++ b/test/ffi/ffi-test-common.js @@ -28,52 +28,52 @@ function ensureFixtureLibrary() { ensureFixtureLibrary(); const fixtureSymbols = { - add_i8: { arguments: ['i8', 'i8'], return: 'i8' }, - add_u8: { arguments: ['u8', 'u8'], return: 'u8' }, - add_i16: { arguments: ['i16', 'i16'], return: 'i16' }, - add_u16: { arguments: ['u16', 'u16'], return: 'u16' }, - add_i32: { arguments: ['i32', 'i32'], return: 'i32' }, - add_u32: { arguments: ['u32', 'u32'], return: 'u32' }, - add_i64: { arguments: ['i64', 'i64'], return: 'i64' }, - add_u64: { arguments: ['u64', 'u64'], return: 'u64' }, + add_i8: { arguments: ['int8', 'int8'], return: 'int8' }, + add_u8: { arguments: ['uint8', 'uint8'], return: 'uint8' }, + add_i16: { arguments: ['int16', 'int16'], return: 'int16' }, + add_u16: { arguments: ['uint16', 'uint16'], return: 'uint16' }, + add_i32: { arguments: ['int32', 'int32'], return: 'int32' }, + add_u32: { arguments: ['uint32', 'uint32'], return: 'uint32' }, + add_i64: { arguments: ['int64', 'int64'], return: 'int64' }, + add_u64: { arguments: ['uint64', 'uint64'], return: 'uint64' }, identity_char: { arguments: ['char'], return: 'char' }, - char_is_signed: { arguments: [], return: 'i32' }, - add_f32: { arguments: ['f32', 'f32'], return: 'f32' }, - multiply_f64: { arguments: ['f64', 'f64'], return: 'f64' }, + char_is_signed: { arguments: [], return: 'int32' }, + add_f32: { arguments: ['float32', 'float32'], return: 'float32' }, + multiply_f64: { arguments: ['float64', 'float64'], return: 'float64' }, identity_pointer: { arguments: ['pointer'], return: 'pointer' }, - pointer_to_usize: { arguments: ['pointer'], return: 'u64' }, - usize_to_pointer: { arguments: ['u64'], return: 'pointer' }, - string_length: { arguments: ['pointer'], return: 'u64' }, + pointer_to_usize: { arguments: ['pointer'], return: 'uint64' }, + usize_to_pointer: { arguments: ['uint64'], return: 'pointer' }, + string_length: { arguments: ['pointer'], return: 'uint64' }, string_concat: { arguments: ['pointer', 'pointer'], return: 'pointer' }, string_duplicate: { arguments: ['pointer'], return: 'pointer' }, free_string: { arguments: ['pointer'], return: 'void' }, - fill_buffer: { arguments: ['pointer', 'u64', 'u32'], return: 'void' }, - sum_buffer: { arguments: ['pointer', 'u64'], return: 'u64' }, - reverse_buffer: { arguments: ['pointer', 'u64'], return: 'void' }, - logical_and: { arguments: ['i32', 'i32'], return: 'i32' }, - logical_or: { arguments: ['i32', 'i32'], return: 'i32' }, - logical_not: { arguments: ['i32'], return: 'i32' }, + fill_buffer: { arguments: ['pointer', 'uint64', 'uint32'], return: 'void' }, + sum_buffer: { arguments: ['pointer', 'uint64'], return: 'uint64' }, + reverse_buffer: { arguments: ['pointer', 'uint64'], return: 'void' }, + logical_and: { arguments: ['int32', 'int32'], return: 'int32' }, + logical_or: { arguments: ['int32', 'int32'], return: 'int32' }, + logical_not: { arguments: ['int32'], return: 'int32' }, increment_counter: { arguments: [], return: 'void' }, - get_counter: { arguments: [], return: 'i32' }, + get_counter: { arguments: [], return: 'int32' }, reset_counter: { arguments: [], return: 'void' }, - call_int_callback: { arguments: ['pointer', 'i32'], return: 'i32' }, - call_int8_callback: { arguments: ['pointer', 'i8'], return: 'i8' }, - call_pointer_callback_is_null: { arguments: ['pointer'], return: 'i32' }, + call_int_callback: { arguments: ['pointer', 'int32'], return: 'int32' }, + call_int8_callback: { arguments: ['pointer', 'int8'], return: 'int8' }, + call_pointer_callback_is_null: { arguments: ['pointer'], return: 'int32' }, call_void_callback: { arguments: ['pointer'], return: 'void' }, call_string_callback: { arguments: ['function', 'pointer'], return: 'void' }, - call_binary_int_callback: { arguments: ['function', 'i32', 'i32'], return: 'i32' }, - call_callback_multiple_times: { arguments: ['pointer', 'i32'], return: 'void' }, - divide_i32: { arguments: ['i32', 'i32'], return: 'i32' }, - safe_strlen: { arguments: ['pointer'], return: 'i32' }, - sum_five_i32: { arguments: ['i32', 'i32', 'i32', 'i32', 'i32'], return: 'i32' }, - sum_five_f64: { arguments: ['f64', 'f64', 'f64', 'f64', 'f64'], return: 'f64' }, - mixed_operation: { arguments: ['i32', 'f32', 'f64', 'u32'], return: 'f64' }, - allocate_memory: { arguments: ['u64'], return: 'pointer' }, + call_binary_int_callback: { arguments: ['function', 'int32', 'int32'], return: 'int32' }, + call_callback_multiple_times: { arguments: ['pointer', 'int32'], return: 'void' }, + divide_i32: { arguments: ['int32', 'int32'], return: 'int32' }, + safe_strlen: { arguments: ['pointer'], return: 'int32' }, + sum_five_i32: { arguments: ['int32', 'int32', 'int32', 'int32', 'int32'], return: 'int32' }, + sum_five_f64: { arguments: ['float64', 'float64', 'float64', 'float64', 'float64'], return: 'float64' }, + mixed_operation: { arguments: ['int32', 'float32', 'float64', 'uint32'], return: 'float64' }, + allocate_memory: { arguments: ['uint64'], return: 'pointer' }, deallocate_memory: { arguments: ['pointer'], return: 'void' }, - array_get_i32: { arguments: ['pointer', 'u64'], return: 'i32' }, - array_set_i32: { arguments: ['pointer', 'u64', 'i32'], return: 'void' }, - array_get_f64: { arguments: ['pointer', 'u64'], return: 'f64' }, - array_set_f64: { arguments: ['pointer', 'u64', 'f64'], return: 'void' }, + array_get_i32: { arguments: ['pointer', 'uint64'], return: 'int32' }, + array_set_i32: { arguments: ['pointer', 'uint64', 'int32'], return: 'void' }, + array_get_f64: { arguments: ['pointer', 'uint64'], return: 'float64' }, + array_set_f64: { arguments: ['pointer', 'uint64', 'float64'], return: 'void' }, }; if (!common.isWindows) { diff --git a/test/ffi/test-ffi-calls.js b/test/ffi/test-ffi-calls.js index e966809de66..50a816872dc 100644 --- a/test/ffi/test-ffi-calls.js +++ b/test/ffi/test-ffi-calls.js @@ -50,7 +50,7 @@ test('ffi calls support floating point and mixed signatures', () => { } }); -test('ffi bool signatures use uint8 values', () => { +test('ffi uint8 signatures use uint8 values', () => { const { lib, functions: symbols } = getLibrary(); try { assert.strictEqual(symbols.logical_and(1, 1), 1); @@ -58,20 +58,20 @@ test('ffi bool signatures use uint8 values', () => { assert.strictEqual(symbols.logical_or(0, 1), 1); assert.strictEqual(symbols.logical_not(0), 1); - const boolAdder = lib.getFunction('add_u8', { - arguments: ['bool', 'bool'], - return: 'bool', + const uint8Adder = lib.getFunction('add_u8', { + arguments: ['uint8', 'uint8'], + return: 'uint8', }); - function callBoolAdder(a, b) { - return boolAdder(a, b); + function callUint8Adder(a, b) { + return uint8Adder(a, b); } - eval('%PrepareFunctionForOptimization(callBoolAdder)'); - assert.strictEqual(callBoolAdder(1, 0), 1); - eval('%OptimizeFunctionOnNextCall(callBoolAdder)'); - assert.strictEqual(callBoolAdder(1, 0), 1); + eval('%PrepareFunctionForOptimization(callUint8Adder)'); + assert.strictEqual(callUint8Adder(1, 0), 1); + eval('%OptimizeFunctionOnNextCall(callUint8Adder)'); + assert.strictEqual(callUint8Adder(1, 0), 1); assert.throws( - () => callBoolAdder(true, false), /Argument 0 must be a uint8/); + () => callUint8Adder(true, false), /Argument 0 must be a uint8/); } finally { lib.close(); } @@ -122,8 +122,8 @@ test('ffi strings and buffers cross the boundary correctly', () => { test('ffi string signatures convert strings to temporary pointers', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - string_length: { arguments: ['string'], return: 'u64' }, - safe_strlen: { arguments: ['str'], return: 'i32' }, + string_length: { arguments: ['string'], return: 'uint64' }, + safe_strlen: { arguments: ['string'], return: 'int32' }, }); try { assert.strictEqual(functions.string_length('hello ffi'), 9n); @@ -138,7 +138,7 @@ test('ffi string signatures convert strings to temporary pointers', () => { test('ffi buffer and ArrayBuffer signatures pass backing-store pointers', () => { { const { lib, functions } = ffi.dlopen(libraryPath, { - first_byte: { arguments: ['buffer'], return: 'u8' }, + first_byte: { arguments: ['buffer'], return: 'uint8' }, }); try { assert.strictEqual(functions.first_byte(Buffer.from([42, 1])), 42); @@ -150,7 +150,7 @@ test('ffi buffer and ArrayBuffer signatures pass backing-store pointers', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - first_byte: { arguments: ['arraybuffer'], return: 'u8' }, + first_byte: { arguments: ['arraybuffer'], return: 'uint8' }, }); try { const ab = new Uint8Array([44, 1]).buffer; @@ -197,7 +197,7 @@ test('ffi callbacks can be registered and invoked', () => { const { lib, functions: symbols } = getLibrary(); const seen = []; const intCallback = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, (value) => value * 2, ); const stringCallback = lib.registerCallback( @@ -205,7 +205,7 @@ test('ffi callbacks can be registered and invoked', () => { (ptr) => seen.push(ffi.toString(ptr)), ); const binaryCallback = lib.registerCallback( - { arguments: ['i32', 'i32'], return: 'i32' }, + { arguments: ['int32', 'int32'], return: 'int32' }, (a, b) => a + b, ); @@ -240,7 +240,7 @@ test('ffi callback ref and unref APIs work', () => { called = true; }); const countingCallback = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, (value) => { values.push(value); return 0; @@ -320,7 +320,7 @@ const ffi = require('node:ffi'); const { fixtureSymbols, libraryPath } = require(${JSON.stringify(require.resolve('./ffi-test-common'))}); const { lib, functions } = ffi.dlopen(libraryPath, fixtureSymbols); const callback = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, () => (${returnExpression}), ); functions.call_int_callback(callback, 21);`, @@ -343,7 +343,7 @@ const ffi = require('node:ffi'); const { fixtureSymbols, libraryPath } = require(${JSON.stringify(require.resolve('./ffi-test-common'))}); const { lib, functions } = ffi.dlopen(libraryPath, fixtureSymbols); const callback = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, () => { ${callbackBody} }, ); functions.call_int_callback(callback, 21);`, @@ -374,7 +374,7 @@ const ffi = require('node:ffi'); const { fixtureSymbols, libraryPath } = require(${JSON.stringify(require.resolve('./ffi-test-common'))}); const { lib } = ffi.dlopen(libraryPath, fixtureSymbols); const callback = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, (value) => value * 2, ); new Worker(${JSON.stringify(workerSource)}, { eval: true, workerData: callback });`, @@ -408,7 +408,7 @@ test('ffi unrefCallback releases callback function', async () => { let callback = () => 1; const ref = new WeakRef(callback); const pointer = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, callback, ); @@ -432,7 +432,7 @@ test('ffi unrefCallback zero-fills narrow callback return', async () => { let callback = () => 1; const ref = new WeakRef(callback); const pointer = lib.registerCallback( - { arguments: ['i8'], return: 'i8' }, + { arguments: ['int8'], return: 'int8' }, callback, ); @@ -455,7 +455,7 @@ test('ffi refCallback retains callback function', async () => { try { let callback = () => 1; const ref = new WeakRef(callback); - const pointer = lib.registerCallback({ return: 'i32' }, callback); + const pointer = lib.registerCallback({ return: 'int32' }, callback); lib.unrefCallback(pointer); lib.refCallback(pointer); diff --git a/test/ffi/test-ffi-dynamic-library.js b/test/ffi/test-ffi-dynamic-library.js index c7dab03f64e..ee4b50b6150 100644 --- a/test/ffi/test-ffi-dynamic-library.js +++ b/test/ffi/test-ffi-dynamic-library.js @@ -27,7 +27,7 @@ test('dlopen resolves symbols from the current process with null path', { skip: common.isWindows, }, () => { const { lib, functions } = ffi.dlopen(null, { - uv_os_getpid: { return: 'i32', arguments: [] }, + uv_os_getpid: { return: 'int32', arguments: [] }, }); try { @@ -41,8 +41,8 @@ test('dlopen resolves symbols from the current process with null path', { test('dlopen resolves functions from definitions', () => { const { lib, functions } = ffi.dlopen(libraryPath, { add_i32: fixtureSymbols.add_i32, - add_f32: { return: 'f32', arguments: ['f32', 'f32'] }, - add_u64: { return: 'u64', arguments: ['u64', 'u64'] }, + add_f32: { return: 'float32', arguments: ['float32', 'float32'] }, + add_u64: { return: 'uint64', arguments: ['uint64', 'uint64'] }, }); try { @@ -94,8 +94,8 @@ test('DynamicLibrary exposes functions and symbols', () => { try { const addI32 = lib.getFunction('add_i32', fixtureSymbols.add_i32); const addU64 = lib.getFunction('add_u64', { - return: 'u64', - arguments: ['u64', 'u64'], + return: 'uint64', + arguments: ['uint64', 'uint64'], }); const addI32Ptr = lib.getSymbol('add_i32'); @@ -105,8 +105,8 @@ test('DynamicLibrary exposes functions and symbols', () => { assert.strictEqual(addI32.pointer, addI32Ptr); const functions = lib.getFunctions({ - add_f32: { return: 'f32', arguments: ['f32', 'f32'] }, - add_i64: { return: 'i64', arguments: ['i64', 'i64'] }, + add_f32: { return: 'float32', arguments: ['float32', 'float32'] }, + add_i64: { return: 'int64', arguments: ['int64', 'int64'] }, }); assert.strictEqual(functions.add_f32(10, 32), 42); @@ -133,11 +133,11 @@ test('DynamicLibrary evaluates function signatures once', () => { get arguments() { reads.arguments++; return reads.arguments === 1 ? - Array(8).fill('i32') : ['i32']; + Array(8).fill('int32') : ['int32']; }, get return() { reads.return++; - return 'i32'; + return 'int32'; }, }, }; @@ -190,7 +190,7 @@ test('getFunction caches signatures consistently', () => { ); assert.throws(() => { - lib.getFunction('add_i32', { arguments: ['u32', 'u32'], return: 'u32' }); + lib.getFunction('add_i32', { arguments: ['uint32', 'uint32'], return: 'uint32' }); }, /already requested with a different signature/); } finally { lib.close(); @@ -411,9 +411,31 @@ test('dynamic library APIs validate failures and bad signatures', () => { }, /Return value type of function add_i32 must not contain null bytes/); assert.throws(() => { - lib.getFunction('add_i32', { return: 'i32', arguments: ['i32\0bad'] }); + lib.getFunction('add_i32', { return: 'int32', arguments: ['i32\0bad'] }); }, /Argument 0 of function add_i32 must not contain null bytes/); + for (const type of [ + 'i8', + 'u8', + 'i16', + 'u16', + 'i32', + 'u32', + 'i64', + 'u64', + 'f32', + 'f64', + 'bool', + 'float', + 'double', + 'ptr', + 'str', + ]) { + assert.throws(() => { + lib.getFunction('add_i32', { return: type, arguments: [] }); + }, new RegExp(`Unsupported FFI type: ${type}`)); + } + assert.throws(() => { lib.getFunctions('not an object'); }, { @@ -461,7 +483,7 @@ test('dynamic library APIs validate failures and bad signatures', () => { const getterError = new Error('signature getter'); assert.throws(() => { lib.getFunction('add_i32', { - return: 'i32', + return: 'int32', get arguments() { throw getterError; }, diff --git a/test/ffi/test-ffi-fast-buffer.js b/test/ffi/test-ffi-fast-buffer.js index add25a27f4e..457dc2ec561 100644 --- a/test/ffi/test-ffi-fast-buffer.js +++ b/test/ffi/test-ffi-fast-buffer.js @@ -19,19 +19,19 @@ test('fast FFI accepts buffer and arraybuffer arguments natively', () => { const functions = { first_byte_buffer: lib.getFunction('first_byte', { arguments: ['buffer'], - return: 'u8', + return: 'uint8', }), first_byte_arraybuffer: lib.getFunction('first_byte', { arguments: ['arraybuffer'], - return: 'u8', + return: 'uint8', }), pointer_to_usize: lib.getFunction('pointer_to_usize', { arguments: ['pointer'], - return: 'u64', + return: 'uint64', }), sum_buffer: { - arguments: ['buffer', 'u64'], - return: 'u64', + arguments: ['buffer', 'uint64'], + return: 'uint64', }, }; functions.sum_buffer = lib.getFunction('sum_buffer', functions.sum_buffer); @@ -58,7 +58,7 @@ test('fast FFI accepts buffer and arraybuffer arguments natively', () => { test('fast FFI buffer arguments reject invalid values', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - first_byte: { arguments: ['buffer'], return: 'u8' }, + first_byte: { arguments: ['buffer'], return: 'uint8' }, }); try { @@ -74,7 +74,7 @@ test('optimized pointer arguments reject direct SharedArrayBuffers', () => { const lib = new ffi.DynamicLibrary(libraryPath); const firstByte = lib.getFunction('first_byte', { arguments: ['pointer'], - return: 'u8', + return: 'uint8', }); const regular = new ArrayBuffer(1); const shared = new SharedArrayBuffer(1); @@ -104,10 +104,10 @@ test('fast FFI string buffers survive reentrant callbacks', { skip: common.isSunOS, }, () => { const { lib, functions } = ffi.dlopen(libraryPath, { - safe_strlen: { arguments: ['string'], return: 'i32' }, + safe_strlen: { arguments: ['string'], return: 'int32' }, string_survives_callback: { arguments: ['string', 'pointer'], - return: 'i32', + return: 'int32', }, }); let nestedLength; @@ -128,8 +128,8 @@ test('fast FFI string buffers survive reentrant callbacks', { test('fast FFI refreshes cached temporary string buffers', () => { const lib = new ffi.DynamicLibrary(libraryPath); const overwriteString = lib.getFunction('overwrite_string', { - arguments: ['string', 'i32', 'u64'], - return: 'u8', + arguments: ['string', 'int32', 'uint64'], + return: 'uint8', }); try { @@ -147,15 +147,15 @@ test('optimized buffer signatures preserve pointer-like conversions', () => { const lib = new ffi.DynamicLibrary(libraryPath); const asPointer = lib.getFunction('pointer_to_usize', { arguments: ['pointer'], - return: 'u64', + return: 'uint64', }); const asBuffer = lib.getFunction('pointer_to_usize', { arguments: ['buffer'], - return: 'u64', + return: 'uint64', }); const asArrayBuffer = lib.getFunction('pointer_to_usize', { arguments: ['arraybuffer'], - return: 'u64', + return: 'uint64', }); function callPointer(value) { @@ -208,8 +208,8 @@ test('optimized buffer signatures preserve pointer-like conversions', () => { test('multi-argument buffer signatures accept pointer BigInts', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - sum_buffer: { arguments: ['buffer', 'u64'], return: 'u64' }, - fill_buffer: { arguments: ['arraybuffer', 'u64', 'u32'], return: 'void' }, + sum_buffer: { arguments: ['buffer', 'uint64'], return: 'uint64' }, + fill_buffer: { arguments: ['arraybuffer', 'uint64', 'uint32'], return: 'void' }, }); try { diff --git a/test/ffi/test-ffi-fast-integer-validation.js b/test/ffi/test-ffi-fast-integer-validation.js index 66b6866b4e4..1e8d82fdbcd 100644 --- a/test/ffi/test-ffi-fast-integer-validation.js +++ b/test/ffi/test-ffi-fast-integer-validation.js @@ -73,15 +73,14 @@ test('fast FFI validates integer argument ranges', () => { test('fast FFI validates pointer BigInt ranges', () => { const lib = new ffi.DynamicLibrary(libraryPath); try { - for (const type of ['pointer', 'ptr', 'string', 'str', - 'buffer', 'arraybuffer']) { + for (const type of ['pointer', 'string', 'buffer', 'arraybuffer']) { const identityPointer = lib.getFunction('identity_pointer', { arguments: [type], return: 'pointer', }); const sumBuffer = lib.getFunction('sum_buffer', { - arguments: [type, 'u64'], - return: 'u64', + arguments: [type, 'uint64'], + return: 'uint64', }); function callSingle(value) { return identityPointer(value); } diff --git a/test/ffi/test-ffi-module.js b/test/ffi/test-ffi-module.js index 7fe265972a7..feb4a2a40c1 100644 --- a/test/ffi/test-ffi-module.js +++ b/test/ffi/test-ffi-module.js @@ -171,11 +171,8 @@ test('ffi.types exports canonical type constants', () => { BUFFER: 'buffer', ARRAY_BUFFER: 'arraybuffer', FUNCTION: 'function', - BOOL: 'bool', CHAR: 'char', STRING: 'string', - FLOAT: 'float', - DOUBLE: 'double', INT_8: 'int8', UINT_8: 'uint8', INT_16: 'int16', diff --git a/test/ffi/test-ffi-shared-buffer.js b/test/ffi/test-ffi-shared-buffer.js index 2e982e37ab2..ddc6b16f4e2 100644 --- a/test/ffi/test-ffi-shared-buffer.js +++ b/test/ffi/test-ffi-shared-buffer.js @@ -29,9 +29,9 @@ const rawGetFunctionUnpatched = ffiBinding.DynamicLibrary.prototype.getFunction; const ffi = require('node:ffi'); const { libraryPath } = require('./ffi-test-common'); -test('numeric-only i32 function uses SB path', () => { +test('numeric-only int32 function uses SB path', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, }); try { assert.strictEqual(functions.add_i32(20, 22), 42); @@ -43,12 +43,12 @@ test('numeric-only i32 function uses SB path', () => { } }); -test('i8/u8/i16/u16 round-trip', () => { +test('int8/uint8/int16/uint16 round-trip', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i8: { return: 'i8', arguments: ['i8', 'i8'] }, - add_u8: { return: 'u8', arguments: ['u8', 'u8'] }, - add_i16: { return: 'i16', arguments: ['i16', 'i16'] }, - add_u16: { return: 'u16', arguments: ['u16', 'u16'] }, + add_i8: { return: 'int8', arguments: ['int8', 'int8'] }, + add_u8: { return: 'uint8', arguments: ['uint8', 'uint8'] }, + add_i16: { return: 'int16', arguments: ['int16', 'int16'] }, + add_u16: { return: 'uint16', arguments: ['uint16', 'uint16'] }, }); try { assert.strictEqual(functions.add_i8(10, 20), 30); @@ -60,10 +60,10 @@ test('i8/u8/i16/u16 round-trip', () => { } }); -test('f32/f64 round-trip', () => { +test('float32/float64 round-trip', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_f32: { return: 'f32', arguments: ['f32', 'f32'] }, - add_f64: { return: 'f64', arguments: ['f64', 'f64'] }, + add_f32: { return: 'float32', arguments: ['float32', 'float32'] }, + add_f64: { return: 'float64', arguments: ['float64', 'float64'] }, }); try { // 1.25 and 2.75 are exactly representable in float32, so the sum is exact. @@ -74,10 +74,10 @@ test('f32/f64 round-trip', () => { } }); -test('i64/u64 BigInt round-trip', () => { +test('int64/uint64 BigInt round-trip', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i64: { return: 'i64', arguments: ['i64', 'i64'] }, - add_u64: { return: 'u64', arguments: ['u64', 'u64'] }, + add_i64: { return: 'int64', arguments: ['int64', 'int64'] }, + add_u64: { return: 'uint64', arguments: ['uint64', 'uint64'] }, }); try { assert.strictEqual(functions.add_i64(10n, 20n), 30n); @@ -89,7 +89,7 @@ test('i64/u64 BigInt round-trip', () => { test('zero-arg function', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - char_is_signed: { return: 'i32', arguments: [] }, + char_is_signed: { return: 'int32', arguments: [] }, }); try { const result = functions.char_is_signed(); @@ -102,7 +102,7 @@ test('zero-arg function', () => { test('6-arg numeric function', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - sum_6_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32', 'i32', 'i32', 'i32'] }, + sum_6_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32', 'int32', 'int32', 'int32'] }, }); try { assert.strictEqual(functions.sum_6_i32(1, 2, 3, 4, 5, 6), 21); @@ -114,7 +114,7 @@ test('6-arg numeric function', () => { test('pointer args: fast path (BigInt/null) and slow-path fallback (Buffer/ArrayBuffer)', () => { const { lib, functions } = ffi.dlopen(libraryPath, { identity_pointer: { return: 'pointer', arguments: ['pointer'] }, - pointer_to_usize: { return: 'u64', arguments: ['pointer'] }, + pointer_to_usize: { return: 'uint64', arguments: ['pointer'] }, }); try { assert.strictEqual(functions.identity_pointer(0n), 0n); @@ -138,8 +138,8 @@ test('pointer args: fast path (BigInt/null) and slow-path fallback (Buffer/Array test('string pointer uses shared-buffer pointer conversion', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - string_length: { return: 'u64', arguments: ['pointer'] }, - safe_strlen: { return: 'i32', arguments: ['string'] }, + string_length: { return: 'uint64', arguments: ['pointer'] }, + safe_strlen: { return: 'int32', arguments: ['string'] }, }); try { assert.strictEqual(functions.string_length('hello'), 5n); @@ -170,14 +170,14 @@ test('reentrancy across two FFI symbols', () => { // A JS callback invoked by one FFI function reenters a different FFI // function. Each has its own ArrayBuffer; neither may clobber the other. const { lib, functions } = ffi.dlopen(libraryPath, { - call_int_callback: { return: 'i32', arguments: ['pointer', 'i32'] }, - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, + call_int_callback: { return: 'int32', arguments: ['pointer', 'int32'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, }); let callDepth = 0; let innerResult = -1; const callback = lib.registerCallback( - { return: 'i32', arguments: ['i32'] }, + { return: 'int32', arguments: ['int32'] }, (x) => { callDepth++; if (callDepth === 1) innerResult = functions.add_i32(x, 100); @@ -197,7 +197,7 @@ test('reentrancy across two FFI symbols', () => { test('arity mismatch throws ERR_INVALID_ARG_VALUE', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, }); try { assert.throws(() => functions.add_i32(1), { @@ -216,8 +216,8 @@ test('arity mismatch throws ERR_INVALID_ARG_VALUE', () => { test('arity 7+ uses the generic rest-params branch', () => { const { lib, functions } = ffi.dlopen(libraryPath, { sum_7_i32: { - return: 'i32', - arguments: ['i32', 'i32', 'i32', 'i32', 'i32', 'i32', 'i32'], + return: 'int32', + arguments: ['int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32'], }, }); try { @@ -233,7 +233,7 @@ test('arity 7+ uses the generic rest-params branch', () => { test('wrappers preserve name/length/pointer and the functions accessor returns wrappers', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, identity_pointer: { return: 'pointer', arguments: ['pointer'] }, }); try { @@ -254,14 +254,14 @@ test('wrappers preserve name/length/pointer and the functions accessor returns w } }); -test('integer boundaries for i8/u8/i16/u16/i32/u32', () => { +test('integer boundaries for int8/uint8/int16/uint16/int32/uint32', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i8: { return: 'i8', arguments: ['i8', 'i8'] }, - add_u8: { return: 'u8', arguments: ['u8', 'u8'] }, - add_i16: { return: 'i16', arguments: ['i16', 'i16'] }, - add_u16: { return: 'u16', arguments: ['u16', 'u16'] }, - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, - add_u32: { return: 'u32', arguments: ['u32', 'u32'] }, + add_i8: { return: 'int8', arguments: ['int8', 'int8'] }, + add_u8: { return: 'uint8', arguments: ['uint8', 'uint8'] }, + add_i16: { return: 'int16', arguments: ['int16', 'int16'] }, + add_u16: { return: 'uint16', arguments: ['uint16', 'uint16'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, + add_u32: { return: 'uint32', arguments: ['uint32', 'uint32'] }, }); try { @@ -300,10 +300,10 @@ test('integer boundaries for i8/u8/i16/u16/i32/u32', () => { } }); -test('i64/u64 BigInt boundaries and Number/BigInt type mismatches', () => { +test('int64/uint64 BigInt boundaries and Number/BigInt type mismatches', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_i64: { return: 'i64', arguments: ['i64', 'i64'] }, - add_u64: { return: 'u64', arguments: ['u64', 'u64'] }, + add_i64: { return: 'int64', arguments: ['int64', 'int64'] }, + add_u64: { return: 'uint64', arguments: ['uint64', 'uint64'] }, }); try { @@ -331,7 +331,7 @@ test('i64/u64 BigInt boundaries and Number/BigInt type mismatches', () => { test('char type picks signed/unsigned range based on host ABI', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - char_is_signed: { return: 'i32', arguments: [] }, + char_is_signed: { return: 'int32', arguments: [] }, identity_char: { return: 'char', arguments: ['char'] }, }); @@ -361,7 +361,7 @@ test('SB metadata is Symbol-keyed, attribute-hardened, and not leaked onto the w const rawLib = new ffiBinding.DynamicLibrary(libraryPath); try { const rawFn = rawGetFunctionUnpatched.call( - rawLib, 'add_i32', { return: 'i32', arguments: ['i32', 'i32'] }); + rawLib, 'add_i32', { return: 'int32', arguments: ['int32', 'int32'] }); for (const [name, sym] of [ ['kFastArguments', kFastArguments], @@ -394,7 +394,7 @@ test('SB metadata is Symbol-keyed, attribute-hardened, and not leaked onto the w // Fast string signatures carry parameter metadata so the JS wrapper can // perform string-to-pointer conversion, but still do not carry SB state. const rawStringFn = rawGetFunctionUnpatched.call( - rawLib, 'safe_strlen', { return: 'u64', arguments: ['string'] }); + rawLib, 'safe_strlen', { return: 'uint64', arguments: ['string'] }); const paramsDesc = Object.getOwnPropertyDescriptor(rawStringFn, kFastArguments); assert.ok(paramsDesc !== undefined, 'kFastArguments missing on Fast string function'); assert.strictEqual(paramsDesc.enumerable, false); @@ -427,7 +427,7 @@ test('SB metadata is Symbol-keyed, attribute-hardened, and not leaked onto the w // Internals must not be forwarded by `inheritMetadata`. const { lib, functions } = ffi.dlopen(libraryPath, { - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, }); try { assert.strictEqual(functions.add_i32[kSbSharedBuffer], undefined); @@ -464,15 +464,15 @@ test('self-recursive reentrancy: a single function\'s ArrayBuffer survives a nes // call can reuse the same buffer without clobbering the outer frame. const { lib, functions } = ffi.dlopen(libraryPath, { call_binary_int_callback: { - return: 'i32', - arguments: ['function', 'i32', 'i32'], + return: 'int32', + arguments: ['function', 'int32', 'int32'], }, }); try { let depth = 0; const callback = lib.registerCallback( - { return: 'i32', arguments: ['i32', 'i32'] }, + { return: 'int32', arguments: ['int32', 'int32'] }, common.mustCall((a, b) => { depth++; if (depth === 1) { @@ -497,7 +497,7 @@ test('void-return 0-arg wrapper branch', () => { const { lib, functions } = ffi.dlopen(libraryPath, { reset_counter: { return: 'void', arguments: [] }, increment_counter: { return: 'void', arguments: [] }, - get_counter: { return: 'i32', arguments: [] }, + get_counter: { return: 'int32', arguments: [] }, }); try { assert.strictEqual(functions.reset_counter(), undefined); @@ -522,26 +522,26 @@ test('void-return wrapper at every specialized arity observes side effects', () // at every arity the ladder specializes (1..6) plus the 7+ rest-params // fallback. const { lib, functions } = ffi.dlopen(libraryPath, { - store_i32: { return: 'void', arguments: ['i32'] }, - store_sum_2_i32: { return: 'void', arguments: ['i32', 'i32'] }, - store_sum_3_i32: { return: 'void', arguments: ['i32', 'i32', 'i32'] }, + store_i32: { return: 'void', arguments: ['int32'] }, + store_sum_2_i32: { return: 'void', arguments: ['int32', 'int32'] }, + store_sum_3_i32: { return: 'void', arguments: ['int32', 'int32', 'int32'] }, store_sum_4_i32: { return: 'void', - arguments: ['i32', 'i32', 'i32', 'i32'], + arguments: ['int32', 'int32', 'int32', 'int32'], }, store_sum_5_i32: { return: 'void', - arguments: ['i32', 'i32', 'i32', 'i32', 'i32'], + arguments: ['int32', 'int32', 'int32', 'int32', 'int32'], }, store_sum_6_i32: { return: 'void', - arguments: ['i32', 'i32', 'i32', 'i32', 'i32', 'i32'], + arguments: ['int32', 'int32', 'int32', 'int32', 'int32', 'int32'], }, store_sum_8_i32: { return: 'void', - arguments: ['i32', 'i32', 'i32', 'i32', 'i32', 'i32', 'i32', 'i32'], + arguments: ['int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32'], }, - get_scratch: { return: 'i32', arguments: [] }, + get_scratch: { return: 'int32', arguments: [] }, }); try { // Powers-of-two summands detect a dropped or duplicated slot at each @@ -624,17 +624,17 @@ test('value-return wrapper arity mismatch hits every specialized branch', () => // value-return closures for arities 1..6 so each specialization's // argument-count guard runs at least once. const { lib, functions } = ffi.dlopen(libraryPath, { - logical_not: { return: 'i32', arguments: ['i32'] }, - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, - sum_3_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32'] }, - sum_4_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32', 'i32'] }, + logical_not: { return: 'int32', arguments: ['int32'] }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, + sum_3_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32'] }, + sum_4_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32', 'int32'] }, sum_five_i32: { - return: 'i32', - arguments: ['i32', 'i32', 'i32', 'i32', 'i32'], + return: 'int32', + arguments: ['int32', 'int32', 'int32', 'int32', 'int32'], }, sum_6_i32: { - return: 'i32', - arguments: ['i32', 'i32', 'i32', 'i32', 'i32', 'i32'], + return: 'int32', + arguments: ['int32', 'int32', 'int32', 'int32', 'int32', 'int32'], }, }); try { @@ -695,10 +695,10 @@ test('pointer-dispatch wrapper rejects wrong-arity calls', () => { test('mid-arity wrappers (1, 3, 4, 5)', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - logical_not: { return: 'i32', arguments: ['i32'] }, - sum_3_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32'] }, - sum_4_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32', 'i32'] }, - sum_five_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32', 'i32', 'i32'] }, + logical_not: { return: 'int32', arguments: ['int32'] }, + sum_3_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32'] }, + sum_4_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32', 'int32'] }, + sum_five_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32', 'int32', 'int32'] }, }); try { assert.strictEqual(functions.logical_not(0), 1); @@ -715,8 +715,8 @@ test('mid-arity wrappers (1, 3, 4, 5)', () => { test('float specials: NaN, ±Infinity, -0 round-trip bit-exact', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - add_f64: { return: 'f64', arguments: ['f64', 'f64'] }, - multiply_f64: { return: 'f64', arguments: ['f64', 'f64'] }, + add_f64: { return: 'float64', arguments: ['float64', 'float64'] }, + multiply_f64: { return: 'float64', arguments: ['float64', 'float64'] }, }); try { assert.ok(Number.isNaN(functions.add_f64(NaN, 1.0))); @@ -730,7 +730,7 @@ test('float specials: NaN, ±Infinity, -0 round-trip bit-exact', () => { test('arity-7+ branch still runs per-arg validation', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - sum_7_i32: { return: 'i32', arguments: ['i32', 'i32', 'i32', 'i32', 'i32', 'i32', 'i32'] }, + sum_7_i32: { return: 'int32', arguments: ['int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32'] }, }); try { assert.throws( @@ -742,11 +742,11 @@ test('arity-7+ branch still runs per-arg validation', () => { } }); -test('mixed-kind signature (i32, f32, f64, u32) dispatches the right writer per slot', () => { +test('mixed-kind signature (int32, float32, float64, uint32) dispatches the right writer per slot', () => { // Four distinct `sbTypeInfo.kind` values (int, float, float, int) — a // wiring bug that reused one writer across slots would surface here. const { lib, functions } = ffi.dlopen(libraryPath, { - mixed_operation: { arguments: ['i32', 'f32', 'f64', 'u32'], return: 'f64' }, + mixed_operation: { arguments: ['int32', 'float32', 'float64', 'uint32'], return: 'float64' }, }); try { @@ -754,9 +754,9 @@ test('mixed-kind signature (i32, f32, f64, u32) dispatches the right writer per assert.strictEqual(functions.mixed_operation(-1, 0.25, 0.75, 0), 0); const expect = { code: 'ERR_INVALID_ARG_VALUE' }; - // -1 on u32 slot: distinguishes u32 writer from i32 (i32 accepts -1). + // -1 on uint32 slot: distinguishes uint32 writer from int32 (int32 accepts -1). assert.throws(() => functions.mixed_operation(0, 0.0, 0.0, -1), expect); - // 2^31 on i32 slot: distinguishes i32 writer from u32 (u32 accepts it). + // 2^31 on int32 slot: distinguishes int32 writer from uint32 (uint32 accepts it). assert.throws(() => functions.mixed_operation(2147483648, 0.0, 0.0, 0), expect); // Float slots reject BigInt / string (the int/float writers both gate on `typeof`). assert.throws(() => functions.mixed_operation(0, 1n, 0.0, 0), expect); @@ -774,11 +774,11 @@ test('lib.getFunctions() with no arguments wraps every cached function', () => { // the early-return path in `wrapWithSharedBuffer` alongside the wrapped // branch. const { lib } = ffi.dlopen(libraryPath, { - add_i32: { return: 'i32', arguments: ['i32', 'i32'] }, - add_f64: { return: 'f64', arguments: ['f64', 'f64'] }, - mixed_operation: { arguments: ['i32', 'f32', 'f64', 'u32'], return: 'f64' }, + add_i32: { return: 'int32', arguments: ['int32', 'int32'] }, + add_f64: { return: 'float64', arguments: ['float64', 'float64'] }, + mixed_operation: { arguments: ['int32', 'float32', 'float64', 'uint32'], return: 'float64' }, identity_pointer: { return: 'pointer', arguments: ['pointer'] }, - string_length: { return: 'u64', arguments: ['string'] }, + string_length: { return: 'uint64', arguments: ['string'] }, }); try { @@ -815,17 +815,17 @@ test('lib.getFunctions() with no arguments wraps every cached function', () => { test('mixed pointer + numeric signature uses the pointer-dispatch wrapper', () => { const { lib, functions } = ffi.dlopen(libraryPath, { - call_int_callback: { return: 'i32', arguments: ['pointer', 'i32'] }, + call_int_callback: { return: 'int32', arguments: ['pointer', 'int32'] }, }); try { const cb = lib.registerCallback( - { return: 'i32', arguments: ['i32'] }, + { return: 'int32', arguments: ['int32'] }, (x) => x * 2, ); try { assert.strictEqual(functions.call_int_callback(cb, 7), 14); - // Negative i32 must land in the numeric writer (not the pointer writer, + // Negative int32 must land in the numeric writer (not the pointer writer, // which would reject a negative BigInt). assert.strictEqual(functions.call_int_callback(cb, -5), -10); } finally { diff --git a/test/ffi/test-ffi-void-parameter.js b/test/ffi/test-ffi-void-parameter.js index d79631ed542..895adb9e69e 100644 --- a/test/ffi/test-ffi-void-parameter.js +++ b/test/ffi/test-ffi-void-parameter.js @@ -16,12 +16,12 @@ const lib = new ffi.DynamicLibrary(libraryPath); try { assert.throws(() => { - lib.getFunction('add_i32', { return: 'i32', arguments: ['void'] }); + lib.getFunction('add_i32', { return: 'int32', arguments: ['void'] }); }, { code: 'ERR_INVALID_ARG_VALUE' }); assert.throws(() => { lib.getFunctions({ - add_i32: { return: 'i32', arguments: ['void'] }, + add_i32: { return: 'int32', arguments: ['void'] }, }); }, { code: 'ERR_INVALID_ARG_VALUE' }); } finally { diff --git a/test/ffi/test-ffi-weakref-calls.js b/test/ffi/test-ffi-weakref-calls.js index b158ee81077..768db95015d 100644 --- a/test/ffi/test-ffi-weakref-calls.js +++ b/test/ffi/test-ffi-weakref-calls.js @@ -15,7 +15,7 @@ test('ffi unrefCallback releases callback function', async (t) => { let callback = () => 1; const ref = new WeakRef(callback); const pointer = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, callback, ); @@ -37,7 +37,7 @@ test('ffi refCallback retains callback function', async (t) => { let callback = () => 1; const ref = new WeakRef(callback); - const pointer = lib.registerCallback({ return: 'i32' }, callback); + const pointer = lib.registerCallback({ return: 'int32' }, callback); lib.unrefCallback(pointer); lib.refCallback(pointer); @@ -58,7 +58,7 @@ test('callback ref/unref throw after callback function is collected', async (t) let callback = () => 1; const ref = new WeakRef(callback); const pointer = lib.registerCallback( - { arguments: ['i32'], return: 'i32' }, + { arguments: ['int32'], return: 'int32' }, callback, );