Add pause on exception support to the Inspector debugger
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 May 2008 17:55:33 +0000 (17:55 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 May 2008 17:55:33 +0000 (17:55 +0000)
with a toggle buttons to enable or disable it.

Reviewed by Adam Roben.

* page/InspectorController.cpp:
(WebCore::pauseOnExceptions): Call the InspectorController.
(WebCore::setPauseOnExceptions): Ditto.
(WebCore::InspectorController::windowScriptObjectAvailable): Add the new
setPauseOnExceptions and pauseOnExceptions functions to the JS class.
(WebCore::InspectorController::pauseOnExceptions): Call JavaScriptDebugServer.
(WebCore::InspectorController::setPauseOnExceptions): Ditto.
* page/InspectorController.h:
* page/JavaScriptDebugServer.cpp:
(WebCore::JavaScriptDebugServer::setPauseOnExceptions): Set m_pauseOnExceptions.
(WebCore::JavaScriptDebugServer::exception): Check m_pauseOnExceptions
and set m_pauseOnNextStatement to true before calling pauseIfNeeded.
* page/JavaScriptDebugServer.h:
* page/inspector/Images/pauseOnExceptionButtons.png: Added.
* page/inspector/ScriptsPanel.js: Adds a status bar button that calls
the new InspectorController functions.
* page/inspector/inspector.css: New styles.

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

WebCore/ChangeLog
WebCore/English.lproj/localizedStrings.js
WebCore/page/InspectorController.cpp
WebCore/page/InspectorController.h
WebCore/page/JavaScriptDebugServer.cpp
WebCore/page/JavaScriptDebugServer.h
WebCore/page/inspector/Images/pauseOnExceptionButtons.png [new file with mode: 0644]
WebCore/page/inspector/ScriptsPanel.js
WebCore/page/inspector/inspector.css

index 044a6e4..9a44fc1 100644 (file)
@@ -1,5 +1,30 @@
 2008-05-14  Timothy Hatcher  <timothy@apple.com>
 
+        Add pause on exception support to the Inspector debugger
+        with a toggle buttons to enable or disable it.
+
+        Reviewed by Adam Roben.
+
+        * page/InspectorController.cpp:
+        (WebCore::pauseOnExceptions): Call the InspectorController.
+        (WebCore::setPauseOnExceptions): Ditto.
+        (WebCore::InspectorController::windowScriptObjectAvailable): Add the new
+        setPauseOnExceptions and pauseOnExceptions functions to the JS class.
+        (WebCore::InspectorController::pauseOnExceptions): Call JavaScriptDebugServer.
+        (WebCore::InspectorController::setPauseOnExceptions): Ditto.
+        * page/InspectorController.h:
+        * page/JavaScriptDebugServer.cpp:
+        (WebCore::JavaScriptDebugServer::setPauseOnExceptions): Set m_pauseOnExceptions.
+        (WebCore::JavaScriptDebugServer::exception): Check m_pauseOnExceptions
+        and set m_pauseOnNextStatement to true before calling pauseIfNeeded.
+        * page/JavaScriptDebugServer.h:
+        * page/inspector/Images/pauseOnExceptionButtons.png: Added.
+        * page/inspector/ScriptsPanel.js: Adds a status bar button that calls
+        the new InspectorController functions.
+        * page/inspector/inspector.css: New styles.
+
+2008-05-14  Timothy Hatcher  <timothy@apple.com>
+
         Rename the Scope Chain pane to Scope Variables. Name the global
         object Global. Name objects before the locals "With Block".
         Name colsure scopes "Closure". Name any element or document
index d36cf83..164e195 100644 (file)
Binary files a/WebCore/English.lproj/localizedStrings.js and b/WebCore/English.lproj/localizedStrings.js differ
index 256ddc9..4a0684c 100644 (file)
@@ -837,6 +837,28 @@ static JSValueRef currentCallFrame(JSContextRef ctx, JSObjectRef /*function*/, J
     return toRef(JSInspectedObjectWrapper::wrap(globalExec, toJS(toJS(ctx), callFrame)));
 }
 
+static JSValueRef pauseOnExceptions(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
+{
+    InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
+    if (!controller)
+        return JSValueMakeUndefined(ctx);
+    return JSValueMakeBoolean(ctx, controller->pauseOnExceptions());
+}
+
+static JSValueRef setPauseOnExceptions(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/)
+{
+    InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
+    if (!controller)
+        return JSValueMakeUndefined(ctx);
+
+    if (argumentCount < 1)
+        return JSValueMakeUndefined(ctx);
+
+    controller->setPauseOnExceptions(JSValueToBoolean(ctx, arguments[0]));
+
+    return JSValueMakeUndefined(ctx);
+}
+
 static JSValueRef pauseInDebugger(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/)
 {
     InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject));
@@ -1171,6 +1193,8 @@ void InspectorController::windowScriptObjectAvailable()
         { "stopDebugging", WebCore::stopDebugging, kJSPropertyAttributeNone },
         { "debuggerAttached", WebCore::debuggerAttached, kJSPropertyAttributeNone },
         { "currentCallFrame", WebCore::currentCallFrame, kJSPropertyAttributeNone },
+        { "pauseOnExceptions", WebCore::pauseOnExceptions, kJSPropertyAttributeNone },
+        { "setPauseOnExceptions", WebCore::setPauseOnExceptions, kJSPropertyAttributeNone },
         { "pauseInDebugger", WebCore::pauseInDebugger, kJSPropertyAttributeNone },
         { "resumeDebugger", WebCore::resumeDebugger, kJSPropertyAttributeNone },
         { "stepOverStatementInDebugger", WebCore::stepOverStatementInDebugger, kJSPropertyAttributeNone },
@@ -2060,6 +2084,16 @@ JavaScriptCallFrame* InspectorController::currentCallFrame() const
     return JavaScriptDebugServer::shared().currentCallFrame();
 }
 
+bool InspectorController::pauseOnExceptions()
+{
+    return JavaScriptDebugServer::shared().pauseOnExceptions();
+}
+
+void InspectorController::setPauseOnExceptions(bool pause)
+{
+    JavaScriptDebugServer::shared().setPauseOnExceptions(pause);
+}
+
 void InspectorController::pauseInDebugger()
 {
     if (!m_debuggerAttached)
index bc2c928..4dcbc75 100644 (file)
@@ -140,6 +140,9 @@ public:
     void addBreakpoint(int sourceID, unsigned lineNumber);
     void removeBreakpoint(int sourceID, unsigned lineNumber);
 
+    bool pauseOnExceptions();
+    void setPauseOnExceptions(bool pause);
+
     void pauseInDebugger();
     void resumeDebugger();
 
index 4d6d01d..c340d12 100644 (file)
@@ -59,6 +59,7 @@ JavaScriptDebugServer& JavaScriptDebugServer::shared()
 
 JavaScriptDebugServer::JavaScriptDebugServer()
     : m_callingListeners(false)
+    , m_pauseOnExceptions(false)
     , m_pauseOnNextStatement(false)
     , m_paused(false)
     , m_pauseOnExecState(0)
@@ -184,6 +185,11 @@ void JavaScriptDebugServer::clearBreakpoints()
     m_breakpoints.clear();
 }
 
