Diff
Modified: trunk/LayoutTests/ChangeLog (138533 => 138534)
--- trunk/LayoutTests/ChangeLog 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/LayoutTests/ChangeLog 2012-12-28 14:42:15 UTC (rev 138534)
@@ -1,3 +1,13 @@
+2012-12-28 Yury Semikhatsky <[email protected]>
+
+ Web Inspector: debugger should step into event handler on event dispatch
+ https://bugs.webkit.org/show_bug.cgi?id=105827
+
+ Reviewed by Pavel Feldman.
+
+ * inspector/debugger/debugger-step-into-event-listener-expected.txt: Added.
+ * inspector/debugger/debugger-step-into-event-listener.html: Added.
+
2012-12-28 Sudarsana Nagineni <[email protected]>
Unreviewed EFL gardening.
Added: trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener-expected.txt (0 => 138534)
--- trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener-expected.txt 2012-12-28 14:42:15 UTC (rev 138534)
@@ -0,0 +1,14 @@
+Tests that stepping into dispatchEvent() method will lead to a pause in the first event listener.
+
+Recieved foo event(1)! Recieved foo event(2)!
+Debugger was enabled.
+Set timer for test function.
+Stepping into...
+Stepping into...
+SUCCESS: Did step into event listener(fooEventHandler1).
+Stepping into...
+Stepping into...
+Stepping into...
+SUCCESS: Did step into event listener(fooEventHandler2).
+Debugger was disabled.
+
Property changes on: trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener-expected.txt
___________________________________________________________________
Added: svn:eol-style
Added: trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener.html (0 => 138534)
--- trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener.html (rev 0)
+++ trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener.html 2012-12-28 14:42:15 UTC (rev 138534)
@@ -0,0 +1,72 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+
+function testFunction()
+{
+ var div = document.getElementById("myDiv");
+ function fooEventHandler1() {
+ div.textContent += "Recieved foo event(1)!\n";
+ }
+ div.addEventListener("foo", fooEventHandler1);
+
+ function fooEventHandler2() {
+ div.textContent += "Recieved foo event(2)!\n";
+ }
+ div.addEventListener("foo", fooEventHandler2);
+
+ var e = new CustomEvent('foo');
+ debugger;
+ div.dispatchEvent(e);
+}
+
+var test = function()
+{
+ InspectorTest.startDebuggerTest(step1, true);
+
+ function step1()
+ {
+ InspectorTest.runTestFunctionAndWaitUntilPaused(step2);
+ }
+
+
+ function checkTopFrameFunction(callFrames, expectedName)
+ {
+ var topFunctionName = callFrames[0].functionName;
+ if (expectedName === topFunctionName)
+ InspectorTest.addResult("SUCCESS: Did step into event listener(" + expectedName + ").");
+ else
+ InspectorTest.addResult("FAIL: Unexpected top function: expected " + expectedName + ", found " + topFunctionName);
+ }
+
+ var stepCount = 0;
+ function step2(callFrames)
+ {
+ if (stepCount === 2)
+ checkTopFrameFunction(callFrames, "fooEventHandler1");
+ else if (stepCount === 5)
+ checkTopFrameFunction(callFrames, "fooEventHandler2");
+
+ if (stepCount < 5) {
+ InspectorTest.addResult("Stepping into...");
+ document.getElementById("scripts-step-into").click();
+ InspectorTest.waitUntilResumed(InspectorTest.waitUntilPaused.bind(InspectorTest, step2));
+ } else
+ InspectorTest.completeDebuggerTest();
+ stepCount++;
+ }
+}
+
+</script>
+</head>
+
+<body _onload_="runTest()">
+<p>
+Tests that stepping into dispatchEvent() method will lead to a pause in the first event listener.
+</p>
+<div id="myDiv"></div>
+
+</body>
+</html>
Property changes on: trunk/LayoutTests/inspector/debugger/debugger-step-into-event-listener.html
___________________________________________________________________
Added: svn:eol-style
Modified: trunk/Source/WebCore/ChangeLog (138533 => 138534)
--- trunk/Source/WebCore/ChangeLog 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/ChangeLog 2012-12-28 14:42:15 UTC (rev 138534)
@@ -1,3 +1,47 @@
+2012-12-28 Yury Semikhatsky <[email protected]>
+
+ Web Inspector: debugger should step into event handler on event dispatch
+ https://bugs.webkit.org/show_bug.cgi?id=105827
+
+ Reviewed by Pavel Feldman.
+
+ Added m_pauseInNextEventListener to InspectorDOMDebuggerAgent. The flag is set
+ to true when "step into" is pressed and reset to false when either JS execution
+ pauses, the agent gets disabled or JS call stack becomes empty. If the flag is
+ true and the next JS stetement to be executed belongs to a JS event listener we
+ will stop in that listener, otherwise we have two options:
+ 1) Control flow directly(without comming through the native bindings) reaches some JS
+ statement and will pause in the corresponding JS function, in which case the
+ flag will be reset;
+ 2) JS call stack becomes empty and execution will continue in the native code. We
+ use didProcessTask to detect such cases and reset the flag to false every time
+ event queue finishes next task.
+
+ Test: inspector/debugger/debugger-step-into-event-listener.html
+
+ * inspector/InspectorController.cpp:
+ (WebCore::InspectorController::InspectorController):
+ (WebCore::InspectorController::reportMemoryUsage):
+ (WebCore::InspectorController::didProcessTask):
+ * inspector/InspectorController.h:
+ (WebCore):
+ (InspectorController):
+ * inspector/InspectorDOMDebuggerAgent.cpp:
+ (WebCore::InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent):
+ (WebCore::InspectorDOMDebuggerAgent::stepInto):
+ (WebCore):
+ (WebCore::InspectorDOMDebuggerAgent::didPause):
+ (WebCore::InspectorDOMDebuggerAgent::cancelStepIntoEventListener):
+ (WebCore::InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded):
+ (WebCore::InspectorDOMDebuggerAgent::clear):
+ * inspector/InspectorDOMDebuggerAgent.h:
+ (InspectorDOMDebuggerAgent):
+ * inspector/InspectorDebuggerAgent.cpp:
+ (WebCore::InspectorDebuggerAgent::stepInto):
+ (WebCore::InspectorDebuggerAgent::didPause):
+ * inspector/InspectorDebuggerAgent.h:
+ (Listener):
+
2012-12-28 Andrey Lushnikov <[email protected]>
Web Inspector: enable mutation observer in LayoutTests
Modified: trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp (138533 => 138534)
--- trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp 2012-12-28 14:42:15 UTC (rev 138534)
@@ -55,6 +55,7 @@
, m_pauseOnExceptionsState(DontPauseOnExceptions)
, m_pauseOnNextStatement(false)
, m_paused(false)
+ , m_runningNestedMessageLoop(false)
, m_doneProcessingDebuggerEvents(true)
, m_breakpointsActivated(true)
, m_pauseOnCallFrame(0)
@@ -440,8 +441,10 @@
TimerBase::fireTimersInNestedEventLoop();
+ m_runningNestedMessageLoop = true;
m_doneProcessingDebuggerEvents = false;
runEventLoopWhilePaused();
+ m_runningNestedMessageLoop = false;
didContinue(dynamicGlobalObject);
dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue, dynamicGlobalObject);
Modified: trunk/Source/WebCore/bindings/js/ScriptDebugServer.h (138533 => 138534)
--- trunk/Source/WebCore/bindings/js/ScriptDebugServer.h 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/bindings/js/ScriptDebugServer.h 2012-12-28 14:42:15 UTC (rev 138534)
@@ -96,6 +96,7 @@
}
bool isPaused() { return m_paused; }
+ bool runningNestedMessageLoop() { return m_runningNestedMessageLoop; }
void compileScript(ScriptState*, const String& _expression_, const String& sourceURL, String* scriptId, String* exceptionMessage);
void clearCompiledScripts();
@@ -155,6 +156,7 @@
PauseOnExceptionsState m_pauseOnExceptionsState;
bool m_pauseOnNextStatement;
bool m_paused;
+ bool m_runningNestedMessageLoop;
bool m_doneProcessingDebuggerEvents;
bool m_breakpointsActivated;
_javascript_CallFrame* m_pauseOnCallFrame;
Modified: trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp (138533 => 138534)
--- trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp 2012-12-28 14:42:15 UTC (rev 138534)
@@ -153,6 +153,7 @@
ScriptDebugServer::ScriptDebugServer()
: m_pauseOnExceptionsState(DontPauseOnExceptions)
, m_breakpointsActivated(true)
+ , m_runningNestedMessageLoop(false)
{
}
@@ -423,7 +424,9 @@
ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedContext);
listener->didPause(currentCallFrameState, currentCallFrame(), ScriptValue(exception));
+ m_runningNestedMessageLoop = true;
runMessageLoopOnPause(m_pausedContext);
+ m_runningNestedMessageLoop = false;
}
void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails)
Modified: trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h (138533 => 138534)
--- trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h 2012-12-28 14:42:15 UTC (rev 138534)
@@ -97,6 +97,7 @@
void runPendingTasks();
bool isPaused();
+ bool runningNestedMessageLoop() { return m_runningNestedMessageLoop; }
v8::Local<v8::Value> functionScopes(v8::Handle<v8::Function>);
v8::Local<v8::Value> getInternalProperties(v8::Handle<v8::Object>&);
@@ -140,6 +141,7 @@
private:
class ScriptPreprocessor;
OwnPtr<ScriptPreprocessor> m_scriptPreprocessor;
+ bool m_runningNestedMessageLoop;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/inspector/InspectorController.cpp (138533 => 138534)
--- trunk/Source/WebCore/inspector/InspectorController.cpp 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/inspector/InspectorController.cpp 2012-12-28 14:42:15 UTC (rev 138534)
@@ -140,7 +140,9 @@
m_debuggerAgent = debuggerAgentPtr.get();
m_agents.append(debuggerAgentPtr.release());
- m_agents.append(InspectorDOMDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent, m_debuggerAgent, m_inspectorAgent));
+ OwnPtr<InspectorDOMDebuggerAgent> domDebuggerAgentPtr(InspectorDOMDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent, m_debuggerAgent, m_inspectorAgent));
+ m_domDebuggerAgent = domDebuggerAgentPtr.get();
+ m_agents.append(domDebuggerAgentPtr.release());
OwnPtr<InspectorProfilerAgent> profilerAgentPtr(InspectorProfilerAgent::create(m_instrumentingAgents.get(), consoleAgent, page, m_state.get(), m_injectedScriptManager.get()));
m_profilerAgent = profilerAgentPtr.get();
@@ -398,6 +400,7 @@
info.addMember(m_pageAgent);
#if ENABLE(_javascript__DEBUGGER)
info.addMember(m_debuggerAgent);
+ info.addMember(m_domDebuggerAgent);
info.addMember(m_profilerAgent);
#endif
@@ -424,6 +427,7 @@
timelineAgent->didProcessTask();
#if ENABLE(_javascript__DEBUGGER)
m_profilerAgent->didProcessTask();
+ m_domDebuggerAgent->didProcessTask();
#endif
}
Modified: trunk/Source/WebCore/inspector/InspectorController.h (138533 => 138534)
--- trunk/Source/WebCore/inspector/InspectorController.h 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/inspector/InspectorController.h 2012-12-28 14:42:15 UTC (rev 138534)
@@ -51,6 +51,7 @@
class InspectorBaseAgentInterface;
class InspectorClient;
class InspectorDOMAgent;
+class InspectorDOMDebuggerAgent;
class InspectorDebuggerAgent;
class InspectorFrontend;
class InspectorFrontendChannel;
@@ -139,6 +140,7 @@
InspectorPageAgent* m_pageAgent;
#if ENABLE(_javascript__DEBUGGER)
InspectorDebuggerAgent* m_debuggerAgent;
+ InspectorDOMDebuggerAgent* m_domDebuggerAgent;
InspectorProfilerAgent* m_profilerAgent;
#endif
Modified: trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp (138533 => 138534)
--- trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.cpp 2012-12-28 14:42:15 UTC (rev 138534)
@@ -79,6 +79,7 @@
: InspectorBaseAgent<InspectorDOMDebuggerAgent>("DOMDebugger", instrumentingAgents, inspectorState)
, m_domAgent(domAgent)
, m_debuggerAgent(debuggerAgent)
+ , m_pauseInNextEventListener(false)
{
m_debuggerAgent->setListener(this);
}
@@ -100,6 +101,25 @@
disable();
}
+void InspectorDOMDebuggerAgent::stepInto()
+{
+ m_pauseInNextEventListener = true;
+}
+
+void InspectorDOMDebuggerAgent::didPause()
+{
+ m_pauseInNextEventListener = false;
+}
+
+void InspectorDOMDebuggerAgent::didProcessTask()
+{
+ if (!m_pauseInNextEventListener)
+ return;
+ if (m_debuggerAgent && m_debuggerAgent->runningNestedMessageLoop())
+ return;
+ m_pauseInNextEventListener = false;
+}
+
void InspectorDOMDebuggerAgent::disable()
{
m_instrumentingAgents->setInspectorDOMDebuggerAgent(0);
@@ -358,9 +378,13 @@
void InspectorDOMDebuggerAgent::pauseOnNativeEventIfNeeded(bool isDOMEvent, const String& eventName, bool synchronous)
{
String fullEventName = (isDOMEvent ? listenerEventCategoryType : instrumentationEventCategoryType) + eventName;
- RefPtr<InspectorObject> eventListenerBreakpoints = m_state->getObject(DOMDebuggerAgentState::eventListenerBreakpoints);
- if (eventListenerBreakpoints->find(fullEventName) == eventListenerBreakpoints->end())
- return;
+ if (m_pauseInNextEventListener)
+ m_pauseInNextEventListener = false;
+ else {
+ RefPtr<InspectorObject> eventListenerBreakpoints = m_state->getObject(DOMDebuggerAgentState::eventListenerBreakpoints);
+ if (eventListenerBreakpoints->find(fullEventName) == eventListenerBreakpoints->end())
+ return;
+ }
RefPtr<InspectorObject> eventData = InspectorObject::create();
eventData->setString("eventName", fullEventName);
@@ -421,6 +445,7 @@
void InspectorDOMDebuggerAgent::clear()
{
m_domBreakpoints.clear();
+ m_pauseInNextEventListener = false;
}
} // namespace WebCore
Modified: trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h (138533 => 138534)
--- trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h 2012-12-28 14:42:15 UTC (rev 138534)
@@ -81,6 +81,8 @@
void willSendXMLHttpRequest(const String& url);
void pauseOnNativeEventIfNeeded(bool isDOMEvent, const String& eventName, bool synchronous);
+ void didProcessTask();
+
virtual void clearFrontend();
virtual void discardAgent();
@@ -90,6 +92,8 @@
// InspectorDebuggerAgent::Listener implementation.
virtual void debuggerWasEnabled();
virtual void debuggerWasDisabled();
+ virtual void stepInto();
+ virtual void didPause();
void disable();
void descriptionForDOMEvent(Node* target, int breakpointType, bool insertion, InspectorObject* description);
@@ -104,6 +108,7 @@
InspectorDOMAgent* m_domAgent;
InspectorDebuggerAgent* m_debuggerAgent;
HashMap<Node*, uint32_t> m_domBreakpoints;
+ bool m_pauseInNextEventListener;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp (138533 => 138534)
--- trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp 2012-12-28 14:42:15 UTC (rev 138534)
@@ -191,6 +191,11 @@
return scriptDebugServer().isPaused();
}
+bool InspectorDebuggerAgent::runningNestedMessageLoop()
+{
+ return scriptDebugServer().runningNestedMessageLoop();
+}
+
void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type)
{
if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions && source == ConsoleAPIMessageSource && type == AssertMessageType)
@@ -458,6 +463,7 @@
if (!assertPaused(errorString))
return;
scriptDebugServer().stepIntoStatement();
+ m_listener->stepInto();
}
void InspectorDebuggerAgent::stepOut(ErrorString* errorString)
@@ -683,6 +689,8 @@
scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
m_continueToLocationBreakpointId = "";
}
+ if (m_listener)
+ m_listener->didPause();
}
void InspectorDebuggerAgent::didContinue()
Modified: trunk/Source/WebCore/inspector/InspectorDebuggerAgent.h (138533 => 138534)
--- trunk/Source/WebCore/inspector/InspectorDebuggerAgent.h 2012-12-28 14:26:00 UTC (rev 138533)
+++ trunk/Source/WebCore/inspector/InspectorDebuggerAgent.h 2012-12-28 14:42:15 UTC (rev 138534)
@@ -79,6 +79,7 @@
virtual void restore();
bool isPaused();
+ bool runningNestedMessageLoop();
void addMessageToConsole(MessageSource, MessageType);
// Part of the protocol.
@@ -124,6 +125,8 @@
virtual ~Listener() { }
virtual void debuggerWasEnabled() = 0;
virtual void debuggerWasDisabled() = 0;
+ virtual void stepInto() = 0;
+ virtual void didPause() = 0;
};
void setListener(Listener* listener) { m_listener = listener; }