Changeset 65731 in webkit


Ignore:
Timestamp:
Aug 20, 2010 6:38:14 AM (14 years ago)
Author:
yurys@chromium.org
Message:

2010-08-19 Pavel Podivilov <podivilov@chromium.org>

Reviewed by Yury Semikhatsky.

Web Inspector: implement breaking on DOM node subtree mutations.
https://bugs.webkit.org/show_bug.cgi?id=42886

Add two entries to Web Inspector DOM element context menu:

  1. "Stop on subtree modifications": will break on adding/removing of any element which is a child of the DOM element
  2. "Remove breakpoints": will remove all breakpoints associated with the DOM element
  • English.lproj/localizedStrings.js:
  • bindings/js/ScriptDebugServer.cpp: (WebCore::ScriptDebugServer::breakProgram):
  • bindings/js/ScriptDebugServer.h:
  • bindings/v8/ScriptDebugServer.cpp: (WebCore::ScriptDebugServer::breakProgram): (WebCore::ScriptDebugServer::breakProgramCallback): (WebCore::ScriptDebugServer::handleV8DebugEvent):
  • bindings/v8/ScriptDebugServer.h:
  • inspector/Inspector.idl:
  • inspector/InspectorDOMAgent.cpp: (WebCore::InspectorDOMAgent::~InspectorDOMAgent): (WebCore::InspectorDOMAgent::discardBindings): (WebCore::InspectorDOMAgent::setDOMBreakpoint): (WebCore::InspectorDOMAgent::removeDOMBreakpoint): (WebCore::InspectorDOMAgent::didInsertDOMNode): (WebCore::InspectorDOMAgent::didRemoveDOMNode): (WebCore::InspectorDOMAgent::hasBreakpoint): (WebCore::InspectorDOMAgent::pauseOnBreakpoint): (WebCore::InspectorDOMAgent::updateSubtreeBreakpoints):
  • inspector/InspectorDOMAgent.h:
  • inspector/front-end/ElementsTreeOutline.js: (WebInspector.ElementsTreeElement.prototype._populateTagContextMenu):
  • inspector/front-end/Settings.js:

2010-08-19 Pavel Podivilov <podivilov@chromium.org>

Reviewed by Yury Semikhatsky.

