Web Inspector: Provide $event in the console when paused on an event listener
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Mar 2019 19:31:31 +0000 (19:31 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Mar 2019 19:31:31 +0000 (19:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188672

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

* inspector/InjectedScript.h:
* inspector/InjectedScript.cpp:
(Inspector::InjectedScript::setEventValue): Added.
(Inspector::InjectedScript::clearEventValue): Added.

* inspector/InjectedScriptManager.h:
* inspector/InjectedScriptManager.cpp:
(Inspector::InjectedScriptManager::clearEventValue): Added.

* inspector/InjectedScriptSource.js:
(WI.InjectedScript.prototype.setEventValue): Added.
(WI.InjectedScript.prototype.clearEventValue): Added.
(BasicCommandLineAPI):

Source/WebCore:

Implement similiar methods/logic as to the way that `$exception` is set.

* inspector/CommandLineAPIModuleSource.js:
(CommandLineAPI):

* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::willHandleEvent):
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::willHandleEventImpl):
(WebCore::InspectorInstrumentation::didHandleEventImpl):

* inspector/agents/InspectorDOMDebuggerAgent.cpp:
* inspector/agents/InspectorDOMDebuggerAgent.h:
(WebCore::InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent):
(WebCore::InspectorDOMDebuggerAgent::willHandleEvent):
(WebCore::InspectorDOMDebuggerAgent::didHandleEvent): Added.

Source/WebInspectorUI:

* UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
(WI.JavaScriptRuntimeCompletionProvider.prototype.completionControllerCompletionsNeeded.receivedPropertyNames):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243161 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/InjectedScript.cpp
Source/JavaScriptCore/inspector/InjectedScript.h
Source/JavaScriptCore/inspector/InjectedScriptManager.cpp
Source/JavaScriptCore/inspector/InjectedScriptManager.h
Source/JavaScriptCore/inspector/InjectedScriptSource.js
Source/WebCore/ChangeLog
Source/WebCore/inspector/CommandLineAPIModuleSource.js
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.cpp
Source/WebCore/inspector/agents/InspectorDOMDebuggerAgent.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js

index 9595002..58ea9cf 100644 (file)
@@ -1,5 +1,26 @@
 2019-03-19  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Provide $event in the console when paused on an event listener
+        https://bugs.webkit.org/show_bug.cgi?id=188672
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/InjectedScript.h:
+        * inspector/InjectedScript.cpp:
+        (Inspector::InjectedScript::setEventValue): Added.
+        (Inspector::InjectedScript::clearEventValue): Added.
+
+        * inspector/InjectedScriptManager.h:
+        * inspector/InjectedScriptManager.cpp:
+        (Inspector::InjectedScriptManager::clearEventValue): Added.
+
+        * inspector/InjectedScriptSource.js:
+        (WI.InjectedScript.prototype.setEventValue): Added.
+        (WI.InjectedScript.prototype.clearEventValue): Added.
+        (BasicCommandLineAPI):
+
+2019-03-19  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: ScriptProfiler: lazily create the agent
         https://bugs.webkit.org/show_bug.cgi?id=195591
         <rdar://problem/48791756>
index 9423331..82e1553 100644 (file)
@@ -347,6 +347,21 @@ RefPtr<Protocol::Runtime::ObjectPreview> InjectedScript::previewValue(JSC::JSVal
     return BindingTraits<Protocol::Runtime::ObjectPreview>::runtimeCast(resultObject);
 }
 
+void InjectedScript::setEventValue(JSC::JSValue value)
+{
+    ASSERT(!hasNoValue());
+    Deprecated::ScriptFunctionCall function(injectedScriptObject(), "setEventValue"_s, inspectorEnvironment()->functionCallHandler());
+    function.appendArgument(value);
+    makeCall(function);
+}
+
+void InjectedScript::clearEventValue()
+{
+    ASSERT(!hasNoValue());
+    Deprecated::ScriptFunctionCall function(injectedScriptObject(), "clearEventValue"_s, inspectorEnvironment()->functionCallHandler());
+    makeCall(function);
+}
+
 void InjectedScript::setExceptionValue(JSC::JSValue value)
 {
     ASSERT(!hasNoValue());
index a8db2d2..1577974 100644 (file)
@@ -80,6 +80,9 @@ public:
     RefPtr<Protocol::Runtime::RemoteObject> wrapTable(JSC::JSValue table, JSC::JSValue columns) const;
     RefPtr<Protocol::Runtime::ObjectPreview> previewValue(JSC::JSValue) const;
 
+    void setEventValue(JSC::JSValue);
+    void clearEventValue();
+
     void setExceptionValue(JSC::JSValue);
     void clearExceptionValue();
 
index b4c6c18..53e88f9 100644 (file)
@@ -122,6 +122,12 @@ void InjectedScriptManager::releaseObjectGroup(const String& objectGroup)
         injectedScript.releaseObjectGroup(objectGroup);
 }
 
+void InjectedScriptManager::clearEventValue()
+{
+    for (auto& injectedScript : m_idToInjectedScript.values())
+        injectedScript.clearEventValue();
+}
+
 void InjectedScriptManager::clearExceptionValue()
 {
     for (auto& injectedScript : m_idToInjectedScript.values())
index ceb8c02..ea48fa9 100644 (file)
@@ -60,6 +60,7 @@ public:
     int injectedScriptIdFor(JSC::ExecState*);
     InjectedScript injectedScriptForObjectId(const String& objectId);
     void releaseObjectGroup(const String& objectGroup);
+    void clearEventValue();
     void clearExceptionValue();
 
 protected:
index 813e9dc..c440c62 100644 (file)
@@ -353,6 +353,16 @@ let InjectedScript = class InjectedScript
         return RemoteObject.createObjectPreviewForValue(value, true);
     }
 
+    setEventValue(value)
+    {
+        this._eventValue = value;
+    }
+
+    clearEventValue()
+    {
+        delete this._eventValue;
+    }
+
     setExceptionValue(value)
     {
         this._exceptionValue = value;
@@ -1446,6 +1456,11 @@ function BasicCommandLineAPI(callFrame)
     this.$_ = injectedScript._lastResult;
     this.$exception = injectedScript._exceptionValue;
 
+    if ("_eventValue" in injectedScript)
+        this.$event = injectedScript._eventValue;
+    else if ("$event" in this)
+        delete this.$event;
+
     // $1-$99
     for (let i = 1; i <= injectedScript._savedResults.length; ++i)
         this.__defineGetter__("$" + i, bind(injectedScript._savedResult, injectedScript, i));
index ece62e8..dd507d9 100644 (file)
@@ -1,5 +1,29 @@
 2019-03-19  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Provide $event in the console when paused on an event listener
+        https://bugs.webkit.org/show_bug.cgi?id=188672
+
+        Reviewed by Timothy Hatcher.
+
+        Implement similiar methods/logic as to the way that `$exception` is set.
+
+        * inspector/CommandLineAPIModuleSource.js:
+        (CommandLineAPI):
+
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::willHandleEvent):
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::willHandleEventImpl):
+        (WebCore::InspectorInstrumentation::didHandleEventImpl):
+
+        * inspector/agents/InspectorDOMDebuggerAgent.cpp:
+        * inspector/agents/InspectorDOMDebuggerAgent.h:
+        (WebCore::InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent):
+        (WebCore::InspectorDOMDebuggerAgent::willHandleEvent):
+        (WebCore::InspectorDOMDebuggerAgent::didHandleEvent): Added.
+
+2019-03-19  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: ScriptProfiler: lazily create the agent
         https://bugs.webkit.org/show_bug.cgi?id=195591
         <rdar://problem/48791756>
