diff options
author | 2023-07-19 17:20:00 -0700 | |
---|---|---|
committer | 2023-07-19 17:20:00 -0700 | |
commit | 9b6dc49575df5fb953918c284505f24741138130 (patch) | |
tree | 3a052876fa8c6524e0c8d18479aabe38e2d5a52a /src/bun.js/bindings/ZigGlobalObject.cpp | |
parent | 723e9d1ea7c7fdb424ecedd0fb023524366322c4 (diff) | |
download | bun-9b6dc49575df5fb953918c284505f24741138130.tar.gz bun-9b6dc49575df5fb953918c284505f24741138130.tar.zst bun-9b6dc49575df5fb953918c284505f24741138130.zip |
Implement `AsyncLocalStorage` (#3089)
* work to get async local storage working.
* a
* a
* everything but queueMicrotask
* sdfghj
* .
* finish
* tests
* test
* ok
* done
* im so stupid
* Upgrade WebKit
* refactor
* refactor
* changes requested
* oops
* cool
* fix runInAsyncScope
Diffstat (limited to 'src/bun.js/bindings/ZigGlobalObject.cpp')
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 99 |
1 files changed, 74 insertions, 25 deletions
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 34ef5e38a..602c60f29 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -5,6 +5,7 @@ #include "BunClientData.h" #include "JavaScriptCore/AggregateError.h" +#include "JavaScriptCore/InternalFieldTuple.h" #include "JavaScriptCore/BytecodeIndex.h" #include "JavaScriptCore/CallFrameInlines.h" #include "JavaScriptCore/ClassInfo.h" @@ -92,6 +93,7 @@ #include "JSReadableState.h" #include "JSReadableHelper.h" #include "Process.h" +#include "AsyncContextFrame.h" #include "WebCoreJSBuiltins.h" #include "JSBuffer.h" @@ -1050,9 +1052,10 @@ JSC_DEFINE_HOST_FUNCTION(functionQueueMicrotask, } Zig::GlobalObject* global = JSC::jsCast<Zig::GlobalObject*>(globalObject); + JSC::JSValue asyncContext = global->m_asyncContextData.get()->getInternalField(0); // This is a JSC builtin function - globalObject->queueMicrotask(global->performMicrotaskFunction(), job, JSC::JSValue {}, + globalObject->queueMicrotask(global->performMicrotaskFunction(), job, asyncContext, JSC::JSValue {}, JSC::JSValue {}); return JSC::JSValue::encode(JSC::jsUndefined()); @@ -1499,6 +1502,23 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj return JSC::JSValue::encode(JSC::jsString(vm, url.fileSystemPath())); } +static void cleanupAsyncHooksData(JSC::VM& vm) +{ + vm.setOnEachMicrotaskTick(nullptr); + Bun__getDefaultGlobal()->m_asyncContextData.get()->putInternalField(vm, 0, jsUndefined()); +} + +// $lazy("async_hooks").cleanupLater +JSC_DEFINE_HOST_FUNCTION(asyncHooksCleanupLater, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + // assumptions and notes: + // - nobody else uses setOnEachMicrotaskTick + // - this is called by js if we set async context in a way we may not clear it + // - AsyncLocalStorage.prototype.run cleans up after itself and does not call this cb + globalObject->vm().setOnEachMicrotaskTick(&cleanupAsyncHooksData); + return JSC::JSValue::encode(JSC::jsUndefined()); +} + JSC_DEFINE_CUSTOM_GETTER(noop_getter, (JSGlobalObject*, EncodedJSValue, PropertyName)) { return JSC::JSValue::encode(JSC::jsUndefined()); @@ -1563,7 +1583,6 @@ JSC: return JSC::JSValue::encode(JSC::JSValue {}); } default: { - JSC::JSValue moduleName = callFrame->argument(0); if (moduleName.isNumber()) { switch (moduleName.toInt32(globalObject)) { @@ -1698,6 +1717,20 @@ JSC: return JSValue::encode(obj); } + if (string == "async_hooks"_s) { + auto* obj = constructEmptyObject(globalObject); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "get"_s)), + JSC::JSFunction::create(vm, asyncContextGetAsyncContextCodeGenerator(vm), globalObject), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "set"_s)), + JSC::JSFunction::create(vm, asyncContextSetAsyncContextCodeGenerator(vm), globalObject), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "cleanupLater"_s)), + JSC::JSFunction::create(vm, globalObject, 0, "cleanupLater"_s, asyncHooksCleanupLater, ImplementationVisibility::Public), 0); + return JSValue::encode(obj); + } + if (UNLIKELY(string == "noop"_s)) { auto* obj = constructEmptyObject(globalObject); obj->putDirectCustomAccessor(vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "getterSetter"_s)), JSC::CustomGetterSetter::create(vm, noop_getter, noop_setter), 0); @@ -2773,24 +2806,25 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotask, (JSGlobalObject * globalObj JSValue result; WTF::NakedPtr<JSC::Exception> exceptionPtr; + JSValue restoreAsyncContext = {}; + InternalFieldTuple* asyncContextData = nullptr; + auto setAsyncContext = callframe->argument(1); + if (!setAsyncContext.isUndefined()) { + asyncContextData = globalObject->m_asyncContextData.get(); + restoreAsyncContext = asyncContextData->getInternalField(0); + asyncContextData->putInternalField(vm, 0, setAsyncContext); + } + size_t argCount = callframe->argumentCount(); switch (argCount) { - case 1: { - break; - } - case 2: { - arguments.append(callframe->uncheckedArgument(1)); - break; - } case 3: { - arguments.append(callframe->uncheckedArgument(1)); arguments.append(callframe->uncheckedArgument(2)); break; } case 4: { - arguments.append(callframe->uncheckedArgument(1)); arguments.append(callframe->uncheckedArgument(2)); arguments.append(callframe->uncheckedArgument(3)); + break; } default: break; @@ -2798,6 +2832,10 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotask, (JSGlobalObject * globalObj JSC::call(globalObject, job, callData, jsUndefined(), arguments, exceptionPtr); + if (asyncContextData) { + asyncContextData->putInternalField(vm, 0, restoreAsyncContext); + } + if (auto* exception = exceptionPtr.get()) { Bun__reportUnhandledError(globalObject, JSValue::encode(exception)); } @@ -2843,12 +2881,25 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotaskVariadic, (JSGlobalObject * g WTF::NakedPtr<JSC::Exception> exceptionPtr; JSValue thisValue = jsUndefined(); - if (callframe->argumentCount() > 2) { - thisValue = callframe->argument(2); + if (callframe->argumentCount() > 3) { + thisValue = callframe->argument(3); + } + + JSValue restoreAsyncContext = {}; + InternalFieldTuple* asyncContextData = nullptr; + auto setAsyncContext = callframe->argument(2); + if (!setAsyncContext.isUndefined()) { + asyncContextData = globalObject->m_asyncContextData.get(); + restoreAsyncContext = asyncContextData->getInternalField(0); + asyncContextData->putInternalField(vm, 0, setAsyncContext); } JSC::call(globalObject, job, callData, thisValue, arguments, exceptionPtr); + if (asyncContextData) { + asyncContextData->putInternalField(vm, 0, restoreAsyncContext); + } + if (auto* exception = exceptionPtr.get()) { Bun__reportUnhandledError(globalObject, JSValue::encode(exception)); } @@ -3194,6 +3245,10 @@ void GlobalObject::finishCreation(VM& vm) [](const Initializer<JSWeakMap>& init) { init.set(JSWeakMap::create(init.vm, init.owner->weakMapStructure())); }); + // m_asyncHooksContext.initLater( + // [](const Initializer<JSC::JSMap>& init) { + // init.set(JSC::JSMap::create(init.vm, init.owner->mapStructure())); + // }); m_JSBufferSubclassStructure.initLater( [](const Initializer<Structure>& init) { @@ -3387,6 +3442,11 @@ void GlobalObject::finishCreation(VM& vm) init.set(Zig::ImportMetaObject::createStructure(init.vm, init.owner)); }); + m_asyncBoundFunctionStructure.initLater( + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) { + init.set(AsyncContextFrame::createStructure(init.vm, init.owner)); + }); + m_JSFileSinkClassStructure.initLater( [](LazyClassStructure::Initializer& init) { auto* prototype = createJSSinkPrototype(init.vm, init.global, WebCore::SinkID::FileSink); @@ -3670,18 +3730,6 @@ JSC_DEFINE_HOST_FUNCTION(functionBunPeekStatus, return JSValue::encode(jsUndefined()); } -extern "C" void Bun__setOnEachMicrotaskTick(JSC::VM* vm, void* ptr, void (*callback)(void* ptr)) -{ - if (callback == nullptr) { - vm->setOnEachMicrotaskTick(nullptr); - return; - } - - vm->setOnEachMicrotaskTick([=](JSC::VM& vm) { - callback(ptr); - }); -} - JSC_DEFINE_CUSTOM_GETTER(BunCommonJSModule_getter, (JSGlobalObject * globalObject, EncodedJSValue thisValue, PropertyName)) { Zig::GlobalObject* bunGlobalObject = jsCast<Zig::GlobalObject*>(globalObject); @@ -4548,6 +4596,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_importMetaRequireFunctionUnbound.visit(visitor); thisObject->m_importMetaRequireResolveFunctionUnbound.visit(visitor); thisObject->m_importMetaObjectStructure.visit(visitor); + thisObject->m_asyncBoundFunctionStructure.visit(visitor); thisObject->m_dnsObject.visit(visitor); thisObject->m_lazyRequireCacheObject.visit(visitor); |