2010-09-14 Pavel Podivilov <podivilov@chromium.org>
authorpfeldman@chromium.org <pfeldman@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 17 Sep 2010 17:16:10 +0000 (17:16 +0000)
committerpfeldman@chromium.org <pfeldman@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 17 Sep 2010 17:16:10 +0000 (17:16 +0000)
        Reviewed by Pavel Feldman.

        Web Inspector: show status message below call stack when debugger is paused on DOM breakpoint
        https://bugs.webkit.org/show_bug.cgi?id=45114

        * English.lproj/localizedStrings.js:
        * inspector/InspectorDOMAgent.cpp:
        (WebCore::InspectorDOMAgent::performSearch):
        (WebCore::InspectorDOMAgent::shouldBreakOnNodeInsertion):
        (WebCore::InspectorDOMAgent::shouldBreakOnNodeRemoval):
        (WebCore::InspectorDOMAgent::shouldBreakOnAttributeModification):
        (WebCore::InspectorDOMAgent::descriptionForDOMEvent):
        * inspector/InspectorDOMAgent.h:
        * inspector/InspectorDebuggerAgent.cpp:
        (WebCore::InspectorDebuggerAgent::didPause):
        * inspector/front-end/CallStackSidebarPane.js:
        (WebInspector.CallStackSidebarPane):
        (WebInspector.CallStackSidebarPane.prototype.updateStatus.formatters.s):
        (WebInspector.CallStackSidebarPane.prototype.updateStatus.append):
        (WebInspector.CallStackSidebarPane.prototype.updateStatus):
        * inspector/front-end/ElementsPanel.js:
        (WebInspector.ElementsPanel.prototype.linkifyNodeById):
        * inspector/front-end/ScriptsPanel.js:
        (WebInspector.ScriptsPanel.prototype.debuggerPaused):
        * inspector/front-end/inspector.css:
        (.pane > .body .placard + .info):
        * inspector/front-end/inspector.js:
        (WebInspector.pausedScript):
        (WebInspector.formatLocalized):
2010-09-14  Pavel Podivilov  <podivilov@chromium.org>

        Reviewed by Pavel Feldman.

        Web Inspector: show status message below call stack when debugger is paused on DOM breakpoint
        https://bugs.webkit.org/show_bug.cgi?id=45114

        * http/tests/inspector/inspector-test2.js:
        (initialize_InspectorTest.InspectorTest.evaluateInPageWithTimeout):

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/inspector-test2.js
LayoutTests/inspector/dom-breakpoints-expected.txt
LayoutTests/inspector/dom-breakpoints.html
WebCore/ChangeLog
WebCore/English.lproj/localizedStrings.js
WebCore/inspector/InspectorDOMAgent.cpp
WebCore/inspector/InspectorDOMAgent.h
WebCore/inspector/InspectorDebuggerAgent.cpp
WebCore/inspector/front-end/CallStackSidebarPane.js
WebCore/inspector/front-end/ElementsPanel.js
WebCore/inspector/front-end/ScriptsPanel.js
WebCore/inspector/front-end/inspector.css
WebCore/inspector/front-end/inspector.js

index ef8a347..e76f997 100644 (file)
@@ -1,3 +1,18 @@
+2010-09-14  Pavel Podivilov  <podivilov@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: show status message below call stack when debugger is paused on DOM breakpoint
+        https://bugs.webkit.org/show_bug.cgi?id=45114
+
+        * http/tests/inspector/inspector-test2.js:
+        (initialize_InspectorTest.InspectorTest.evaluateInPageWithTimeout):
+        (initialize_InspectorTest.InspectorTest.findDOMNode.findDOMNode.processChildren):
+        (initialize_InspectorTest.InspectorTest.findDOMNode.findDOMNode):
+        (initialize_InspectorTest.InspectorTest.findDOMNode):
+        * inspector/dom-breakpoints-expected.txt:
+        * inspector/dom-breakpoints.html:
+
 2010-09-17  Johnny Ding  <jnd@chromium.org>
 
         Reviewed by Adam Barth.