+void JavaScriptDebugServer::setPauseOnExceptions(bool pause)
+{
+    m_pauseOnExceptions = pause;
+}
+
 void JavaScriptDebugServer::pauseOnNextStatement()
 {
     m_pauseOnNextStatement = true;
@@ -465,8 +471,8 @@ bool JavaScriptDebugServer::exception(ExecState* exec, int sourceID, int lineNum
         m_currentCallFrame->setLine(lineNumber);
     else
         m_currentCallFrame = JavaScriptCallFrame::create(exec, 0, sourceID, lineNumber);
-    // FIXME: ideally this should only pause if a "pause on exception" flag is set,
-    // not m_pauseOnNextStatement, etc.
+    if (m_pauseOnExceptions)
+        m_pauseOnNextStatement = true;
     pauseIfNeeded(exec, sourceID, lineNumber);
     return true;
 }
index edeb2e3..d5b4be3 100644 (file)
@@ -60,6 +60,9 @@ namespace WebCore {
         bool hasBreakpoint(int sourceID, unsigned lineNumber) const;
         void clearBreakpoints();
 
+        bool pauseOnExceptions() const { return m_pauseOnExceptions; }
+        void setPauseOnExceptions(bool);
+
         void pauseOnNextStatement();
         void resume();
 
@@ -99,6 +102,7 @@ namespace WebCore {
         PageListenersMap m_pageListenersMap;
         ListenerSet m_listeners;
         bool m_callingListeners;
+        bool m_pauseOnExceptions;
         bool m_pauseOnNextStatement;
         bool m_paused;
         KJS::ExecState* m_pauseOnExecState;
diff --git a/WebCore/page/inspector/Images/pauseOnExceptionButtons.png b/WebCore/page/inspector/Images/pauseOnExceptionButtons.png
new file mode 100644 (file)
index 0000000..a4dd33a
Binary files /dev/null and b/WebCore/page/inspector/Images/pauseOnExceptionButtons.png differ
index 9b2269b..56d1c85 100644 (file)
@@ -162,6 +162,11 @@ WebInspector.ScriptsPanel = function()
     this.debuggingButton.className = "status-bar-item";
     this.debuggingButton.addEventListener("click", this._toggleDebugging.bind(this), false);
 
+    this.pauseOnExceptionButtons = document.createElement("button");
+    this.pauseOnExceptionButtons.id = "scripts-pause-on-exceptions-status-bar-item";
+    this.pauseOnExceptionButtons.className = "status-bar-item";
+    this.pauseOnExceptionButtons.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
+
     this._breakpointsURLMap = {};
 
     this.reset();
@@ -177,7 +182,7 @@ WebInspector.ScriptsPanel.prototype = {
 
     get statusBarItems()
     {
-        return [this.debuggingButton];
+        return [this.debuggingButton, this.pauseOnExceptionButtons];
     },
 
     show: function()
@@ -521,6 +526,17 @@ WebInspector.ScriptsPanel.prototype = {
         event.preventDefault();
     },
 
+    _updatePauseOnExceptionsButton: function()
+    {
+        if (InspectorController.pauseOnExceptions()) {
+            this.debuggingButton.title = WebInspector.UIString("Pause on exceptions.");
+            this.pauseOnExceptionButtons.addStyleClass("toggled-on");
+        } else {
+            this.debuggingButton.title = WebInspector.UIString("Don't pause on exceptions.");
+            this.pauseOnExceptionButtons.removeStyleClass("toggled-on");
+        }
+    },
+
     _updateDebuggerButtons: function()
     {
         if (InspectorController.debuggerAttached()) {
@@ -533,6 +549,8 @@ WebInspector.ScriptsPanel.prototype = {
             this.pauseButton.disabled = true;
         }
 
+        this._updatePauseOnExceptionsButton();
+
         if (this._paused) {
             this.pauseButton.addStyleClass("paused");
 
@@ -585,6 +603,12 @@ WebInspector.ScriptsPanel.prototype = {
         }
     },
 
+    _togglePauseOnExceptions: function()
+    {
+        InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions());
+        this._updatePauseOnExceptionsButton();
+    },
+
     _togglePause: function()
     {
         if (this._paused) {
index f3302a4..39cf564 100644 (file)
@@ -1505,6 +1505,22 @@ body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-des
     background-position: 32px 24px;
 }
 
+#scripts-pause-on-exceptions-status-bar-item {
+    background-image: url(Images/pauseOnExceptionButtons.png);
+}
+
+#scripts-pause-on-exceptions-status-bar-item:active {
+    background-position: 32px 0;
+}
+
+#scripts-pause-on-exceptions-status-bar-item.toggled-on {
+    background-position: 0 24px;
+}
+
+#scripts-pause-on-exceptions-status-bar-item.toggled-on:active {
+    background-position: 32px 24px;
+}
+
 #scripts-status-bar {
     position: absolute;
     top: -1px;