Web Inspector: enable DOM breakpoints for chromium
https://bugs.webkit.org/show_bug.cgi?id=42886

Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r65730 r65731  
     12010-08-19  Pavel Podivilov  <podivilov@chromium.org>
     2
     3        Reviewed by Yury Semikhatsky.
     4
     5        Web Inspector: implement breaking on DOM node subtree mutations.
     6        https://bugs.webkit.org/show_bug.cgi?id=42886
     7
     8        Add two entries to Web Inspector DOM element context menu:
     9        1. "Stop on subtree modifications": will break on adding/removing of any element which is a child of the DOM element
     10        2. "Remove breakpoints": will remove all breakpoints associated with the DOM element
     11
     12        * English.lproj/localizedStrings.js:
     13        * bindings/js/ScriptDebugServer.cpp:
     14        (WebCore::ScriptDebugServer::breakProgram):
     15        * bindings/js/ScriptDebugServer.h:
     16        * bindings/v8/ScriptDebugServer.cpp:
     17        (WebCore::ScriptDebugServer::breakProgram):
     18        (WebCore::ScriptDebugServer::breakProgramCallback):
     19        (WebCore::ScriptDebugServer::handleV8DebugEvent):
     20        * bindings/v8/ScriptDebugServer.h:
     21        * inspector/Inspector.idl:
     22        * inspector/InspectorDOMAgent.cpp:
     23        (WebCore::InspectorDOMAgent::~InspectorDOMAgent):
     24        (WebCore::InspectorDOMAgent::discardBindings):
     25        (WebCore::InspectorDOMAgent::setDOMBreakpoint):
     26        (WebCore::InspectorDOMAgent::removeDOMBreakpoint):
     27        (WebCore::InspectorDOMAgent::didInsertDOMNode):
     28        (WebCore::InspectorDOMAgent::didRemoveDOMNode):
     29        (WebCore::InspectorDOMAgent::hasBreakpoint):
     30        (WebCore::InspectorDOMAgent::pauseOnBreakpoint):
     31        (WebCore::InspectorDOMAgent::updateSubtreeBreakpoints):
     32        * inspector/InspectorDOMAgent.h:
     33        * inspector/front-end/ElementsTreeOutline.js:
     34        (WebInspector.ElementsTreeElement.prototype._populateTagContextMenu):
     35        * inspector/front-end/Settings.js:
     36
    1372010-08-20  Yury Semikhatsky  <yurys@chromium.org>
    238
  • trunk/WebCore/bindings/js/ScriptDebugServer.cpp

    r65505 r65731  
    206206}
    207207
     208void ScriptDebugServer::breakProgram()
     209{
     210    // FIXME(WK43332): implement this.
     211}
     212
    208213void ScriptDebugServer::continueProgram()
    209214{
  • trunk/WebCore/bindings/js/ScriptDebugServer.h

    r63309 r65731  
    8080
    8181    void pause();
     82    void breakProgram();
    8283    void continueProgram();
    8384    void stepIntoStatement();
  • trunk/WebCore/bindings/v8/ScriptDebugServer.cpp

    r65304 r65731  
    229229}
    230230
     231void ScriptDebugServer::breakProgram()
     232{
     233    DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, callbackTemplate, ());
     234
     235    if (!v8::Context::InContext())
     236        return;
     237
     238    if (callbackTemplate.IsEmpty()) {
     239        callbackTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
     240        callbackTemplate->SetCallHandler(&ScriptDebugServer::breakProgramCallback);
     241    }
     242
     243    v8::Handle<v8::Context> context = v8::Context::GetCurrent();
     244    if (context.IsEmpty())
     245        return;
     246
     247    m_pausedPageContext = *context;
     248    v8::Handle<v8::Function> breakProgramFunction = callbackTemplate->GetFunction();
     249    v8::Debug::Call(breakProgramFunction);
     250    m_pausedPageContext.Clear();
     251}
     252
    231253void ScriptDebugServer::continueProgram()
    232254{
     
    322344{
    323345    v8::Debug::ProcessDebugMessages();
     346}
     347
     348v8::Handle<v8::Value> ScriptDebugServer::breakProgramCallback(const v8::Arguments& args)
     349{
     350    ASSERT(2 == args.Length());
     351    ScriptDebugServer::shared().breakProgram(v8::Handle<v8::Object>::Cast(args[0]));
     352    return v8::Undefined();
     353}
     354
     355void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState)
     356{
     357    // Don't allow nested breaks.
     358    if (m_pausedPage)
     359        return;
     360
     361    Frame* frame = retrieveFrame(m_pausedPageContext);
     362    if (!frame)
     363        return;
     364
     365    ScriptDebugListener* listener = m_listenersMap.get(frame->page());
     366    if (!listener)
     367        return;
     368
     369    m_executionState.set(executionState);
     370    m_pausedPage = frame->page();
     371    ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedPageContext);
     372    listener->didPause(currentCallFrameState);
     373
     374    // Wait for continue or step command.
     375    m_clientMessageLoop->run(m_pausedPage);
     376    ASSERT(!m_pausedPage);
     377
     378    // The listener may have been removed in the nested loop.
     379    if (ScriptDebugListener* listener = m_listenersMap.get(frame->page()))
     380        listener->didContinue();
    324381}
    325382
     
    366423                }
    367424
    368                 // Don't allow nested breaks.
    369                 if (m_pausedPage)
    370                     return;
    371                 m_executionState.set(eventDetails.GetExecutionState());
    372                 m_pausedPage = frame->page();
    373                 ScriptState* currentCallFrameState = mainWorldScriptState(frame);
    374                 listener->didPause(currentCallFrameState);
    375 
    376                 // Wait for continue or step command.
    377                 m_clientMessageLoop->run(m_pausedPage);
    378                 ASSERT(!m_pausedPage);
    379 
    380                 // The listener may have been removed in the nested loop.
    381                 if (ScriptDebugListener* listener = m_listenersMap.get(frame->page()))
    382                     listener->didContinue();
     425                m_pausedPageContext = *eventContext;
     426                breakProgram(eventDetails.GetExecutionState());
     427                m_pausedPageContext.Clear();
    383428            }
    384429        }
  • trunk/WebCore/bindings/v8/ScriptDebugServer.h

    r65304 r65731  
    7272
    7373    void pause();
     74    void breakProgram();
    7475    void continueProgram();
    7576    void stepIntoStatement();
     
    112113    ~ScriptDebugServer() { }
    113114
     115    static v8::Handle<v8::Value> breakProgramCallback(const v8::Arguments& args);
     116    void breakProgram(v8::Handle<v8::Object> executionState);
     117
    114118    static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails);
    115119    void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails);
     
    129133    OwnPtr<ClientMessageLoop> m_clientMessageLoop;
    130134    Page* m_pausedPage;
     135    v8::Local<v8::Context> m_pausedPageContext;
    131136    bool m_enabled;
    132137};
  • trunk/WebCore/inspector/Inspector.idl

    r65412 r65731  
    177177        [handler=DOM] void searchCanceled();
    178178        [handler=DOM] void pushNodeByPathToFrontend(in long callId, in String path, out long nodeId);
     179        [handler=DOM] void setDOMBreakpoint(in long nodeId, in long type);
     180        [handler=DOM] void removeDOMBreakpoint(in long nodeId, in long type);
    179181
    180182        [handler=Controller] void clearConsoleMessages();
  • trunk/WebCore/inspector/InspectorDOMAgent.cpp

    r65468 r65731  
    6363#include "RenderStyle.h"
    6464#include "RenderStyleConstants.h"
     65#include "ScriptDebugServer.h"
    6566#include "ScriptEventListener.h"
    6667#include "StyleSheetList.h"
     
    197198};
    198199
    199 }
     200enum DOMBreakpointType {
     201    DOMBreakpointTypeSubtreeModified = 0
     202};
     203
     204const int domBreakpointDerivedTypeShift = 16;
     205
     206}
     207
     208InspectorDOMAgent* InspectorDOMAgent::s_domAgentOnBreakpoint = 0;
    200209
    201210InspectorDOMAgent::InspectorDOMAgent(InspectorCSSStore* cssStore, RemoteInspectorFrontend* frontend)
     
    211220{
    212221    reset();
     222
     223    if (this == s_domAgentOnBreakpoint)
     224        s_domAgentOnBreakpoint = 0;
    213225}
    214226
     
    372384    m_childrenRequested.clear();
    373385    m_inspectedNodes.clear();
     386    m_breakpoints.clear();
    374387}
    375388
     
    721734}
    722735
     736void InspectorDOMAgent::setDOMBreakpoint(long nodeId, long type)
     737{
     738    Node* node = nodeForId(nodeId);
     739    if (!node)
     740        return;
     741
     742    uint32_t rootBit = 1 << type;
     743    m_breakpoints.set(node, m_breakpoints.get(node) | rootBit);
     744    for (Node* child = innerFirstChild(node); child; child = innerNextSibling(child))
     745        updateSubtreeBreakpoints(child, rootBit, true);
     746}
     747
     748void InspectorDOMAgent::removeDOMBreakpoint(long nodeId, long type)
     749{
     750    Node* node = nodeForId(nodeId);
     751    if (!node)
     752        return;
     753
     754    uint32_t rootBit = 1 << type;
     755    uint32_t mask = m_breakpoints.get(node) & ~rootBit;
     756    if (mask)
     757        m_breakpoints.set(node, mask);
     758    else
     759        m_breakpoints.remove(node);
     760    if (mask & (rootBit << domBreakpointDerivedTypeShift))
     761        return;
     762
     763    for (Node* child = innerFirstChild(node); child; child = innerNextSibling(child))
     764        updateSubtreeBreakpoints(child, rootBit, false);
     765}
     766
    723767String InspectorDOMAgent::documentURLString(Document* document) const
    724768{
     
    921965        return;
    922966
     967    if (m_breakpoints.size()) {
     968        Node* parent = innerParentNode(node);
     969        if (hasBreakpoint(parent, DOMBreakpointTypeSubtreeModified)) {
     970            if (!pauseOnBreakpoint())
     971                return;
     972        }
     973        uint32_t mask = m_breakpoints.get(parent);
     974        mask = mask | (mask >> domBreakpointDerivedTypeShift) & ((1 << domBreakpointDerivedTypeShift) - 1);
     975        updateSubtreeBreakpoints(node, mask, true);
     976    }
     977
    923978    // We could be attaching existing subtree. Forget the bindings.
    924979    unbind(node, &m_documentNodeToIdMap);
     
    9471002        return;
    9481003
     1004    if (m_breakpoints.size()) {
     1005        if (hasBreakpoint(innerParentNode(node), DOMBreakpointTypeSubtreeModified)) {
     1006            if (!pauseOnBreakpoint())
     1007                return;
     1008        }
     1009        // Remove subtree breakpoints.
     1010        m_breakpoints.remove(node);
     1011        Vector<Node*> stack(1, innerFirstChild(node));
     1012        do {
     1013            Node* node = stack.last();
     1014            stack.removeLast();
     1015            if (!node)
     1016                continue;
     1017            m_breakpoints.remove(node);
     1018            stack.append(innerFirstChild(node));
     1019            stack.append(innerNextSibling(node));
     1020        } while (!stack.isEmpty());
     1021    }
     1022
    9491023    Node* parent = node->parentNode();
    9501024    long parentId = m_documentNodeToIdMap.get(parent);
     
    9701044
    9711045    m_frontend->attributesUpdated(id, buildArrayForElementAttributes(element));
     1046}
     1047
     1048bool InspectorDOMAgent::hasBreakpoint(Node* node, long type)
     1049{
     1050    uint32_t rootBit = 1 << type;
     1051    uint32_t derivedBit = rootBit << domBreakpointDerivedTypeShift;
     1052    return m_breakpoints.get(node) & (rootBit | derivedBit);
     1053}
     1054
     1055bool InspectorDOMAgent::pauseOnBreakpoint()
     1056{
     1057#if ENABLE(JAVASCRIPT_DEBUGGER)
     1058    s_domAgentOnBreakpoint = this;
     1059    ScriptDebugServer::shared().breakProgram();
     1060    bool deleted = !s_domAgentOnBreakpoint;
     1061    s_domAgentOnBreakpoint = 0;
     1062    return !deleted;
     1063#endif
     1064}
     1065
     1066void InspectorDOMAgent::updateSubtreeBreakpoints(Node* node, uint32_t rootMask, bool set)
     1067{
     1068    uint32_t oldMask = m_breakpoints.get(node);
     1069    uint32_t derivedMask = rootMask << domBreakpointDerivedTypeShift;
     1070    uint32_t newMask = set ? oldMask | derivedMask : oldMask & ~derivedMask;
     1071    if (newMask)
     1072        m_breakpoints.set(node, newMask);
     1073    else
     1074        m_breakpoints.remove(node);
     1075
     1076    uint32_t newRootMask = rootMask & ~newMask;
     1077    if (!newRootMask)
     1078        return;
     1079
     1080    for (Node* child = innerFirstChild(node); child; child = innerNextSibling(child))
     1081        updateSubtreeBreakpoints(child, newRootMask, set);
    9721082}
    9731083
  • trunk/WebCore/inspector/InspectorDOMAgent.h

    r65077 r65731  
    113113        void performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously);
    114114        void searchCanceled();
     115        void setDOMBreakpoint(long nodeId, long type);
     116        void removeDOMBreakpoint(long nodeId, long type);
    115117
    116118        // Methods called from the frontend for CSS styles inspection.
     
    156158
    157159        bool pushDocumentToFrontend();
     160
     161        bool hasBreakpoint(Node* node, long type);
     162        bool pauseOnBreakpoint();
     163        void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value);
    158164
    159165        PassRefPtr<InspectorObject> buildObjectForAttributeStyles(Element* element);
     
    210216        HashSet<RefPtr<Node> > m_searchResults;
    211217        Vector<long> m_inspectedNodes;
     218        HashMap<Node*, uint32_t> m_breakpoints;
     219
     220        static InspectorDOMAgent* s_domAgentOnBreakpoint;
    212221    };
    213222
  • trunk/WebCore/inspector/front-end/ElementsTreeOutline.js

    r65499 r65731  
    327327].keySet();
    328328
     329WebInspector.ElementsTreeElement.DOMBreakpointTypeSubtreeModified = 0;
     330
    329331WebInspector.ElementsTreeElement.prototype = {
    330332    highlightSearchResults: function(searchQuery)
     
    762764        contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this));
    763765        contextMenu.appendItem(WebInspector.UIString("Delete Node"), this.remove.bind(this));
     766
     767        if (Preferences.domBreakpointsEnabled) {
     768            // Add debbuging-related actions
     769            contextMenu.appendSeparator();
     770            contextMenu.appendItem(WebInspector.UIString("Stop on subtree modifications"),
     771                InspectorBackend.setDOMBreakpoint.bind(InspectorBackend, this.representedObject.id, WebInspector.ElementsTreeElement.DOMBreakpointTypeSubtreeModified));
     772            contextMenu.appendItem(WebInspector.UIString("Remove Breakpoints"),
     773                InspectorBackend.removeDOMBreakpoint.bind(InspectorBackend, this.representedObject.id, WebInspector.ElementsTreeElement.DOMBreakpointTypeSubtreeModified));
     774        }
    764775    },
    765776
  • trunk/WebCore/inspector/front-end/Settings.js

    r64844 r65731  
    4444    profilerAlwaysEnabled: false,
    4545    auditsPanelEnabled: true,
    46     onlineDetectionEnabled: true
     46    onlineDetectionEnabled: true,
     47    domBreakpointsEnabled: false
    4748}
    4849
  • trunk/WebKit/chromium/ChangeLog

    r65726 r65731  
     12010-08-19  Pavel Podivilov  <podivilov@chromium.org>
     2
     3        Reviewed by Yury Semikhatsky.
     4
     5        Web Inspector: enable DOM breakpoints for chromium
     6        https://bugs.webkit.org/show_bug.cgi?id=42886
     7
     8        * src/js/DevTools.js:
     9        (WebInspector.loaded):
     10
    1112010-08-19  Vincent Scheib  <scheib@chromium.org>
    212
  • trunk/WebKit/chromium/src/js/DevTools.js

    r65415 r65731  
    7575    Preferences.canEditScriptSource = true;
    7676    Preferences.onlineDetectionEnabled = false;
     77    Preferences.domBreakpointsEnabled = true;
    7778
    7879    oldLoaded.call(WebInspector);
Note: See TracChangeset for help on using the changeset viewer.