index 13f3b25..df65d8a 100644 (file)
@@ -27,6 +27,11 @@ InspectorTest.evaluateInPage = function(code, callback)
     InjectedScriptAccess.getDefault().evaluate(code, "console", callback || function() {});
 };
 
+InspectorTest.evaluateInPageWithTimeout = function(code, callback)
+{
+    InspectorTest.evaluateInPage("setTimeout(unescape('" + escape(code) + "'))", callback);
+};
+
 InspectorTest.addResult = function(text)
 {
     results.push(text);
@@ -107,7 +112,7 @@ InspectorTest.disableResourceTracking = function()
 InspectorTest.findDOMNode = function(root, filter, callback)
 {
     var found = false;
-    var pendingCalls = 0;
+    var pendingCalls = 1;
 
     if (root)
         findDOMNode(root);
@@ -128,20 +133,19 @@ InspectorTest.findDOMNode = function(root, filter, callback)
         if (filter(node)) {
             callback(node);
             found = true;
-        } else {
-            pendingCalls += 1;
+        } else
             WebInspector.domAgent.getChildNodesAsync(node, processChildren);
-        }
+
+        --pendingCalls;
+
+        if (!found && !pendingCalls)
+            setTimeout(findDOMNode.bind(null, root), 0);
 
         function processChildren(children)
         {
-            pendingCalls -= 1;
-
+            pendingCalls += children ? children.length : 0;
             for (var i = 0; !found && children && i < children.length; ++i)
                 findDOMNode(children[i]);
-
-            if (!found && !pendingCalls && node == root)
-                callback(null);
         }
     }
 };
index 2d875ec..636e0ed 100644 (file)
@@ -1,30 +1,59 @@
 Tests DOM breakpoints. Bug 42886
 
 Debugger was enabled.
-Test that 'Subtree Modified' breakpoint is hit when appending child.
-Set subtree modified DOM breakpoint on d0.
-Append d1 to d0.
+Test that 'Subtree Modified' breakpoint is hit when appending child.
+Set 'Subtree Modified' DOM breakpoint on rootElement.
+Append childElement to rootElement.
 Script execution paused.
-line: 11, function: appendElement
+Call stack:
+    0) appendElement (dom-breakpoints.html:11)
+    1)  (:1)
+Paused on a "Subtree Modified" breakpoint set on div#rootElement, because a new child was added to that node.
+Script execution resumed.
+Test that 'Subtree Modified' breakpoint is hit when appending a grandchild.
+Append grandchildElement to childElement.
+Script execution paused.
+Call stack:
+    0) appendElement (dom-breakpoints.html:11)
+    1)  (:1)
+Paused on a "Subtree Modified" breakpoint set on div#rootElement, because a new child was added to its descendant div#childElement.
+Script execution resumed.
+Test that 'Subtree Modified' breakpoint is hit when removing a child.
+Remove grandchildElement.
+Script execution paused.
+Call stack:
+    0) removeElement (dom-breakpoints.html:23)
+    1)  (:1)
+Paused on a "Subtree Modified" breakpoint set on div#rootElement, because its descendant div#grandchildElement was removed.
 Script execution resumed.
 Test that 'Attribute Modified' breakpoint is hit when modifying attribute.
-Set attribute modified DOM breakpoint on d1.
-Modify d1 className.
+Set 'Attribute Modified' DOM breakpoint on rootElement.
+Modify rootElement className.
 Script execution paused.
-line: 17, function: modifyAttribute
+Call stack:
+    0) modifyAttribute (dom-breakpoints.html:17)
+    1)  (:1)
+Paused on a "Attribute Modified" breakpoint set on div#rootElement.
 Script execution resumed.
 Test that 'Node Removed' breakpoint is hit when removing a node.
-Set node removed DOM breakpoint on d1.
-Remove d1.
+Append elementToRemove to rootElement.
+Set 'Node Removed' DOM breakpoint on elementToRemove.
+Remove elementToRemove.
 Script execution paused.
-line: 23, function: removeElement
+Call stack:
+    0) removeElement (dom-breakpoints.html:23)
+    1)  (:1)
+Paused on a "Node Removed" breakpoint set on div#elementToRemove.
 Script execution resumed.
 Test that DOM breakpoints are persisted between page reloads.
-Set subtree modified DOM breakpoint on d0.
+Set 'Subtree Modified' DOM breakpoint on rootElement.
 Page reloaded.
-Append d1 to d0.
+Append childElement to rootElement.
 Script execution paused.
-line: 11, function: appendElement
+Call stack:
+    0) appendElement (dom-breakpoints.html:11)
+    1)  (:1)
+Paused on a "Subtree Modified" breakpoint set on div#rootElement, because a new child was added to that node.
 Script execution resumed.
 Debugger was disabled.
 
index 7625a47..b66a151 100644 (file)
@@ -25,85 +25,127 @@ function removeElement(elementId)
 
 var test = function()
 {
-    InspectorTest.startDebuggerTest(step1);
-
-    var d0, d1;
+    testInsertChild = {};
+    testInsertChild.step1 = function()
+    {
+        InspectorTest.addResult("Test that 'Subtree Modified' breakpoint is hit when appending a child.");
+        findDOMNodeById("rootElement", testInsertChild.step2);
+    };
+    testInsertChild.step2 = function(node)
+    {
+        node.setBreakpoint(WebInspector.DOMBreakpoint.Types.SubtreeModified);
+        InspectorTest.addResult("Set 'Subtree Modified' DOM breakpoint on rootElement.");
+        InspectorTest.evaluateInPageWithTimeout("appendElement('rootElement', 'childElement')");
+        InspectorTest.addResult("Append childElement to rootElement.");
+        InspectorTest.waitUntilPaused(testInsertChild.step3);
+    };
+    testInsertChild.step3 = function(callFrames)
+    {
+        dumpStatus(callFrames);
+        InspectorTest.resumeExecution(testInsertGrandchild.step1);
+    };
 
-    function step1()
+    var testInsertGrandchild = {};
+    testInsertGrandchild.step1 = function()
     {
-        findDOMNodeById("d0", step2);
+        InspectorTest.addResult("Test that 'Subtree Modified' breakpoint is hit when appending a grandchild.");
+        InspectorTest.evaluateInPageWithTimeout("appendElement('childElement', 'grandchildElement')");
+        InspectorTest.addResult("Append grandchildElement to childElement.");
+        InspectorTest.waitUntilPaused(testInsertGrandchild.step2);
     }
-
-    function step2(node)
+    testInsertGrandchild.step2 = function(callFrames)
     {
-        d0 = node;
-        InspectorTest.addResult("Test that 'Subtree Modified' breakpoint is hit when appending child.");
-        d0.setBreakpoint(WebInspector.DOMBreakpoint.Types.SubtreeModified);
-        InspectorTest.addResult("Set subtree modified DOM breakpoint on d0.");
-        InspectorTest.evaluateInConsole("appendElement('d0', 'd1')");
-        InspectorTest.addResult("Append d1 to d0.");
-        InspectorTest.waitUntilPaused(step3);
+        dumpStatus(callFrames);
+        InspectorTest.resumeExecution(testRemoveChild.step1);
     }
 
-    function step3(callFrames)
+    var testRemoveChild = {};
+    testRemoveChild.step1 = function()
     {
-        InspectorTest.addResult("line: " + callFrames[0].line + ", function: " + callFrames[0].functionName);
-        d0.removeBreakpoint(WebInspector.DOMBreakpoint.Types.SubtreeModified);
-        InspectorTest.resumeExecution(findDOMNodeById.bind(null, "d1", step4));
+        InspectorTest.addResult("Test that 'Subtree Modified' breakpoint is hit when removing a child.");
+        InspectorTest.evaluateInPageWithTimeout("removeElement('grandchildElement')");
+        InspectorTest.addResult("Remove grandchildElement.");
+        InspectorTest.waitUntilPaused(testRemoveChild.step2);
+
+    }
+    testRemoveChild.step2 = function(callFrames)
+    {
+        dumpStatus(callFrames);
+        findDOMNodeById("rootElement", testRemoveChild.step3);
+    }
+    testRemoveChild.step3 = function(node)
+    {
+        node.removeBreakpoint(WebInspector.DOMBreakpoint.Types.SubtreeModified);
+        InspectorTest.resumeExecution(testModifyAttribute.step1);
     }
 
-    function step4(node)
+    var testModifyAttribute = {};
+    testModifyAttribute.step1 = function()
     {
-        d1 = node;
         InspectorTest.addResult("Test that 'Attribute Modified' breakpoint is hit when modifying attribute.");
-        d1.setBreakpoint(WebInspector.DOMBreakpoint.Types.AttributeModified);
-        InspectorTest.addResult("Set attribute modified DOM breakpoint on d1.");
-        InspectorTest.evaluateInConsole("modifyAttribute('d1', 'className', 'foo')");
-        InspectorTest.addResult("Modify d1 className.");
-        InspectorTest.waitUntilPaused(step5);
+        findDOMNodeById("rootElement", testModifyAttribute.step2);
     }
-
-    function step5(callFrames)
+    testModifyAttribute.step2 = function(node)
+    {
+        node.setBreakpoint(WebInspector.DOMBreakpoint.Types.AttributeModified);
+        InspectorTest.addResult("Set 'Attribute Modified' DOM breakpoint on rootElement.");
+        InspectorTest.evaluateInPageWithTimeout("modifyAttribute('rootElement', 'className', 'foo')");
+        InspectorTest.addResult("Modify rootElement className.");
+        InspectorTest.waitUntilPaused(testModifyAttribute.step3.bind(null, node));
+    }
+    testModifyAttribute.step3 = function(node, callFrames)
     {
-        InspectorTest.addResult("line: " + callFrames[0].line + ", function: " + callFrames[0].functionName);
-        d1.removeBreakpoint(WebInspector.DOMBreakpoint.Types.AttributeModified);
-        InspectorTest.resumeExecution(step6);
+        dumpStatus(callFrames);
+        node.removeBreakpoint(WebInspector.DOMBreakpoint.Types.AttributeModified);
+        InspectorTest.resumeExecution(testRemoveNode.step1);
     }
 
-    function step6()
+    var testRemoveNode = {};
+    testRemoveNode.step1 = function()
     {
         InspectorTest.addResult("Test that 'Node Removed' breakpoint is hit when removing a node.");
-        d1.setBreakpoint(WebInspector.DOMBreakpoint.Types.NodeRemoved);
-        InspectorTest.addResult("Set node removed DOM breakpoint on d1.");
-        InspectorTest.evaluateInConsole("removeElement('d1')");
-        InspectorTest.addResult("Remove d1.");
-        InspectorTest.waitUntilPaused(step7);
+        InspectorTest.evaluateInPageWithTimeout("appendElement('rootElement', 'elementToRemove')", testRemoveNode.step2);
     }
-
-    function step7(callFrames)
+    testRemoveNode.step2 = function()
+    {
+        InspectorTest.addResult("Append elementToRemove to rootElement.");
+        findDOMNodeById("elementToRemove", testRemoveNode.step3);
+    }
+    testRemoveNode.step3 = function(node)
     {
-        InspectorTest.addResult("line: " + callFrames[0].line + ", function: " + callFrames[0].functionName);
-        InspectorTest.resumeExecution(step8);
+        node.setBreakpoint(WebInspector.DOMBreakpoint.Types.NodeRemoved);
+        InspectorTest.addResult("Set 'Node Removed' DOM breakpoint on elementToRemove.");
+        InspectorTest.evaluateInPageWithTimeout("removeElement('elementToRemove')");
+        InspectorTest.addResult("Remove elementToRemove.");
+        InspectorTest.waitUntilPaused(testRemoveNode.step4);
+    }
+    testRemoveNode.step4 = function(callFrames)
+    {
+        dumpStatus(callFrames);
+        InspectorTest.resumeExecution(testReload.step1);
     }
 
-    function step8()
+    var testReload= {};
+    testReload.step1 = function()
     {
         InspectorTest.addResult("Test that DOM breakpoints are persisted between page reloads.");
-        d0.setBreakpoint(WebInspector.DOMBreakpoint.Types.SubtreeModified);
-        InspectorTest.addResult("Set subtree modified DOM breakpoint on d0.");
-        InspectorTest.reloadPage(step9);
+        findDOMNodeById("rootElement", testReload.step2);
     }
-
-    function step9()
+    testReload.step2 = function(node)
     {
-        InspectorTest.evaluateInConsole("appendElement('d0', 'd1')");
-        InspectorTest.addResult("Append d1 to d0.");
-        InspectorTest.waitUntilPaused(step10);
+        node.setBreakpoint(WebInspector.DOMBreakpoint.Types.SubtreeModified);
+        InspectorTest.addResult("Set 'Subtree Modified' DOM breakpoint on rootElement.");
+        InspectorTest.reloadPage(testReload.step3);
     }
-
-    function step10(callFrames)
+    testReload.step3 = function()
     {
-        InspectorTest.addResult("line: " + callFrames[0].line + ", function: " + callFrames[0].functionName);
+        InspectorTest.evaluateInPageWithTimeout("appendElement('rootElement', 'childElement')");
+        InspectorTest.addResult("Append childElement to rootElement.");
+        InspectorTest.waitUntilPaused(testReload.step4);
+    }
+    testReload.step4 = function(callFrames)
+    {
+        dumpStatus(callFrames);
         InspectorTest.completeDebuggerTest();
     }
 
@@ -113,6 +155,14 @@ var test = function()
             return node.getAttribute("id") === id;
         }, callback);
     }
