Changeset 65731 in webkit
- Timestamp:
- Aug 20, 2010 6:38:14 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r65730 r65731 1 2010-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 1 37 2010-08-20 Yury Semikhatsky <yurys@chromium.org> 2 38 -
trunk/WebCore/bindings/js/ScriptDebugServer.cpp
r65505 r65731 206 206 } 207 207 208 void ScriptDebugServer::breakProgram() 209 { 210 // FIXME(WK43332): implement this. 211 } 212 208 213 void ScriptDebugServer::continueProgram() 209 214 { -
trunk/WebCore/bindings/js/ScriptDebugServer.h
r63309 r65731 80 80 81 81 void pause(); 82 void breakProgram(); 82 83 void continueProgram(); 83 84 void stepIntoStatement(); -
trunk/WebCore/bindings/v8/ScriptDebugServer.cpp
r65304 r65731 229 229 } 230 230 231 void 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 231 253 void ScriptDebugServer::continueProgram() 232 254 { … … 322 344 { 323 345 v8::Debug::ProcessDebugMessages(); 346 } 347 348 v8::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 355 void 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(); 324 381 } 325 382 … … 366 423 } 367 424 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(); 383 428 } 384 429 } -
trunk/WebCore/bindings/v8/ScriptDebugServer.h
r65304 r65731 72 72 73 73 void pause(); 74 void breakProgram(); 74 75 void continueProgram(); 75 76 void stepIntoStatement(); … … 112 113 ~ScriptDebugServer() { } 113 114 115 static v8::Handle<v8::Value> breakProgramCallback(const v8::Arguments& args); 116 void breakProgram(v8::Handle<v8::Object> executionState); 117 114 118 static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails); 115 119 void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails); … … 129 133 OwnPtr<ClientMessageLoop> m_clientMessageLoop; 130 134 Page* m_pausedPage; 135 v8::Local<v8::Context> m_pausedPageContext; 131 136 bool m_enabled; 132 137 }; -
trunk/WebCore/inspector/Inspector.idl
r65412 r65731 177 177 [handler=DOM] void searchCanceled(); 178 178 [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); 179 181 180 182 [handler=Controller] void clearConsoleMessages(); -
trunk/WebCore/inspector/InspectorDOMAgent.cpp
r65468 r65731 63 63 #include "RenderStyle.h" 64 64 #include "RenderStyleConstants.h" 65 #include "ScriptDebugServer.h" 65 66 #include "ScriptEventListener.h" 66 67 #include "StyleSheetList.h" … … 197 198 }; 198 199 199 } 200 enum DOMBreakpointType { 201 DOMBreakpointTypeSubtreeModified = 0 202 }; 203 204 const int domBreakpointDerivedTypeShift = 16; 205 206 } 207 208 InspectorDOMAgent* InspectorDOMAgent::s_domAgentOnBreakpoint = 0; 200 209 201 210 InspectorDOMAgent::InspectorDOMAgent(InspectorCSSStore* cssStore, RemoteInspectorFrontend* frontend) … … 211 220 { 212 221 reset(); 222 223 if (this == s_domAgentOnBreakpoint) 224 s_domAgentOnBreakpoint = 0; 213 225 } 214 226 … … 372 384 m_childrenRequested.clear(); 373 385 m_inspectedNodes.clear(); 386 m_breakpoints.clear(); 374 387 } 375 388 … … 721 734 } 722 735 736 void 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 748 void 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 723 767 String InspectorDOMAgent::documentURLString(Document* document) const 724 768 { … … 921 965 return; 922 966 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 923 978 // We could be attaching existing subtree. Forget the bindings. 924 979 unbind(node, &m_documentNodeToIdMap); … … 947 1002 return; 948 1003 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 949 1023 Node* parent = node->parentNode(); 950 1024 long parentId = m_documentNodeToIdMap.get(parent); … … 970 1044 971 1045 m_frontend->attributesUpdated(id, buildArrayForElementAttributes(element)); 1046 } 1047 1048 bool 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 1055 bool 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 1066 void 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); 972 1082 } 973 1083 -
trunk/WebCore/inspector/InspectorDOMAgent.h
r65077 r65731 113 113 void performSearch(const String& whitespaceTrimmedQuery, bool runSynchronously); 114 114 void searchCanceled(); 115 void setDOMBreakpoint(long nodeId, long type); 116 void removeDOMBreakpoint(long nodeId, long type); 115 117 116 118 // Methods called from the frontend for CSS styles inspection. … … 156 158 157 159 bool pushDocumentToFrontend(); 160 161 bool hasBreakpoint(Node* node, long type); 162 bool pauseOnBreakpoint(); 163 void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value); 158 164 159 165 PassRefPtr<InspectorObject> buildObjectForAttributeStyles(Element* element); … … 210 216 HashSet<RefPtr<Node> > m_searchResults; 211 217 Vector<long> m_inspectedNodes; 218 HashMap<Node*, uint32_t> m_breakpoints; 219 220 static InspectorDOMAgent* s_domAgentOnBreakpoint; 212 221 }; 213 222 -
trunk/WebCore/inspector/front-end/ElementsTreeOutline.js
r65499 r65731 327 327 ].keySet(); 328 328 329 WebInspector.ElementsTreeElement.DOMBreakpointTypeSubtreeModified = 0; 330 329 331 WebInspector.ElementsTreeElement.prototype = { 330 332 highlightSearchResults: function(searchQuery) … … 762 764 contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this)); 763 765 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 } 764 775 }, 765 776 -
trunk/WebCore/inspector/front-end/Settings.js
r64844 r65731 44 44 profilerAlwaysEnabled: false, 45 45 auditsPanelEnabled: true, 46 onlineDetectionEnabled: true 46 onlineDetectionEnabled: true, 47 domBreakpointsEnabled: false 47 48 } 48 49 -
trunk/WebKit/chromium/ChangeLog
r65726 r65731 1 2010-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 1 11 2010-08-19 Vincent Scheib <scheib@chromium.org> 2 12 -
trunk/WebKit/chromium/src/js/DevTools.js
r65415 r65731 75 75 Preferences.canEditScriptSource = true; 76 76 Preferences.onlineDetectionEnabled = false; 77 Preferences.domBreakpointsEnabled = true; 77 78 78 79 oldLoaded.call(WebInspector);
Note: See TracChangeset
for help on using the changeset viewer.