Skip to content

ffi: Fast FFI buffer/arraybuffer signatures reject bigint after optimization #64638

Description

@trivikr

Version

main

Platform

macOS 26.5.2

Subsystem

ffi

What steps will reproduce the bug?

repro.c

#include <stdint.h>

__attribute__((visibility("default")))
uintptr_t pointer_to_usize(void* pointer) {
  return (uintptr_t)pointer;
}

Build it by running

$ cc -dynamiclib repro.c -o librepro.dylib

repro.js

import { dlopen } from "node:ffi";

const { lib, functions } = dlopen("./librepro.dylib", {
  pointer_to_usize: {
    arguments: ["buffer"], // Also reproduces with 'arraybuffer'.
    return: "u64",
  },
});

function call(value) {
  return functions.pointer_to_usize(value);
}

console.log("before:", call(0n));

try {
  for (let i = 0; i < 1_000_000; i++)
    call(0n);
  console.log('after:', call(0n));
} catch (error) {
  console.log('after:', error.code, error.message);
}

lib.close();

Run it using

$ node --no-warnings --experimental-ffi --allow-natives-syntax repro.js

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

before: 0n
after: 0n

Optimization should not change accepted inputs; buffer and arraybuffer signatures should continue accepting documented pointer-like values such as bigint.

What do you see instead?

before: 0n
after: ERR_INVALID_ARG_VALUE Argument 0 must be a buffer or an ArrayBuffer

The initial generic call accepts 0n, but after optimization the same call throws ERR_INVALID_ARG_VALUE

Additional information

No response

Metadata

Metadata

Assignees

Labels

ffiIssues and PRs related to experimental Foreign Function Interface support.

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions