aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/AsyncContextFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/bindings/AsyncContextFrame.cpp')
-rw-r--r--src/bun.js/bindings/AsyncContextFrame.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/bun.js/bindings/AsyncContextFrame.cpp b/src/bun.js/bindings/AsyncContextFrame.cpp
new file mode 100644
index 000000000..326350664
--- /dev/null
+++ b/src/bun.js/bindings/AsyncContextFrame.cpp
@@ -0,0 +1,107 @@
+#pragma once
+
+#include "root.h"
+#include "ZigGlobalObject.h"
+#include "AsyncContextFrame.h"
+#include "JavaScriptCore/InternalFieldTuple.h"
+
+using namespace JSC;
+using namespace WebCore;
+
+const ClassInfo AsyncContextFrame::s_info = { "AsyncContextFrame"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(AsyncContextFrame) };
+
+AsyncContextFrame* AsyncContextFrame::create(VM& vm, JSC::Structure* structure, JSValue callback, JSValue context)
+{
+ AsyncContextFrame* asyncContextData = new (NotNull, allocateCell<AsyncContextFrame>(vm)) AsyncContextFrame(vm, structure);
+ asyncContextData->finishCreation(vm);
+ asyncContextData->callback.set(vm, asyncContextData, callback);
+ asyncContextData->context.set(vm, asyncContextData, context);
+ return asyncContextData;
+}
+
+AsyncContextFrame* AsyncContextFrame::create(JSGlobalObject* global, JSValue callback, JSValue context)
+{
+ auto& vm = global->vm();
+ AsyncContextFrame* asyncContextData = new (NotNull, allocateCell<AsyncContextFrame>(vm)) AsyncContextFrame(vm, static_cast<Zig::GlobalObject*>(global)->AsyncContextFrameStructure());
+ asyncContextData->finishCreation(vm);
+ asyncContextData->callback.set(vm, asyncContextData, callback);
+ asyncContextData->context.set(vm, asyncContextData, context);
+ return asyncContextData;
+}
+
+JSC::Structure* AsyncContextFrame::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), info());
+}
+
+JSValue AsyncContextFrame::withAsyncContextIfNeeded(JSGlobalObject* globalObject, JSValue callback)
+{
+ JSValue context = globalObject->m_asyncContextData.get()->getInternalField(0);
+
+ // If there is no async context, do not snapshot the callback.
+ if (context.isUndefined()) {
+ return callback;
+ }
+
+ // Construct a low-overhead wrapper
+ auto& vm = globalObject->vm();
+ return AsyncContextFrame::create(
+ vm,
+ static_cast<Zig::GlobalObject*>(globalObject)->AsyncContextFrameStructure(),
+ callback,
+ context);
+}
+
+template<typename Visitor>
+void AsyncContextFrame::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ auto* thisObject = jsCast<AsyncContextFrame*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ visitor.append(thisObject->callback);
+ visitor.append(thisObject->context);
+}
+
+DEFINE_VISIT_CHILDREN(AsyncContextFrame);
+
+extern "C" EncodedJSValue AsyncContextFrame__withAsyncContextIfNeeded(JSGlobalObject* globalObject, EncodedJSValue callback)
+{
+ return JSValue::encode(AsyncContextFrame::withAsyncContextIfNeeded(globalObject, JSValue::decode(callback)));
+}
+
+#define ASYNCCONTEXTFRAME_CALL_IMPL(...) \
+ if (!functionObject.isCell()) \
+ return jsUndefined(); \
+ auto& vm = global->vm(); \
+ JSValue restoreAsyncContext; \
+ InternalFieldTuple* asyncContextData = nullptr; \
+ if (auto* wrapper = jsDynamicCast<AsyncContextFrame*>(functionObject)) { \
+ functionObject = jsCast<JSC::JSObject*>(wrapper->callback.get()); \
+ asyncContextData = global->m_asyncContextData.get(); \
+ restoreAsyncContext = asyncContextData->getInternalField(0); \
+ asyncContextData->putInternalField(vm, 0, wrapper->context.get()); \
+ } \
+ auto result = JSC::call(__VA_ARGS__); \
+ if (asyncContextData) { \
+ asyncContextData->putInternalField(vm, 0, restoreAsyncContext); \
+ } \
+ return result;
+
+JSValue AsyncContextFrame::call(JSGlobalObject* global, JSValue functionObject, const ArgList& args, ASCIILiteral errorMessage)
+{
+ ASYNCCONTEXTFRAME_CALL_IMPL(global, functionObject, args, errorMessage);
+}
+JSValue AsyncContextFrame::call(JSGlobalObject* global, JSValue functionObject, JSValue thisValue, const ArgList& args, ASCIILiteral errorMessage)
+{
+ ASYNCCONTEXTFRAME_CALL_IMPL(global, functionObject, thisValue, args, errorMessage);
+}
+JSValue AsyncContextFrame::call(JSGlobalObject* global, JSValue functionObject, JSValue thisValue, const ArgList& args)
+{
+ ASYNCCONTEXTFRAME_CALL_IMPL(global, functionObject, JSC::getCallData(functionObject), thisValue, args);
+}
+JSValue AsyncContextFrame::call(JSGlobalObject* global, JSValue functionObject, JSValue thisValue, const ArgList& args, NakedPtr<Exception>& returnedException)
+{
+ ASYNCCONTEXTFRAME_CALL_IMPL(global, functionObject, JSC::getCallData(functionObject), thisValue, args, returnedException);
+}
+
+#undef ASYNCCONTEXTFRAME_CALL_IMPL