+
+    function dumpStatus(callFrames)
+    {
+        InspectorTest.captureStackTrace(callFrames);
+        InspectorTest.addResult(WebInspector.panels.scripts.sidebarPanes.callstack.bodyElement.lastChild.innerText);
+    }
+
+    InspectorTest.startDebuggerTest(testInsertChild.step1);
 };
 
 </script>
@@ -122,7 +172,7 @@ var test = function()
 <p>
 Tests DOM breakpoints. <a href="https://bugs.webkit.org/show_bug.cgi?id=42886">Bug 42886</a>
 </p>
-<div id="d0"></div>
+<div id="rootElement"></div>
 </body>
 </html>
 
index 049529d..9d0fe71 100644 (file)
@@ -1,3 +1,35 @@
+2010-09-14  Pavel Podivilov  <podivilov@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: show status message below call stack when debugger is paused on DOM breakpoint
+        https://bugs.webkit.org/show_bug.cgi?id=45114
+
+        * English.lproj/localizedStrings.js:
+        * inspector/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::performSearch):
+        (WebCore::InspectorDOMAgent::shouldBreakOnNodeInsertion):
+        (WebCore::InspectorDOMAgent::shouldBreakOnNodeRemoval):
+        (WebCore::InspectorDOMAgent::shouldBreakOnAttributeModification):
+        (WebCore::InspectorDOMAgent::descriptionForDOMEvent):
+        * inspector/InspectorDOMAgent.h:
+        * inspector/InspectorDebuggerAgent.cpp:
+        (WebCore::InspectorDebuggerAgent::didPause):
+        * inspector/front-end/CallStackSidebarPane.js:
+        (WebInspector.CallStackSidebarPane):
+        (WebInspector.CallStackSidebarPane.prototype.updateStatus.formatters.s):
+        (WebInspector.CallStackSidebarPane.prototype.updateStatus.append):
+        (WebInspector.CallStackSidebarPane.prototype.updateStatus):
+        * inspector/front-end/ElementsPanel.js:
+        (WebInspector.ElementsPanel.prototype.linkifyNodeById):
+        * inspector/front-end/ScriptsPanel.js:
+        (WebInspector.ScriptsPanel.prototype.debuggerPaused):
+        * inspector/front-end/inspector.css:
+        (.pane > .body .placard + .info):
+        * inspector/front-end/inspector.js:
+        (WebInspector.pausedScript):
+        (WebInspector.formatLocalized):
+
 2010-09-17  Johnny Ding  <jnd@chromium.org>
 
         Reviewed by Adam Barth.
index eedf225..a3720e2 100644 (file)
Binary files a/WebCore/English.lproj/localizedStrings.js and b/WebCore/English.lproj/localizedStrings.js differ
index 36b448f..f1df5b0 100644 (file)
@@ -708,7 +708,7 @@ void InspectorDOMAgent::performSearch(const String& whitespaceTrimmedQuery, bool
             m_pendingMatchJobs.append(new MatchPlainTextJob(document, escapedQuery));
             continue;
         }
-            
+
         m_pendingMatchJobs.append(new MatchExactIdJob(document, whitespaceTrimmedQuery));
         m_pendingMatchJobs.append(new MatchExactClassNamesJob(document, whitespaceTrimmedQuery));
         m_pendingMatchJobs.append(new MatchExactTagNamesJob(document, tagNameQuery));
@@ -777,38 +777,70 @@ void InspectorDOMAgent::removeDOMBreakpoint(long nodeId, long type)
 
 bool InspectorDOMAgent::shouldBreakOnNodeInsertion(Node*, Node* parent, PassRefPtr<InspectorValue>* details)
 {
-    if (!hasBreakpoint(parent, SubtreeModified))
-        return false;
-    RefPtr<InspectorObject> detailsObject = InspectorObject::create();
-    detailsObject->setObject("breakpoint", createBreakpoint(parent, SubtreeModified));
-    *details = detailsObject;
-    return true;
+    if (hasBreakpoint(parent, SubtreeModified)) {
+        *details = descriptionForDOMEvent(parent, SubtreeModified, true);
+        return true;
+    }
+    return false;
 }
 
 bool InspectorDOMAgent::shouldBreakOnNodeRemoval(Node* node, PassRefPtr<InspectorValue>* details)
 {
-    bool hasNodeRemovedBreakpoint = hasBreakpoint(node, NodeRemoved);
-    bool hasAnyBreakpoint = hasNodeRemovedBreakpoint || hasBreakpoint(innerParentNode(node), SubtreeModified);
-    if (!hasAnyBreakpoint)
-        return false;
-
-    RefPtr<InspectorObject> detailsObject = InspectorObject::create();
-    if (hasNodeRemovedBreakpoint)
-        detailsObject->setObject("breakpoint", createBreakpoint(node, NodeRemoved));
-    else
-        detailsObject->setObject("breakpoint", createBreakpoint(innerParentNode(node), SubtreeModified));
-    *details = detailsObject;
-    return true;
+    if (hasBreakpoint(node, NodeRemoved)) {
+        *details = descriptionForDOMEvent(node, NodeRemoved, false);
+        return true;
+    }
+    if (hasBreakpoint(innerParentNode(node), SubtreeModified)) {
+        *details = descriptionForDOMEvent(node, SubtreeModified, false);
+        return true;
+    }
+    return false;
 }
 
 bool InspectorDOMAgent::shouldBreakOnAttributeModification(Element* element, PassRefPtr<InspectorValue>* details)
 {
-    if (!hasBreakpoint(element, AttributeModified))
-        return false;
-    RefPtr<InspectorObject> detailsObject = InspectorObject::create();
-    detailsObject->setObject("breakpoint", createBreakpoint(element, AttributeModified));
-    *details = detailsObject;
-    return true;
+    if (hasBreakpoint(element, AttributeModified)) {
+        *details = descriptionForDOMEvent(element, AttributeModified, false);
+        return true;
+    }
+    return false;
+}
+
+PassRefPtr<InspectorValue> InspectorDOMAgent::descriptionForDOMEvent(Node* target, long breakpointType, bool insertion)
+{
+    ASSERT(hasBreakpoint(target, breakpointType));
+
+    RefPtr<InspectorObject> description = InspectorObject::create();
+    Node* breakpointOwner = target;
+    if ((1 << breakpointType) & inheritableDOMBreakpointTypesMask) {
+        // For inheritable breakpoint types, target node isn't always the same as the node that owns a breakpoint.
+        // Target node may be unknown to frontend, so we need to push it first.
+        long targetNodeId = pushNodePathToFrontend(target);
+        ASSERT(targetNodeId);
+        description->setNumber("targetNodeId", targetNodeId);
+
+        // Find breakpoint owner node.
+        if (!insertion)
+            breakpointOwner = innerParentNode(target);
+        ASSERT(breakpointOwner);
+        while (!(m_breakpoints.get(breakpointOwner) & (1 << breakpointType))) {
+            breakpointOwner = innerParentNode(breakpointOwner);
+            ASSERT(breakpointOwner);
+        }
+
+        if (breakpointType == SubtreeModified)
+            description->setBoolean("insertion", insertion);
+    }
+
+    long breakpointOwnerNodeId = m_documentNodeToIdMap.get(breakpointOwner);
+    ASSERT(breakpointOwnerNodeId);
+
+    RefPtr<InspectorObject> breakpoint = InspectorObject::create();
+    breakpoint->setNumber("nodeId", breakpointOwnerNodeId);
+    breakpoint->setNumber("type", breakpointType);
+    description->setObject("breakpoint", breakpoint);
+
+    return description;
 }
 
 String InspectorDOMAgent::documentURLString(Document* document) const
@@ -1088,23 +1120,6 @@ void InspectorDOMAgent::didModifyDOMAttr(Element* element)
     m_frontend->attributesUpdated(id, buildArrayForElementAttributes(element));
 }
 
-PassRefPtr<InspectorObject> InspectorDOMAgent::createBreakpoint(Node* node, long type)
-{
-    RefPtr<InspectorObject> breakpoint = InspectorObject::create();
-
-    // Find breakpoint owner.
-    while (!(m_breakpoints.get(node) & (1 << type))) {
-        node = innerParentNode(node);
-        ASSERT(node);
-    }
-    long nodeId = m_documentNodeToIdMap.get(node);
-    ASSERT(nodeId);
-
-    breakpoint->setNumber("nodeId", nodeId);
-    breakpoint->setNumber("type", type);
-    return breakpoint.release();
-}
-
 bool InspectorDOMAgent::hasBreakpoint(Node* node, long type)
 {
     uint32_t rootBit = 1 << type;
index 7a9f6bc..7d86997 100644 (file)
@@ -161,8 +161,8 @@ namespace WebCore {
         bool pushDocumentToFrontend();
 
         bool hasBreakpoint(Node* node, long type);
-        PassRefPtr<InspectorObject> createBreakpoint(Node* node, long type);
         void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value);
+        PassRefPtr<InspectorValue> descriptionForDOMEvent(Node* target, long breakpointType, bool insertion);
 
         PassRefPtr<InspectorObject> buildObjectForAttributeStyles(Element* element);
         PassRefPtr<InspectorArray> buildArrayForCSSRules(Document* ownerDocument, CSSRuleList*);
index a111197..3875be0 100644 (file)
@@ -293,7 +293,7 @@ void InspectorDebuggerAgent::didPause(ScriptState* scriptState)
     m_pausedScriptState = scriptState;
     RefPtr<InspectorObject> details = InspectorObject::create();
     details->setValue("callFrames", currentCallFrames());
-    details->setValue("reason", m_breakProgramReason);
+    details->setValue("status", m_breakProgramReason);
     m_frontend->pausedScript(details);
 }
 
