diff options
-rw-r--r-- | src/bun.js/bindings/bindings.cpp | 13 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/EventEmitter.cpp | 66 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/IdentifierEventListenerMap.h | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSEventEmitterCustom.cpp | 15 |
4 files changed, 57 insertions, 41 deletions
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 8e401b4cd..114b59163 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -3819,21 +3819,23 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskJob(JSC__JSGlobalObject* arg0 JSC::JSValue::decode(JSValue4)); } -extern "C" JSC__JSValue JSC__AbortSignal__create(JSC__JSGlobalObject* globalObject) { +extern "C" JSC__JSValue JSC__AbortSignal__create(JSC__JSGlobalObject* globalObject) +{ Zig::GlobalObject* thisObject = JSC::jsCast<Zig::GlobalObject*>(globalObject); auto* context = thisObject->scriptExecutionContext(); auto abortSignal = WebCore::AbortSignal::create(context); return JSValue::encode(toJSNewlyCreated<IDLInterface<JSC__AbortSignal>>(*globalObject, *jsCast<JSDOMGlobalObject*>(globalObject), WTFMove(abortSignal))); } -extern "C" JSC__JSValue JSC__AbortSignal__toJS(JSC__AbortSignal* arg0, JSC__JSGlobalObject* globalObject) { +extern "C" JSC__JSValue JSC__AbortSignal__toJS(JSC__AbortSignal* arg0, JSC__JSGlobalObject* globalObject) +{ WebCore::AbortSignal* abortSignal = reinterpret_cast<WebCore::AbortSignal*>(arg0); return JSValue::encode(toJS<IDLInterface<JSC__AbortSignal>>(*globalObject, *jsCast<JSDOMGlobalObject*>(globalObject), *abortSignal)); } - -extern "C" JSC__AbortSignal* JSC__AbortSignal__signal(JSC__AbortSignal* arg0, JSC__JSValue JSValue1) { +extern "C" JSC__AbortSignal* JSC__AbortSignal__signal(JSC__AbortSignal* arg0, JSC__JSValue JSValue1) +{ WebCore::AbortSignal* abortSignal = reinterpret_cast<WebCore::AbortSignal*>(arg0); abortSignal->signalAbort(JSC::JSValue::decode(JSValue1)); @@ -3865,7 +3867,8 @@ extern "C" JSC__AbortSignal* JSC__AbortSignal__unref(JSC__AbortSignal* arg0) abortSignal->deref(); return arg0; } -extern "C" void JSC__AbortSignal__cleanNativeBindings(JSC__AbortSignal* arg0, void* arg1) { +extern "C" void JSC__AbortSignal__cleanNativeBindings(JSC__AbortSignal* arg0, void* arg1) +{ WebCore::AbortSignal* abortSignal = reinterpret_cast<WebCore::AbortSignal*>(arg0); abortSignal->cleanNativeBindings(arg1); } diff --git a/src/bun.js/bindings/webcore/EventEmitter.cpp b/src/bun.js/bindings/webcore/EventEmitter.cpp index 02770be68..4ea10587e 100644 --- a/src/bun.js/bindings/webcore/EventEmitter.cpp +++ b/src/bun.js/bindings/webcore/EventEmitter.cpp @@ -177,12 +177,14 @@ void EventEmitter::fireEventListeners(const Identifier& eventType, const MarkedA if (!data) return; - SetForScope firingEventListenersScope(data->isFiringEventListeners, true); - - if (auto* listenersVector = data->eventListenerMap.find(eventType)) { - innerInvokeEventListeners(eventType, *listenersVector, arguments); + auto* listenersVector = data->eventListenerMap.find(eventType); + if (UNLIKELY(!listenersVector)) return; - } + + bool prevFiringEventListeners = data->isFiringEventListeners; + data->isFiringEventListeners = true; + innerInvokeEventListeners(eventType, *listenersVector, arguments); + data->isFiringEventListeners = prevFiringEventListeners; } // Intentionally creates a copy of the listeners vector to avoid event listeners added after this point from being run. @@ -204,39 +206,45 @@ void EventEmitter::innerInvokeEventListeners(const Identifier& eventType, Simple if (UNLIKELY(registeredListener->wasRemoved())) continue; + auto& callback = registeredListener->callback(); + // Make sure the JS wrapper and function stay alive until the end of this scope. Otherwise, // event listeners with 'once' flag may get collected as soon as they get unregistered below, // before we call the js function. - JSC::EnsureStillAliveScope wrapperProtector(registeredListener->callback().wrapper()); - JSC::EnsureStillAliveScope jsFunctionProtector(registeredListener->callback().jsFunction()); + JSObject* jsFunction = callback.jsFunction(); + JSC::EnsureStillAliveScope wrapperProtector(callback.wrapper()); + JSC::EnsureStillAliveScope jsFunctionProtector(jsFunction); // Do this before invocation to avoid reentrancy issues. if (registeredListener->isOnce()) - removeListener(eventType, registeredListener->callback()); + removeListener(eventType, callback); - if (JSC::JSObject* jsFunction = registeredListener->callback().jsFunction()) { - JSC::JSGlobalObject* lexicalGlobalObject = jsFunction->globalObject(); - auto callData = JSC::getCallData(jsFunction); - if (callData.type == JSC::CallData::Type::None) - continue; + if (UNLIKELY(!jsFunction)) + continue; + + JSC::JSGlobalObject* lexicalGlobalObject = jsFunction->globalObject(); + auto callData = JSC::getCallData(jsFunction); + if (UNLIKELY(callData.type == JSC::CallData::Type::None)) + continue; - WTF::NakedPtr<JSC::Exception> exceptionPtr; - JSC::call(jsFunction->globalObject(), jsFunction, callData, thisValue, arguments, exceptionPtr); - if (auto* exception = exceptionPtr.get()) { - auto errorIdentifier = JSC::Identifier::fromString(vm, eventNames().errorEvent); - auto hasErrorListener = this->hasActiveEventListeners(errorIdentifier); - if (!hasErrorListener || eventType == errorIdentifier) { - // If the event type is error, report the exception to the console. - Bun__reportUnhandledError(lexicalGlobalObject, JSValue::encode(JSValue(exception))); - } else if (hasErrorListener) { - MarkedArgumentBuffer expcep; - JSValue errorValue = exception->value(); - if (!errorValue) { - errorValue = JSC::jsUndefined(); - } - expcep.append(errorValue); - fireEventListeners(errorIdentifier, WTFMove(expcep)); + WTF::NakedPtr<JSC::Exception> exceptionPtr; + JSC::call(lexicalGlobalObject, jsFunction, callData, thisValue, arguments, exceptionPtr); + auto* exception = exceptionPtr.get(); + + if (UNLIKELY(exception)) { + auto errorIdentifier = JSC::Identifier::fromString(vm, eventNames().errorEvent); + auto hasErrorListener = this->hasActiveEventListeners(errorIdentifier); + if (!hasErrorListener || eventType == errorIdentifier) { + // If the event type is error, report the exception to the console. + Bun__reportUnhandledError(lexicalGlobalObject, JSValue::encode(JSValue(exception))); + } else if (hasErrorListener) { + MarkedArgumentBuffer expcep; + JSValue errorValue = exception->value(); + if (!errorValue) { + errorValue = JSC::jsUndefined(); } + expcep.append(errorValue); + fireEventListeners(errorIdentifier, WTFMove(expcep)); } } } diff --git a/src/bun.js/bindings/webcore/IdentifierEventListenerMap.h b/src/bun.js/bindings/webcore/IdentifierEventListenerMap.h index 1d3f00cbd..d78f7ec11 100644 --- a/src/bun.js/bindings/webcore/IdentifierEventListenerMap.h +++ b/src/bun.js/bindings/webcore/IdentifierEventListenerMap.h @@ -36,8 +36,8 @@ private: Ref<EventListener> m_callback; }; -using SimpleEventListenerVector = Vector<RefPtr<SimpleRegisteredEventListener>, 0, CrashOnOverflow, 2>; -using EntriesVector = Vector<std::pair<JSC::Identifier, SimpleEventListenerVector>, 0, CrashOnOverflow, 4>; +using SimpleEventListenerVector = Vector<RefPtr<SimpleRegisteredEventListener>, 2, CrashOnOverflow, 6>; +using EntriesVector = Vector<std::pair<JSC::Identifier, SimpleEventListenerVector>, 4, CrashOnOverflow, 8>; class IdentifierEventListenerMap { public: diff --git a/src/bun.js/bindings/webcore/JSEventEmitterCustom.cpp b/src/bun.js/bindings/webcore/JSEventEmitterCustom.cpp index e6e15b874..fd2a61822 100644 --- a/src/bun.js/bindings/webcore/JSEventEmitterCustom.cpp +++ b/src/bun.js/bindings/webcore/JSEventEmitterCustom.cpp @@ -42,19 +42,24 @@ std::unique_ptr<JSEventEmitterWrapper> jsEventEmitterCast(VM& vm, JSC::JSGlobalO JSEventEmitter* jsEventEmitterCastFast(VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSValue thisValue) { - if (thisValue.inherits<JSEventEmitter>()) - return jsCast<JSEventEmitter*>(asObject(thisValue)); + if (UNLIKELY(!thisValue.isCell())) { + return nullptr; + } - if (UNLIKELY(thisValue.isUndefinedOrNull() || !thisValue.isObject())) { + JSCell* thisCell = thisValue.asCell(); + if (UNLIKELY(!thisCell->isObject())) { return nullptr; } - auto* thisObject = asObject(thisValue); + auto* thisObject = asObject(thisCell); + + if (thisObject->inherits<JSEventEmitter>()) + return jsCast<JSEventEmitter*>(thisObject); auto clientData = WebCore::clientData(vm); auto name = clientData->builtinNames()._eventsPublicName(); if (JSValue _events = thisObject->getIfPropertyExists(lexicalGlobalObject, name)) { - if (!_events.isUndefinedOrNull() && _events.inherits<JSEventEmitter>()) { + if (_events.isCell() && _events.inherits<JSEventEmitter>()) { return jsCast<JSEventEmitter*>(asObject(_events)); } } |