index 18d6326..a1f7d57 100644 (file)
@@ -47,6 +47,7 @@ function bind(func, thisObject, ...outerArgs)
 function CommandLineAPI(commandLineAPIImpl, callFrame)
 {
     this.$_ = injectedScript._lastResult;
+    this.$event = injectedScript._eventValue;
     this.$exception = injectedScript._exceptionValue;
 
     // $0
index 2b43062..8c4eb1c 100644 (file)
@@ -396,7 +396,7 @@ InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventImpl(I
     return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
 }
 
-void InspectorInstrumentation::willHandleEventImpl(InstrumentingAgents& instrumentingAgents, const Event& event, const RegisteredEventListener& listener)
+void InspectorInstrumentation::willHandleEventImpl(InstrumentingAgents& instrumentingAgents, Event& event, const RegisteredEventListener& listener)
 {
     if (PageDebuggerAgent* pageDebuggerAgent = instrumentingAgents.pageDebuggerAgent())
         pageDebuggerAgent->willHandleEvent(listener);
@@ -409,6 +409,9 @@ void InspectorInstrumentation::didHandleEventImpl(InstrumentingAgents& instrumen
 {
     if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents.inspectorDebuggerAgent())
         debuggerAgent->didDispatchAsyncCall();
+
+    if (InspectorDOMDebuggerAgent* domDebuggerAgent = instrumentingAgents.inspectorDOMDebuggerAgent())
+        domDebuggerAgent->didHandleEvent();
 }
 
 void InspectorInstrumentation::didDispatchEventImpl(const InspectorInstrumentationCookie& cookie)
index e10285d..a8c85a4 100644 (file)
@@ -153,7 +153,7 @@ public:
     static bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     static InspectorInstrumentationCookie willDispatchEvent(Document&, const Event&, bool hasEventListeners);
     static void didDispatchEvent(const InspectorInstrumentationCookie&);
-    static void willHandleEvent(ScriptExecutionContext&, const Event&, const RegisteredEventListener&);
+    static void willHandleEvent(ScriptExecutionContext&, Event&, const RegisteredEventListener&);
     static void didHandleEvent(ScriptExecutionContext&);
     static InspectorInstrumentationCookie willDispatchEventOnWindow(Frame*, const Event&, DOMWindow&);
     static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&);
@@ -345,7 +345,7 @@ private:
     static void willRemoveEventListenerImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     static bool isEventListenerDisabledImpl(InstrumentingAgents&, EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     static InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents&, Document&, const Event&, bool hasEventListeners);
-    static void willHandleEventImpl(InstrumentingAgents&, const Event&, const RegisteredEventListener&);
+    static void willHandleEventImpl(InstrumentingAgents&, Event&, const RegisteredEventListener&);
     static void didHandleEventImpl(InstrumentingAgents&);
     static void didDispatchEventImpl(const InspectorInstrumentationCookie&);
     static InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InstrumentingAgents&, const Event&, DOMWindow&);
@@ -800,7 +800,7 @@ inline void InspectorInstrumentation::didDispatchEvent(const InspectorInstrument
         didDispatchEventImpl(cookie);
 }
 
-inline void InspectorInstrumentation::willHandleEvent(ScriptExecutionContext& context, const Event& event, const RegisteredEventListener& listener)
+inline void InspectorInstrumentation::willHandleEvent(ScriptExecutionContext& context, Event& event, const RegisteredEventListener& listener)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
index 5213bdd..7caa375 100644 (file)
 #include "HTMLElement.h"
 #include "InspectorDOMAgent.h"
 #include "InstrumentingAgents.h"
+#include "JSEvent.h"
 #include "RegisteredEventListener.h"
 #include <JavaScriptCore/ContentSearchUtilities.h>
+#include <JavaScriptCore/InjectedScript.h>
+#include <JavaScriptCore/InjectedScriptManager.h>
 #include <JavaScriptCore/InspectorFrontendDispatchers.h>
 #include <JavaScriptCore/RegularExpression.h>
 #include <wtf/JSONValues.h>
@@ -65,6 +68,7 @@ using namespace Inspector;
 InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent(WebAgentContext& context, InspectorDOMAgent* domAgent, InspectorDebuggerAgent* debuggerAgent)
     : InspectorAgentBase("DOMDebugger"_s, context)
     , m_backendDispatcher(Inspector::DOMDebuggerBackendDispatcher::create(context.backendDispatcher, this))
+    , m_injectedScriptManager(context.injectedScriptManager)
     , m_domAgent(domAgent)
     , m_debuggerAgent(debuggerAgent)
 {
@@ -365,11 +369,20 @@ void InspectorDOMDebuggerAgent::updateSubtreeBreakpoints(Node* node, uint32_t ro
         updateSubtreeBreakpoints(child, newRootMask, set);
 }
 
-void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const RegisteredEventListener& registeredEventListener)
+void InspectorDOMDebuggerAgent::willHandleEvent(Event& event, const RegisteredEventListener& registeredEventListener)
 {
     if (!m_debuggerAgent->breakpointsActive())
         return;
 
+    auto state = event.target()->scriptExecutionContext()->execState();
+    auto injectedScript = m_injectedScriptManager.injectedScriptFor(state);
+    ASSERT(!injectedScript.hasNoValue());
+    {
+        JSC::JSLockHolder lock(state);
+
+        injectedScript.setEventValue(toJS(state, deprecatedGlobalObjectForPrototype(state), event));
+    }
+
     bool shouldPause = m_debuggerAgent->pauseOnNextStatementEnabled() || m_eventBreakpoints.contains(std::make_pair(Inspector::Protocol::DOMDebugger::EventBreakpointType::Listener, event.type()));
 
     if (!shouldPause && m_domAgent)
@@ -389,6 +402,11 @@ void InspectorDOMDebuggerAgent::willHandleEvent(const Event& event, const Regist
     m_debuggerAgent->schedulePauseOnNextStatement(Inspector::DebuggerFrontendDispatcher::Reason::EventListener, WTFMove(eventData));
 }
 
+void InspectorDOMDebuggerAgent::didHandleEvent()
+{
+    m_injectedScriptManager.clearEventValue();
+}
+
 void InspectorDOMDebuggerAgent::willFireTimer(bool oneShot)
 {
     if (!m_debuggerAgent->breakpointsActive())
index 459cb36..f266475 100644 (file)
 #include <wtf/JSONValues.h>
 #include <wtf/text/WTFString.h>
 
+namespace Inspector {
+class InjectedScriptManager;
+}
+
 namespace WebCore {
 
 class Element;
@@ -74,7 +78,8 @@ public:
     void willSendXMLHttpRequest(const String& url);
     void willFetch(const String& url);
     void frameDocumentUpdated(Frame&);
-    void willHandleEvent(const Event&, const RegisteredEventListener&);
+    void willHandleEvent(Event&, const RegisteredEventListener&);
+    void didHandleEvent();
     void willFireTimer(bool oneShot);
     void willFireAnimationFrame();
     void mainFrameDOMContentLoaded();
@@ -98,6 +103,7 @@ private:
     void discardBindings();
 
     RefPtr<Inspector::DOMDebuggerBackendDispatcher> m_backendDispatcher;
+    Inspector::InjectedScriptManager& m_injectedScriptManager;
     InspectorDOMAgent* m_domAgent { nullptr };
     Inspector::InspectorDebuggerAgent* m_debuggerAgent { nullptr };
 
index 164d022..57c75c5 100644 (file)
@@ -1,5 +1,15 @@
 2019-03-19  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Provide $event in the console when paused on an event listener
+        https://bugs.webkit.org/show_bug.cgi?id=188672
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
+        (WI.JavaScriptRuntimeCompletionProvider.prototype.completionControllerCompletionsNeeded.receivedPropertyNames):
+
+2019-03-19  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: DOM: "Capture Screenshot" should only be shown if the node is attached
         https://bugs.webkit.org/show_bug.cgi?id=195793
         <rdar://problem/48916594>
index e71d677..9f21a88 100644 (file)
@@ -221,7 +221,9 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid
                 let commandLineAPI = WI.JavaScriptRuntimeCompletionProvider._commandLineAPI.slice(0);
                 if (WI.debuggerManager.paused) {
                     let targetData = WI.debuggerManager.dataForTarget(WI.runtimeManager.activeExecutionContext.target);
-                    if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Exception)
+                    if (targetData.pauseReason === WI.DebuggerManager.PauseReason.EventListener)
+                        commandLineAPI.push("$event");
+                    else if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Exception)
                         commandLineAPI.push("$exception");
                 }
                 for (let name of commandLineAPI)