Skip to content

ffi: SharedArrayBuffer pointer argument changes from rejected to accepted after optimization #65232

Description

@trivikr

Version

main

Platform

macOS 26.6.0

Subsystem

ffi

What steps will reproduce the bug?

repro.c

#include <stdint.h>

uint8_t first_byte(const uint8_t* pointer) {
  return pointer[0];
}

repro.js

import { DynamicLibrary, suffix } from 'node:ffi';

const lib = new DynamicLibrary(`./repro.${suffix}`);
const call = lib.getFunction('first_byte', {
  arguments: ['pointer'],
  return: 'u8',
});

const regular = new ArrayBuffer(1);
const shared = new SharedArrayBuffer(1);
new Uint8Array(shared)[0] = 42;

function printResult(label) {
  try {
    console.log(label, call(shared));
  } catch (error) {
    console.log(label, error.code, error.message);
  }
}

printResult('before optimization');

%PrepareFunctionForOptimization(call);
call(regular);

%OptimizeFunctionOnNextCall(call);
call(regular);

printResult('after optimization');

lib.close();

Commands to run:

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

$ 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?

Argument validation and behavior should be identical regardless of optimization state. Either consistently reject SAB or consistently support it.

What do you see instead?

before optimization ERR_INVALID_ARG_VALUE Argument 0 must be a buffer, an ArrayBuffer, a string, or a bigint
after optimization 42

The unoptimized path rejects the direct SharedArrayBuffer, but the optimized Fast API path accepts the identical value and calls C

Additional information

No response

Metadata

Metadata

Assignees

Labels

ffiIssues and PRs related to experimental Foreign Function Interface support.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions