aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/JSFFIFunction.cpp
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-11-02 01:16:13 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-11-02 01:16:13 -0700
commit81033c52fb8c4c6b9370b960451b21ac9f876744 (patch)
tree1b45a75645e94eeaefd7eebafb64f11df8ea601a /src/bun.js/bindings/JSFFIFunction.cpp
parent86639fe62a8b94fe68c64846d18de4dcf16c09e6 (diff)
downloadbun-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.cpp239
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);
+}