#include "root.h" #include "JavaScriptCore/JSCJSValueInlines.h" #include "JavaScriptCore/JSInternalPromise.h" #include "JavaScriptCore/LazyPropertyInlines.h" #include #include #include "JSNextTickQueue.h" #include #include #include #include "ExtendedDOMClientIsoSubspaces.h" #include "ExtendedDOMIsoSubspaces.h" #include "BunClientData.h" namespace Bun { using namespace JSC; const JSC::ClassInfo JSNextTickQueue::s_info = { "JSNextTickQueue"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSNextTickQueue) }; template JSC::GCClient::IsoSubspace* JSNextTickQueue::subspaceFor(JSC::VM& vm) { return WebCore::subspaceForImpl( vm, [](auto& spaces) { return spaces.m_clientSubspaceForJSNextTickQueue.get(); }, [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForJSNextTickQueue = std::forward(space); }, [](auto& spaces) { return spaces.m_subspaceForJSNextTickQueue.get(); }, [](auto& spaces, auto&& space) { spaces.m_subspaceForJSNextTickQueue = std::forward(space); }); } JSNextTickQueue* JSNextTickQueue::create(VM& vm, Structure* structure) { JSNextTickQueue* mod = new (NotNull, allocateCell(vm)) JSNextTickQueue(vm, structure); return mod; } Structure* JSNextTickQueue::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info()); } JSNextTickQueue::JSNextTickQueue(VM& vm, Structure* structure) : Base(vm, structure) { } void JSNextTickQueue::finishCreation(VM& vm) { Base::finishCreation(vm); } template void JSNextTickQueue::visitChildrenImpl(JSCell* cell, Visitor& visitor) { auto* thisObject = jsCast(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); Base::visitChildren(thisObject, visitor); } DEFINE_VISIT_CHILDREN(JSNextTickQueue); JSNextTickQueue* JSNextTickQueue::create(JSC::JSGlobalObject* globalObject) { auto& vm = globalObject->vm(); auto* obj = create(vm, createStructure(vm, globalObject, jsNull())); obj->finishCreation(vm); return obj; } bool JSNextTickQueue::isEmpty() { return !internalField(0) || internalField(0).get().asNumber() == 0; } void JSNextTickQueue::drain(JSC::VM& vm, JSC::JSGlobalObject* globalObject) { bool mustResetContext = false; if (isEmpty()) { vm.drainMicrotasks(); mustResetContext = true; } if (!isEmpty()) { if (mustResetContext) { globalObject->m_asyncContextData.get()->putInternalField(vm, 0, jsUndefined()); } auto* drainFn = internalField(2).get().getObject(); auto throwScope = DECLARE_THROW_SCOPE(vm); MarkedArgumentBuffer drainArgs; JSC::call(globalObject, drainFn, drainArgs, "Failed to drain next tick queue"_s); } } }