Version
main
Platform
Subsystem
ffi
What steps will reproduce the bug?
repro.c
#include<stdint.h>#include<stdio.h>int32_tadd_i32(int32_ta, int32_tb) {
fprintf(stderr, "native add_i32 invoked: %d + %d\n", a, b);
returna+b;
}
doublemultiply_f64(doublea, doubleb) {
returna*b;
}repro.js
import{dlopen,suffix}from'node:ffi';const{ functions }=dlopen(`./repro.${suffix}`,{add_i32: {arguments: ['i32','i32'],return: 'i32',},multiply_f64: {arguments: ['f64','f64'],return: 'f64',},});const{ add_i32, multiply_f64 }=functions;console.log('add_i32 has own prototype:',Object.hasOwn(add_i32,'prototype'),);try{Reflect.construct(add_i32,[20,22]);console.log('Reflect.construct(add_i32): succeeded');}catch(error){console.log('Reflect.construct(add_i32):',`${error.name}: ${error.message}`,);}console.log('multiply_f64 has own prototype:',Object.hasOwn(multiply_f64,'prototype'),);try{Reflect.construct(multiply_f64,[6,7]);console.log('Reflect.construct(multiply_f64): succeeded');}catch(error){console.log('Reflect.construct(multiply_f64):',`${error.name}: ${error.message}`,);}Commands to run:
$ cc -dynamiclib -o repro.dylib repro.c
$ node --no-warnings --experimental-ffi repro.js
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
Wrapped functions should preserve the native function’s non-constructible behavior: no own .prototype, and Reflect.construct() should throw a TypeError without invoking native code.
What do you see instead?
add_i32 has own prototype: truenative add_i32 invoked: 20 + 22Reflect.construct(add_i32): succeededmultiply_f64 has own prototype: falseReflect.construct(multiply_f64): TypeError: function multiply_f64() { [native code] } is not a constructorWrapped native functions such as add_i32 gain an own .prototype, and Reflect.construct(add_i32, [20, 22]) succeeds and invokes native code.
Additional information
No response
Version
main
Platform
Subsystem
ffi
What steps will reproduce the bug?
repro.crepro.jsCommands to run:
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
Wrapped functions should preserve the native function’s non-constructible behavior: no own
.prototype, andReflect.construct()should throw aTypeErrorwithout invoking native code.What do you see instead?
Wrapped native functions such as
add_i32gain an own.prototype, andReflect.construct(add_i32, [20, 22])succeeds and invokes native code.Additional information
No response