Commit Graph
23 Commits
Author SHA1 Message Date
Trivikram Kamat 2b350bb8e4 ffi: accept pointer BigInts in multi-argument fast calls
convertPointerArg ended with an unconditional getRawPointer call for
buffer and arraybuffer types, rejecting BigInt addresses that the
single-argument fast path and ToFFIArgument both accept. Drop the
fallback; hasPointerMemoryArg already converts memory-backed values,
and null, undefined, and strings are handled earlier.

Signed-off-by: Trivikram Kamat <16024985+trivikr@users.noreply.github.com>
Assisted-by: claude:opus-5
PR-URL: https://github.com/nodejs/node/pull/64964
Fixes: https://github.com/nodejs/node/issues/64963
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-08-04 17:15:37 +00:00
Junsoo Ha 7cb4e7fc46 ffi: support SharedArrayBuffer in getRawPointer
Signed-off-by: Junsoo Ha <junsoo2018@naver.com>
PR-URL: https://github.com/nodejs/node/pull/64864
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
2026-08-04 15:58:10 +00:00
Trivikram Kamat f43086d1e4 ffi: fix crash in refCallback and unrefCallback
Both handlers called fn.ClearWeak() and fn.SetWeak() without checking
whether the persistent handle was still populated. After the callback
function is garbage collected following an earlier unrefCallback()
call, the handle is empty and both V8 methods dereference a null slot.

InvokeCallback() already guarded against this. Add the same check to
both handlers and throw ERR_INVALID_ARG_VALUE, matching the existing
behavior for a pointer that is not in the callback map.

Signed-off-by: Trivikram Kamat <16024985+trivikr@users.noreply.github.com>
Assisted-by: claude:opus-5
PR-URL: https://github.com/nodejs/node/pull/64881
Fixes: https://github.com/nodejs/node/issues/64880
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
2026-08-02 20:18:19 +00:00
Trivikram Kamat c55eb4acb1 ffi: reject fast calls after library close
Optimized Fast API calls bypass InvokeFunction and can jump directly to
a symbol after DynamicLibrary::close() unloads its library.

Check the function's closed state in the AArch64 and SysV x64
trampolines before entering the target. If the library is closed,
schedule ERR_FFI_LIBRARY_CLOSED and return without calling the symbol.

Keep the JavaScript guard on platforms without a native trampoline guard
and for signatures that already require argument conversion or
validation. This keeps raw scalar fast calls close to their original
performance on supported platforms.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: codex:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64860
Fixes: https://github.com/nodejs/node/issues/64854
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-08-02 14:54:42 +00:00
Seongeun Lee b9dacd417f test: reuse ffi.suffix instead of reimplementing it
ffi-test-common.js duplicated the platform branch already exposed
as ffi.suffix, risking drift if lib/ffi.js changes. Reuse it, and
require it after skipIfFFIMissing() so a build without FFI skips
instead of throwing.

Also assert ffi.suffix resolves to the correct value per platform,
since test-ffi-module.js only checked that the key exists.

Signed-off-by: leah-1ee <dltjddms1028@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/64840
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Aviv Keller <me@aviv.sh>
2026-08-01 08:47:38 +00:00
Trivikram Kamat c8e2a82400 ffi: validate fast 32-bit integer argument ranges
Add i32, int32, u32, and uint32 to Fast API integer validation so
optimized calls reject invalid values instead of allowing V8 to
coerce or truncate them.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64691
Fixes: https://github.com/nodejs/node/issues/64690
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-07-30 18:57:57 +00:00
Trivikram Kamat f85fdabc47 ffi: fix optimized buffer conversions
Preserve pointer-like argument conversions for buffer and arraybuffer
signatures after Fast API optimization. Keep memory-backed arguments
on the specialized native fast path.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64639
Fixes: https://github.com/nodejs/node/issues/64638
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Aviv Keller <me@aviv.sh>
2026-07-30 18:57:47 +00:00
Trivikram Kamat 241fb9a8f1 ffi: preserve strings during reentrant calls
Cache temporary string conversion buffers by wrapper and active call
depth. This prevents nested FFI calls from overwriting or replacing
buffers still in use by an outer native call.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64551
Fixes: https://github.com/nodejs/node/issues/64550
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-07-23 15:27:21 +00:00
Trivikram Kamat 0992f6b87e ffi: preserve uint8 semantics for bool fast calls
Normalize bool to kUint8 when creating Fast API metadata. This keeps
optimized calls consistent with generic FFI behavior, including numeric
return values and rejection of JavaScript Boolean values.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64527
Fixes: https://github.com/nodejs/node/issues/64526
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-07-23 03:33:17 +00:00
Trivikram Kamat fbab458611 ffi: validate fast integer argument ranges
Validate narrow integer and 64-bit BigInt arguments before entering
the Fast API trampoline. This prevents out-of-range values from being
silently truncated or wrapped and matches the generic FFI path.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64614
Fixes: https://github.com/nodejs/node/issues/64613
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-07-22 06:49:15 +00:00
Trivikram Kamat 00917ba54c ffi: evaluate function signatures once
Function signatures were read by the native implementation and then
read again while creating JavaScript wrappers. Accessors, proxies,
or mutations could therefore produce different native and JavaScript
signatures.

Build wrappers from signature metadata captured by native code instead.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.6-sol
PR-URL: https://github.com/nodejs/node/pull/64559
Fixes: https://github.com/nodejs/node/issues/64558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-07-20 05:24:57 +00:00
Paolo Insogna 3e8aa7de27 ffi: add getCurrentEventLoop
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Assisted-By: OpenAI:GPT-5.5 <openai/gpt-5.5>
PR-URL: https://github.com/nodejs/node/pull/64323
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com>
2026-07-08 13:24:50 +00:00
Paolo InsognaandBryan English 3e55527eef ffi: add experimental fast FFI call API for AArch64 and x86_64
Add fast API trampolines for AArch64 and x86_64.

IsJitMemorySupported() maps an RW page, writes a ret instruction
(0xD65F03C0 AArch64 / 0xC3 x86_64), and mprotects it to RX. A
successful RX transition is treated as the support signal. The page is
deliberately not executed: this check may run during normal operation
(when an FFI function is first created), and executing freshly written
code from a capability probe could SIGSEGV/SIGKILL the process on
systems that block executable memory. The real trampoline emitter
performs the same mprotect at creation time and falls back to libffi
when it is rejected.

The result is computed once via std::call_once and cached for the
lifetime of the process, so concurrent callers never observe a
provisional value.

Wired into CreateFastFFIMetadata() for early nullptr bail-out when
JIT memory is unavailable.

Windows stub returns false (no trampolines yet on this branch).

IsFastCallEligible() validates at parse time whether a signature can
use the fast-call path, covering:

- Return and argument type eligibility (numeric, pointer; no structs)
- Argument count cap (8, matching V8 fast-call limit)
- Per-ABI register pressure limits that mirror the trampoline emitters
  (AArch64 and x86_64 SysV). Platforms without an emitter, including
  Win64, are reported ineligible.
- Buffer and float args cannot coexist, and buffer args additionally
  consume an extra GP register slot on both supported ABIs.

The arg/arg-name lengths are checked before the per-arg loop so a
malformed signature cannot index out of bounds.

Returns nullptr from CreateFastFFIMetadata() for ineligible signatures,
falling back to libffi.

Co-authored-by: Bryan English <bryan@bryanenglish.com>
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Signed-off-by: Bryan English <bryan@bryanenglish.com>
Assisted-By: OpenAI:GPT-5.5 <openai/gpt-5.5>
PR-URL: https://github.com/nodejs/node/pull/63068
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-06-16 09:35:02 +00:00
Anshika Jain 31c40f0073 ffi: validate 'void' as parameter type in getFunction and getFunctions
Fixes: https://github.com/nodejs/node/issues/63461
Signed-off-by: Anshikakalpana <anshikajain196872@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/63504
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-05-27 08:13:43 +00:00
René df09b2a48c ffi: remove function signature property aliases
Signed-off-by: Renegade334 <contact.9a5d6388@renegade334.me.uk>
PR-URL: https://github.com/nodejs/node/pull/63482
Refs: https://github.com/nodejs/node/pull/62072/changes#r3067834658
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-05-24 12:39:53 +00:00
Paolo Insogna a2aeb72bff deps: add missing static linking targets for libffi
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
PR-URL: https://github.com/nodejs/node/pull/63168
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
2026-05-11 17:30:23 +00:00
Jordan Harband 2f5d7e77de module: exclude node:ffi from builtinModules when not enabled
`Module.builtinModules` is supposed to only list modules
that are accessible to user code.
`node:ffi` requires `--experimental-ffi` to be required,
so filter it out when the flag is not set,
mirroring the existing handling for `--experimental-quic`.

Refs: https://github.com/nodejs/node/pull/63137#issuecomment-4390371187
Signed-off-by: Jordan Harband <ljharb@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/63158
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Jacob Smith <jacob@frende.me>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-05-07 00:47:41 +02:00
semimikoh 9c0101860e ffi: prevent premature GC of DynamicLibrary
Signed-off-by: semimikoh <ejffjeosms@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/63024
Fixes: https://github.com/nodejs/node/issues/63010
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-05-01 09:52:10 +00:00
Matteo Collina 61db2609e3 ffi: support Symbol.dispose on DynamicLibrary
Install [Symbol.dispose]() on DynamicLibrary.prototype (calling close())
and on the object returned from ffi.dlopen(), so both can be used with
the `using` declaration for automatic cleanup.

Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/62925
Reviewed-By: Bryan English <bryan@bryanenglish.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2026-04-29 11:13:47 +00:00
Bryan English 1ad06ff9a7 ffi: add shared-buffer fast path for numeric and pointer signatures
Adds an ArrayBuffer-based invocation path for FFI functions whose
signatures are composed entirely of numeric types (i8..i64, u8..u64,
f32, f64, bool, char) and/or pointer types. The JS wrapper packs
arguments directly into a per-function AB via primordial DataView
setters and the C++ invoker (`InvokeFunctionSB`) reads them without
going through V8's `FunctionCallbackInfo`. Results are returned the same
way.

Pointer arguments use runtime dispatch: BigInt, null, and undefined take
the fast path, while Buffer, ArrayBuffer, ArrayBufferView, and String
fall back transparently to the classic `InvokeFunction` path via a
stashed `_invokeSlow` function. Signatures containing
non-numeric/non-pointer types also bypass the fast path.

The fast path is disabled on big-endian platforms.

Callers do not opt in, and the fast path is transparent in every way
users should rely on. One observable change: function wrappers returned
by `library.getFunction`, `library.getFunctions`, and `library.functions`
now have `.length` equal to the declared parameter count rather than
`0`. Code that relied on the previous value will need to be updated.

Adds microbenchmarks covering the common FFI call shapes so future
changes to the invoker can be evaluated:

- add-i32.js: 2-arg integer
- add-f64.js: 2-arg float
- many-args.js: 6-arg integer
- pointer-bigint.js: 1-arg pointer (BigInt)
- sum-buffer.js: pointer + length (Buffer)

A `common.js` helper resolves the fixture-library path from
`test/ffi/fixture_library` without pulling in the test harness, and
throws a clear message if the fixture hasn't been built yet.

Also adds `sum_6_i32` to the fixture library for the many-args case.

Signed-off-by: Bryan English <bryan@bryanenglish.com>
PR-URL: https://github.com/nodejs/node/pull/62918
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
2026-04-28 14:55:52 +02:00
Bryan English 3a5344710a doc,test: mem protection must be observed in ffi
When using ffi.toBuffer, memory protection on any memory pages exposed
must be observed by the caller, otherwise crashes will occur.

Now documented, and tested.

PR-URL: https://github.com/nodejs/node/pull/62818
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-04-22 08:18:11 +00:00
Paolo Insogna 14e16db1bf lib: add new methods and error codes
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
PR-URL: https://github.com/nodejs/node/pull/62762
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-04-19 18:39:01 +00:00
cjihrigandPaolo Insogna d0fa608c07 lib,src,test,doc: add node:ffi module
PR-URL: https://github.com/nodejs/node/pull/62072
Co-authored-by: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Bryan English <bryan@bryanenglish.com>
2026-04-14 10:44:30 +01:00