Title: [155132] trunk
Revision
155132
Author
[email protected]
Date
2013-09-05 11:00:53 -0700 (Thu, 05 Sep 2013)

Log Message

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):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (155131 => 155132)


--- trunk/LayoutTests/ChangeLog	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/LayoutTests/ChangeLog	2013-09-05 18:00:53 UTC (rev 155132)
@@ -1,3 +1,18 @@
+2013-09-05  Joseph Pecoraro  <[email protected]>
+
+        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  <[email protected]>
 
         Fix repaint issue on "paints into ancestor" filtered layers

Modified: trunk/LayoutTests/inspector-protocol/debugger/resources/breakpoint.js (155131 => 155132)


--- trunk/LayoutTests/inspector-protocol/debugger/resources/breakpoint.js	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/LayoutTests/inspector-protocol/debugger/resources/breakpoint.js	2013-09-05 18:00:53 UTC (rev 155132)
@@ -12,3 +12,8 @@
 {
     log("inside breakpointAutomaticallyContinue");
 }
+
+function breakpointActions(a, b)
+{
+    log("inside breakpointActions a:(" + a + ") b:(" + b + ")");
+}

Added: trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-actions-expected.txt (0 => 155132)


--- trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-actions-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-actions-expected.txt	2013-09-05 18:00:53 UTC (rev 155132)
@@ -0,0 +1,24 @@
+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"}
+

Added: trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-actions.html (0 => 155132)


--- trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-actions.html	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-actions.html	2013-09-05 18:00:53 UTC (rev 155132)
@@ -0,0 +1,82 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<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>

Added: trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-options-exception-expected.txt (0 => 155132)


--- trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-options-exception-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-options-exception-expected.txt	2013-09-05 18:00:53 UTC (rev 155132)
@@ -0,0 +1,13 @@
+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"}
+

Added: trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-options-exception.html (0 => 155132)


--- trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-options-exception.html	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/debugger/setBreakpoint-options-exception.html	2013-09-05 18:00:53 UTC (rev 155132)
@@ -0,0 +1,63 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<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>

Added: trunk/LayoutTests/inspector-protocol/resources/console-helper.js (0 => 155132)


--- trunk/LayoutTests/inspector-protocol/resources/console-helper.js	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/resources/console-helper.js	2013-09-05 18:00:53 UTC (rev 155132)
@@ -0,0 +1,31 @@
+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;
+}

Modified: trunk/Source/WebCore/ChangeLog (155131 => 155132)


--- trunk/Source/WebCore/ChangeLog	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/Source/WebCore/ChangeLog	2013-09-05 18:00:53 UTC (rev 155132)
@@ -1,3 +1,41 @@
+2013-09-05  Joseph Pecoraro  <[email protected]>
+
+        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  <[email protected]>
 
         Fix repaint issue on "paints into ancestor" filtered layers

Modified: trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp (155131 => 155132)


--- trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp	2013-09-05 18:00:53 UTC (rev 155132)
@@ -35,11 +35,14 @@
 
 #include "ContentSearchUtils.h"
 #include "Frame.h"
+#include "JSDOMWindowCustom.h"
 #include "JSJavaScriptCallFrame.h"
 #include "_javascript_CallFrame.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 @@
     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::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 @@
         return;
 
     if (didHitBreakpoint) {
-        // FIXME: Evaluate breakpoint actions here.
+        evaluateBreakpointActions(breakpoint);
         if (breakpoint.autoContinue)
             return;
     }

Modified: trunk/Source/WebCore/bindings/js/ScriptDebugServer.h (155131 => 155132)


--- trunk/Source/WebCore/bindings/js/ScriptDebugServer.h	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/Source/WebCore/bindings/js/ScriptDebugServer.h	2013-09-05 18:00:53 UTC (rev 155132)
@@ -125,6 +125,8 @@
     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(_javascript_ExecutionCallback, JSC::JSGlobalObject*);
     void dispatchFunctionToListeners(const ListenerSet& listeners, _javascript_ExecutionCallback callback);

Modified: trunk/Source/WebCore/inspector/Inspector.json (155131 => 155132)


--- trunk/Source/WebCore/inspector/Inspector.json	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/Source/WebCore/inspector/Inspector.json	2013-09-05 18:00:53 UTC (rev 155132)
@@ -2661,10 +2661,20 @@
                 "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."

Modified: trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp (155131 => 155132)


--- trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp	2013-09-05 18:00:53 UTC (rev 155132)
@@ -202,7 +202,7 @@
         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 @@
     breakpointObject->setString("condition", condition);
     breakpointObject->setBoolean("isRegex", isRegex);
     breakpointObject->setBoolean("autoContinue", autoContinue);
+    if (actions)
+        breakpointObject->setArray("actions", actions);
+
     return breakpointObject;
 }
 
@@ -223,6 +226,63 @@
     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 @@
 
     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::_javascript_Breakpoints, 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 @@
 
     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 @@
 
                 sourceMapHeader = resource->response().httpHeaderField(sourceMapHTTPHeaderDeprecated);
                 if (!sourceMapHeader.isEmpty())
-                    return sourceMapHeader;                
+                    return sourceMapHeader;
             }
         }
     }
@@ -698,6 +770,13 @@
         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);

Modified: trunk/Source/WebCore/inspector/ScriptBreakpoint.h (155131 => 155132)


--- trunk/Source/WebCore/inspector/ScriptBreakpoint.h	2013-09-05 17:56:58 UTC (rev 155131)
+++ trunk/Source/WebCore/inspector/ScriptBreakpoint.h	2013-09-05 18:00:53 UTC (rev 155132)
@@ -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 @@
     {
     }
 
+    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;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to