Diff
Modified: trunk/Source/WebCore/ChangeLog (287292 => 287293)
--- trunk/Source/WebCore/ChangeLog 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/ChangeLog 2021-12-21 02:15:25 UTC (rev 287293)
@@ -1,3 +1,61 @@
+2021-12-20 Alexey Shvayka <[email protected]>
+
+ Introduce a fast path for replacing an attribute event listener
+ https://bugs.webkit.org/show_bug.cgi?id=234441
+
+ Reviewed by Chris Dumez.
+
+ This patch makes replacing attribute event listener (via EventHandler IDL attribute)
+ 2.6x faster by avoiding creation of intermediate JSEventListener instance.
+
+ Reusing is safe even for JSErrorHandler listeners as they can be replaced only with
+ instances of the same class. Uninitialized JSLazyEventListener can also be "replaced"
+ if m_isInitialized if set, which makes it behave like a regular JSEventListener.
+ All this is caught by existing tests.
+
+ Additionaly, this change slightly (about 3% according to a microbenchmark) speeds up
+ lookup of attribute event listeners by removing virtual isAttribute() call and related
+ downcasts from the hot path. Also, inlines event handler's getters / setters,
+ and simplifies call forwarding.
+
+ Altogether, this patch improves Speedometer2/Inferno-TodoMVC score by 4%.
+
+ No new tests, no behavior change.
+
+ * bindings/js/JSErrorHandler.h:
+ (WebCore::createJSErrorHandler): Deleted.
+ * bindings/js/JSEventListener.cpp:
+ (WebCore::JSEventListener::create):
+ (WebCore::JSEventListener::replaceJSFunctionForAttributeListener):
+ (WebCore::eventHandlerAttribute):
+ (WebCore::createEventListenerForEventHandlerAttribute): Deleted.
+ (WebCore::setEventHandlerAttribute): Deleted.
+ (WebCore::windowEventHandlerAttribute): Deleted.
+ (WebCore::setWindowEventHandlerAttribute): Deleted.
+ * bindings/js/JSEventListener.h:
+
+ Although setWindowEventHandlerAttribute<JSErrorHandler> is currently unused, it's
+ templatized to accommodate a follow-up patch that will fix a web-compat issue.
+ This change carefully preserves current (slightly incorrect) `onerror` behavior.
+
+ While we don't care about performance of `onerror`, using templates improves uniformity
+ (aligns signatures of create() methods) and will simplify code generation in the follow-up.
+
+ (WebCore::setEventHandlerAttribute):
+ (WebCore::windowEventHandlerAttribute):
+ (WebCore::setWindowEventHandlerAttribute):
+ * bindings/scripts/CodeGeneratorJS.pm:
+ (GenerateAttributeSetterBodyDefinition):
+ * bindings/scripts/test/JS/*: Updated.
+ * dom/Document.cpp:
+ (WebCore::Document::setWindowAttributeEventListener):
+ (WebCore::Document::getWindowAttributeEventListener): Deleted.
+ * dom/Document.h:
+ * dom/EventTarget.cpp:
+ (WebCore::EventTarget::setAttributeEventListener):
+ (WebCore::EventTarget::attributeEventListener):
+ * dom/EventTarget.h:
+
2021-12-19 Simon Fraser <[email protected]>
Remove EventHandler::scrollDistance()
Modified: trunk/Source/WebCore/bindings/js/JSErrorHandler.h (287292 => 287293)
--- trunk/Source/WebCore/bindings/js/JSErrorHandler.h 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/bindings/js/JSErrorHandler.h 2021-12-21 02:15:25 UTC (rev 287293)
@@ -45,13 +45,4 @@
void handleEvent(ScriptExecutionContext&, Event&) final;
};
-// Creates a listener for "onerror" event handler.
-// It has custom implementation because, unlike other event listeners, it accepts three parameters.
-inline RefPtr<JSErrorHandler> createJSErrorHandler(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue listener, JSC::JSObject& wrapper)
-{
- if (!listener.isObject())
- return nullptr;
- return JSErrorHandler::create(*asObject(listener), wrapper, true, currentWorld(lexicalGlobalObject));
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSEventListener.cpp (287292 => 287293)
--- trunk/Source/WebCore/bindings/js/JSEventListener.cpp 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.cpp 2021-12-21 02:15:25 UTC (rev 287293)
@@ -61,9 +61,9 @@
JSEventListener::~JSEventListener() = default;
-Ref<JSEventListener> JSEventListener::create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world)
+Ref<JSEventListener> JSEventListener::create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world)
{
- return adoptRef(*new JSEventListener(listener, wrapper, isAttribute, world));
+ return adoptRef(*new JSEventListener(&listener, &wrapper, isAttribute, world));
}
RefPtr<JSEventListener> JSEventListener::create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world)
@@ -71,7 +71,7 @@
if (UNLIKELY(!listener.isObject()))
return nullptr;
- return create(JSC::asObject(listener), &wrapper, isAttribute, world);
+ return adoptRef(*new JSEventListener(asObject(listener), &wrapper, isAttribute, world));
}
JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext&) const
@@ -79,6 +79,29 @@
return nullptr;
}
+void JSEventListener::replaceJSFunctionForAttributeListener(JSObject* function, JSObject* wrapper)
+{
+ ASSERT(m_isAttribute);
+ ASSERT(function);
+ ASSERT(wrapper);
+
+ m_jsFunction = Weak { function };
+ m_wrapper = wrapper;
+ m_isInitialized = true;
+}
+
+JSValue eventHandlerAttribute(EventTarget& eventTarget, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ if (auto* jsListener = eventTarget.attributeEventListener(eventType, isolatedWorld)) {
+ if (auto* context = eventTarget.scriptExecutionContext()) {
+ if (auto* jsFunction = jsListener->ensureJSFunction(*context))
+ return jsFunction;
+ }
+ }
+
+ return jsNull();
+}
+
template<typename Visitor>
inline void JSEventListener::visitJSFunctionImpl(Visitor& visitor)
{
@@ -262,58 +285,4 @@
return handlerFunction->name(vm);
}
-static inline JSC::JSValue eventHandlerAttribute(EventListener* abstractListener, ScriptExecutionContext& context)
-{
- if (!is<JSEventListener>(abstractListener))
- return jsNull();
-
- auto* function = downcast<JSEventListener>(*abstractListener).ensureJSFunction(context);
- if (!function)
- return jsNull();
-
- return function;
-}
-
-static inline RefPtr<JSEventListener> createEventListenerForEventHandlerAttribute(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue listener, JSC::JSObject& wrapper)
-{
- if (!listener.isObject())
- return nullptr;
- return JSEventListener::create(asObject(listener), &wrapper, true, currentWorld(lexicalGlobalObject));
-}
-
-JSC::JSValue eventHandlerAttribute(EventTarget& target, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
-{
- auto* context = target.scriptExecutionContext();
- if (!context)
- return jsNull();
- return eventHandlerAttribute(target.attributeEventListener(eventType, isolatedWorld), *context);
-}
-
-void setEventHandlerAttribute(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSObject& wrapper, EventTarget& target, const AtomString& eventType, JSC::JSValue value)
-{
- target.setAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(lexicalGlobalObject, value, wrapper), currentWorld(lexicalGlobalObject));
-}
-
-JSC::JSValue windowEventHandlerAttribute(HTMLElement& element, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
-{
- auto& document = element.document();
- return eventHandlerAttribute(document.getWindowAttributeEventListener(eventType, isolatedWorld), document);
-}
-
-void setWindowEventHandlerAttribute(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSObject& wrapper, HTMLElement& element, const AtomString& eventType, JSC::JSValue value)
-{
- ASSERT(wrapper.globalObject());
- element.document().setWindowAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(lexicalGlobalObject, value, *wrapper.globalObject()), currentWorld(lexicalGlobalObject));
-}
-
-JSC::JSValue windowEventHandlerAttribute(DOMWindow& window, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
-{
- return eventHandlerAttribute(window, eventType, isolatedWorld);
-}
-
-void setWindowEventHandlerAttribute(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSObject& wrapper, DOMWindow& window, const AtomString& eventType, JSC::JSValue value)
-{
- setEventHandlerAttribute(lexicalGlobalObject, wrapper, window, eventType, value);
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/js/JSEventListener.h (287292 => 287293)
--- trunk/Source/WebCore/bindings/js/JSEventListener.h 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.h 2021-12-21 02:15:25 UTC (rev 287293)
@@ -19,8 +19,11 @@
#pragma once
+#include "DOMWindow.h"
#include "DOMWrapperWorld.h"
#include "EventListener.h"
+#include "EventNames.h"
+#include "HTMLElement.h"
#include <_javascript_Core/StrongInlines.h>
#include <_javascript_Core/Weak.h>
#include <_javascript_Core/WeakInlines.h>
@@ -31,14 +34,9 @@
namespace WebCore {
-class DOMWindow;
-class Document;
-class EventTarget;
-class HTMLElement;
-
class JSEventListener : public EventListener {
public:
- WEBCORE_EXPORT static Ref<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
+ WEBCORE_EXPORT static Ref<JSEventListener> create(JSC::JSObject& listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&);
WEBCORE_EXPORT static RefPtr<JSEventListener> create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld&);
virtual ~JSEventListener();
@@ -60,6 +58,8 @@
String functionName() const;
+ void replaceJSFunctionForAttributeListener(JSC::JSObject* function, JSC::JSObject* wrapper);
+
private:
virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext&) const;
@@ -84,14 +84,39 @@
// For "onxxx" attributes that automatically set up _javascript_ event listeners.
JSC::JSValue eventHandlerAttribute(EventTarget&, const AtomString& eventType, DOMWrapperWorld&);
-void setEventHandlerAttribute(JSC::JSGlobalObject&, JSC::JSObject&, EventTarget&, const AtomString& eventType, JSC::JSValue);
+template<typename JSMaybeErrorEventListener>
+inline void setEventHandlerAttribute(EventTarget& eventTarget, const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget)
+{
+ eventTarget.setAttributeEventListener<JSMaybeErrorEventListener>(eventType, listener, jsEventTarget);
+}
+
// Like the functions above, but for attributes that forward event handlers to the window object rather than setting them on the target.
-JSC::JSValue windowEventHandlerAttribute(HTMLElement&, const AtomString& eventType, DOMWrapperWorld&);
-void setWindowEventHandlerAttribute(JSC::JSGlobalObject&, JSC::JSObject&, HTMLElement&, const AtomString& eventType, JSC::JSValue);
-JSC::JSValue windowEventHandlerAttribute(DOMWindow&, const AtomString& eventType, DOMWrapperWorld&);
-void setWindowEventHandlerAttribute(JSC::JSGlobalObject&, JSC::JSObject&, DOMWindow&, const AtomString& eventType, JSC::JSValue);
+inline JSC::JSValue windowEventHandlerAttribute(DOMWindow& window, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ return eventHandlerAttribute(window, eventType, isolatedWorld);
+}
+inline JSC::JSValue windowEventHandlerAttribute(HTMLElement& element, const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ if (auto* domWindow = element.document().domWindow())
+ return eventHandlerAttribute(*domWindow, eventType, isolatedWorld);
+ return JSC::jsNull();
+}
+
+template<typename JSMaybeErrorEventListener>
+inline void setWindowEventHandlerAttribute(DOMWindow& window, const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget)
+{
+ window.setAttributeEventListener<JSMaybeErrorEventListener>(eventType, listener, jsEventTarget);
+}
+
+template<typename JSMaybeErrorEventListener>
+inline void setWindowEventHandlerAttribute(HTMLElement& element, const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget)
+{
+ if (auto* domWindow = element.document().domWindow())
+ setWindowEventHandlerAttribute<JSMaybeErrorEventListener>(*domWindow, eventType, listener, jsEventTarget);
+}
+
inline JSC::JSObject* JSEventListener::ensureJSFunction(ScriptExecutionContext& scriptExecutionContext) const
{
// initializeJSFunction can trigger code that deletes this event listener
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (287292 => 287293)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2021-12-21 02:15:25 UTC (rev 287293)
@@ -5438,11 +5438,11 @@
# FIXME: Find a way to do this special case without hardcoding the class and attribute names here.
if (($interface->type->name eq "DOMWindow" or $interface->type->name eq "WorkerGlobalScope") and $attribute->name eq "onerror") {
AddToImplIncludes("JSErrorHandler.h", $conditional);
- push(@$outputArray, " thisObject.wrapped().setAttributeEventListener($eventName, createJSErrorHandler(lexicalGlobalObject, value, thisObject), worldForDOMObject(thisObject));\n");
+ push(@$outputArray, " setEventHandlerAttribute<JSErrorHandler>(thisObject.wrapped(), ${eventName}, value, thisObject);\n");
} else {
AddToImplIncludes("JSEventListener.h", $conditional);
my $setter = $attribute->extendedAttributes->{WindowEventHandler} ? "setWindowEventHandlerAttribute" : "setEventHandlerAttribute";
- push(@$outputArray, " $setter(lexicalGlobalObject, thisObject, thisObject.wrapped(), ${eventName}, value);\n");
+ push(@$outputArray, " $setter<JSEventListener>(thisObject.wrapped(), ${eventName}, value, thisObject);\n");
}
push(@$outputArray, " vm.writeBarrier(&thisObject, value);\n");
push(@$outputArray, " ensureStillAliveHere(value);\n\n");
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSON.cpp (287292 => 287293)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSON.cpp 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSON.cpp 2021-12-21 02:15:25 UTC (rev 287293)
@@ -318,7 +318,7 @@
static inline bool setJSTestDefaultToJSON_eventHandlerAttributeSetter(JSGlobalObject& lexicalGlobalObject, JSTestDefaultToJSON& thisObject, JSValue value)
{
auto& vm = JSC::getVM(&lexicalGlobalObject);
- setEventHandlerAttribute(lexicalGlobalObject, thisObject, thisObject.wrapped(), eventNames().entHandlerAttributeEvent, value);
+ setEventHandlerAttribute<JSEventListener>(thisObject.wrapped(), eventNames().entHandlerAttributeEvent, value, thisObject);
vm.writeBarrier(&thisObject, value);
ensureStillAliveHere(value);
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp (287292 => 287293)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp 2021-12-21 02:15:25 UTC (rev 287293)
@@ -4178,7 +4178,7 @@
static inline bool setJSTestObj_onfooSetter(JSGlobalObject& lexicalGlobalObject, JSTestObj& thisObject, JSValue value)
{
auto& vm = JSC::getVM(&lexicalGlobalObject);
- setEventHandlerAttribute(lexicalGlobalObject, thisObject, thisObject.wrapped(), eventNames().fooEvent, value);
+ setEventHandlerAttribute<JSEventListener>(thisObject.wrapped(), eventNames().fooEvent, value, thisObject);
vm.writeBarrier(&thisObject, value);
ensureStillAliveHere(value);
@@ -4204,7 +4204,7 @@
static inline bool setJSTestObj_onwebkitfooSetter(JSGlobalObject& lexicalGlobalObject, JSTestObj& thisObject, JSValue value)
{
auto& vm = JSC::getVM(&lexicalGlobalObject);
- setEventHandlerAttribute(lexicalGlobalObject, thisObject, thisObject.wrapped(), eventNames().fooEvent, value);
+ setEventHandlerAttribute<JSEventListener>(thisObject.wrapped(), eventNames().fooEvent, value, thisObject);
vm.writeBarrier(&thisObject, value);
ensureStillAliveHere(value);
Modified: trunk/Source/WebCore/dom/Document.cpp (287292 => 287293)
--- trunk/Source/WebCore/dom/Document.cpp 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/dom/Document.cpp 2021-12-21 02:15:25 UTC (rev 287293)
@@ -5104,13 +5104,6 @@
setAttributeEventListener(eventType, JSLazyEventListener::create(*this, attributeName, attributeValue), isolatedWorld);
}
-void Document::setWindowAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&& listener, DOMWrapperWorld& isolatedWorld)
-{
- if (!m_domWindow)
- return;
- m_domWindow->setAttributeEventListener(eventType, WTFMove(listener), isolatedWorld);
-}
-
void Document::setWindowAttributeEventListener(const AtomString& eventType, const QualifiedName& attributeName, const AtomString& attributeValue, DOMWrapperWorld& isolatedWorld)
{
if (!m_domWindow)
@@ -5117,16 +5110,9 @@
return;
if (!m_domWindow->frame())
return;
- setWindowAttributeEventListener(eventType, JSLazyEventListener::create(*m_domWindow, attributeName, attributeValue), isolatedWorld);
+ m_domWindow->setAttributeEventListener(eventType, JSLazyEventListener::create(*m_domWindow, attributeName, attributeValue), isolatedWorld);
}
-EventListener* Document::getWindowAttributeEventListener(const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
-{
- if (!m_domWindow)
- return nullptr;
- return m_domWindow->attributeEventListener(eventType, isolatedWorld);
-}
-
void Document::dispatchWindowEvent(Event& event, EventTarget* target)
{
ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
Modified: trunk/Source/WebCore/dom/Document.h (287292 => 287293)
--- trunk/Source/WebCore/dom/Document.h 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/dom/Document.h 2021-12-21 02:15:25 UTC (rev 287293)
@@ -878,8 +878,6 @@
// Helper functions for forwarding DOMWindow event related tasks to the DOMWindow if it exists.
void setWindowAttributeEventListener(const AtomString& eventType, const QualifiedName& attributeName, const AtomString& value, DOMWrapperWorld&);
- void setWindowAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&&, DOMWrapperWorld&);
- EventListener* getWindowAttributeEventListener(const AtomString& eventType, DOMWrapperWorld&);
WEBCORE_EXPORT void dispatchWindowEvent(Event&, EventTarget* = nullptr);
void dispatchWindowLoadEvent();
Modified: trunk/Source/WebCore/dom/EventTarget.cpp (287292 => 287293)
--- trunk/Source/WebCore/dom/EventTarget.cpp 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/dom/EventTarget.cpp 2021-12-21 02:15:25 UTC (rev 287293)
@@ -39,8 +39,8 @@
#include "HTMLBodyElement.h"
#include "HTMLHtmlElement.h"
#include "InspectorInstrumentation.h"
+#include "JSErrorHandler.h"
#include "JSEventListener.h"
-#include "JSLazyEventListener.h"
#include "Logging.h"
#include "Quirks.h"
#include "ScriptController.h"
@@ -160,6 +160,27 @@
return false;
}
+template<typename JSMaybeErrorEventListener>
+void EventTarget::setAttributeEventListener(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget)
+{
+ auto& isolatedWorld = worldForDOMObject(jsEventTarget);
+ auto* existingListener = attributeEventListener(eventType, isolatedWorld);
+ if (!listener.isObject()) {
+ if (existingListener)
+ removeEventListener(eventType, *existingListener, false);
+ } else if (existingListener) {
+ bool capture = false;
+
+ InspectorInstrumentation::willRemoveEventListener(*this, eventType, *existingListener, capture);
+ existingListener->replaceJSFunctionForAttributeListener(asObject(listener), &jsEventTarget);
+ InspectorInstrumentation::didAddEventListener(*this, eventType, *existingListener, capture);
+ } else
+ addEventListener(eventType, JSMaybeErrorEventListener::create(*asObject(listener), jsEventTarget, true, isolatedWorld), { });
+}
+
+template void EventTarget::setAttributeEventListener<JSErrorHandler>(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget);
+template void EventTarget::setAttributeEventListener<JSEventListener>(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget);
+
bool EventTarget::setAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&& listener, DOMWrapperWorld& isolatedWorld)
{
auto* existingListener = attributeEventListener(eventType, isolatedWorld);
@@ -185,16 +206,16 @@
return addEventListener(eventType, listener.releaseNonNull(), { });
}
-EventListener* EventTarget::attributeEventListener(const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
+JSEventListener* EventTarget::attributeEventListener(const AtomString& eventType, DOMWrapperWorld& isolatedWorld)
{
for (auto& eventListener : eventListeners(eventType)) {
auto& listener = eventListener->callback();
- if (!listener.isAttribute())
+ if (listener.type() != EventListener::JSEventListenerType)
continue;
- auto& listenerWorld = downcast<JSEventListener>(listener).isolatedWorld();
- if (&listenerWorld == &isolatedWorld)
- return &listener;
+ auto& jsListener = downcast<JSEventListener>(listener);
+ if (jsListener.isAttribute() && &jsListener.isolatedWorld() == &isolatedWorld)
+ return &jsListener;
}
return nullptr;
Modified: trunk/Source/WebCore/dom/EventTarget.h (287292 => 287293)
--- trunk/Source/WebCore/dom/EventTarget.h 2021-12-21 01:31:08 UTC (rev 287292)
+++ trunk/Source/WebCore/dom/EventTarget.h 2021-12-21 02:15:25 UTC (rev 287293)
@@ -41,10 +41,16 @@
#include <wtf/IsoMalloc.h>
#include <wtf/WeakPtr.h>
+namespace JSC {
+class JSValue;
+class JSObject;
+}
+
namespace WebCore {
struct AddEventListenerOptions;
class DOMWrapperWorld;
+class JSEventListener;
struct EventTargetData {
WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED;
@@ -82,8 +88,10 @@
WEBCORE_EXPORT virtual void uncaughtExceptionInEventHandler();
// Used for legacy "onevent" attributes.
+ template<typename JSMaybeErrorEventListener>
+ void setAttributeEventListener(const AtomString& eventType, JSC::JSValue listener, JSC::JSObject& jsEventTarget);
bool setAttributeEventListener(const AtomString& eventType, RefPtr<EventListener>&&, DOMWrapperWorld&);
- EventListener* attributeEventListener(const AtomString& eventType, DOMWrapperWorld&);
+ JSEventListener* attributeEventListener(const AtomString& eventType, DOMWrapperWorld&);
bool hasEventListeners() const;
bool hasEventListeners(const AtomString& eventType) const;