Commit 96853f1c authored by aandrey@chromium.org's avatar aandrey@chromium.org

DevTools: Debugger StepInto/Out/Over initiated from a framework should not black-box it.

BUG=267592
R=yurys, pfeldman@chromium.org

Review URL: https://codereview.chromium.org/342713002

git-svn-id: svn://svn.chromium.org/blink/trunk@177170 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 9dc53c67
Tests stepping from framework call frames.
Set timer for test function.
Call stack:
* 0) Framework.breakInFramework (framework.js:26)
* 1) Framework.safeRun (framework.js:8)
2) testFunction (frameworks-step-from-framework.html:10)
Executing StepInto...
Call stack:
* 0) Framework.breakInFramework (framework.js:27)
* 1) Framework.safeRun (framework.js:8)
2) testFunction (frameworks-step-from-framework.html:10)
Executing StepOver...
Call stack:
* 0) Framework.safeRun (framework.js:9)
1) testFunction (frameworks-step-from-framework.html:10)
Executing StepOut...
Call stack:
0) testFunction (frameworks-step-from-framework.html:11)
Executing StepInto...
Call stack:
0) testFunction (frameworks-step-from-framework.html:12)
Executing Resume...
Call stack:
* 0) Framework.sendXHR (framework.js:79)
1) testFunction (frameworks-step-from-framework.html:13)
Executing StepInto...
Call stack:
* 0) Framework.sendXHR (framework.js:80)
1) testFunction (frameworks-step-from-framework.html:13)
<html>
<head>
<script src="../../../http/tests/inspector/inspector-test.js"></script>
<script src="../../../http/tests/inspector/debugger-test.js"></script>
<script src="resources/framework.js"></script>
<script>
function testFunction()
{
Framework.safeRun(Framework.breakInFramework, Framework.empty)
Framework.safeRun(Framework.empty); // should not step inside
Framework.empty(); // dummy call
Framework.sendXHR('/foo?a=b');
}
function test()
{
var frameworkRegexString = "/framework\\.js$";
WebInspector.experimentsSettings.frameworksDebuggingSupport.enableForTest();
WebInspector.settings.skipStackFramesSwitch.set(true);
WebInspector.settings.skipStackFramesPattern.set(frameworkRegexString);
InspectorTest.setQuiet(true);
InspectorTest.startDebuggerTest(step1);
var xhrPane;
function step1()
{
xhrPane = WebInspector.panels.sources.sidebarPanes.xhrBreakpoints;
xhrPane._setBreakpoint("foo", true);
InspectorTest.runTestFunctionAndWaitUntilPaused(didPause);
}
var actions = [
"Print", // debugger;
"StepInto", "Print",
"StepOver", "Print",
"StepOut", "Print",
"StepInto", "Print", // should not step inside
"Resume", "Print", // should stop on XHR.send()
"StepInto", "Print", // should step inside framework
];
function didPause(callFrames, reason, breakpointIds, asyncStackTrace)
{
var action = actions.shift();
if (action === "Print") {
InspectorTest.captureStackTrace(callFrames);
InspectorTest.addResult("");
while (action === "Print")
action = actions.shift();
}
if (!action) {
completeTest()
return;
}
InspectorTest.addResult("Executing " + action + "...");
switch (action) {
case "StepInto":
WebInspector.panels.sources._stepIntoButton.element.click();
break;
case "StepOver":
WebInspector.panels.sources._stepOverButton.element.click();
break;
case "StepOut":
WebInspector.panels.sources._stepOutButton.element.click();
break;
case "Resume":
InspectorTest.resumeExecution(InspectorTest.waitUntilPaused.bind(InspectorTest, didPause));
break;
default:
InspectorTest.addResult("FAIL: Unknown action: " + action);
completeTest()
return;
}
InspectorTest.waitUntilResumed(InspectorTest.waitUntilPaused.bind(InspectorTest, didPause));
}
function completeTest()
{
xhrPane._removeBreakpoint("foo");
InspectorTest.completeDebuggerTest();
}
}
</script>
</head>
<body onload="runTest()">
<input type='button' onclick='testFunction()' value='Test'/>
<p>
Tests stepping from framework call frames.
</p>
</body>
</html>
......@@ -76,7 +76,7 @@ Framework.sendXHR = function(url)
{
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.send();
try { request.send(); } catch (e) {}
}
Framework.addEventListener = function(element, eventType, listener, capture)
......
......@@ -106,6 +106,7 @@ InspectorDebuggerAgent::InspectorDebuggerAgent(InjectedScriptManager* injectedSc
, m_pausedScriptState(nullptr)
, m_javaScriptPauseScheduled(false)
, m_debuggerStepScheduled(false)
, m_steppingFromFramework(false)
, m_pausingOnNativeEvent(false)
, m_listener(0)
, m_skippedStepInCount(0)
......@@ -474,6 +475,9 @@ String InspectorDebuggerAgent::scriptURL(JavaScriptCallFrame* frame)
ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipExceptionPause()
{
if (m_steppingFromFramework)
return ScriptDebugListener::NoSkip;
// FIXME: Fast return: if (!m_cachedSkipStackRegExp && !has_any_anti_breakpoint) return ScriptDebugListener::NoSkip;
RefPtrWillBeRawPtr<JavaScriptCallFrame> topFrame = scriptDebugServer().topCallFrameNoScopes();
......@@ -526,7 +530,7 @@ ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipExceptio
ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipStepPause()
{
if (!m_cachedSkipStackRegExp)
if (!m_cachedSkipStackRegExp || m_steppingFromFramework)
return ScriptDebugListener::NoSkip;
RefPtrWillBeRawPtr<JavaScriptCallFrame> topFrame = scriptDebugServer().topCallFrameNoScopes();
......@@ -556,6 +560,16 @@ ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipStepPaus
return ScriptDebugListener::StepInto;
}
bool InspectorDebuggerAgent::isTopCallFrameInFramework()
{
if (!m_cachedSkipStackRegExp)
return false;
RefPtrWillBeRawPtr<JavaScriptCallFrame> topFrame = scriptDebugServer().topCallFrameNoScopes();
String scriptUrl = scriptURL(topFrame.get());
return !scriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(scriptUrl) != -1;
}
PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
{
ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
......@@ -803,6 +817,7 @@ void InspectorDebuggerAgent::resume(ErrorString* errorString)
if (!assertPaused(errorString))
return;
m_debuggerStepScheduled = false;
m_steppingFromFramework = false;
m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().continueProgram();
}
......@@ -812,6 +827,7 @@ void InspectorDebuggerAgent::stepOver(ErrorString* errorString)
if (!assertPaused(errorString))
return;
m_debuggerStepScheduled = true;
m_steppingFromFramework = isTopCallFrameInFramework();
m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().stepOverStatement();
}
......@@ -821,6 +837,7 @@ void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
if (!assertPaused(errorString))
return;
m_debuggerStepScheduled = true;
m_steppingFromFramework = isTopCallFrameInFramework();
m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().stepIntoStatement();
if (m_listener)
......@@ -832,6 +849,7 @@ void InspectorDebuggerAgent::stepOut(ErrorString* errorString)
if (!assertPaused(errorString))
return;
m_debuggerStepScheduled = true;
m_steppingFromFramework = isTopCallFrameInFramework();
m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
scriptDebugServer().stepOutOfFunction();
}
......@@ -1192,6 +1210,7 @@ ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::didPause(ScriptSta
m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData, hitBreakpointIds, currentAsyncStackTrace());
m_javaScriptPauseScheduled = false;
m_debuggerStepScheduled = false;
m_steppingFromFramework = false;
m_pausingOnNativeEvent = false;
m_skippedStepInCount = 0;
......@@ -1224,6 +1243,7 @@ void InspectorDebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::E
m_breakReason = breakReason;
m_breakAuxData = data;
m_debuggerStepScheduled = false;
m_steppingFromFramework = false;
m_pausingOnNativeEvent = false;
scriptDebugServer().breakProgram();
}
......@@ -1239,6 +1259,7 @@ void InspectorDebuggerAgent::clear()
clearBreakDetails();
m_javaScriptPauseScheduled = false;
m_debuggerStepScheduled = false;
m_steppingFromFramework = false;
m_pausingOnNativeEvent = false;
ErrorString error;
setOverlayMessage(&error, 0);
......
......@@ -199,6 +199,7 @@ protected:
private:
SkipPauseRequest shouldSkipExceptionPause();
SkipPauseRequest shouldSkipStepPause();
bool isTopCallFrameInFramework();
void cancelPauseOnNextStatement();
void addMessageToConsole(MessageSource, MessageType);
......@@ -237,6 +238,7 @@ private:
RefPtr<JSONObject> m_breakAuxData;
bool m_javaScriptPauseScheduled;
bool m_debuggerStepScheduled;
bool m_steppingFromFramework;
bool m_pausingOnNativeEvent;
Listener* m_listener;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment