Commit 3178be9c authored by joepeck@webkit.org's avatar joepeck@webkit.org

Web Inspector: Breakpoint Actions

https://bugs.webkit.org/show_bug.cgi?id=120576

Reviewed by Timothy Hatcher.

Source/WebCore:

Tests: inspector-protocol/debugger/setBreakpoint-actions.html
       inspector-protocol/debugger/setBreakpoint-options-exception.html

* inspector/ScriptBreakpoint.h:
(WebCore::ScriptBreakpointAction::ScriptBreakpointAction):
(WebCore::ScriptBreakpoint::ScriptBreakpoint):
Struct for a breakpoint action. Type and string of data.

* bindings/js/ScriptDebugServer.h:
* bindings/js/ScriptDebugServer.cpp:
(WebCore::ScriptDebugServer::hasBreakpoint):
(WebCore::ScriptDebugServer::evaluateBreakpointAction):
(WebCore::ScriptDebugServer::evaluateBreakpointActions):
(WebCore::ScriptDebugServer::updateCallFrameAndPauseIfNeeded):
(WebCore::ScriptDebugServer::pauseIfNeeded):
When a breakpoint is triggered evaluate each of its breakpoint
actions in order. If there are exceptions, log them.

* inspector/Inspector.json:
* inspector/InspectorDebuggerAgent.cpp:
(WebCore::buildObjectForBreakpointCookie):
(WebCore::InspectorDebuggerAgent::didParseSource):
Save and restore breakpoint actions where needed.

(WebCore::breakpointActionTypeForString):
(WebCore::breakpointActionsFromProtocol):
(WebCore::InspectorDebuggerAgent::setBreakpointByUrl):
(WebCore::InspectorDebuggerAgent::setBreakpoint):
Parse optional breakpoint actions from the protocol into
ScriptBreakpointAction objects.

LayoutTests:

* inspector-protocol/debugger/resources/breakpoint.js:
* inspector-protocol/debugger/setBreakpoint-actions-expected.txt: Added.
* inspector-protocol/debugger/setBreakpoint-actions.html: Added.
* inspector-protocol/debugger/setBreakpoint-options-exception-expected.txt: Added.
* inspector-protocol/debugger/setBreakpoint-options-exception.html: Added.
* inspector-protocol/resources/console-helper.js: Added.
(ConsoleHelper.simplifiedConsoleMessage):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@155132 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 840fcfdc
2013-09-05 Joseph Pecoraro <pecoraro@apple.com>
Web Inspector: Breakpoint Actions
https://bugs.webkit.org/show_bug.cgi?id=120576
Reviewed by Timothy Hatcher.
* inspector-protocol/debugger/resources/breakpoint.js:
* inspector-protocol/debugger/setBreakpoint-actions-expected.txt: Added.
* inspector-protocol/debugger/setBreakpoint-actions.html: Added.
* inspector-protocol/debugger/setBreakpoint-options-exception-expected.txt: Added.
* inspector-protocol/debugger/setBreakpoint-options-exception.html: Added.
* inspector-protocol/resources/console-helper.js: Added.
(ConsoleHelper.simplifiedConsoleMessage):
2013-09-05 Simon Fraser <simon.fraser@apple.com>
Fix repaint issue on "paints into ancestor" filtered layers
......@@ -12,3 +12,8 @@ function breakpointAutomaticallyContinue()
{
log("inside breakpointAutomaticallyContinue");
}
function breakpointActions(a, b)
{
log("inside breakpointActions a:(" + a + ") b:(" + b + ")");
}
CONSOLE MESSAGE: log-action-before
CONSOLE MESSAGE: line 1: eval-action
CONSOLE MESSAGE: log-action-after
CONSOLE MESSAGE: log-action-before
CONSOLE MESSAGE: line 1: eval-action
CONSOLE MESSAGE: log-action-after
Debugger.setBreakpoint options.actions
Breakpoints Enabled
Found breakpoint.js
Running breakpointActions a few times that should not trigger
inside breakpointActions a:(1) b:(undefined)
inside breakpointActions a:(2) b:(12)
inside breakpointActions a:(2) b:([object Object])
Running breakpointActions to triggering the breakpoint actions
inside breakpointActions a:(12) b:([object Object])
PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-before","location":"breakpoint.js:19:1"}
PASS: Console Message: {"source":"console-api","level":"log","text":"eval-action","location":"???:1:26","parameters":[{"type":"string"},{"type":"number"},{"type":"object"}]}
PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-after","location":"breakpoint.js:19:1"}
inside breakpointActions a:(100) b:([object HTMLBodyElement])
PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-before","location":"breakpoint.js:19:1"}
PASS: Console Message: {"source":"console-api","level":"log","text":"eval-action","location":"???:1:26","parameters":[{"type":"string"},{"type":"number"},{"type":"object","subtype":"node"}]}
PASS: Console Message: {"source":"javascript","level":"log","text":"log-action-after","location":"breakpoint.js:19:1"}
<html>
<head>
<script src="../../http/tests/inspector-protocol/resources/protocol-test.js"></script>
<script src="resources/breakpoint.js"></script>
<script>
function test()
{
InspectorTest.importScript("../../../../inspector-protocol/resources/console-helper.js");
InspectorTest.sendCommand("Console.enable", {});
InspectorTest.sendCommand("Debugger.enable", {});
InspectorTest.sendCommand("Debugger.setBreakpointsActive", {active: true}, function() {
InspectorTest.log("Breakpoints Enabled");
});
var expectLogs = false;
var logsSeen = 0;
const expectedLogs = 6;
InspectorTest.eventHandler["Debugger.scriptParsed"] = function(messageObject)
{
if (/resources\/breakpoint\.js$/.test(messageObject.params.url)) {
InspectorTest.log("Found breakpoint.js");
var scriptIdentifier = messageObject.params.scriptId;
var location = {scriptId: scriptIdentifier, lineNumber: 18, columnNumber: 0};
var options = {
condition: "a > 10",
autoContinue: true,
actions: [
{"type": "log", "data": "log-action-before"},
{"type": "sound"},
{"type": "evaluate", "data": "(function() { console.log('eval-action', a, b); })()"},
{"type": "log", "data": "log-action-after"}
]
};
InspectorTest.sendCommand("Debugger.setBreakpoint", {location: location, options: options}, function(responseObject) {
InspectorTest.checkForError(responseObject);
breakpointIdentifier = responseObject.result.breakpointId;
InspectorTest.log("Running breakpointActions a few times that should not trigger");
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointActions(1)"});
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointActions(2, 12)"});
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointActions(2, {x:1,y:2})"}, function() {
expectLogs = true;
InspectorTest.log("Running breakpointActions to triggering the breakpoint actions");
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointActions(12, {x:1,y:2})"}, function() {
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointActions(100, document.body)"});
});
});
});
}
}
InspectorTest.eventHandler["Debugger.paused"] = function(messageObject)
{
InspectorTest.log("Hit Breakpoint!");
InspectorTest.log("FAIL: should not have hit breakpoint, autoContinue was true");
InspectorTest.completeTest();
}
InspectorTest.eventHandler["Console.messageAdded"] = function(messageObject)
{
if (!expectLogs) {
InspectorTest.log("FAIL: unexpected log, logs should only have come from breakpoint actions.");
InspectorTest.completeTest();
return;
}
var simplifiedMessage = ConsoleHelper.simplifiedConsoleMessage(messageObject);
InspectorTest.log("PASS: Console Message: " + JSON.stringify(simplifiedMessage));
if (++logsSeen === expectedLogs)
InspectorTest.completeTest();
}
}
</script>
</head>
<body onload="runTest()">
<p>Debugger.setBreakpoint options.actions</p>
</body>
</html>
CONSOLE MESSAGE: line 1: TypeError: undefined is not an object (evaluating 'this.will.cause')
CONSOLE MESSAGE: line 1: TypeError: undefined is not an object (evaluating 'this.will.cause')
Debugger.setBreakpoint options.condition or options.action with exception
Breakpoints Enabled
Found breakpoint.js
Running breakpointWithCondition to trigger condition exception.
inside breakpointWithCondition a:(1) b:(2) a+b:(3)
PASS: Console Message: {"source":"javascript","level":"error","text":"TypeError: undefined is not an object (evaluating 'this.will.cause')","location":"undefined:1:10"}
Running breakpointActions to trigger actions exception.
inside breakpointActions a:(1) b:(2)
PASS: Console Message: {"source":"javascript","level":"error","text":"TypeError: undefined is not an object (evaluating 'this.will.cause')","location":"undefined:1:10"}
<html>
<head>
<script src="../../http/tests/inspector-protocol/resources/protocol-test.js"></script>
<script src="resources/breakpoint.js"></script>
<script>
function test()
{
InspectorTest.importScript("../../../../inspector-protocol/resources/console-helper.js");
InspectorTest.sendCommand("Console.enable", {});
InspectorTest.sendCommand("Debugger.enable", {});
InspectorTest.sendCommand("Debugger.setBreakpointsActive", {active: true}, function() {
InspectorTest.log("Breakpoints Enabled");
});
var logsSeen = 0;
const expectedLogs = 2;
InspectorTest.eventHandler["Debugger.scriptParsed"] = function(messageObject)
{
if (/resources\/breakpoint\.js$/.test(messageObject.params.url)) {
InspectorTest.log("Found breakpoint.js");
var scriptIdentifier = messageObject.params.scriptId;
var location = {scriptId: scriptIdentifier, lineNumber: 8, columnNumber: 0};
var options = {condition: "this.will.cause.exception", autoContinue: true};
InspectorTest.sendCommand("Debugger.setBreakpoint", {location: location, options: options}, function(responseObject) {
InspectorTest.checkForError(responseObject);
InspectorTest.log("Running breakpointWithCondition to trigger condition exception.");
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointWithCondition(1,2)"}, function() {
location = {scriptId: scriptIdentifier, lineNumber: 18, columnNumber: 0};
options = {actions: [{"type": "evaluate", "data": "this.will.cause.exception"}], autoContinue: true};
InspectorTest.sendCommand("Debugger.setBreakpoint", {location: location, options: options}, function(responseObject) {
InspectorTest.log("Running breakpointActions to trigger actions exception.");
InspectorTest.sendCommand("Runtime.evaluate", {expression: "breakpointActions(1,2)"});
});
});
});
}
}
InspectorTest.eventHandler["Debugger.paused"] = function(messageObject)
{
InspectorTest.log("Hit Breakpoint!");
InspectorTest.log("FAIL: should not have hit breakpoint, autoContinue was true");
InspectorTest.completeTest();
}
InspectorTest.eventHandler["Console.messageAdded"] = function(messageObject)
{
var simplifiedMessage = ConsoleHelper.simplifiedConsoleMessage(messageObject);
InspectorTest.log("PASS: Console Message: " + JSON.stringify(simplifiedMessage));
if (++logsSeen === expectedLogs)
InspectorTest.completeTest();
}
}
</script>
</head>
<body onload="runTest()">
<p>Debugger.setBreakpoint options.condition or options.action with exception</p>
</body>
</html>
window.ConsoleHelper = {};
ConsoleHelper.simplifiedConsoleMessage = function(messageObject)
{
function basename(url)
{
return url.substring(url.lastIndexOf("/") + 1) || "???";
}
var message = messageObject.params.message;
var obj = {
source: message.source,
level: message.level,
text: message.text,
location: basename(message.url) + ":" + message.line + ":" + message.column
};
if (message.parameters) {
var params = [];
for (var i = 0; i < message.parameters.length; ++i) {
var param = message.parameters[i];
var o = {type: param.type};
if (param.subtype)
o.subtype = param.subtype;
params.push(o);
}
obj.parameters = params;
}
return obj;
}
2013-09-05 Joseph Pecoraro <pecoraro@apple.com>
Web Inspector: Breakpoint Actions
https://bugs.webkit.org/show_bug.cgi?id=120576
Reviewed by Timothy Hatcher.
Tests: inspector-protocol/debugger/setBreakpoint-actions.html
inspector-protocol/debugger/setBreakpoint-options-exception.html
* inspector/ScriptBreakpoint.h:
(WebCore::ScriptBreakpointAction::ScriptBreakpointAction):
(WebCore::ScriptBreakpoint::ScriptBreakpoint):
Struct for a breakpoint action. Type and string of data.
* bindings/js/ScriptDebugServer.h:
* bindings/js/ScriptDebugServer.cpp:
(WebCore::ScriptDebugServer::hasBreakpoint):
(WebCore::ScriptDebugServer::evaluateBreakpointAction):
(WebCore::ScriptDebugServer::evaluateBreakpointActions):
(WebCore::ScriptDebugServer::updateCallFrameAndPauseIfNeeded):
(WebCore::ScriptDebugServer::pauseIfNeeded):
When a breakpoint is triggered evaluate each of its breakpoint
actions in order. If there are exceptions, log them.
* inspector/Inspector.json:
* inspector/InspectorDebuggerAgent.cpp:
(WebCore::buildObjectForBreakpointCookie):
(WebCore::InspectorDebuggerAgent::didParseSource):
Save and restore breakpoint actions where needed.
(WebCore::breakpointActionTypeForString):
(WebCore::breakpointActionsFromProtocol):
(WebCore::InspectorDebuggerAgent::setBreakpointByUrl):
(WebCore::InspectorDebuggerAgent::setBreakpoint):
Parse optional breakpoint actions from the protocol into
ScriptBreakpointAction objects.
2013-09-05 Simon Fraser <simon.fraser@apple.com>
Fix repaint issue on "paints into ancestor" filtered layers
......@@ -35,11 +35,14 @@
#include "ContentSearchUtils.h"
#include "Frame.h"
#include "JSDOMWindowCustom.h"
#include "JSJavaScriptCallFrame.h"
#include "JavaScriptCallFrame.h"
#include "PageConsole.h"
#include "ScriptBreakpoint.h"
#include "ScriptDebugListener.h"
#include "ScriptValue.h"
#include "Sound.h"
#include <debugger/DebuggerCallFrame.h>
#include <parser/SourceProvider.h>
#include <runtime/JSLock.h>
......@@ -174,11 +177,46 @@ bool ScriptDebugServer::hasBreakpoint(intptr_t sourceID, const TextPosition& pos
JSValue result = m_currentCallFrame->evaluate(breaksVector.at(i).condition, exception);
if (exception) {
// An erroneous condition counts as "false".
reportException(m_currentCallFrame->exec(), exception);
return false;
}
return result.toBoolean(m_currentCallFrame->exec());
}
bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& breakpointAction) const
{
switch (breakpointAction.type) {
case ScriptBreakpointActionTypeLog: {
DOMWindow* window = asJSDOMWindow(m_currentCallFrame->dynamicGlobalObject())->impl();
if (PageConsole* console = window->pageConsole())
console->addMessage(JSMessageSource, LogMessageLevel, breakpointAction.data);
break;
}
case ScriptBreakpointActionTypeEvaluate: {
JSValue exception;
JSValue result = m_currentCallFrame->evaluate(breakpointAction.data, exception);
if (exception)
reportException(m_currentCallFrame->exec(), exception);
break;
}
case ScriptBreakpointActionTypeSound:
systemBeep();
break;
}
return true;
}
bool ScriptDebugServer::evaluateBreakpointActions(const ScriptBreakpoint& breakpoint) const
{
for (size_t i = 0; i < breakpoint.actions.size(); ++i) {
if (!evaluateBreakpointAction(breakpoint.actions[i]))
return false;
}
return true;
}
void ScriptDebugServer::clearBreakpoints()
{
m_sourceIdToBreakpoints.clear();
......@@ -403,7 +441,7 @@ void ScriptDebugServer::createCallFrame(const DebuggerCallFrame& debuggerCallFra
void ScriptDebugServer::updateCallFrameAndPauseIfNeeded(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int columnNumber)
{
ASSERT(m_currentCallFrame);
// ASSERT(m_currentCallFrame);
if (!m_currentCallFrame)
return;
......@@ -430,7 +468,7 @@ void ScriptDebugServer::pauseIfNeeded(JSGlobalObject* dynamicGlobalObject)
return;
if (didHitBreakpoint) {
// FIXME: Evaluate breakpoint actions here.
evaluateBreakpointActions(breakpoint);
if (breakpoint.autoContinue)
return;
}
......
......@@ -125,6 +125,8 @@ protected:
virtual bool isContentScript(JSC::ExecState*);
bool hasBreakpoint(intptr_t sourceID, const TextPosition&, ScriptBreakpoint* hitBreakpoint) const;
bool evaluateBreakpointAction(const ScriptBreakpointAction&) const;
bool evaluateBreakpointActions(const ScriptBreakpoint&) const;
void dispatchFunctionToListeners(JavaScriptExecutionCallback, JSC::JSGlobalObject*);
void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback);
......
......@@ -2660,11 +2660,21 @@
],
"description": "Location in the source code."
},
{
"id": "BreakpointAction",
"type": "object",
"properties": [
{ "name": "type", "type": "string", "enum": ["log", "evaluate", "sound"], "description": "Different kinds of breakpoint actions." },
{ "name": "data", "type": "string", "optional": true, "description": "Data associated with this breakpoint type (e.g. for type \"eval\" this is the JavaScript string to evalulate)." }
],
"description": "Action to perform when a breakpoint is triggered."
},
{
"id": "BreakpointOptions",
"type": "object",
"properties": [
{ "name": "condition", "type": "string", "optional": true, "description": "Expression to use as a breakpoint condition. When specified, debugger will only stop on the breakpoint if this expression evaluates to true." },
{ "name": "actions", "type": "array", "optional": true, "items": { "$ref": "BreakpointAction" }, "description": "Actions to perform automatically when the breakpoint is triggered." },
{ "name": "autoContinue", "type": "boolean", "optional": true, "description": "Automatically continue after hitting this breakpoint and running actions." }
],
"description": "Extra options that modify breakpoint behavior."
......
......@@ -202,7 +202,7 @@ void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageTy
breakProgram(InspectorFrontend::Debugger::Reason::Assert, 0);
}
static PassRefPtr<InspectorObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex, bool autoContinue)
static PassRefPtr<InspectorObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, RefPtr<InspectorArray>& actions, bool isRegex, bool autoContinue)
{
RefPtr<InspectorObject> breakpointObject = InspectorObject::create();
breakpointObject->setString("url", url);
......@@ -211,6 +211,9 @@ static PassRefPtr<InspectorObject> buildObjectForBreakpointCookie(const String&
breakpointObject->setString("condition", condition);
breakpointObject->setBoolean("isRegex", isRegex);
breakpointObject->setBoolean("autoContinue", autoContinue);
if (actions)
breakpointObject->setArray("actions", actions);
return breakpointObject;
}
......@@ -223,6 +226,63 @@ static bool matches(const String& url, const String& pattern, bool isRegex)
return url == pattern;
}
static bool breakpointActionTypeForString(const String& typeString, ScriptBreakpointActionType* output)
{
if (typeString == TypeBuilder::getEnumConstantValue(TypeBuilder::Debugger::BreakpointAction::Type::Log)) {
*output = ScriptBreakpointActionTypeLog;
return true;
}
if (typeString == TypeBuilder::getEnumConstantValue(TypeBuilder::Debugger::BreakpointAction::Type::Evaluate)) {
*output = ScriptBreakpointActionTypeEvaluate;
return true;
}
if (typeString == TypeBuilder::getEnumConstantValue(TypeBuilder::Debugger::BreakpointAction::Type::Sound)) {
*output = ScriptBreakpointActionTypeSound;
return true;
}
return false;
}
static bool breakpointActionsFromProtocol(ErrorString* errorString, RefPtr<InspectorArray>& actions, Vector<ScriptBreakpointAction>* result)
{
if (!actions)
return true;
unsigned actionsLength = actions->length();
if (!actionsLength)
return true;
result->reserveCapacity(actionsLength);
for (unsigned i = 0; i < actionsLength; ++i) {
RefPtr<InspectorValue> value = actions->get(i);
RefPtr<InspectorObject> object;
if (!value->asObject(&object)) {
*errorString = "BreakpointAction of incorrect type, expected object";
return false;
}
String typeString;
if (!object->getString("type", &typeString)) {
*errorString = "BreakpointAction had type missing";
return false;
}
ScriptBreakpointActionType type;
if (!breakpointActionTypeForString(typeString, &type)) {
*errorString = "BreakpointAction had unknown type";
return false;
}
String data;
object->getString("data", &data);
result->append(ScriptBreakpointAction(type, data));
}
return true;
}
void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const RefPtr<InspectorObject>* options, TypeBuilder::Debugger::BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Array<TypeBuilder::Debugger::Location> >& locations)
{
locations = Array<TypeBuilder::Debugger::Location>::create();
......@@ -244,15 +304,21 @@ void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int li
String condition = emptyString();
bool autoContinue = false;
RefPtr<InspectorArray> actions;
if (options) {
(*options)->getString("condition", &condition);
(*options)->getBoolean("autoContinue", &autoContinue);
actions = (*options)->getArray("actions");
}
breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex, autoContinue));
Vector<ScriptBreakpointAction> breakpointActions;
if (!breakpointActionsFromProtocol(errorString, actions, &breakpointActions))
return;
breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, actions, isRegex, autoContinue));
m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, autoContinue);
ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, breakpointActions, autoContinue);
for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
if (!matches(it->value.url, url, isRegex))
continue;
......@@ -286,17 +352,23 @@ void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPt
String condition = emptyString();
bool autoContinue = false;
RefPtr<InspectorArray> actions;
if (options) {
(*options)->getString("condition", &condition);
(*options)->getBoolean("autoContinue", &autoContinue);
actions = (*options)->getArray("actions");
}
Vector<ScriptBreakpointAction> breakpointActions;
if (!breakpointActionsFromProtocol(errorString, actions, &breakpointActions))
return;
String breakpointId = scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end()) {
*errorString = "Breakpoint at specified location already exists.";
return;
}
ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, autoContinue);
ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, breakpointActions, autoContinue);
actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint);
if (actualLocation)
*outBreakpointId = breakpointId;
......@@ -655,7 +727,7 @@ String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script)
sourceMapHeader = resource->response().httpHeaderField(sourceMapHTTPHeaderDeprecated);
if (!sourceMapHeader.isEmpty())
return sourceMapHeader;
return sourceMapHeader;
}
}
}
......@@ -698,6 +770,13 @@ void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script
breakpointObject->getNumber("columnNumber", &breakpoint.columnNumber);
breakpointObject->getString("condition", &breakpoint.condition);
breakpointObject->getBoolean("autoContinue", &breakpoint.autoContinue);
ErrorString errorString;
RefPtr<InspectorArray> actions = breakpointObject->getArray("actions");
if (!breakpointActionsFromProtocol(&errorString, actions, &breakpoint.actions)) {
ASSERT_NOT_REACHED();
continue;
}
RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, scriptId, breakpoint);
if (location)
m_frontend->breakpointResolved(it->key, location);
......
......@@ -30,10 +30,28 @@
#ifndef ScriptBreakpoint_h
#define ScriptBreakpoint_h
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
typedef enum {
ScriptBreakpointActionTypeLog,
ScriptBreakpointActionTypeEvaluate,
ScriptBreakpointActionTypeSound
} ScriptBreakpointActionType;
struct ScriptBreakpointAction {
ScriptBreakpointAction(ScriptBreakpointActionType type, const String& data)
: type(type)
, data(data)
{
}
ScriptBreakpointActionType type;
String data;
};
struct ScriptBreakpoint {
ScriptBreakpoint()
{
......@@ -47,9 +65,19 @@ struct ScriptBreakpoint {
{
}
ScriptBreakpoint(int lineNumber, int columnNumber, const String& condition, Vector<ScriptBreakpointAction>& actions, bool autoContinue)
: lineNumber(lineNumber)
, columnNumber(columnNumber)
, condition(condition)
, actions(actions)
, autoContinue(autoContinue)
{
}
int lineNumber;
int columnNumber;
String condition;
Vector<ScriptBreakpointAction> actions;
bool autoContinue;
};
......
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