diff options
author | 2022-11-02 01:16:13 -0700 | |
---|---|---|
committer | 2022-11-02 01:16:13 -0700 | |
commit | 81033c52fb8c4c6b9370b960451b21ac9f876744 (patch) | |
tree | 1b45a75645e94eeaefd7eebafb64f11df8ea601a /src/bun.js/bindings/JSFFIFunction.cpp | |
parent | 86639fe62a8b94fe68c64846d18de4dcf16c09e6 (diff) | |
download | bun-81033c52fb8c4c6b9370b960451b21ac9f876744.tar.gz bun-81033c52fb8c4c6b9370b960451b21ac9f876744.tar.zst bun-81033c52fb8c4c6b9370b960451b21ac9f876744.zip |
[bun:ffi] Implement `JSCallback` so C can call into JS
Diffstat (limited to 'src/bun.js/bindings/JSFFIFunction.cpp')
-rw-r--r-- | src/bun.js/bindings/JSFFIFunction.cpp | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/bun.js/bindings/JSFFIFunction.cpp b/src/bun.js/bindings/JSFFIFunction.cpp index 07fefac1f..66fdc701d 100644 --- a/src/bun.js/bindings/JSFFIFunction.cpp +++ b/src/bun.js/bindings/JSFFIFunction.cpp @@ -36,6 +36,40 @@ #include "DOMJITIDLTypeFilter.h" #include "DOMJITHelpers.h" +class FFICallbackFunctionWrapper { + + WTF_MAKE_FAST_ALLOCATED; + +public: + JSC::Strong<JSC::JSFunction> m_function; + JSC::Strong<Zig::GlobalObject> globalObject; + ~FFICallbackFunctionWrapper() = default; + + FFICallbackFunctionWrapper(JSC::JSFunction* function, Zig::GlobalObject* globalObject) + : m_function(globalObject->vm(), function) + , globalObject(globalObject->vm(), globalObject) + { + } +}; +extern "C" void FFICallbackFunctionWrapper_destroy(FFICallbackFunctionWrapper* wrapper) +{ + delete wrapper; +} + +extern "C" FFICallbackFunctionWrapper* Bun__createFFICallbackFunction( + Zig::GlobalObject* globalObject, + JSC::EncodedJSValue callbackFn) +{ + auto* vm = &globalObject->vm(); + auto scope = DECLARE_THROW_SCOPE(*vm); + + auto* callbackFunction = jsCast<JSC::JSFunction*>(JSC::JSValue::decode(callbackFn)); + + auto* wrapper = new FFICallbackFunctionWrapper(callbackFunction, globalObject); + + return wrapper; +} + extern "C" Zig::JSFFIFunction* Bun__CreateFFIFunction(Zig::GlobalObject* globalObject, const ZigString* symbolName, unsigned argCount, Zig::FFIFunction functionPointer, bool strong) { JSC::VM& vm = globalObject->vm(); @@ -96,3 +130,208 @@ JSFFIFunction* JSFFIFunction::create(VM& vm, Zig::GlobalObject* globalObject, un } } // namespace JSC + +extern "C" JSC::EncodedJSValue +FFI_Callback_call(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + JSC::MarkedArgumentBuffer arguments; + for (size_t i = 0; i < argCount; ++i) + arguments.appendWithCrashOnOverflow(JSC::JSValue::decode(args[i])); + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue +FFI_Callback_call_0(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue +FFI_Callback_call_1(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue +FFI_Callback_call_2(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + arguments.append(JSC::JSValue::decode(args[1])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue FFI_Callback_call_3(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + arguments.append(JSC::JSValue::decode(args[1])); + arguments.append(JSC::JSValue::decode(args[2])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue FFI_Callback_call_4(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + arguments.append(JSC::JSValue::decode(args[1])); + arguments.append(JSC::JSValue::decode(args[2])); + arguments.append(JSC::JSValue::decode(args[3])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue FFI_Callback_call_5(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + arguments.append(JSC::JSValue::decode(args[1])); + arguments.append(JSC::JSValue::decode(args[2])); + arguments.append(JSC::JSValue::decode(args[3])); + arguments.append(JSC::JSValue::decode(args[4])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue +FFI_Callback_call_6(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + arguments.append(JSC::JSValue::decode(args[1])); + arguments.append(JSC::JSValue::decode(args[2])); + arguments.append(JSC::JSValue::decode(args[3])); + arguments.append(JSC::JSValue::decode(args[4])); + arguments.append(JSC::JSValue::decode(args[5])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} + +extern "C" JSC::EncodedJSValue +FFI_Callback_call_7(FFICallbackFunctionWrapper& wrapper, size_t argCount, JSC::EncodedJSValue* args) +{ + auto* function = wrapper.m_function.get(); + auto* globalObject = wrapper.globalObject.get(); + auto& vm = globalObject->vm(); + + JSC::MarkedArgumentBuffer arguments; + arguments.append(JSC::JSValue::decode(args[0])); + arguments.append(JSC::JSValue::decode(args[1])); + arguments.append(JSC::JSValue::decode(args[2])); + arguments.append(JSC::JSValue::decode(args[3])); + arguments.append(JSC::JSValue::decode(args[4])); + arguments.append(JSC::JSValue::decode(args[5])); + arguments.append(JSC::JSValue::decode(args[6])); + + WTF::NakedPtr<JSC::Exception> exception; + auto result = JSC::call(globalObject, function, JSC::getCallData(function), JSC::jsUndefined(), arguments, exception); + if (UNLIKELY(exception)) { + auto scope = DECLARE_THROW_SCOPE(vm); + scope.throwException(globalObject, exception); + return JSC::JSValue::encode(JSC::jsNull()); + } + + return JSC::JSValue::encode(result); +} |