Changeset 57660 in webkit
- Timestamp:
- Apr 15, 2010 11:40:34 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r57659 r57660 1 2010-04-15 Yury Semikhatsky <yurys@google.com> 2 3 Reviewed by Pavel Feldman. 4 5 Support basic debugging capabilities including step in/over/out in v8 6 implementation of ScriptDebugServer. 7 8 https://bugs.webkit.org/show_bug.cgi?id=37604 9 10 * bindings/js/JSInjectedScriptHostCustom.cpp: 11 (WebCore::InjectedScriptHost::createInjectedScript): 12 * bindings/v8/ScriptDebugServer.cpp: 13 (WebCore::ScriptDebugServer::ScriptDebugServer): 14 (WebCore::ScriptDebugServer::setDebuggerScriptSource): 15 (WebCore::ScriptDebugServer::addListener): 16 (WebCore::ScriptDebugServer::removeListener): 17 (WebCore::ScriptDebugServer::setBreakpoint): 18 (WebCore::ScriptDebugServer::removeBreakpoint): 19 (WebCore::ScriptDebugServer::clearBreakpoints): 20 (WebCore::ScriptDebugServer::setBreakpointsActivated): 21 (WebCore::ScriptDebugServer::continueProgram): 22 (WebCore::ScriptDebugServer::stepIntoStatement): 23 (WebCore::ScriptDebugServer::stepOverStatement): 24 (WebCore::ScriptDebugServer::stepOutOfFunction): 25 (WebCore::ScriptDebugServer::currentCallFrameState): 26 (WebCore::ScriptDebugServer::currentCallFrameV8): 27 (WebCore::ScriptDebugServer::onV8DebugMessage): 28 (WebCore::ScriptDebugServer::onV8DebugHostDispatch): 29 (WebCore::ScriptDebugServer::handleV8DebugHostDispatch): 30 (WebCore::ScriptDebugServer::handleV8DebugMessage): 31 (WebCore::ScriptDebugServer::dispatchDidParseSource): 32 (WebCore::ScriptDebugServer::ensureDebuggerScriptCompiled): 33 (WebCore::ScriptDebugServer::didResume): 34 * bindings/v8/ScriptDebugServer.h: 35 (WebCore::ScriptDebugServer::pauseOnExceptionsState): 36 (WebCore::ScriptDebugServer::setPauseOnExceptionsState): 37 (WebCore::ScriptDebugServer::setMessageLoopDispatchHandler): 38 * bindings/v8/custom/V8InjectedScriptHostCustom.cpp: 39 (WebCore::InjectedScriptHost::createInjectedScript): 40 (WebCore::V8InjectedScriptHost::currentCallFrameCallback): 41 (WebCore::V8InjectedScriptHost::isActivationCallback): 42 * inspector/front-end/InjectedScript.js: 43 (injectedScriptConstructor): 44 (injectedScriptConstructor.): 45 * inspector/front-end/ScriptsPanel.js: 46 (WebInspector.ScriptsPanel): 47 1 48 2010-04-15 Nikolas Zimmermann <nzimmermann@rim.com> 2 49 -
trunk/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp
r56841 r57660 96 96 args.append(globalThisValue); 97 97 args.append(jsNumber(scriptState, id)); 98 args.append(jsString(scriptState, String("JSC"))); 98 99 JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); 99 100 if (result.isObject()) -
trunk/WebCore/bindings/v8/ScriptDebugServer.cpp
r57231 r57660 34 34 #if ENABLE(JAVASCRIPT_DEBUGGER) 35 35 36 #include "Frame.h" 37 #include "Page.h" 38 #include "ScriptDebugListener.h" 36 39 #include "V8Binding.h" 37 #include <v8-debug.h>38 40 #include "V8DOMWindow.h" 41 #include "V8Proxy.h" 39 42 #include <wtf/StdLibExtras.h> 40 43 … … 42 45 43 46 v8::Persistent<v8::Context> ScriptDebugServer::s_utilityContext; 47 48 ScriptDebugServer::MessageLoopDispatchHandler ScriptDebugServer::s_messageLoopDispatchHandler = 0; 44 49 45 50 ScriptDebugServer& ScriptDebugServer::shared() … … 47 52 DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ()); 48 53 return server; 54 } 55 56 ScriptDebugServer::ScriptDebugServer() 57 : m_pauseOnExceptionsState(DontPauseOnExceptions) 58 , m_currentCallFrameState(0) 59 { 60 } 61 62 void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource) 63 { 64 m_debuggerScriptSource = scriptSource; 65 } 66 67 void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) 68 { 69 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 70 v8::HandleScope scope; 71 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 72 v8::Context::Scope contextScope(debuggerContext); 73 74 if (!m_listenersMap.size()) { 75 ensureDebuggerScriptCompiled(); 76 ASSERT(!m_debuggerScript->IsUndefined()); 77 v8::Debug::SetMessageHandler2(&ScriptDebugServer::onV8DebugMessage); 78 v8::Debug::SetHostDispatchHandler(&ScriptDebugServer::onV8DebugHostDispatch, 100 /* ms */); 79 } 80 m_listenersMap.set(page, listener); 81 V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); 82 v8::Local<v8::Context> context = proxy->mainWorldContext(); 83 String contextData = toWebCoreStringWithNullCheck(context->GetData()); 84 m_contextDataMap.set(listener, contextData); 85 86 v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("getScripts"))); 87 v8::Handle<v8::Value> value = v8::Debug::Call(getScriptsFunction); 88 if (value.IsEmpty()) 89 return; 90 ASSERT(!value->IsUndefined() && value->IsArray()); 91 v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); 92 for (unsigned i = 0; i < scriptsArray->Length(); ++i) 93 dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); 94 #endif 95 } 96 97 void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) 98 { 99 if (!m_listenersMap.contains(page)) 100 return; 101 102 m_listenersMap.remove(page); 103 104 if (m_listenersMap.isEmpty()) { 105 v8::Debug::SetMessageHandler2(0); 106 v8::Debug::SetHostDispatchHandler(0); 107 } 108 // FIXME: Remove all breakpoints set by the agent. 109 // FIXME: Force continue if detach happened in nessted message loop while 110 // debugger was paused on a breakpoint(as long as there are other 111 // attached agents v8 will wait for explicit'continue' message). 112 // FIXME: send continue command to v8 if necessary; 113 } 114 115 void ScriptDebugServer::setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint) 116 { 117 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 118 v8::HandleScope scope; 119 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 120 v8::Context::Scope contextScope(debuggerContext); 121 122 v8::Local<v8::Object> args = v8::Object::New(); 123 args->Set(v8::String::New("scriptId"), v8String(sourceID)); 124 args->Set(v8::String::New("lineNumber"), v8::Integer::New(lineNumber)); 125 args->Set(v8::String::New("condition"), v8String(breakpoint.condition)); 126 args->Set(v8::String::New("enabled"), v8::Boolean::New(breakpoint.enabled)); 127 128 v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("setBreakpoint"))); 129 v8::Debug::Call(setBreakpointFunction, args); 130 #endif 131 } 132 133 void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNumber) 134 { 135 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 136 v8::HandleScope scope; 137 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 138 v8::Context::Scope contextScope(debuggerContext); 139 140 v8::Local<v8::Object> args = v8::Object::New(); 141 args->Set(v8::String::New("scriptId"), v8String(sourceID)); 142 args->Set(v8::String::New("lineNumber"), v8::Integer::New(lineNumber)); 143 144 v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("removeBreakpoint"))); 145 v8::Debug::Call(removeBreakpointFunction, args); 146 #endif 147 } 148 149 void ScriptDebugServer::clearBreakpoints() 150 { 151 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 152 ensureDebuggerScriptCompiled(); 153 v8::HandleScope scope; 154 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 155 v8::Context::Scope contextScope(debuggerContext); 156 157 v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("clearBreakpoints"))); 158 v8::Debug::Call(setBreakpointsActivated); 159 #endif 160 } 161 162 void ScriptDebugServer::setBreakpointsActivated(bool enabled) 163 { 164 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 165 ensureDebuggerScriptCompiled(); 166 v8::HandleScope scope; 167 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 168 v8::Context::Scope contextScope(debuggerContext); 169 170 v8::Local<v8::Object> args = v8::Object::New(); 171 args->Set(v8::String::New("enabled"), v8::Boolean::New(enabled)); 172 v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("setBreakpointsActivated"))); 173 v8::Debug::Call(setBreakpointsActivated, args); 174 #endif 175 } 176 177 void ScriptDebugServer::continueProgram() 178 { 179 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 180 String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\"}"); 181 v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); 182 didResume(); 183 #endif 184 } 185 186 void ScriptDebugServer::stepIntoStatement() 187 { 188 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 189 String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"in\"}}"); 190 v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); 191 didResume(); 192 #endif 193 } 194 195 void ScriptDebugServer::stepOverStatement() 196 { 197 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 198 String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"next\"}}"); 199 v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); 200 didResume(); 201 #endif 202 } 203 204 void ScriptDebugServer::stepOutOfFunction() 205 { 206 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 207 String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"out\"}}"); 208 v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); 209 didResume(); 210 #endif 211 } 212 213 ScriptState* ScriptDebugServer::currentCallFrameState() 214 { 215 return m_currentCallFrameState; 216 } 217 218 v8::Handle<v8::Value> ScriptDebugServer::currentCallFrameV8() 219 { 220 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 221 if (!m_currentCallFrame.IsEmpty()) 222 return m_currentCallFrame; 223 224 // Check on a bp. 225 v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("currentCallFrame"))); 226 v8::Handle<v8::Value> argv[] = { m_executionState }; 227 v8::Handle<v8::Value> result = currentCallFrameFunction->Call(m_debuggerScript, 1, argv); 228 m_currentCallFrame = v8::Persistent<v8::Value>::New(result); 229 return result; 230 #else 231 return v8::Handle<v8::Value>(); 232 #endif 233 } 234 235 void ScriptDebugServer::onV8DebugMessage(const v8::Debug::Message& message) 236 { 237 ScriptDebugServer::shared().handleV8DebugMessage(message); 238 } 239 240 void ScriptDebugServer::onV8DebugHostDispatch() 241 { 242 ScriptDebugServer::shared().handleV8DebugHostDispatch(); 243 } 244 245 void ScriptDebugServer::handleV8DebugHostDispatch() 246 { 247 if (!s_messageLoopDispatchHandler) 248 return; 249 250 Vector<WebCore::Page*> pages; 251 for (ListenersMap::iterator it = m_listenersMap.begin(); it != m_listenersMap.end(); ++it) 252 pages.append(it->first); 253 254 s_messageLoopDispatchHandler(pages); 255 } 256 257 void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) 258 { 259 v8::HandleScope scope; 260 261 if (!message.IsEvent()) 262 return; 263 264 // Ignore unsupported event types. 265 if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break) 266 return; 267 268 v8::Handle<v8::Context> context = message.GetEventContext(); 269 // If the context is from one of the inpected tabs it should have its context 270 // data. Skip events from unknown contexts. 271 if (context.IsEmpty()) 272 return; 273 274 // Test that context has associated global dom window object. 275 v8::Handle<v8::Object> global = context->Global(); 276 if (global.IsEmpty()) 277 return; 278 279 global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); 280 if (global.IsEmpty()) 281 return; 282 283 Frame* frame = V8Proxy::retrieveFrame(context); 284 if (frame) { 285 ScriptDebugListener* listener = m_listenersMap.get(frame->page()); 286 if (listener) { 287 if (message.GetEvent() == v8::AfterCompile) { 288 v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); 289 v8::Local<v8::Object> args = v8::Object::New(); 290 args->Set(v8::String::New("eventData"), message.GetEventData()); 291 v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript->Get(v8::String::New("getAfterCompileScript"))); 292 v8::Handle<v8::Value> argv[] = { message.GetExecutionState(), args }; 293 v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript, 2, argv); 294 ASSERT(value->IsObject()); 295 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); 296 dispatchDidParseSource(listener, object); 297 } else if (message.GetEvent() == v8::Break) { 298 m_executionState = v8::Persistent<v8::Object>::New(message.GetExecutionState()); 299 m_currentCallFrameState = mainWorldScriptState(frame); 300 listener->didPause(); 301 m_currentCallFrameState = 0; 302 } 303 } 304 } 305 } 306 307 void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> object) 308 { 309 String contextData = toWebCoreStringWithNullCheck(object->Get(v8::String::New("contextData"))); 310 if (contextData != m_contextDataMap.get(listener)) 311 return; 312 313 listener->didParseSource( 314 toWebCoreStringWithNullCheck(object->Get(v8::String::New("id"))), 315 toWebCoreStringWithNullCheck(object->Get(v8::String::New("name"))), 316 toWebCoreStringWithNullCheck(object->Get(v8::String::New("source"))), 317 object->Get(v8::String::New("lineOffset"))->ToInteger()->Value()); 318 } 319 320 void ScriptDebugServer::ensureDebuggerScriptCompiled() 321 { 322 if (m_debuggerScript.IsEmpty()) { 323 v8::HandleScope scope; 324 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 325 v8::Context::Scope contextScope(debuggerContext); 326 m_debuggerScript = v8::Persistent<v8::Object>::New(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(m_debuggerScriptSource))->Run())); 327 } 328 } 329 330 void ScriptDebugServer::didResume() 331 { 332 if (!m_currentCallFrame.IsEmpty()) { 333 m_currentCallFrame.Dispose(); 334 m_currentCallFrame.Clear(); 335 } 336 if (!m_executionState.IsEmpty()) { 337 m_executionState.Dispose(); 338 m_executionState.Clear(); 339 } 49 340 } 50 341 -
trunk/WebCore/bindings/v8/ScriptDebugServer.h
r57231 r57660 37 37 #include "ScriptBreakpoint.h" 38 38 #include "ScriptState.h" 39 #include "StringHash.h" 39 40 #include "Timer.h" 40 41 #include <v8-debug.h> 42 #include <wtf/HashMap.h> 41 43 #include <wtf/Noncopyable.h> 42 44 43 45 namespace WebCore { 44 46 47 class Page; 45 48 class ScriptDebugListener; 46 49 … … 58 61 static bool topStackFrame(String& sourceName, int& lineNumber, String& functionName); 59 62 60 void addListener(ScriptDebugListener*, Page*) { }61 void removeListener(ScriptDebugListener*, Page*) { }63 void addListener(ScriptDebugListener*, Page*); 64 void removeListener(ScriptDebugListener*, Page*); 62 65 63 void setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint) { }64 void removeBreakpoint(const String& sourceID, unsigned lineNumber) { }65 void clearBreakpoints() { }66 void setBreakpointsActivated(bool activated) { }66 void setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint); 67 void removeBreakpoint(const String& sourceID, unsigned lineNumber); 68 void clearBreakpoints(); 69 void setBreakpointsActivated(bool activated); 67 70 68 71 enum PauseOnExceptionsState { … … 71 74 PauseOnUncaughtExceptions 72 75 }; 73 PauseOnExceptionsState pauseOnExceptionsState() const { return DontPauseOnExceptions; }74 void setPauseOnExceptionsState(PauseOnExceptionsState ) {}76 PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } 77 void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) { m_pauseOnExceptionsState = pauseOnExceptionsState; } 75 78 76 79 void pauseProgram() { } 77 void continueProgram() { }78 void stepIntoStatement() { }79 void stepOverStatement() { }80 void stepOutOfFunction() { }80 void continueProgram(); 81 void stepIntoStatement(); 82 void stepOverStatement(); 83 void stepOutOfFunction(); 81 84 82 85 void recompileAllJSFunctionsSoon() { } 83 86 void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) { } 84 87 85 ScriptState* currentCallFrameState() { return 0; }88 ScriptState* currentCallFrameState(); 86 89 87 90 void pageCreated(Page*) { } 88 91 92 // v8-specific methods. 93 void setDebuggerScriptSource(const String& scriptSource); 94 95 typedef void (*MessageLoopDispatchHandler)(const Vector<WebCore::Page*>&); 96 static void setMessageLoopDispatchHandler(MessageLoopDispatchHandler messageLoopDispatchHandler) { s_messageLoopDispatchHandler = messageLoopDispatchHandler; } 97 98 v8::Handle<v8::Value> currentCallFrameV8(); 99 89 100 private: 90 ScriptDebugServer() { }101 ScriptDebugServer(); 91 102 ~ScriptDebugServer() { } 103 104 static void onV8DebugMessage(const v8::Debug::Message& message); 105 static void onV8DebugHostDispatch(); 106 107 void handleV8DebugMessage(const v8::Debug::Message& message); 108 void handleV8DebugHostDispatch(); 109 110 void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); 111 112 void ensureDebuggerScriptCompiled(); 113 void didResume(); 92 114 93 115 static void createUtilityContext(); … … 103 125 // Utility context holding JavaScript functions used internally. 104 126 static v8::Persistent<v8::Context> s_utilityContext; 127 128 typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; 129 ListenersMap m_listenersMap; 130 typedef HashMap<ScriptDebugListener*, String> ContextDataMap; 131 ContextDataMap m_contextDataMap; 132 String m_debuggerScriptSource; 133 PauseOnExceptionsState m_pauseOnExceptionsState; 134 v8::Persistent<v8::Object> m_debuggerScript; 135 ScriptState* m_currentCallFrameState; 136 v8::Persistent<v8::Value> m_currentCallFrame; 137 v8::Persistent<v8::Object> m_executionState; 138 139 static MessageLoopDispatchHandler s_messageLoopDispatchHandler; 105 140 }; 106 141 -
trunk/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
r56844 r57660 40 40 #include "Node.h" 41 41 #include "Page.h" 42 #include "ScriptDebugServer.h" 42 43 #include "SerializedScriptValue.h" 43 44 … … 111 112 scriptHostWrapper, 112 113 windowGlobal, 113 v8::Number::New(id) 114 v8::Number::New(id), 115 v8::String::New("v8") 114 116 }; 115 v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args);117 v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 4, args); 116 118 v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue)); 117 119 return ScriptObject(inspectedScriptState, injectedScript); … … 157 159 { 158 160 INC_STATS("InjectedScriptHost.currentCallFrame()"); 159 return v8::Undefined();161 return ScriptDebugServer::shared().currentCallFrameV8(); 160 162 } 161 163 … … 163 165 { 164 166 INC_STATS("InjectedScriptHost.isActivation()"); 165 return v8:: Undefined();167 return v8::Boolean::New(true); 166 168 } 167 169 #endif -
trunk/WebCore/inspector/front-end/InjectedScript.js
r57405 r57660 27 27 */ 28 28 29 var injectedScriptConstructor = (function (InjectedScriptHost, inspectedWindow, injectedScriptId ) {29 var injectedScriptConstructor = (function (InjectedScriptHost, inspectedWindow, injectedScriptId, jsEngine) { 30 30 31 31 var InjectedScript = {}; … … 126 126 return false; 127 127 var properties = []; 128 128 129 var propertyNames = ignoreHasOwnProperty ? InjectedScript._getPropertyNames(object) : Object.getOwnPropertyNames(object); 129 130 if (!ignoreHasOwnProperty && object.__proto__) 130 131 propertyNames.push("__proto__"); 131 132 133 if (jsEngine === "v8") { 134 // Check if the object is a scope. 135 if (InjectedScript._isScopeProxy(objectProxy)) { 136 propertyNames = []; 137 for (var name in object) 138 propertyNames.push(name); 139 } else { 140 // FIXME(http://crbug.com/41243): Object.getOwnPropertyNames may return duplicated names. 141 var a = []; 142 propertyNames.sort(); 143 var prev; 144 for (var i = 0; i < propertyNames.length; i++) { 145 var n = propertyNames[i]; 146 if (n != prev) 147 a.push(n); 148 prev = n; 149 } 150 propertyNames = a; 151 } 152 } 153 132 154 // Go over properties, prepare results. 133 155 for (var i = 0; i < propertyNames.length; ++i) { … … 158 180 return properties; 159 181 } 182 183 InjectedScript._isScopeProxy = function(objectProxy) 184 { 185 var objectId = objectProxy.objectId; 186 return typeof objectId === "object" && !objectId.thisObject; 187 } 160 188 161 189 InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression) … … 814 842 } 815 843 844 // FIXME(37663): unify scope chain representation and remove this if. 845 if (jsEngine === "v8") { 846 847 InjectedScript.CallFrameProxy.prototype = { 848 849 850 _wrapScopeChain: function(callFrame) 851 { 852 var ScopeType = { Global: 0, 853 Local: 1, 854 With: 2, 855 Closure: 3, 856 Catch: 4 }; 857 var scopeChain = callFrame.scopeChain; 858 var scopeChainProxy = []; 859 for (var i = 0; i < scopeChain.length; i += 2) { 860 var scopeType = scopeChain[i]; 861 var scopeObject = scopeChain[i + 1]; 862 var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: (i + 1) }, true); 863 864 var foundLocalScope = false; 865 switch(scopeType) { 866 case ScopeType.Local: { 867 foundLocalScope = true; 868 scopeObjectProxy.isLocal = true; 869 scopeObjectProxy.thisObject = InjectedScript.createProxyObject(callFrame.thisObject, { callFrame: this.id, thisObject: true }, true); 870 break; 871 } 872 case ScopeType.Closure: { 873 scopeObjectProxy.isClosure = true; 874 break; 875 } 876 case ScopeType.With: { 877 scopeObjectProxy.isWithBlock = true; 878 break; 879 } 880 } 881 882 if (foundLocalScope) { 883 if (scopeObject instanceof inspectedWindow.Element) 884 scopeObjectProxy.isElement = true; 885 else if (scopeObject instanceof inspectedWindow.Document) 886 scopeObjectProxy.isDocument = true; 887 } 888 889 scopeChainProxy.push(scopeObjectProxy); 890 } 891 return scopeChainProxy; 892 } 893 } 894 895 } else { 896 816 897 InjectedScript.CallFrameProxy.prototype = { 817 898 _wrapScopeChain: function(callFrame) … … 841 922 return scopeChainProxy; 842 923 } 924 } 925 843 926 } 844 927 -
trunk/WebCore/inspector/front-end/ScriptsPanel.js
r55771 r57660 199 199 200 200 this._debuggerEnabled = Preferences.debuggerAlwaysEnabled; 201 if (Preferences.debuggerAlwaysEnabled) 202 this._attachDebuggerWhenShown = true; 201 203 this.reset(); 202 204 } -
trunk/WebKit/chromium/ChangeLog
r57655 r57660 1 2010-04-15 Yury Semikhatsky <yurys@google.com> 2 3 Reviewed by Pavel Feldman. 4 5 Support basic debugging capabilities including step in/over/out in v8 6 implementation of ScriptDebugServer. 7 8 https://bugs.webkit.org/show_bug.cgi?id=37604 9 10 * WebKit.gypi: 11 * src/DebuggerAgent.h: 12 * src/DebuggerAgentImpl.cpp: 13 (WebKit::DebuggerAgentImpl::setDebuggerScriptSource): 14 * src/DebuggerAgentImpl.h: 15 * src/DebuggerAgentManager.cpp: 16 (WebKit::DebuggerAgentManager::hostDispatchHandler): 17 (WebKit::DebuggerAgentManager::debugAttach): 18 (WebKit::DebuggerAgentManager::debugDetach): 19 (WebKit::DebuggerAgentManager::setMessageLoopDispatchHandler): 20 * src/DebuggerAgentManager.h: 21 * src/InspectorFrontendClientImpl.cpp: 22 (WebKit::InspectorFrontendClientImpl::windowObjectCleared): 23 * src/js/DebuggerScript.js: Added. 24 (debuggerScriptConstructor.DebuggerScript.getAfterCompileScript): 25 (debuggerScriptConstructor.DebuggerScript.getScripts): 26 (debuggerScriptConstructor.DebuggerScript._formatScript): 27 (debuggerScriptConstructor.DebuggerScript.setBreakpoint): 28 (debuggerScriptConstructor.DebuggerScript.removeBreakpoint): 29 (debuggerScriptConstructor.DebuggerScript.currentCallFrame): 30 (debuggerScriptConstructor.DebuggerScript.stepIntoStatement): 31 (debuggerScriptConstructor.DebuggerScript.stepOverStatement): 32 (debuggerScriptConstructor.DebuggerScript.stepOutOfFunction): 33 (debuggerScriptConstructor.DebuggerScript.clearBreakpoints): 34 (debuggerScriptConstructor.DebuggerScript.setBreakpointsActivated): 35 (debuggerScriptConstructor.DebuggerScript._frameMirrorToJSCallFrame): 36 (debuggerScriptConstructor.DebuggerScript._webkitToV8LineNumber): 37 (debuggerScriptConstructor.DebuggerScript._v8ToWwebkitLineNumber): 38 (debuggerScriptConstructor): 39 * src/js/DevTools.js: 40 (WebInspector.loaded): 41 (.): 42 (): 43 * src/js/DevToolsHostStub.js: 44 (.RemoteDebuggerAgentStub.prototype.setDebuggerScriptSource): 45 * src/js/InspectorControllerImpl.js: 46 (devtools.InspectorBackendImpl): 47 1 48 2010-04-15 Ben Murdoch <benm@google.com> 2 49 -
trunk/WebKit/chromium/WebKit.gypi
r57220 r57660 36 36 'src/js/InspectorControllerImpl.js', 37 37 'src/js/DebuggerAgent.js', 38 'src/js/DebuggerScript.js', 38 39 'src/js/ProfilerAgent.js', 39 40 'src/js/ProfilerProcessor.js', -
trunk/WebKit/chromium/src/DebuggerAgent.h
r54592 r57660 41 41 \ 42 42 /* Request v8 to process all debug commands in the queue. */ \ 43 METHOD0(processDebugCommands) 43 METHOD0(processDebugCommands) \ 44 \ 45 /* Push DebuggerScript.js content to the agent. */ \ 46 METHOD1(setDebuggerScriptSource, String) 44 47 45 48 DEFINE_RPC_CLASS(DebuggerAgent, DEBUGGER_AGENT_STRUCT) -
trunk/WebKit/chromium/src/DebuggerAgentImpl.cpp
r55726 r57660 36 36 #include "Frame.h" 37 37 #include "Page.h" 38 #include "ScriptDebugServer.h" 38 39 #include "V8Binding.h" 39 40 #include "WebDevToolsAgentImpl.h" … … 77 78 DebuggerAgentManager::UtilityContextScope utilityScope; 78 79 v8::Debug::ProcessDebugMessages(); 80 } 81 82 void DebuggerAgentImpl::setDebuggerScriptSource(const String& source) 83 { 84 WebCore::ScriptDebugServer::shared().setDebuggerScriptSource(source); 79 85 } 80 86 -
trunk/WebKit/chromium/src/DebuggerAgentImpl.h
r55726 r57660 61 61 virtual void getContextId(); 62 62 virtual void processDebugCommands(); 63 virtual void setDebuggerScriptSource(const String&); 63 64 64 65 void debuggerOutput(const WebCore::String& out); -
trunk/WebKit/chromium/src/DebuggerAgentManager.cpp
r54232 r57660 35 35 #include "Frame.h" 36 36 #include "PageGroupLoadDeferrer.h" 37 #include "ScriptDebugServer.h" 37 38 #include "V8Proxy.h" 38 39 #include "WebDevToolsAgentImpl.h" … … 73 74 74 75 76 void DebuggerAgentManager::hostDispatchHandler(const Vector<WebCore::Page*>& pages) 77 { 78 if (!s_messageLoopDispatchHandler) 79 return; 80 81 if (s_inHostDispatchHandler) 82 return; 83 84 s_inHostDispatchHandler = true; 85 86 Vector<WebViewImpl*> views; 87 // 1. Disable active objects and input events. 88 for (size_t i = 0; i < pages.size(); i++) { 89 WebCore::Page* page = pages[i]; 90 WebViewImpl* view = WebViewImpl::fromPage(page); 91 s_pageDeferrers.set(view , new WebCore::PageGroupLoadDeferrer(page, true)); 92 views.append(view); 93 view->setIgnoreInputEvents(true); 94 } 95 96 // 2. Process messages. 97 s_messageLoopDispatchHandler(); 98 99 // 3. Bring things back. 100 for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) { 101 if (s_pageDeferrers.contains(*it)) { 102 // The view was not closed during the dispatch. 103 (*it)->setIgnoreInputEvents(false); 104 } 105 } 106 deleteAllValues(s_pageDeferrers); 107 s_pageDeferrers.clear(); 108 109 s_inHostDispatchHandler = false; 110 } 111 75 112 void DebuggerAgentManager::debugHostDispatchHandler() 76 113 { … … 117 154 void DebuggerAgentManager::debugAttach(DebuggerAgentImpl* debuggerAgent) 118 155 { 156 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 157 return; 158 #endif 119 159 if (!s_attachedAgentsMap) { 120 160 s_attachedAgentsMap = new AttachedAgentsMap(); … … 129 169 void DebuggerAgentManager::debugDetach(DebuggerAgentImpl* debuggerAgent) 130 170 { 171 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 172 return; 173 #endif 131 174 if (!s_attachedAgentsMap) { 132 175 ASSERT_NOT_REACHED(); … … 250 293 { 251 294 s_messageLoopDispatchHandler = handler; 295 WebCore::ScriptDebugServer::setMessageLoopDispatchHandler(DebuggerAgentManager::hostDispatchHandler); 252 296 } 253 297 -
trunk/WebKit/chromium/src/DebuggerAgentManager.h
r54232 r57660 32 32 #define DebuggerAgentManager_h 33 33 34 #include "WebCString.h" 34 35 #include "WebDevToolsAgent.h" 35 36 #include <v8-debug.h> 36 37 #include <wtf/HashMap.h> 37 38 #include <wtf/Noncopyable.h> 39 #include <wtf/Vector.h> 38 40 39 41 namespace WebCore { 42 class Page; 40 43 class PageGroupLoadDeferrer; 41 44 class String; … … 98 101 ~DebuggerAgentManager(); 99 102 103 static void hostDispatchHandler(const Vector<WebCore::Page*>&); 100 104 static void debugHostDispatchHandler(); 101 105 static void onV8DebugMessage(const v8::Debug::Message& message); -
trunk/WebKit/chromium/src/InspectorFrontendClientImpl.cpp
r57146 r57660 70 70 71 71 global->Set(v8::String::New("InspectorFrontendHost"), frontendHostObj); 72 #if ENABLE(V8_SCRIPT_DEBUG_SERVER) 73 global->Set(v8::String::New("v8ScriptDebugServerEnabled"), v8::True()); 74 #endif 72 75 } 73 76 -
trunk/WebKit/chromium/src/js/DevTools.js
r57220 r57660 184 184 Preferences.debuggerAlwaysEnabled = true; 185 185 Preferences.profilerAlwaysEnabled = true; 186 RemoteDebuggerAgent.setDebuggerScriptSource("(" + debuggerScriptConstructor + ")();"); 187 186 188 oldLoaded.call(this); 187 189 … … 189 191 }; 190 192 193 194 if (!window.v8ScriptDebugServerEnabled) { 191 195 192 196 /** … … 226 230 227 231 228 /**229 * @param {string} type Type of the the property value("object" or "function").230 * @param {string} className Class name of the property value.231 * @constructor232 */233 WebInspector.UnresolvedPropertyValue = function(type, className)234 {235 this.type = type;236 this.className = className;237 };238 239 240 232 (function() 241 233 { … … 248 240 }; 249 241 })(); 242 243 244 (function () { 245 var orig = InjectedScriptAccess.prototype.getProperties; 246 InjectedScriptAccess.prototype.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate, callback) 247 { 248 if (objectProxy.isScope) 249 devtools.tools.getDebuggerAgent().resolveScope(objectProxy.objectId, callback); 250 else if (objectProxy.isV8Ref) 251 devtools.tools.getDebuggerAgent().resolveChildren(objectProxy.objectId, callback, false); 252 else 253 orig.apply(this, arguments); 254 }; 255 })(); 256 257 258 (function() 259 { 260 InjectedScriptAccess.prototype.evaluateInCallFrame = function(callFrameId, code, objectGroup, callback) 261 { 262 //TODO(pfeldman): remove once 49084 is rolled. 263 if (!callback) 264 callback = objectGroup; 265 devtools.tools.getDebuggerAgent().evaluateInCallFrame(callFrameId, code, callback); 266 }; 267 })(); 268 269 270 (function() 271 { 272 var orig = InjectedScriptAccess.prototype.getCompletions; 273 InjectedScriptAccess.prototype.getCompletions = function(expressionString, includeInspectorCommandLineAPI, callFrameId, reportCompletions) 274 { 275 if (typeof callFrameId === "number") 276 devtools.tools.getDebuggerAgent().resolveCompletionsOnFrame(expressionString, callFrameId, reportCompletions); 277 else 278 return orig.apply(this, arguments); 279 }; 280 })(); 281 282 } 250 283 251 284 … … 344 377 345 378 346 (function () {347 var orig = InjectedScriptAccess.prototype.getProperties;348 InjectedScriptAccess.prototype.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate, callback)349 {350 if (objectProxy.isScope)351 devtools.tools.getDebuggerAgent().resolveScope(objectProxy.objectId, callback);352 else if (objectProxy.isV8Ref)353 devtools.tools.getDebuggerAgent().resolveChildren(objectProxy.objectId, callback, false);354 else355 orig.apply(this, arguments);356 };357 })();358 359 360 (function()361 {362 InjectedScriptAccess.prototype.evaluateInCallFrame = function(callFrameId, code, objectGroup, callback)363 {364 //TODO(pfeldman): remove once 49084 is rolled.365 if (!callback)366 callback = objectGroup;367 devtools.tools.getDebuggerAgent().evaluateInCallFrame(callFrameId, code, callback);368 };369 })();370 371 372 (function()373 {374 var orig = InjectedScriptAccess.prototype.getCompletions;375 InjectedScriptAccess.prototype.getCompletions = function(expressionString, includeInspectorCommandLineAPI, callFrameId, reportCompletions)376 {377 if (typeof callFrameId === "number")378 devtools.tools.getDebuggerAgent().resolveCompletionsOnFrame(expressionString, callFrameId, reportCompletions);379 else380 return orig.apply(this, arguments);381 };382 })();383 384 385 379 // We need to have a place for postponed tasks 386 380 // which should be executed when all the messages between agent and frontend -
trunk/WebKit/chromium/src/js/DevToolsHostStub.js
r54592 r57660 56 56 57 57 58 RemoteDebuggerAgentStub.prototype.setDebuggerScriptSource = function(source) 59 { 60 }; 61 62 58 63 /** 59 64 * @constructor -
trunk/WebKit/chromium/src/js/InspectorControllerImpl.js
r57505 r57660 87 87 this.installInspectorControllerDelegate_("setRuleSelector"); 88 88 this.installInspectorControllerDelegate_("addRule"); 89 90 if (window.v8ScriptDebugServerEnabled) { 91 this.installInspectorControllerDelegate_("disableDebugger"); 92 this.installInspectorControllerDelegate_("enableDebugger"); 93 this.installInspectorControllerDelegate_("setBreakpoint"); 94 this.installInspectorControllerDelegate_("removeBreakpoint"); 95 this.installInspectorControllerDelegate_("activateBreakpoints"); 96 this.installInspectorControllerDelegate_("deactivateBreakpoints"); 97 this.installInspectorControllerDelegate_("pauseInDebugger"); 98 this.installInspectorControllerDelegate_("resumeDebugger"); 99 this.installInspectorControllerDelegate_("stepIntoStatementInDebugger"); 100 this.installInspectorControllerDelegate_("stepOutOfFunctionInDebugger"); 101 this.installInspectorControllerDelegate_("stepOverStatementInDebugger"); 102 this.installInspectorControllerDelegate_("setPauseOnExceptionsState"); 103 } 89 104 }; 90 105 devtools.InspectorBackendImpl.prototype.__proto__ = WebInspector.InspectorBackendStub.prototype; … … 108 123 }; 109 124 125 126 if (!window.v8ScriptDebugServerEnabled) { 110 127 111 128 devtools.InspectorBackendImpl.prototype.setBreakpoint = function(sourceID, line, enabled, condition) … … 194 211 }; 195 212 213 } 214 196 215 197 216 /**
Note: See TracChangeset
for help on using the changeset viewer.