aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-07-18 20:48:51 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-07-18 20:49:11 -0700
commit8bd2b784a272f4ee571cbc924f8822d7ba6f7b51 (patch)
tree4f8515084f85ccf220738749187a0c8d7579eae2
parentf494e1b50d1d1b2d49998af0ef9b2b8f12b47620 (diff)
downloadbun-8bd2b784a272f4ee571cbc924f8822d7ba6f7b51.tar.gz
bun-8bd2b784a272f4ee571cbc924f8822d7ba6f7b51.tar.zst
bun-8bd2b784a272f4ee571cbc924f8822d7ba6f7b51.zip
more progress on fixing gc issue
-rw-r--r--src/bun.js/bindings/ScriptExecutionContext.h2
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp178
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.h10
-rw-r--r--src/bun.js/bindings/webcore/JSEventTargetCustom.cpp3
-rw-r--r--src/bun.js/bindings/webcore/Worker.cpp29
-rw-r--r--src/bun.js/bindings/webcore/Worker.h1
6 files changed, 162 insertions, 61 deletions
diff --git a/src/bun.js/bindings/ScriptExecutionContext.h b/src/bun.js/bindings/ScriptExecutionContext.h
index c3fbd7c9b..520954c29 100644
--- a/src/bun.js/bindings/ScriptExecutionContext.h
+++ b/src/bun.js/bindings/ScriptExecutionContext.h
@@ -86,6 +86,7 @@ public:
, m_globalObject(globalObject)
, m_identifier(identifier)
{
+ addToContextsMap();
}
static ScriptExecutionContextIdentifier generateIdentifier();
@@ -183,6 +184,7 @@ public:
void setGlobalObject(JSC::JSGlobalObject* globalObject)
{
m_globalObject = globalObject;
+ m_vm = &globalObject->vm();
}
private:
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index a8d14e533..0262050ff 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -179,6 +179,17 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers;
#include "webcrypto/JSSubtleCrypto.h"
#include "JSDOMFormData.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConstructor.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertBoolean.h"
+#include "JSDOMConvertDictionary.h"
+#include "JSDOMConvertEventListener.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertNullable.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMConvertUnion.h"
+#include "AddEventListenerOptions.h"
#include "ErrorStackTrace.h"
#include "CallSite.h"
@@ -423,11 +434,10 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* globalObje
Zig::GlobalObject* globalObject;
if (UNLIKELY(executionContextId > -1)) {
- ScriptExecutionContext* context = new WebCore::ScriptExecutionContext(&vm, nullptr, static_cast<ScriptExecutionContextIdentifier>(executionContextId));
globalObject = Zig::GlobalObject::create(
vm,
Zig::GlobalObject::createStructure(vm, JSC::JSGlobalObject::create(vm, JSC::JSGlobalObject::createStructure(vm, JSC::jsNull())), JSC::jsNull()),
- context);
+ static_cast<ScriptExecutionContextIdentifier>(executionContextId));
} else {
globalObject = Zig::GlobalObject::create(
vm,
@@ -435,7 +445,7 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* globalObje
JSC::jsNull()));
}
- globalObject->setConsole(globalObject);
+ globalObject->setConsole(console_client);
globalObject->isThreadLocalDefaultGlobalObject = true;
globalObject->setStackTraceLimit(DEFAULT_ERROR_STACK_TRACE_LIMIT); // Node.js defaults to 10
vm.setOnComputeErrorInfo(computeErrorInfo);
@@ -699,27 +709,25 @@ GlobalObject::GlobalObject(JSC::VM& vm, JSC::Structure* structure)
, m_world(WebCore::DOMWrapperWorld::create(vm, WebCore::DOMWrapperWorld::Type::Normal))
, m_worldIsNormal(true)
, m_builtinInternalFunctions(vm)
- , globalEventScope(Bun::GlobalScope::create(nullptr))
-
+ , m_scriptExecutionContext(new WebCore::ScriptExecutionContext(&vm, this))
+ , globalEventScope(*new Bun::GlobalScope(m_scriptExecutionContext))
{
- m_scriptExecutionContext = new WebCore::ScriptExecutionContext(&vm, this);
- globalEventScope->m_context = m_scriptExecutionContext;
mockModule = Bun::JSMockModule::create(this);
+ globalEventScope.m_context = m_scriptExecutionContext;
}
-GlobalObject::GlobalObject(JSC::VM& vm, JSC::Structure* structure, WebCore::ScriptExecutionContext* context)
+GlobalObject::GlobalObject(JSC::VM& vm, JSC::Structure* structure, WebCore::ScriptExecutionContextIdentifier contextId)
: JSC::JSGlobalObject(vm, structure, &s_globalObjectMethodTable)
, m_bunVM(Bun__getVM())
, m_constructors(makeUnique<WebCore::DOMConstructors>())
, m_world(WebCore::DOMWrapperWorld::create(vm, WebCore::DOMWrapperWorld::Type::Normal))
, m_worldIsNormal(true)
, m_builtinInternalFunctions(vm)
- , globalEventScope(Bun::GlobalScope::create(context))
+ , m_scriptExecutionContext(new WebCore::ScriptExecutionContext(&vm, this, contextId))
+ , globalEventScope(*new Bun::GlobalScope(m_scriptExecutionContext))
{
mockModule = Bun::JSMockModule::create(this);
- m_scriptExecutionContext = context;
- context->setGlobalObject(this);
- context->addToContextsMap();
+ globalEventScope.m_context = m_scriptExecutionContext;
}
GlobalObject::~GlobalObject()
@@ -774,12 +782,9 @@ void GlobalObject::promiseRejectionTracker(JSGlobalObject* obj, JSC::JSPromise*
}
}
-static Zig::ConsoleClient* m_console;
-
void GlobalObject::setConsole(void* console)
{
- m_console = new Zig::ConsoleClient(console);
- this->setConsoleClient(m_console);
+ this->setConsoleClient(new Zig::ConsoleClient(console));
}
#pragma mark - Globals
@@ -826,7 +831,7 @@ JSC_DEFINE_CUSTOM_SETTER(globalSetterOnError,
return true;
}
-Ref<WebCore::EventTarget> GlobalObject::eventTarget()
+WebCore::EventTarget& GlobalObject::eventTarget()
{
return globalEventScope;
}
@@ -1689,6 +1694,84 @@ JSC:
}
}
+static inline JSC::EncodedJSValue jsFunctionAddEventListenerBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, Zig::GlobalObject* castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->globalEventScope;
+ if (UNLIKELY(callFrame->argumentCount() < 2))
+ return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
+ auto type = convert<IDLAtomStringAdaptor<IDLDOMString>>(*lexicalGlobalObject, argument0.value());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1);
+ auto listener = convert<IDLNullable<IDLEventListener<JSEventListener>>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "addEventListener"); });
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ EnsureStillAliveScope argument2 = callFrame->argument(2);
+ auto options = argument2.value().isUndefined() ? false : convert<IDLUnion<IDLDictionary<AddEventListenerOptions>, IDLBoolean>>(*lexicalGlobalObject, argument2.value());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ auto result = JSValue::encode(WebCore::toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.addEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(options)); }));
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ vm.writeBarrier(&static_cast<JSObject&>(*castedThis), argument1.value());
+ return result;
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionAddEventListener, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return jsFunctionAddEventListenerBody(lexicalGlobalObject, callFrame, jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject));
+}
+
+static inline JSC::EncodedJSValue jsFunctionRemoveEventListenerBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, Zig::GlobalObject* castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->globalEventScope;
+ if (UNLIKELY(callFrame->argumentCount() < 2))
+ return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
+ auto type = convert<IDLAtomStringAdaptor<IDLDOMString>>(*lexicalGlobalObject, argument0.value());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1);
+ auto listener = convert<IDLNullable<IDLEventListener<JSEventListener>>>(*lexicalGlobalObject, argument1.value(), *castedThis, [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentMustBeObjectError(lexicalGlobalObject, scope, 1, "listener", "EventTarget", "removeEventListener"); });
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ EnsureStillAliveScope argument2 = callFrame->argument(2);
+ auto options = argument2.value().isUndefined() ? false : convert<IDLUnion<IDLDictionary<EventListenerOptions>, IDLBoolean>>(*lexicalGlobalObject, argument2.value());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ auto result = JSValue::encode(WebCore::toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.removeEventListenerForBindings(WTFMove(type), WTFMove(listener), WTFMove(options)); }));
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ vm.writeBarrier(&static_cast<JSObject&>(*castedThis), argument1.value());
+ return result;
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionRemoveEventListener, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return jsFunctionRemoveEventListenerBody(lexicalGlobalObject, callFrame, jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject));
+}
+
+static inline JSC::EncodedJSValue jsFunctionDispatchEventBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, Zig::GlobalObject* castedThis)
+{
+ auto& vm = JSC::getVM(lexicalGlobalObject);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ UNUSED_PARAM(throwScope);
+ UNUSED_PARAM(callFrame);
+ auto& impl = castedThis->globalEventScope;
+ if (UNLIKELY(callFrame->argumentCount() < 1))
+ return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject));
+ EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0);
+ auto event = convert<IDLInterface<Event>>(*lexicalGlobalObject, argument0.value(), [](JSC::JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope) { throwArgumentTypeError(lexicalGlobalObject, scope, 0, "event", "EventTarget", "dispatchEvent", "Event"); });
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ RELEASE_AND_RETURN(throwScope, JSValue::encode(WebCore::toJS<IDLBoolean>(*lexicalGlobalObject, throwScope, impl.dispatchEventForBindings(*event))));
+}
+
+JSC_DEFINE_HOST_FUNCTION(jsFunctionDispatchEvent, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame))
+{
+ return jsFunctionDispatchEventBody(lexicalGlobalObject, callFrame, jsDynamicCast<Zig::GlobalObject*>(lexicalGlobalObject));
+}
+
static inline JSValue jsServiceWorkerGlobalScope_ByteLengthQueuingStrategyConstructorGetter(JSGlobalObject& lexicalGlobalObject, Zig::GlobalObject& thisObject)
{
UNUSED_PARAM(lexicalGlobalObject);
@@ -3463,11 +3546,11 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPostMessage,
return JSValue::encode(jsUndefined());
}
- ScriptExecutionContext::postTaskTo(context->identifier(), [message = serialized.releaseReturnValue(), protectedThis = Ref { *worker }](ScriptExecutionContext& context) {
+ RefPtr<SerializedScriptValue> message = serialized.releaseReturnValue();
+ ScriptExecutionContext::postTaskTo(context->identifier(), [message = WTFMove(message), protectedThis = Ref { *worker }](ScriptExecutionContext& context) {
Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(context.jsGlobalObject());
bool didFail = false;
JSValue value = message->deserialize(*globalObject, globalObject, SerializationErrorMode::NonThrowing, &didFail);
- message->deref();
if (didFail) {
protectedThis->dispatchEvent(MessageEvent::create(eventNames().messageerrorEvent, MessageEvent::Init {}, MessageEvent::IsTrusted::Yes));
@@ -3774,7 +3857,6 @@ JSC_DEFINE_HOST_FUNCTION(functionGetDirectStreamDetails, (JSC::JSGlobalObject *
return JSC::JSValue::encode(resultObject);
}
-
JSC::GCClient::IsoSubspace* GlobalObject::subspaceForImpl(JSC::VM& vm)
{
return WebCore::subspaceForImpl<GlobalObject, WebCore::UseCustomHeapCellType::Yes>(
@@ -3881,31 +3963,6 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 });
}
- {
- JSC::Identifier addEventListener = JSC::Identifier::fromString(vm, "addEventListener"_s);
- extraStaticGlobals.uncheckedAppend(
- GlobalPropertyInfo { addEventListener,
- JSC::JSFunction::create(vm, this, 2,
- "addEventListener"_s, WebCore::jsEventTargetPrototypeFunction_addEventListener, ImplementationVisibility::Public),
- JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 });
- }
-
- {
- extraStaticGlobals.uncheckedAppend(
- GlobalPropertyInfo { JSC::Identifier::fromString(vm, "dispatchEvent"_s),
- JSC::JSFunction::create(vm, this, 1,
- "dispatchEvent"_s, WebCore::jsEventTargetPrototypeFunction_dispatchEvent, ImplementationVisibility::Public),
- JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 });
- }
-
- {
- extraStaticGlobals.uncheckedAppend(
- GlobalPropertyInfo { JSC::Identifier::fromString(vm, "removeEventListener"_s),
- JSC::JSFunction::create(vm, this, 1,
- "removeEventListener"_s, WebCore::jsEventTargetPrototypeFunction_removeEventListener, ImplementationVisibility::Public),
- JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0 });
- }
-
extraStaticGlobals.uncheckedAppend(
GlobalPropertyInfo { builtinNames.startDirectStreamPrivateName(),
JSC::JSFunction::create(vm, this, 1,
@@ -4101,6 +4158,30 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm)
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "CountQueuingStrategy"_s), CustomGetterSetter::create(vm, jsServiceWorkerGlobalScope_CountQueuingStrategyConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "SubtleCrypto"_s), JSC::CustomGetterSetter::create(vm, getterSubtleCryptoConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "CryptoKey"_s), JSC::CustomGetterSetter::create(vm, getterCryptoKeyConstructor, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
+
+ putDirectNativeFunction(vm, this,
+ Identifier::fromString(vm, "addEventListener"_s),
+ 2,
+ jsFunctionAddEventListener,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
+
+ putDirectNativeFunction(vm, this,
+ Identifier::fromString(vm, "dispatchEvent"_s),
+ 1,
+ jsFunctionDispatchEvent,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
+
+ putDirectNativeFunction(vm, this,
+ Identifier::fromString(vm, "removeEventListener"_s),
+ 2,
+ jsFunctionRemoveEventListener,
+ ImplementationVisibility::Public,
+ NoIntrinsic,
+ JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0);
}
// We set it in here since it's a global
@@ -4474,8 +4555,6 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
thisObject->visitGeneratedLazyClasses<Visitor>(thisObject, visitor);
visitor.append(thisObject->m_BunCommonJSModuleValue);
thisObject->visitAdditionalChildren<Visitor>(visitor);
- ScriptExecutionContext* context = thisObject->scriptExecutionContext();
- visitor.addOpaqueRoot(context);
}
extern "C" bool JSGlobalObject__setTimeZone(JSC::JSGlobalObject* globalObject, const ZigString* timeZone)
@@ -4547,7 +4626,10 @@ void GlobalObject::visitAdditionalChildren(Visitor& visitor)
GlobalObject* thisObject = this;
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- thisObject->globalEventScope->visitJSEventListeners(visitor);
+ thisObject->globalEventScope.visitJSEventListeners(visitor);
+
+ ScriptExecutionContext* context = thisObject->scriptExecutionContext();
+ visitor.addOpaqueRoot(context);
}
DEFINE_VISIT_ADDITIONAL_CHILDREN(GlobalObject);
diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h
index 5df1560b0..7501be89e 100644
--- a/src/bun.js/bindings/ZigGlobalObject.h
+++ b/src/bun.js/bindings/ZigGlobalObject.h
@@ -133,9 +133,9 @@ public:
return ptr;
}
- static GlobalObject* create(JSC::VM& vm, JSC::Structure* structure, WebCore::ScriptExecutionContext* scriptExecutionContext)
+ static GlobalObject* create(JSC::VM& vm, JSC::Structure* structure, uint32_t scriptExecutionContextId)
{
- GlobalObject* ptr = new (NotNull, JSC::allocateCell<GlobalObject>(vm)) GlobalObject(vm, structure, scriptExecutionContext);
+ GlobalObject* ptr = new (NotNull, JSC::allocateCell<GlobalObject>(vm)) GlobalObject(vm, structure, scriptExecutionContextId);
ptr->finishCreation(vm);
return ptr;
}
@@ -312,8 +312,8 @@ public:
EncodedJSValue assignToStream(JSValue stream, JSValue controller);
- Ref<WebCore::EventTarget> eventTarget();
- Ref<Bun::GlobalScope> globalEventScope;
+ WebCore::EventTarget& eventTarget();
+ Bun::GlobalScope& globalEventScope;
enum class PromiseFunctions : uint8_t {
Bun__HTTPRequestContext__onReject,
@@ -448,7 +448,7 @@ private:
friend void WebCore::JSBuiltinInternalFunctions::initialize(Zig::GlobalObject&);
WebCore::JSBuiltinInternalFunctions m_builtinInternalFunctions;
GlobalObject(JSC::VM& vm, JSC::Structure* structure);
- GlobalObject(JSC::VM& vm, JSC::Structure* structure, WebCore::ScriptExecutionContext*);
+ GlobalObject(JSC::VM& vm, JSC::Structure* structure, uint32_t);
std::unique_ptr<WebCore::DOMConstructors> m_constructors;
uint8_t m_worldIsNormal;
JSDOMStructureMap m_structures WTF_GUARDED_BY_LOCK(m_gcLock);
diff --git a/src/bun.js/bindings/webcore/JSEventTargetCustom.cpp b/src/bun.js/bindings/webcore/JSEventTargetCustom.cpp
index 75ee90c9f..1b00dc987 100644
--- a/src/bun.js/bindings/webcore/JSEventTargetCustom.cpp
+++ b/src/bun.js/bindings/webcore/JSEventTargetCustom.cpp
@@ -36,6 +36,7 @@
// #include "JSWindowProxy.h"
// #include "JSWorkerGlobalScope.h"
// #include "WorkerGlobalScope.h"
+#include "BunWorkerGlobalScope.h"
#if ENABLE(OFFSCREEN_CANVAS)
#include "OffscreenCanvas.h"
@@ -56,7 +57,7 @@ EventTarget* JSEventTarget::toWrapped(VM& vm, JSValue value)
// if (value.inherits<JSDOMWindow>())
// return &jsCast<JSDOMWindow*>(asObject(value))->wrapped();
if (value.inherits<JSDOMGlobalObject>())
- return jsCast<JSDOMGlobalObject*>(asObject(value))->eventTarget().ptr();
+ return &jsCast<JSDOMGlobalObject*>(asObject(value))->globalEventScope;
if (value.inherits<JSEventTarget>())
return &jsCast<JSEventTarget*>(asObject(value))->wrapped();
return nullptr;
diff --git a/src/bun.js/bindings/webcore/Worker.cpp b/src/bun.js/bindings/webcore/Worker.cpp
index 4ffbc0684..d92b6e2e5 100644
--- a/src/bun.js/bindings/webcore/Worker.cpp
+++ b/src/bun.js/bindings/webcore/Worker.cpp
@@ -60,6 +60,7 @@
#include "JavaScriptCore/DeferredWorkTimer.h"
#include "MessageEvent.h"
#include <JavaScriptCore/HashMapImplInlines.h>
+#include "BunWorkerGlobalScope.h"
namespace WebCore {
@@ -176,20 +177,21 @@ ExceptionOr<void> Worker::postMessage(JSC::JSGlobalObject& state, JSC::JSValue m
if (message.hasException())
return message.releaseException();
- this->postTaskToWorkerGlobalScope([message = message.releaseReturnValue()](auto& context) {
+ RefPtr<SerializedScriptValue> result = message.releaseReturnValue();
+
+ this->postTaskToWorkerGlobalScope([message = WTFMove(result)](auto& context) {
Zig::GlobalObject* globalObject = jsCast<Zig::GlobalObject*>(context.jsGlobalObject());
bool didFail = false;
JSValue value = message->deserialize(*globalObject, globalObject, SerializationErrorMode::NonThrowing, &didFail);
- message->deref();
if (didFail) {
- globalObject->eventTarget()->dispatchEvent(MessageEvent::create(eventNames().messageerrorEvent, MessageEvent::Init {}, MessageEvent::IsTrusted::Yes));
+ globalObject->globalEventScope.dispatchEvent(MessageEvent::create(eventNames().messageerrorEvent, MessageEvent::Init {}, MessageEvent::IsTrusted::Yes));
return;
}
WebCore::MessageEvent::Init init;
init.data = value;
- globalObject->eventTarget()->dispatchEvent(MessageEvent::create(eventNames().messageEvent, WTFMove(init), MessageEvent::IsTrusted::Yes));
+ globalObject->globalEventScope.dispatchEvent(MessageEvent::create(eventNames().messageEvent, WTFMove(init), MessageEvent::IsTrusted::Yes));
});
return {};
}
@@ -229,6 +231,10 @@ void Worker::terminate()
bool Worker::hasPendingActivity() const
{
+ if (this->refCount() > 0) {
+ return true;
+ }
+
if (this->m_isOnline) {
return !this->m_isClosing;
}
@@ -241,7 +247,7 @@ void Worker::dispatchEvent(Event& event)
if (m_wasTerminated)
return;
- EventTarget::dispatchEvent(event);
+ EventTargetWithInlineData::dispatchEvent(event);
}
#if ENABLE(WEB_RTC)
@@ -259,6 +265,7 @@ void Worker::createRTCRtpScriptTransformer(RTCRtpScriptTransform& transform, Mes
void Worker::drainEvents()
{
+ Locker lock(this->m_pendingTasksMutex);
for (auto& task : m_pendingTasks)
postTaskToWorkerGlobalScope(WTFMove(task));
m_pendingTasks.clear();
@@ -277,19 +284,26 @@ void Worker::dispatchOnline(Zig::GlobalObject* workerGlobalObject)
});
}
+ Locker lock(this->m_pendingTasksMutex);
+
this->m_isOnline = true;
auto* thisContext = workerGlobalObject->scriptExecutionContext();
if (!thisContext) {
return;
}
+ RELEASE_ASSERT(&thisContext->vm() == &workerGlobalObject->vm());
+ RELEASE_ASSERT(thisContext == workerGlobalObject->globalEventScope.scriptExecutionContext());
- if (workerGlobalObject->eventTarget()->hasActiveEventListeners(eventNames().messageEvent)) {
+ if (workerGlobalObject->globalEventScope.hasActiveEventListeners(eventNames().messageEvent)) {
auto tasks = std::exchange(this->m_pendingTasks, {});
+ lock.unlockEarly();
for (auto& task : tasks) {
task(*thisContext);
}
} else {
auto tasks = std::exchange(this->m_pendingTasks, {});
+ lock.unlockEarly();
+
thisContext->postTask([tasks = WTFMove(tasks)](auto& ctx) mutable {
for (auto& task : tasks) {
task(ctx);
@@ -334,6 +348,7 @@ void Worker::dispatchExit()
void Worker::postTaskToWorkerGlobalScope(Function<void(ScriptExecutionContext&)>&& task)
{
if (!this->m_isOnline) {
+ Locker lock(this->m_pendingTasksMutex);
this->m_pendingTasks.append(WTFMove(task));
return;
}
@@ -388,7 +403,7 @@ extern "C" void WebWorker__dispatchError(Zig::GlobalObject* globalObject, Worker
init.cancelable = false;
init.bubbles = false;
- globalObject->eventTarget()->dispatchEvent(ErrorEvent::create(eventNames().errorEvent, init, EventIsTrusted::Yes));
+ globalObject->globalEventScope.dispatchEvent(ErrorEvent::create(eventNames().errorEvent, init, EventIsTrusted::Yes));
worker->dispatchError(Bun::toWTFString(message));
}
diff --git a/src/bun.js/bindings/webcore/Worker.h b/src/bun.js/bindings/webcore/Worker.h
index edd9f082d..99a54e37f 100644
--- a/src/bun.js/bindings/webcore/Worker.h
+++ b/src/bun.js/bindings/webcore/Worker.h
@@ -126,6 +126,7 @@ private:
// bool m_isSuspendedForBackForwardCache { false };
// JSC::RuntimeFlags m_runtimeFlags;
Deque<RefPtr<Event>> m_pendingEvents;
+ Lock m_pendingTasksMutex;
Deque<Function<void(ScriptExecutionContext&)>> m_pendingTasks;
bool m_wasTerminated { false };
bool m_didStartWorkerGlobalScope { false };