index 60eee34..91f35a6 100644 (file)
@@ -26,7 +26,6 @@
 WebInspector.CallStackSidebarPane = function()
 {
     WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
-    
 }
 
 WebInspector.CallStackSidebarPane.prototype = {
@@ -83,6 +82,39 @@ WebInspector.CallStackSidebarPane.prototype = {
         }
     },
 
+    updateStatus:  function(status)
+    {
+        var statusElement = document.createElement("div");
+        statusElement.className = "info";
+
+        var breakpointType = status.breakpoint.type;
+        var substitutions = [WebInspector.DOMBreakpoint.labelForType(breakpointType), WebInspector.panels.elements.linkifyNodeById(status.breakpoint.nodeId)];
+        var formatters = {
+            s: function(substitution)
+            {
+                return substitution;
+            }
+        };
+        function append(a, b)
+        {
+            if (typeof b === "string")
+                b = document.createTextNode(b);
+            statusElement.appendChild(b);
+        }
+        if (breakpointType === WebInspector.DOMBreakpoint.Types.SubtreeModified) {
+            var targetNode = WebInspector.panels.elements.linkifyNodeById(status.targetNodeId);
+            if (status.insertion) {
+                if (status.targetNodeId !== status.breakpoint.nodeId)
+                    WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", substitutions.concat(targetNode), formatters, "", append);
+                else
+                    WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.", substitutions, formatters, "", append);
+            } else
+                WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", substitutions.concat(targetNode), formatters, "", append);
+        } else
+            WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s.", substitutions, formatters, "", append);
+        this.bodyElement.appendChild(statusElement);
+    },
+
     get selectedCallFrame()
     {
         return this._selectedCallFrame;
index 728c48e..9cff3a7 100644 (file)
@@ -783,6 +783,14 @@ WebInspector.ElementsPanel.prototype = {
         return link;
     },
 
+    linkifyNodeById: function(nodeId)
+    {
+        var node = WebInspector.domAgent.nodeForId(nodeId);
+        if (!node)
+            return document.createTextNode(WebInspector.UIString("<node>"));
+        return this.linkifyNodeReference(node);
+    },
+
     updateBreadcrumbSizes: function(focusedCrumb)
     {
         if (!this.visible)
index c5267f7..715339d 100644 (file)
@@ -375,7 +375,7 @@ WebInspector.ScriptsPanel.prototype = {
         InjectedScriptAccess.get(callFrame.worldId).evaluateInCallFrame(callFrame.id, code, objectGroup, evalCallback);
     },
 
-    debuggerPaused: function(callFrames)
+    debuggerPaused: function(details)
     {
         WebInspector.breakpointManager.removeOneTimeBreakpoint();
         this._paused = true;
@@ -384,8 +384,11 @@ WebInspector.ScriptsPanel.prototype = {
 
         this._updateDebuggerButtons();
 
-        this.sidebarPanes.callstack.update(callFrames, this._sourceIDMap);
-        this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
+        this.sidebarPanes.callstack.update(details.callFrames, this._sourceIDMap);
+        this.sidebarPanes.callstack.selectedCallFrame = details.callFrames[0];
+
+        if (details.status)
+            this.sidebarPanes.callstack.updateStatus(details.status);
 
         WebInspector.currentPanel = this;
         window.focus();
index 2823418..6d8571c 100644 (file)
@@ -1693,6 +1693,10 @@ li.editing .swatch, li.editing .enabled-button,  li.editing-sub-part .delete-but
     color: gray;
 }
 
+.pane > .body .placard + .info {
+    border-top: 1px solid gray
+}
+
 .pane.expanded > .body, .pane.expanded > .growbar {
     display: block;
 }
index 704f16a..ac3f3fc 100644 (file)
@@ -1430,7 +1430,7 @@ WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLin
 
 WebInspector.pausedScript = function(details)
 {
-    this.panels.scripts.debuggerPaused(details.callFrames);
+    this.panels.scripts.debuggerPaused(details);
     InspectorFrontendHost.bringToFront();
 }
 
@@ -2012,6 +2012,11 @@ WebInspector.UIString = function(string)
     return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
 }
 
+WebInspector.formatLocalized = function(format, substitutions, formatters, initialValue, append)
+{
+    return String.format(WebInspector.UIString(format), substitutions, formatters, initialValue, append);
+}
+
 WebInspector.isMac = function()
 {
     if (!("_isMac" in this))