diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 8cfb0330ed..eb297c9374 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -2543,6 +2543,42 @@ extern "C" napi_status napi_create_symbol(napi_env env, napi_value description, return napi_ok; } +// https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/src/js_native_api_v8.cc#L2904-L2930 +extern "C" napi_status napi_new_instance(napi_env env, napi_value constructor, + size_t argc, const napi_value* argv, + napi_value* result) +{ + NAPI_PREMABLE + if (UNLIKELY(!result)) { + return napi_invalid_arg; + } + + Zig::GlobalObject* globalObject = toJS(env); + JSC::VM& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + + JSC::JSValue constructorValue = toJS(constructor); + if (UNLIKELY(!constructorValue.isObject())) { + return napi_function_expected; + } + + JSC::JSObject* constructorObject = constructorValue.getObject(); + JSC::CallData constructData = getConstructData(constructorObject); + if (UNLIKELY(constructData.type == JSC::CallData::Type::None)) { + return napi_function_expected; + } + + JSC::MarkedArgumentBuffer args; + args.fill(vm, argc, [&](auto* slot) { + memcpy(slot, argv, sizeof(JSC::JSValue) * argc); + }); + + auto value = construct(globalObject, constructorObject, constructData, args); + RETURN_IF_EXCEPTION(throwScope, napi_pending_exception); + *result = toNapi(value); + + RELEASE_AND_RETURN(throwScope, napi_ok); +} extern "C" napi_status napi_call_function(napi_env env, napi_value recv_napi, napi_value func_napi, size_t argc, const napi_value* argv, diff --git a/src/napi/napi.zig b/src/napi/napi.zig index f7fc6c0aec..8a1799c3de 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -648,37 +648,7 @@ pub export fn napi_strict_equals(env: napi_env, lhs: napi_value, rhs: napi_value return .ok; } pub extern fn napi_call_function(env: napi_env, recv: napi_value, func: napi_value, argc: usize, argv: [*c]const napi_value, result: *napi_value) napi_status; -pub export fn napi_new_instance(env: napi_env, constructor: napi_value, argc: usize, argv: [*c]const napi_value, result_: ?*napi_value) napi_status { - log("napi_new_instance", .{}); - JSC.markBinding(@src()); - - if (argc > 0 and argv == null) { - return invalidArg(); - } - - const result = result_ orelse { - return invalidArg(); - }; - - var exception = [_]JSC.C.JSValueRef{null}; - result.* = JSValue.c( - JSC.C.JSObjectCallAsConstructor( - env.ref(), - constructor.asObjectRef(), - argc, - if (argv != null) - @as([*]const JSC.C.JSValueRef, @ptrCast(argv)) - else - null, - &exception, - ), - ); - if (exception[0] != null) { - return genericFailure(); - } - - return .ok; -} +pub extern fn napi_new_instance(env: napi_env, constructor: napi_value, argc: usize, argv: [*c]const napi_value, result_: ?*napi_value) napi_status; pub export fn napi_instanceof(env: napi_env, object: napi_value, constructor: napi_value, result_: ?*bool) napi_status { log("napi_instanceof", .{}); const result = result_ orelse {