| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Provides communication interface to remote v8 debugger. See | 6 * @fileoverview Provides communication interface to remote v8 debugger. See |
| 7 * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol | 7 * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol |
| 8 */ | 8 */ |
| 9 goog.provide('devtools.DebuggerAgent'); | 9 goog.provide('devtools.DebuggerAgent'); |
| 10 | 10 |
| 11 | 11 |
| 12 /** | 12 /** |
| 13 * @constructor | 13 * @constructor |
| 14 */ | 14 */ |
| 15 devtools.DebuggerAgent = function() { | 15 devtools.DebuggerAgent = function() { |
| 16 RemoteDebuggerAgent.DebuggerOutput = | 16 RemoteDebuggerAgent.DebuggerOutput = |
| 17 goog.bind(this.handleDebuggerOutput_, this); | 17 goog.bind(this.handleDebuggerOutput_, this); |
| 18 RemoteDebuggerAgent.DidGetContextId = | 18 RemoteDebuggerAgent.SetContextId = |
| 19 goog.bind(this.didGetContextId_, this); | 19 goog.bind(this.setContextId_, this); |
| 20 RemoteDebuggerAgent.DidIsProfilingStarted = | 20 RemoteDebuggerAgent.DidGetActiveProfilerModules = |
| 21 goog.bind(this.didIsProfilingStarted_, this); | 21 goog.bind(this.didGetActiveProfilerModules_, this); |
| 22 RemoteDebuggerAgent.DidGetLogLines = | 22 RemoteDebuggerAgent.DidGetNextLogLines = |
| 23 goog.bind(this.didGetLogLines_, this); | 23 goog.bind(this.didGetNextLogLines_, this); |
| 24 | 24 |
| 25 /** | 25 /** |
| 26 * Id of the inspected page global context. It is used for filtering scripts. | 26 * Id of the inspected page global context. It is used for filtering scripts. |
| 27 * @type {number} | 27 * @type {number} |
| 28 */ | 28 */ |
| 29 this.contextId_ = null; | 29 this.contextId_ = null; |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * Mapping from script id to script info. | 32 * Mapping from script id to script info. |
| 33 * @type {Object} | 33 * @type {Object} |
| 34 */ | 34 */ |
| 35 this.parsedScripts_ = null; | 35 this.parsedScripts_ = null; |
| 36 | 36 |
| 37 /** | 37 /** |
| 38 * Mapping from the request id to the devtools.BreakpointInfo for the | 38 * Mapping from the request id to the devtools.BreakpointInfo for the |
| 39 * breakpoints whose v8 ids are not set yet. These breakpoints are waiting for | 39 * breakpoints whose v8 ids are not set yet. These breakpoints are waiting for |
| 40 * 'setbreakpoint' responses to learn their ids in the v8 debugger. | 40 * 'setbreakpoint' responses to learn their ids in the v8 debugger. |
| 41 * @see #handleSetBreakpointResponse_ | 41 * @see #handleSetBreakpointResponse_ |
| 42 * @type {Object} | 42 * @type {Object} |
| 43 */ | 43 */ |
| 44 this.requestNumberToBreakpointInfo_ = null; | 44 this.requestNumberToBreakpointInfo_ = null; |
| 45 | 45 |
| 46 /** | 46 /** |
| 47 * Information on current stack top frame. | 47 * Information on current stack frames. |
| 48 * See JavaScriptCallFrame.idl. | 48 * @type {Array.<devtools.CallFrame>} |
| 49 * @type {?devtools.CallFrame} | |
| 50 */ | 49 */ |
| 51 this.currentCallFrame_ = null; | 50 this.callFrames_ = []; |
| 52 | 51 |
| 53 /** | 52 /** |
| 54 * Whether to stop in the debugger on the exceptions. | 53 * Whether to stop in the debugger on the exceptions. |
| 55 * @type {boolean} | 54 * @type {boolean} |
| 56 */ | 55 */ |
| 57 this.pauseOnExceptions_ = true; | 56 this.pauseOnExceptions_ = true; |
| 58 | 57 |
| 59 /** | 58 /** |
| 60 * Mapping: request sequence number->callback. | 59 * Mapping: request sequence number->callback. |
| 61 * @type {Object} | 60 * @type {Object} |
| 62 */ | 61 */ |
| 63 this.requestSeqToCallback_ = null; | 62 this.requestSeqToCallback_ = null; |
| 64 | 63 |
| 65 /** | 64 /** |
| 66 * Whether the scripts list has been requested. | 65 * Whether the scripts list has been requested. |
| 67 * @type {boolean} | 66 * @type {boolean} |
| 68 */ | 67 */ |
| 69 this.scriptsCacheInitialized_ = false; | 68 this.scriptsCacheInitialized_ = false; |
| 70 | 69 |
| 71 /** | 70 /** |
| 72 * Whether user has stopped profiling and we are retrieving the rest of | 71 * Active profiler modules flags. |
| 73 * profiler's log. | |
| 74 * @type {boolean} | |
| 75 */ | |
| 76 this.isProcessingProfile_ = false; | |
| 77 | |
| 78 /** | |
| 79 * The position in log file to read from. | |
| 80 * @type {number} | 72 * @type {number} |
| 81 */ | 73 */ |
| 82 this.lastProfileLogPosition_ = 0; | 74 this.activeProfilerModules_ = |
| 75 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE; |
| 83 | 76 |
| 84 /** | 77 /** |
| 85 * Profiler processor instance. | 78 * Profiler processor instance. |
| 86 * @type {devtools.profiler.Processor} | 79 * @type {devtools.profiler.Processor} |
| 87 */ | 80 */ |
| 88 this.profilerProcessor_ = new devtools.profiler.Processor(); | 81 this.profilerProcessor_ = new devtools.profiler.Processor(); |
| 82 |
| 83 /** |
| 84 * Container of all breakpoints set using resource URL. These breakpoints |
| 85 * survive page reload. Breakpoints set by script id(for scripts that don't |
| 86 * have URLs) are stored in ScriptInfo objects. |
| 87 * @type {Object} |
| 88 */ |
| 89 this.urlToBreakpoints_ = {}; |
| 90 |
| 91 |
| 92 /** |
| 93 * Exception message that is shown to user while on exception break. |
| 94 * @type {WebInspector.ConsoleMessage} |
| 95 */ |
| 96 this.currentExceptionMessage_ = null; |
| 89 }; | 97 }; |
| 90 | 98 |
| 91 | 99 |
| 100 /** |
| 101 * A copy of the scope types from v8/src/mirror-delay.js |
| 102 * @enum {number} |
| 103 */ |
| 104 devtools.DebuggerAgent.ScopeType = { |
| 105 Global: 0, |
| 106 Local: 1, |
| 107 With: 2, |
| 108 Closure: 3 |
| 109 }; |
| 110 |
| 111 |
| 112 /** |
| 113 * A no-op JS expression that is sent to the inspected page in order to force v8 |
| 114 * execution. |
| 115 */ |
| 116 devtools.DebuggerAgent.VOID_SCRIPT = 'javascript:void(0)'; |
| 117 |
| 118 |
| 119 /** |
| 120 * A copy of enum from include/v8.h |
| 121 * @enum {number} |
| 122 */ |
| 123 devtools.DebuggerAgent.ProfilerModules = { |
| 124 PROFILER_MODULE_NONE: 0, |
| 125 PROFILER_MODULE_CPU: 1, |
| 126 PROFILER_MODULE_HEAP_STATS: 1 << 1, |
| 127 PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2, |
| 128 PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16 |
| 129 }; |
| 130 |
| 131 |
| 92 /** | 132 /** |
| 93 * Resets debugger agent to its initial state. | 133 * Resets debugger agent to its initial state. |
| 94 */ | 134 */ |
| 95 devtools.DebuggerAgent.prototype.reset = function() { | 135 devtools.DebuggerAgent.prototype.reset = function() { |
| 96 this.scriptsCacheInitialized_ = false; | |
| 97 this.contextId_ = null; | 136 this.contextId_ = null; |
| 98 this.parsedScripts_ = {}; | 137 this.parsedScripts_ = {}; |
| 99 this.requestNumberToBreakpointInfo_ = {}; | 138 this.requestNumberToBreakpointInfo_ = {}; |
| 100 this.currentCallFrame_ = null; | 139 this.callFrames_ = []; |
| 101 this.requestSeqToCallback_ = {}; | 140 this.requestSeqToCallback_ = {}; |
| 141 |
| 142 // Profiler isn't reset because it contains no data that is |
| 143 // specific for a particular V8 instance. All such data is |
| 144 // managed by an agent on the Render's side. |
| 102 }; | 145 }; |
| 103 | 146 |
| 104 | 147 |
| 105 /** | 148 /** |
| 106 * Requests scripts list if it has not been requested yet. | 149 * Initializes scripts UI. Asynchronously requests for all parsed scripts |
| 150 * if necessary. Response will be processed in handleScriptsResponse_. |
| 107 */ | 151 */ |
| 108 devtools.DebuggerAgent.prototype.initializeScriptsCache = function() { | 152 devtools.DebuggerAgent.prototype.initUI = function() { |
| 109 if (!this.scriptsCacheInitialized_) { | 153 // There can be a number of scripts from after-compile events that are |
| 110 this.scriptsCacheInitialized_ = true; | 154 // pending addition into the UI. |
| 111 this.requestScripts(); | 155 for (var scriptId in this.parsedScripts_) { |
| 156 var script = this.parsedScripts_[scriptId]; |
| 157 WebInspector.parsedScriptSource(scriptId, script.getUrl(), |
| 158 undefined /* script source */, script.getLineOffset()); |
| 112 } | 159 } |
| 113 }; | |
| 114 | 160 |
| 115 | 161 if (this.contextId_) { |
| 116 /** | 162 // We already have context id. This means that we are here from the |
| 117 * Asynchronously requests for all parsed script sources. Response will be | 163 // very beginning of the page load cycle and hence will get all scripts |
| 118 * processed in handleScriptsResponse_. | 164 // via after-compile events. No need to request scripts for this session. |
| 119 */ | |
| 120 devtools.DebuggerAgent.prototype.requestScripts = function() { | |
| 121 if (this.contextId_ === null) { | |
| 122 // Update context id first to filter the scripts. | |
| 123 RemoteDebuggerAgent.GetContextId(); | |
| 124 return; | 165 return; |
| 125 } | 166 } |
| 167 |
| 168 RemoteDebuggerAgent.GetContextId(); |
| 126 var cmd = new devtools.DebugCommand('scripts', { | 169 var cmd = new devtools.DebugCommand('scripts', { |
| 127 'includeSource': false | 170 'includeSource': false |
| 128 }); | 171 }); |
| 129 devtools.DebuggerAgent.sendCommand_(cmd); | 172 devtools.DebuggerAgent.sendCommand_(cmd); |
| 130 // Force v8 execution so that it gets to processing the requested command. | 173 // Force v8 execution so that it gets to processing the requested command. |
| 131 devtools.tools.evaluateJavaScript('javascript:void(0)'); | 174 devtools.tools.evaluateJavaScript(devtools.DebuggerAgent.VOID_SCRIPT); |
| 132 }; | 175 }; |
| 133 | 176 |
| 134 | 177 |
| 135 /** | 178 /** |
| 136 * Asynchronously requests the debugger for the script source. | 179 * Asynchronously requests the debugger for the script source. |
| 137 * @param {number} scriptId Id of the script whose source should be resolved. | 180 * @param {number} scriptId Id of the script whose source should be resolved. |
| 138 * @param {function(source:?string):void} callback Function that will be called | 181 * @param {function(source:?string):void} callback Function that will be called |
| 139 * when the source resolution is completed. 'source' parameter will be null | 182 * when the source resolution is completed. 'source' parameter will be null |
| 140 * if the resolution fails. | 183 * if the resolution fails. |
| 141 */ | 184 */ |
| 142 devtools.DebuggerAgent.prototype.resolveScriptSource = function( | 185 devtools.DebuggerAgent.prototype.resolveScriptSource = function( |
| 143 scriptId, callback) { | 186 scriptId, callback) { |
| 144 var script = this.parsedScripts_[scriptId]; | 187 var script = this.parsedScripts_[scriptId]; |
| 145 if (!script) { | 188 if (!script || script.isUnresolved()) { |
| 146 callback(null); | 189 callback(null); |
| 147 return; | 190 return; |
| 148 } | 191 } |
| 149 | 192 |
| 150 var cmd = new devtools.DebugCommand('scripts', { | 193 var cmd = new devtools.DebugCommand('scripts', { |
| 151 'ids': [scriptId], | 194 'ids': [scriptId], |
| 152 'includeSource': true | 195 'includeSource': true |
| 153 }); | 196 }); |
| 154 devtools.DebuggerAgent.sendCommand_(cmd); | 197 devtools.DebuggerAgent.sendCommand_(cmd); |
| 155 // Force v8 execution so that it gets to processing the requested command. | 198 // Force v8 execution so that it gets to processing the requested command. |
| 156 devtools.tools.evaluateJavaScript('javascript:void(0)'); | 199 devtools.tools.evaluateJavaScript(devtools.DebuggerAgent.VOID_SCRIPT); |
| 157 | 200 |
| 158 this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { | 201 this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { |
| 159 if (msg.isSuccess()) { | 202 if (msg.isSuccess()) { |
| 160 var scriptJson = msg.getBody()[0]; | 203 var scriptJson = msg.getBody()[0]; |
| 161 callback(scriptJson.source); | 204 callback(scriptJson.source); |
| 162 } else { | 205 } else { |
| 163 callback(null); | 206 callback(null); |
| 164 } | 207 } |
| 165 }; | 208 }; |
| 166 }; | 209 }; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 179 * @param {number} line Number of the line for the breakpoint. | 222 * @param {number} line Number of the line for the breakpoint. |
| 180 */ | 223 */ |
| 181 devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line) { | 224 devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line) { |
| 182 var script = this.parsedScripts_[sourceId]; | 225 var script = this.parsedScripts_[sourceId]; |
| 183 if (!script) { | 226 if (!script) { |
| 184 return; | 227 return; |
| 185 } | 228 } |
| 186 | 229 |
| 187 line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); | 230 line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); |
| 188 | 231 |
| 189 var breakpointInfo = script.getBreakpointInfo(line); | 232 var commandArguments; |
| 190 if (breakpointInfo) { | 233 if (script.getUrl()) { |
| 191 return; | 234 var breakpoints = this.urlToBreakpoints_[script.getUrl()]; |
| 235 if (breakpoints && breakpoints[line]) { |
| 236 return; |
| 237 } |
| 238 if (!breakpoints) { |
| 239 breakpoints = {}; |
| 240 this.urlToBreakpoints_[script.getUrl()] = breakpoints; |
| 241 } |
| 242 |
| 243 var breakpointInfo = new devtools.BreakpointInfo(line); |
| 244 breakpoints[line] = breakpointInfo; |
| 245 |
| 246 commandArguments = { |
| 247 'groupId': this.contextId_, |
| 248 'type': 'script', |
| 249 'target': script.getUrl(), |
| 250 'line': line |
| 251 }; |
| 252 } else { |
| 253 var breakpointInfo = script.getBreakpointInfo(line); |
| 254 if (breakpointInfo) { |
| 255 return; |
| 256 } |
| 257 |
| 258 breakpointInfo = new devtools.BreakpointInfo(line); |
| 259 script.addBreakpointInfo(breakpointInfo); |
| 260 |
| 261 commandArguments = { |
| 262 'groupId': this.contextId_, |
| 263 'type': 'scriptId', |
| 264 'target': sourceId, |
| 265 'line': line |
| 266 }; |
| 192 } | 267 } |
| 193 | 268 |
| 194 breakpointInfo = new devtools.BreakpointInfo(sourceId, line); | 269 var cmd = new devtools.DebugCommand('setbreakpoint', commandArguments); |
| 195 script.addBreakpointInfo(breakpointInfo); | |
| 196 | |
| 197 var cmd = new devtools.DebugCommand('setbreakpoint', { | |
| 198 'type': 'scriptId', | |
| 199 'target': sourceId, | |
| 200 'line': line | |
| 201 }); | |
| 202 | 270 |
| 203 this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo; | 271 this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo; |
| 204 | 272 |
| 205 devtools.DebuggerAgent.sendCommand_(cmd); | 273 devtools.DebuggerAgent.sendCommand_(cmd); |
| 206 }; | 274 }; |
| 207 | 275 |
| 208 | 276 |
| 209 /** | 277 /** |
| 210 * @param {number} sourceId Id of the script fot the breakpoint. | 278 * @param {number} sourceId Id of the script fot the breakpoint. |
| 211 * @param {number} line Number of the line for the breakpoint. | 279 * @param {number} line Number of the line for the breakpoint. |
| 212 */ | 280 */ |
| 213 devtools.DebuggerAgent.prototype.removeBreakpoint = function(sourceId, line) { | 281 devtools.DebuggerAgent.prototype.removeBreakpoint = function(sourceId, line) { |
| 214 var script = this.parsedScripts_[sourceId]; | 282 var script = this.parsedScripts_[sourceId]; |
| 215 if (!script) { | 283 if (!script) { |
| 216 return; | 284 return; |
| 217 } | 285 } |
| 218 | 286 |
| 219 line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); | 287 line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); |
| 220 | 288 |
| 221 var breakpointInfo = script.getBreakpointInfo(line); | 289 var breakpointInfo; |
| 222 script.removeBreakpointInfo(breakpointInfo); | 290 if (script.getUrl()) { |
| 291 var breakpoints = this.urlToBreakpoints_[script.getUrl()]; |
| 292 breakpointInfo = breakpoints[line]; |
| 293 delete breakpoints[line]; |
| 294 } else { |
| 295 breakpointInfo = script.getBreakpointInfo(line); |
| 296 if (breakpointInfo) { |
| 297 script.removeBreakpointInfo(breakpointInfo); |
| 298 } |
| 299 } |
| 300 |
| 301 if (!breakpointInfo) { |
| 302 return; |
| 303 } |
| 304 |
| 223 breakpointInfo.markAsRemoved(); | 305 breakpointInfo.markAsRemoved(); |
| 224 | 306 |
| 225 var id = breakpointInfo.getV8Id(); | 307 var id = breakpointInfo.getV8Id(); |
| 226 | 308 |
| 227 // If we don't know id of this breakpoint in the v8 debugger we cannot send | 309 // If we don't know id of this breakpoint in the v8 debugger we cannot send |
| 228 // 'clearbreakpoint' request. In that case it will be removed in | 310 // 'clearbreakpoint' request. In that case it will be removed in |
| 229 // 'setbreakpoint' response handler when we learn the id. | 311 // 'setbreakpoint' response handler when we learn the id. |
| 230 if (id != -1) { | 312 if (id != -1) { |
| 231 this.requestClearBreakpoint_(id); | 313 this.requestClearBreakpoint_(id); |
| 232 } | 314 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 255 devtools.DebuggerAgent.prototype.stepOverStatement = function() { | 337 devtools.DebuggerAgent.prototype.stepOverStatement = function() { |
| 256 this.stepCommand_('next'); | 338 this.stepCommand_('next'); |
| 257 }; | 339 }; |
| 258 | 340 |
| 259 | 341 |
| 260 /** | 342 /** |
| 261 * Tells the v8 debugger to continue execution after it has been stopped on a | 343 * Tells the v8 debugger to continue execution after it has been stopped on a |
| 262 * breakpoint or an exception. | 344 * breakpoint or an exception. |
| 263 */ | 345 */ |
| 264 devtools.DebuggerAgent.prototype.resumeExecution = function() { | 346 devtools.DebuggerAgent.prototype.resumeExecution = function() { |
| 347 this.clearExceptionMessage_(); |
| 265 var cmd = new devtools.DebugCommand('continue'); | 348 var cmd = new devtools.DebugCommand('continue'); |
| 266 devtools.DebuggerAgent.sendCommand_(cmd); | 349 devtools.DebuggerAgent.sendCommand_(cmd); |
| 267 }; | 350 }; |
| 268 | 351 |
| 269 | 352 |
| 270 /** | 353 /** |
| 354 * Creates exception message and schedules it for addition to the resource upon |
| 355 * backtrace availability. |
| 356 * @param {string} url Resource url. |
| 357 * @param {number} line Resource line number. |
| 358 * @param {string} message Exception text. |
| 359 */ |
| 360 devtools.DebuggerAgent.prototype.createExceptionMessage_ = function( |
| 361 url, line, message) { |
| 362 this.currentExceptionMessage_ = new WebInspector.ConsoleMessage( |
| 363 WebInspector.ConsoleMessage.MessageSource.JS, |
| 364 WebInspector.ConsoleMessage.MessageType.Log, |
| 365 WebInspector.ConsoleMessage.MessageLevel.Error, |
| 366 line, |
| 367 url, |
| 368 0 /* group level */, |
| 369 1 /* repeat count */, |
| 370 '[Exception] ' + message); |
| 371 }; |
| 372 |
| 373 |
| 374 /** |
| 375 * Shows pending exception message that is created with createExceptionMessage_ |
| 376 * earlier. |
| 377 */ |
| 378 devtools.DebuggerAgent.prototype.showPendingExceptionMessage_ = function() { |
| 379 if (!this.currentExceptionMessage_) { |
| 380 return; |
| 381 } |
| 382 var msg = this.currentExceptionMessage_; |
| 383 var resource = WebInspector.resourceURLMap[msg.url]; |
| 384 if (resource) { |
| 385 msg.resource = resource; |
| 386 WebInspector.panels.resources.addMessageToResource(resource, msg); |
| 387 } else { |
| 388 this.currentExceptionMessage_ = null; |
| 389 } |
| 390 }; |
| 391 |
| 392 |
| 393 /** |
| 394 * Clears exception message from the resource. |
| 395 */ |
| 396 devtools.DebuggerAgent.prototype.clearExceptionMessage_ = function() { |
| 397 if (this.currentExceptionMessage_) { |
| 398 var messageElement = |
| 399 this.currentExceptionMessage_._resourceMessageLineElement; |
| 400 var bubble = messageElement.parentElement; |
| 401 bubble.removeChild(messageElement); |
| 402 if (!bubble.firstChild) { |
| 403 // Last message in bubble removed. |
| 404 bubble.parentElement.removeChild(bubble); |
| 405 } |
| 406 this.currentExceptionMessage_ = null; |
| 407 } |
| 408 }; |
| 409 |
| 410 |
| 411 /** |
| 271 * @return {boolean} True iff the debugger will pause execution on the | 412 * @return {boolean} True iff the debugger will pause execution on the |
| 272 * exceptions. | 413 * exceptions. |
| 273 */ | 414 */ |
| 274 devtools.DebuggerAgent.prototype.pauseOnExceptions = function() { | 415 devtools.DebuggerAgent.prototype.pauseOnExceptions = function() { |
| 275 return this.pauseOnExceptions_; | 416 return this.pauseOnExceptions_; |
| 276 }; | 417 }; |
| 277 | 418 |
| 278 | 419 |
| 279 /** | 420 /** |
| 280 * Tells whether to pause in the debugger on the exceptions or not. | 421 * Tells whether to pause in the debugger on the exceptions or not. |
| 281 * @param {boolean} value True iff execution should be stopped in the debugger | 422 * @param {boolean} value True iff execution should be stopped in the debugger |
| 282 * on the exceptions. | 423 * on the exceptions. |
| 283 */ | 424 */ |
| 284 devtools.DebuggerAgent.prototype.setPauseOnExceptions = function(value) { | 425 devtools.DebuggerAgent.prototype.setPauseOnExceptions = function(value) { |
| 285 this.pauseOnExceptions_ = value; | 426 this.pauseOnExceptions_ = value; |
| 286 }; | 427 }; |
| 287 | 428 |
| 288 | 429 |
| 289 /** | 430 /** |
| 290 * Current stack top frame. | |
| 291 * @return {devtools.CallFrame} | |
| 292 */ | |
| 293 devtools.DebuggerAgent.prototype.getCurrentCallFrame = function() { | |
| 294 return this.currentCallFrame_; | |
| 295 }; | |
| 296 | |
| 297 | |
| 298 /** | |
| 299 * Sends 'evaluate' request to the debugger. | 431 * Sends 'evaluate' request to the debugger. |
| 300 * @param {Object} arguments Request arguments map. | 432 * @param {Object} arguments Request arguments map. |
| 301 * @param {function(devtools.DebuggerMessage)} callback Callback to be called | 433 * @param {function(devtools.DebuggerMessage)} callback Callback to be called |
| 302 * when response is received. | 434 * when response is received. |
| 303 */ | 435 */ |
| 304 devtools.DebuggerAgent.prototype.requestEvaluate = function( | 436 devtools.DebuggerAgent.prototype.requestEvaluate = function( |
| 305 arguments, callback) { | 437 arguments, callback) { |
| 306 var cmd = new devtools.DebugCommand('evaluate', arguments); | 438 var cmd = new devtools.DebugCommand('evaluate', arguments); |
| 307 devtools.DebuggerAgent.sendCommand_(cmd); | 439 devtools.DebuggerAgent.sendCommand_(cmd); |
| 308 this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; | 440 this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; |
| 309 }; | 441 }; |
| 310 | 442 |
| 311 | 443 |
| 312 /** | 444 /** |
| 313 * Sends 'lookup' request for each unresolved property of the object. When | 445 * Sends 'lookup' request for each unresolved property of the object. When |
| 314 * response is received the properties will be changed with their resolved | 446 * response is received the properties will be changed with their resolved |
| 315 * values. | 447 * values. |
| 316 * @param {Object} object Object whose properties should be resolved. | 448 * @param {Object} object Object whose properties should be resolved. |
| 317 * @param {function(devtools.DebuggerMessage)} Callback to be called when all | 449 * @param {function(devtools.DebuggerMessage)} Callback to be called when all |
| 318 * children are resolved. | 450 * children are resolved. |
| 451 * @param {boolean} noIntrinsic Whether intrinsic properties should be included. |
| 319 */ | 452 */ |
| 320 devtools.DebuggerAgent.prototype.resolveChildren = function(object, callback) { | 453 devtools.DebuggerAgent.prototype.resolveChildren = function(object, callback, |
| 321 if ('ref' in object) { | 454 noIntrinsic) { |
| 455 if ('handle' in object) { |
| 456 var result = []; |
| 457 devtools.DebuggerAgent.formatObjectProperties_(object, result, |
| 458 noIntrinsic); |
| 459 callback(result); |
| 460 } else { |
| 322 this.requestLookup_([object.ref], function(msg) { | 461 this.requestLookup_([object.ref], function(msg) { |
| 323 var result = {}; | 462 var result = []; |
| 324 if (msg.isSuccess()) { | 463 if (msg.isSuccess()) { |
| 325 var handleToObject = msg.getBody(); | 464 var handleToObject = msg.getBody(); |
| 326 var resolved = handleToObject[object.ref]; | 465 var resolved = handleToObject[object.ref]; |
| 327 devtools.DebuggerAgent.formatObjectProperties_(resolved, result); | 466 devtools.DebuggerAgent.formatObjectProperties_(resolved, result, |
| 467 noIntrinsic); |
| 468 callback(result); |
| 328 } else { | 469 } else { |
| 329 result.error = 'Failed to resolve children: ' + msg.getMessage(); | 470 callback([]); |
| 330 } | 471 } |
| 331 object.resolvedValue = result; | |
| 332 callback(object); | |
| 333 }); | 472 }); |
| 334 | |
| 335 return; | |
| 336 } else { | |
| 337 if (!object.resolvedValue) { | |
| 338 var message = 'Corrupted object: ' + JSON.stringify(object); | |
| 339 object.resolvedValue = {}; | |
| 340 object.resolvedValue.error = message; | |
| 341 } | |
| 342 callback(object); | |
| 343 } | 473 } |
| 344 }; | 474 }; |
| 345 | 475 |
| 346 | 476 |
| 347 /** | 477 /** |
| 348 * Starts (resumes) profiling. | 478 * Sends 'scope' request for the scope object to resolve its variables. |
| 479 * @param {Object} scope Scope to be resolved. |
| 480 * @param {function(Array.<WebInspector.ObjectPropertyProxy>)} callback |
| 481 * Callback to be called when all scope variables are resolved. |
| 349 */ | 482 */ |
| 350 devtools.DebuggerAgent.prototype.startProfiling = function() { | 483 devtools.DebuggerAgent.prototype.resolveScope = function(scope, callback) { |
| 351 if (this.isProcessingProfile_) { | 484 var cmd = new devtools.DebugCommand('scope', { |
| 352 return; | 485 'frameNumber': scope.frameNumber, |
| 353 } | 486 'number': scope.index, |
| 354 RemoteDebuggerAgent.StartProfiling(); | 487 'compactFormat': true |
| 355 // Query if profiling has been really started. | 488 }); |
| 356 RemoteDebuggerAgent.IsProfilingStarted(); | 489 devtools.DebuggerAgent.sendCommand_(cmd); |
| 490 this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { |
| 491 var result = []; |
| 492 if (msg.isSuccess()) { |
| 493 var scopeObjectJson = msg.getBody().object; |
| 494 devtools.DebuggerAgent.formatObjectProperties_(scopeObjectJson, result, |
| 495 true /* no intrinsic */); |
| 496 } |
| 497 callback(result); |
| 498 }; |
| 357 }; | 499 }; |
| 358 | 500 |
| 359 | 501 |
| 360 /** | 502 /** |
| 361 * Stops (pauses) profiling. | 503 * Sets up callbacks that deal with profiles processing. |
| 362 */ | 504 */ |
| 363 devtools.DebuggerAgent.prototype.stopProfiling = function() { | 505 devtools.DebuggerAgent.prototype.setupProfilerProcessorCallbacks = function() { |
| 364 this.isProcessingProfile_ = true; | 506 // A temporary icon indicating that the profile is being processed. |
| 365 RemoteDebuggerAgent.StopProfiling(); | 507 var processingIcon = new WebInspector.SidebarTreeElement( |
| 508 'profile-sidebar-tree-item', |
| 509 WebInspector.UIString('Processing...'), |
| 510 '', null, false); |
| 511 var profilesSidebar = WebInspector.panels.profiles.sidebarTree; |
| 512 |
| 513 this.profilerProcessor_.setCallbacks( |
| 514 function onProfileProcessingStarted() { |
| 515 // Set visually empty string. Subtitle hiding is done via styles |
| 516 // manipulation which doesn't play well with dynamic append / removal. |
| 517 processingIcon.subtitle = ' '; |
| 518 profilesSidebar.appendChild(processingIcon); |
| 519 }, |
| 520 function onProfileProcessingStatus(ticksCount) { |
| 521 processingIcon.subtitle = |
| 522 WebInspector.UIString('%d ticks processed', ticksCount); |
| 523 }, |
| 524 function onProfileProcessingFinished(profile) { |
| 525 profilesSidebar.removeChild(processingIcon); |
| 526 WebInspector.addProfile(profile); |
| 527 // If no profile is currently shown, show the new one. |
| 528 var profilesPanel = WebInspector.panels.profiles; |
| 529 if (!profilesPanel.visibleView) { |
| 530 profilesPanel.showProfile(profile); |
| 531 } |
| 532 } |
| 533 ); |
| 366 }; | 534 }; |
| 367 | 535 |
| 368 | 536 |
| 537 /** |
| 538 * Initializes profiling state. |
| 539 */ |
| 540 devtools.DebuggerAgent.prototype.initializeProfiling = function() { |
| 541 this.setupProfilerProcessorCallbacks(); |
| 542 RemoteDebuggerAgent.GetActiveProfilerModules(); |
| 543 }; |
| 544 |
| 545 |
| 546 /** |
| 547 * Starts profiling. |
| 548 * @param {number} modules List of modules to enable. |
| 549 */ |
| 550 devtools.DebuggerAgent.prototype.startProfiling = function(modules) { |
| 551 RemoteDebuggerAgent.StartProfiling(modules); |
| 552 if (modules & |
| 553 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT) { |
| 554 // Active modules will not change, instead, a snapshot will be logged. |
| 555 RemoteDebuggerAgent.GetNextLogLines(); |
| 556 } else { |
| 557 RemoteDebuggerAgent.GetActiveProfilerModules(); |
| 558 } |
| 559 }; |
| 560 |
| 561 |
| 562 /** |
| 563 * Stops profiling. |
| 564 */ |
| 565 devtools.DebuggerAgent.prototype.stopProfiling = function(modules) { |
| 566 RemoteDebuggerAgent.StopProfiling(modules); |
| 567 }; |
| 568 |
| 569 |
| 570 /** |
| 571 * @param{number} scriptId |
| 572 * @return {string} Type of the context of the script with specified id. |
| 573 */ |
| 574 devtools.DebuggerAgent.prototype.getScriptContextType = function(scriptId) { |
| 575 return this.parsedScripts_[scriptId].getContextType(); |
| 576 }; |
| 577 |
| 578 |
| 369 /** | 579 /** |
| 370 * Removes specified breakpoint from the v8 debugger. | 580 * Removes specified breakpoint from the v8 debugger. |
| 371 * @param {number} breakpointId Id of the breakpoint in the v8 debugger. | 581 * @param {number} breakpointId Id of the breakpoint in the v8 debugger. |
| 372 */ | 582 */ |
| 373 devtools.DebuggerAgent.prototype.requestClearBreakpoint_ = function( | 583 devtools.DebuggerAgent.prototype.requestClearBreakpoint_ = function( |
| 374 breakpointId) { | 584 breakpointId) { |
| 375 var cmd = new devtools.DebugCommand('clearbreakpoint', { | 585 var cmd = new devtools.DebugCommand('clearbreakpoint', { |
| 376 'breakpoint': breakpointId | 586 'breakpoint': breakpointId |
| 377 }); | 587 }); |
| 378 devtools.DebuggerAgent.sendCommand_(cmd); | 588 devtools.DebuggerAgent.sendCommand_(cmd); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 397 devtools.DebuggerAgent.sendCommand_ = function(cmd) { | 607 devtools.DebuggerAgent.sendCommand_ = function(cmd) { |
| 398 RemoteDebuggerCommandExecutor.DebuggerCommand(cmd.toJSONProtocol()); | 608 RemoteDebuggerCommandExecutor.DebuggerCommand(cmd.toJSONProtocol()); |
| 399 }; | 609 }; |
| 400 | 610 |
| 401 | 611 |
| 402 /** | 612 /** |
| 403 * Tells the v8 debugger to make the next execution step. | 613 * Tells the v8 debugger to make the next execution step. |
| 404 * @param {string} action 'in', 'out' or 'next' action. | 614 * @param {string} action 'in', 'out' or 'next' action. |
| 405 */ | 615 */ |
| 406 devtools.DebuggerAgent.prototype.stepCommand_ = function(action) { | 616 devtools.DebuggerAgent.prototype.stepCommand_ = function(action) { |
| 617 this.clearExceptionMessage_(); |
| 407 var cmd = new devtools.DebugCommand('continue', { | 618 var cmd = new devtools.DebugCommand('continue', { |
| 408 'stepaction': action, | 619 'stepaction': action, |
| 409 'stepcount': 1 | 620 'stepcount': 1 |
| 410 }); | 621 }); |
| 411 devtools.DebuggerAgent.sendCommand_(cmd); | 622 devtools.DebuggerAgent.sendCommand_(cmd); |
| 412 }; | 623 }; |
| 413 | 624 |
| 414 | 625 |
| 415 /** | 626 /** |
| 416 * Sends 'lookup' request to v8. | 627 * Sends 'lookup' request to v8. |
| 417 * @param {number} handle Handle to the object to lookup. | 628 * @param {number} handle Handle to the object to lookup. |
| 418 */ | 629 */ |
| 419 devtools.DebuggerAgent.prototype.requestLookup_ = function(handles, callback) { | 630 devtools.DebuggerAgent.prototype.requestLookup_ = function(handles, callback) { |
| 420 var cmd = new devtools.DebugCommand('lookup', { | 631 var cmd = new devtools.DebugCommand('lookup', { |
| 421 'compactFormat':true, | 632 'compactFormat':true, |
| 422 'handles': handles | 633 'handles': handles |
| 423 }); | 634 }); |
| 424 devtools.DebuggerAgent.sendCommand_(cmd); | 635 devtools.DebuggerAgent.sendCommand_(cmd); |
| 425 this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; | 636 this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; |
| 426 }; | 637 }; |
| 427 | 638 |
| 428 | 639 |
| 429 /** | 640 /** |
| 430 * Handles GetContextId response. | 641 * Sets debugger context id for scripts filtering. |
| 431 * @param {number} contextId Id of the inspected page global context. | 642 * @param {number} contextId Id of the inspected page global context. |
| 432 */ | 643 */ |
| 433 devtools.DebuggerAgent.prototype.didGetContextId_ = function(contextId) { | 644 devtools.DebuggerAgent.prototype.setContextId_ = function(contextId) { |
| 434 this.contextId_ = contextId; | 645 this.contextId_ = contextId; |
| 435 // Update scripts. | |
| 436 this.requestScripts(); | |
| 437 }; | 646 }; |
| 438 | 647 |
| 439 | 648 |
| 440 /** | 649 /** |
| 441 * Handles output sent by v8 debugger. The output is either asynchronous event | 650 * Handles output sent by v8 debugger. The output is either asynchronous event |
| 442 * or response to a previously sent request. See protocol definitioun for more | 651 * or response to a previously sent request. See protocol definitioun for more |
| 443 * details on the output format. | 652 * details on the output format. |
| 444 * @param {string} output | 653 * @param {string} output |
| 445 */ | 654 */ |
| 446 devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) { | 655 devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) { |
| 447 var msg; | 656 var msg; |
| 448 try { | 657 try { |
| 449 msg = new devtools.DebuggerMessage(output); | 658 msg = new devtools.DebuggerMessage(output); |
| 450 } catch(e) { | 659 } catch(e) { |
| 451 debugPrint('Failed to handle debugger reponse:\n' + e); | 660 debugPrint('Failed to handle debugger reponse:\n' + e); |
| 452 throw e; | 661 throw e; |
| 453 } | 662 } |
| 454 | 663 |
| 455 | |
| 456 if (msg.getType() == 'event') { | 664 if (msg.getType() == 'event') { |
| 457 if (msg.getEvent() == 'break') { | 665 if (msg.getEvent() == 'break') { |
| 458 this.handleBreakEvent_(msg); | 666 this.handleBreakEvent_(msg); |
| 459 } else if (msg.getEvent() == 'exception') { | 667 } else if (msg.getEvent() == 'exception') { |
| 460 this.handleExceptionEvent_(msg); | 668 this.handleExceptionEvent_(msg); |
| 461 } else if (msg.getEvent() == 'afterCompile') { | 669 } else if (msg.getEvent() == 'afterCompile') { |
| 462 this.handleAfterCompileEvent_(msg); | 670 this.handleAfterCompileEvent_(msg); |
| 463 } | 671 } |
| 464 } else if (msg.getType() == 'response') { | 672 } else if (msg.getType() == 'response') { |
| 465 if (msg.getCommand() == 'scripts') { | 673 if (msg.getCommand() == 'scripts') { |
| 466 this.handleScriptsResponse_(msg); | 674 this.handleScriptsResponse_(msg); |
| 467 } else if (msg.getCommand() == 'setbreakpoint') { | 675 } else if (msg.getCommand() == 'setbreakpoint') { |
| 468 this.handleSetBreakpointResponse_(msg); | 676 this.handleSetBreakpointResponse_(msg); |
| 469 } else if (msg.getCommand() == 'clearbreakpoint') { | 677 } else if (msg.getCommand() == 'clearbreakpoint') { |
| 470 this.handleClearBreakpointResponse_(msg); | 678 this.handleClearBreakpointResponse_(msg); |
| 471 } else if (msg.getCommand() == 'backtrace') { | 679 } else if (msg.getCommand() == 'backtrace') { |
| 472 this.handleBacktraceResponse_(msg); | 680 this.handleBacktraceResponse_(msg); |
| 473 } else if (msg.getCommand() == 'lookup') { | 681 } else if (msg.getCommand() == 'lookup') { |
| 474 this.invokeCallbackForResponse_(msg); | 682 this.invokeCallbackForResponse_(msg); |
| 475 } else if (msg.getCommand() == 'evaluate') { | 683 } else if (msg.getCommand() == 'evaluate') { |
| 476 this.invokeCallbackForResponse_(msg); | 684 this.invokeCallbackForResponse_(msg); |
| 685 } else if (msg.getCommand() == 'scope') { |
| 686 this.invokeCallbackForResponse_(msg); |
| 477 } | 687 } |
| 478 } | 688 } |
| 479 }; | 689 }; |
| 480 | 690 |
| 481 | 691 |
| 482 /** | 692 /** |
| 483 * @param {devtools.DebuggerMessage} msg | 693 * @param {devtools.DebuggerMessage} msg |
| 484 */ | 694 */ |
| 485 devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) { | 695 devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) { |
| 696 // Force scrips panel to be shown first. |
| 697 WebInspector.currentPanel = WebInspector.panels.scripts; |
| 698 |
| 486 var body = msg.getBody(); | 699 var body = msg.getBody(); |
| 487 | 700 |
| 488 var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); | 701 var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); |
| 489 this.currentCallFrame_ = new devtools.CallFrame(); | |
| 490 this.currentCallFrame_.sourceID = body.script.id; | |
| 491 this.currentCallFrame_.line = line; | |
| 492 this.currentCallFrame_.script = body.script; | |
| 493 this.requestBacktrace_(); | 702 this.requestBacktrace_(); |
| 494 }; | 703 }; |
| 495 | 704 |
| 496 | 705 |
| 497 /** | 706 /** |
| 498 * @param {devtools.DebuggerMessage} msg | 707 * @param {devtools.DebuggerMessage} msg |
| 499 */ | 708 */ |
| 500 devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) { | 709 devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) { |
| 710 // Force scrips panel to be shown first. |
| 711 WebInspector.currentPanel = WebInspector.panels.scripts; |
| 712 |
| 501 var body = msg.getBody(); | 713 var body = msg.getBody(); |
| 502 debugPrint('Uncaught exception in ' + body.script.name + ':' + | |
| 503 body.sourceLine + '\n' + body.sourceLineText); | |
| 504 if (this.pauseOnExceptions_) { | 714 if (this.pauseOnExceptions_) { |
| 505 var body = msg.getBody(); | 715 var body = msg.getBody(); |
| 506 | |
| 507 var sourceId = -1; | |
| 508 // The exception may happen in native code in which case there is no script. | |
| 509 if (body.script) { | |
| 510 sourceId = body.script.id; | |
| 511 } | |
| 512 | |
| 513 var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); | 716 var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); |
| 514 | 717 this.createExceptionMessage_(body.script.name, line, body.exception.text); |
| 515 this.currentCallFrame_ = new devtools.CallFrame(); | |
| 516 this.currentCallFrame_.sourceID = sourceId; | |
| 517 this.currentCallFrame_.line = line; | |
| 518 this.currentCallFrame_.script = body.script; | |
| 519 this.requestBacktrace_(); | 718 this.requestBacktrace_(); |
| 520 } else { | 719 } else { |
| 521 this.resumeExecution(); | 720 this.resumeExecution(); |
| 522 } | 721 } |
| 523 }; | 722 }; |
| 524 | 723 |
| 525 | 724 |
| 526 /** | 725 /** |
| 527 * @param {devtools.DebuggerMessage} msg | 726 * @param {devtools.DebuggerMessage} msg |
| 528 */ | 727 */ |
| 529 devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) { | 728 devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) { |
| 530 if (this.invokeCallbackForResponse_(msg)) { | 729 if (this.invokeCallbackForResponse_(msg)) { |
| 531 return; | 730 return; |
| 532 } | 731 } |
| 533 | 732 |
| 534 var scripts = msg.getBody(); | 733 var scripts = msg.getBody(); |
| 535 for (var i = 0; i < scripts.length; i++) { | 734 for (var i = 0; i < scripts.length; i++) { |
| 536 var script = scripts[i]; | 735 var script = scripts[i]; |
| 537 | 736 |
| 538 // Skip scripts from other tabs. | 737 // Skip scripts from other tabs. |
| 539 if (!this.isScriptFromInspectedContext_(script, msg)) { | 738 if (!this.isScriptFromInspectedContext_(script, msg)) { |
| 540 continue; | 739 continue; |
| 541 } | 740 } |
| 542 | 741 |
| 742 // There is no script source |
| 743 if (this.isVoidScript_(script)) { |
| 744 continue; |
| 745 } |
| 746 |
| 543 // We may already have received the info in an afterCompile event. | 747 // We may already have received the info in an afterCompile event. |
| 544 if (script.id in this.parsedScripts_) { | 748 if (script.id in this.parsedScripts_) { |
| 545 continue; | 749 continue; |
| 546 } | 750 } |
| 547 this.addScriptInfo_(script); | 751 this.addScriptInfo_(script, msg); |
| 548 } | 752 } |
| 549 }; | 753 }; |
| 550 | 754 |
| 551 | 755 |
| 552 /** | 756 /** |
| 553 * @param {Object} script Json object representing script. | 757 * @param {Object} script Json object representing script. |
| 554 * @param {devtools.DebuggerMessage} msg Debugger response. | 758 * @param {devtools.DebuggerMessage} msg Debugger response. |
| 555 */ | 759 */ |
| 556 devtools.DebuggerAgent.prototype.isScriptFromInspectedContext_ = function( | 760 devtools.DebuggerAgent.prototype.isScriptFromInspectedContext_ = function( |
| 557 script, msg) { | 761 script, msg) { |
| 558 if (!script.context) { | 762 if (!script.context) { |
| 559 // Always ignore scripts from the utility context. | 763 // Always ignore scripts from the utility context. |
| 560 return false; | 764 return false; |
| 561 } | 765 } |
| 562 var context = msg.lookup(script.context.ref); | 766 var context = msg.lookup(script.context.ref); |
| 563 var scriptContextId = context.data; | 767 var scriptContextId = context.data; |
| 564 if (!goog.isDef(scriptContextId)) { | 768 if (!goog.isDef(scriptContextId)) { |
| 565 return false; // Always ignore scripts from the utility context. | 769 return false; // Always ignore scripts from the utility context. |
| 566 } | 770 } |
| 567 if (this.contextId_ === null) { | 771 if (this.contextId_ === null) { |
| 568 return true; | 772 return true; |
| 569 } | 773 } |
| 570 return (scriptContextId == this.contextId_); | 774 return (scriptContextId.value == this.contextId_); |
| 571 }; | 775 }; |
| 572 | 776 |
| 573 | 777 |
| 574 /** | 778 /** |
| 575 * @param {devtools.DebuggerMessage} msg | 779 * @param {devtools.DebuggerMessage} msg |
| 576 */ | 780 */ |
| 577 devtools.DebuggerAgent.prototype.handleSetBreakpointResponse_ = function(msg) { | 781 devtools.DebuggerAgent.prototype.handleSetBreakpointResponse_ = function(msg) { |
| 578 var requestSeq = msg.getRequestSeq(); | 782 var requestSeq = msg.getRequestSeq(); |
| 579 var breakpointInfo = this.requestNumberToBreakpointInfo_[requestSeq]; | 783 var breakpointInfo = this.requestNumberToBreakpointInfo_[requestSeq]; |
| 580 if (!breakpointInfo) { | 784 if (!breakpointInfo) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 592 if (breakpointInfo.isRemoved()) { | 796 if (breakpointInfo.isRemoved()) { |
| 593 this.requestClearBreakpoint_(idInV8); | 797 this.requestClearBreakpoint_(idInV8); |
| 594 } | 798 } |
| 595 }; | 799 }; |
| 596 | 800 |
| 597 | 801 |
| 598 /** | 802 /** |
| 599 * @param {devtools.DebuggerMessage} msg | 803 * @param {devtools.DebuggerMessage} msg |
| 600 */ | 804 */ |
| 601 devtools.DebuggerAgent.prototype.handleAfterCompileEvent_ = function(msg) { | 805 devtools.DebuggerAgent.prototype.handleAfterCompileEvent_ = function(msg) { |
| 806 if (!this.contextId_) { |
| 807 // Ignore scripts delta if main request has not been issued yet. |
| 808 return; |
| 809 } |
| 602 var script = msg.getBody().script; | 810 var script = msg.getBody().script; |
| 811 |
| 812 if (this.isVoidScript_(script)) { |
| 813 return; |
| 814 } |
| 815 |
| 603 // Ignore scripts from other tabs. | 816 // Ignore scripts from other tabs. |
| 604 if (!this.isScriptFromInspectedContext_(script, msg)) { | 817 if (!this.isScriptFromInspectedContext_(script, msg)) { |
| 605 return; | 818 return; |
| 606 } | 819 } |
| 607 this.addScriptInfo_(script); | 820 this.addScriptInfo_(script, msg); |
| 821 }; |
| 822 |
| 823 |
| 824 /** |
| 825 * @param {Object} script Parsed JSON object representing script. |
| 826 * @return {boolean} Whether the script is a result of the void script |
| 827 * evaluation and should not appear in the UI. |
| 828 */ |
| 829 devtools.DebuggerAgent.prototype.isVoidScript_ = function(script) { |
| 830 return !script.name && |
| 831 (script.sourceStart == devtools.DebuggerAgent.VOID_SCRIPT || |
| 832 script.source == devtools.DebuggerAgent.VOID_SCRIPT); |
| 608 }; | 833 }; |
| 609 | 834 |
| 610 | 835 |
| 611 /** | 836 /** |
| 612 * Handles current profiler status. | 837 * Handles current profiler status. |
| 838 * @param {number} modules List of active (started) modules. |
| 613 */ | 839 */ |
| 614 devtools.DebuggerAgent.prototype.didIsProfilingStarted_ = function( | 840 devtools.DebuggerAgent.prototype.didGetActiveProfilerModules_ = function( |
| 615 is_started) { | 841 modules) { |
| 616 if (is_started) { | 842 var profModules = devtools.DebuggerAgent.ProfilerModules; |
| 843 var profModuleNone = profModules.PROFILER_MODULE_NONE; |
| 844 if (modules != profModuleNone && |
| 845 this.activeProfilerModules_ == profModuleNone) { |
| 617 // Start to query log data. | 846 // Start to query log data. |
| 618 RemoteDebuggerAgent.GetLogLines(this.lastProfileLogPosition_); | 847 RemoteDebuggerAgent.GetNextLogLines(); |
| 619 } | 848 } |
| 620 WebInspector.setRecordingProfile(is_started); | 849 this.activeProfilerModules_ = modules; |
| 850 // Update buttons. |
| 851 WebInspector.setRecordingProfile(modules & profModules.PROFILER_MODULE_CPU); |
| 852 if (modules != profModuleNone) { |
| 853 // Monitor profiler state. It can stop itself on buffer fill-up. |
| 854 setTimeout( |
| 855 function() { RemoteDebuggerAgent.GetActiveProfilerModules(); }, 1000); |
| 856 } |
| 621 }; | 857 }; |
| 622 | 858 |
| 623 | 859 |
| 624 /** | 860 /** |
| 625 * Handles a portion of a profiler log retrieved by GetLogLines call. | 861 * Handles a portion of a profiler log retrieved by GetNextLogLines call. |
| 626 * @param {string} log A portion of profiler log. | 862 * @param {string} log A portion of profiler log. |
| 627 * @param {number} newPosition The position in log file to read from | |
| 628 * next time. | |
| 629 */ | 863 */ |
| 630 devtools.DebuggerAgent.prototype.didGetLogLines_ = function( | 864 devtools.DebuggerAgent.prototype.didGetNextLogLines_ = function(log) { |
| 631 log, newPosition) { | |
| 632 if (log.length > 0) { | 865 if (log.length > 0) { |
| 633 this.profilerProcessor_.processLogChunk(log); | 866 this.profilerProcessor_.processLogChunk(log); |
| 634 this.lastProfileLogPosition_ = newPosition; | 867 } else if (this.activeProfilerModules_ == |
| 635 } else if (this.isProcessingProfile_) { | 868 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE) { |
| 636 this.isProcessingProfile_ = false; | 869 // No new data and profiling is stopped---suspend log reading. |
| 637 WebInspector.setRecordingProfile(false); | |
| 638 WebInspector.addProfile(this.profilerProcessor_.createProfileForView()); | |
| 639 return; | 870 return; |
| 640 } | 871 } |
| 641 setTimeout(function() { RemoteDebuggerAgent.GetLogLines(newPosition); }, | 872 setTimeout(function() { RemoteDebuggerAgent.GetNextLogLines(); }, 500); |
| 642 this.isProcessingProfile_ ? 100 : 1000); | |
| 643 }; | 873 }; |
| 644 | 874 |
| 645 | 875 |
| 646 /** | 876 /** |
| 647 * Adds the script info to the local cache. This method assumes that the script | 877 * Adds the script info to the local cache. This method assumes that the script |
| 648 * is not in the cache yet. | 878 * is not in the cache yet. |
| 649 * @param {Object} script Script json object from the debugger message. | 879 * @param {Object} script Script json object from the debugger message. |
| 880 * @param {devtools.DebuggerMessage} msg Debugger message containing the script |
| 881 * data. |
| 650 */ | 882 */ |
| 651 devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script) { | 883 devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script, msg) { |
| 884 var context = msg.lookup(script.context.ref); |
| 885 var contextType = context.data.type; |
| 652 this.parsedScripts_[script.id] = new devtools.ScriptInfo( | 886 this.parsedScripts_[script.id] = new devtools.ScriptInfo( |
| 653 script.id, script.lineOffset); | 887 script.id, script.name, script.lineOffset, contextType); |
| 654 WebInspector.parsedScriptSource( | 888 if (WebInspector.panels.scripts.element.parentElement) { |
| 655 script.id, script.name, script.source, script.lineOffset); | 889 // Only report script as parsed after scripts panel has been shown. |
| 890 WebInspector.parsedScriptSource( |
| 891 script.id, script.name, script.source, script.lineOffset); |
| 892 } |
| 656 }; | 893 }; |
| 657 | 894 |
| 658 | 895 |
| 659 /** | 896 /** |
| 660 * @param {devtools.DebuggerMessage} msg | 897 * @param {devtools.DebuggerMessage} msg |
| 661 */ | 898 */ |
| 662 devtools.DebuggerAgent.prototype.handleClearBreakpointResponse_ = function( | 899 devtools.DebuggerAgent.prototype.handleClearBreakpointResponse_ = function( |
| 663 msg) { | 900 msg) { |
| 664 // Do nothing. | 901 // Do nothing. |
| 665 }; | 902 }; |
| 666 | 903 |
| 667 | 904 |
| 668 /** | 905 /** |
| 669 * Handles response to 'backtrace' command. | 906 * Handles response to 'backtrace' command. |
| 670 * @param {devtools.DebuggerMessage} msg | 907 * @param {devtools.DebuggerMessage} msg |
| 671 */ | 908 */ |
| 672 devtools.DebuggerAgent.prototype.handleBacktraceResponse_ = function(msg) { | 909 devtools.DebuggerAgent.prototype.handleBacktraceResponse_ = function(msg) { |
| 673 if (!this.currentCallFrame_) { | 910 var frames = msg.getBody().frames; |
| 674 return; | 911 this.callFrames_ = []; |
| 912 for (var i = 0; i < frames.length; ++i) { |
| 913 this.callFrames_.push(this.formatCallFrame_(frames[i])); |
| 675 } | 914 } |
| 676 | 915 WebInspector.pausedScript(this.callFrames_); |
| 677 var script = this.currentCallFrame_.script; | 916 this.showPendingExceptionMessage_(); |
| 678 | |
| 679 var callerFrame = null; | |
| 680 var f = null; | |
| 681 var frames = msg.getBody().frames; | |
| 682 for (var i = frames.length - 1; i>=0; i--) { | |
| 683 var nextFrame = frames[i]; | |
| 684 var f = devtools.DebuggerAgent.formatCallFrame_(nextFrame, script, msg); | |
| 685 f.frameNumber = i; | |
| 686 f.caller = callerFrame; | |
| 687 callerFrame = f; | |
| 688 } | |
| 689 | |
| 690 this.currentCallFrame_ = f; | |
| 691 | |
| 692 WebInspector.pausedScript(); | |
| 693 DevToolsHost.activateWindow(); | 917 DevToolsHost.activateWindow(); |
| 694 }; | 918 }; |
| 695 | 919 |
| 696 | 920 |
| 921 /** |
| 922 * Returns current suspended stack. |
| 923 */ |
| 924 devtools.DebuggerAgent.prototype.getCallFrames = function(callback) { |
| 925 return this.callFrames_; |
| 926 }; |
| 927 |
| 928 |
| 929 /** |
| 930 * Evaluates code on given callframe. |
| 931 */ |
| 932 devtools.DebuggerAgent.prototype.evaluateInCallFrame = function( |
| 933 callFrameId, code, callback) { |
| 934 var callFrame = this.callFrames_[callFrameId]; |
| 935 callFrame.evaluate_(code, callback); |
| 936 }; |
| 937 |
| 938 |
| 697 /** | 939 /** |
| 698 * Handles response to a command by invoking its callback (if any). | 940 * Handles response to a command by invoking its callback (if any). |
| 699 * @param {devtools.DebuggerMessage} msg | 941 * @param {devtools.DebuggerMessage} msg |
| 700 * @return {boolean} Whether a callback for the given message was found and | 942 * @return {boolean} Whether a callback for the given message was found and |
| 701 * excuted. | 943 * excuted. |
| 702 */ | 944 */ |
| 703 devtools.DebuggerAgent.prototype.invokeCallbackForResponse_ = function(msg) { | 945 devtools.DebuggerAgent.prototype.invokeCallbackForResponse_ = function(msg) { |
| 704 var callback = this.requestSeqToCallback_[msg.getRequestSeq()]; | 946 var callback = this.requestSeqToCallback_[msg.getRequestSeq()]; |
| 705 if (!callback) { | 947 if (!callback) { |
| 706 // It may happend if reset was called. | 948 // It may happend if reset was called. |
| 707 return false; | 949 return false; |
| 708 } | 950 } |
| 709 delete this.requestSeqToCallback_[msg.getRequestSeq()]; | 951 delete this.requestSeqToCallback_[msg.getRequestSeq()]; |
| 710 callback(msg); | 952 callback(msg); |
| 711 return true; | 953 return true; |
| 712 }; | 954 }; |
| 713 | 955 |
| 714 | 956 |
| 715 devtools.DebuggerAgent.prototype.evaluateInCallFrame_ = function(expression) { | |
| 716 }; | |
| 717 | |
| 718 | |
| 719 /** | 957 /** |
| 720 * @param {Object} stackFrame Frame json object from 'backtrace' response. | 958 * @param {Object} stackFrame Frame json object from 'backtrace' response. |
| 721 * @param {Object} script Script json object from 'break' event. | |
| 722 * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response. | |
| 723 * @return {!devtools.CallFrame} Object containing information related to the | 959 * @return {!devtools.CallFrame} Object containing information related to the |
| 724 * call frame in the format expected by ScriptsPanel and its panes. | 960 * call frame in the format expected by ScriptsPanel and its panes. |
| 725 */ | 961 */ |
| 726 devtools.DebuggerAgent.formatCallFrame_ = function(stackFrame, script, msg) { | 962 devtools.DebuggerAgent.prototype.formatCallFrame_ = function(stackFrame) { |
| 727 var sourceId = script.id; | |
| 728 | |
| 729 var func = stackFrame.func; | 963 var func = stackFrame.func; |
| 730 var sourceId = func.scriptId; | 964 var sourceId = func.scriptId; |
| 965 |
| 966 // Add service script if it does not exist. |
| 967 var existingScript = this.parsedScripts_[sourceId]; |
| 968 if (!existingScript) { |
| 969 this.parsedScripts_[sourceId] = new devtools.ScriptInfo( |
| 970 sourceId, null /* name */, 0 /* line */, 'unknown' /* type */, |
| 971 true /* unresolved */); |
| 972 WebInspector.parsedScriptSource(sourceId, null, null, 0); |
| 973 } |
| 974 |
| 731 var funcName = func.name || func.inferredName || '(anonymous function)'; | 975 var funcName = func.name || func.inferredName || '(anonymous function)'; |
| 976 var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(stackFrame.line); |
| 732 | 977 |
| 733 var scope = {}; | 978 // Add basic scope chain info with scope variables. |
| 734 | 979 var scopeChain = []; |
| 735 // Add arguments. | 980 var ScopeType = devtools.DebuggerAgent.ScopeType; |
| 736 devtools.DebuggerAgent.argumentsArrayToMap_(stackFrame.arguments, scope); | 981 for (var i = 0; i < stackFrame.scopes.length; i++) { |
| 737 | 982 var scope = stackFrame.scopes[i]; |
| 738 // Add local variables. | 983 scope.frameNumber = stackFrame.index; |
| 739 devtools.DebuggerAgent.propertiesToMap_(stackFrame.locals, scope); | 984 var scopeObjectProxy = new WebInspector.ObjectProxy(scope, [], 0, '', true); |
| 740 | 985 scopeObjectProxy.isScope = true; |
| 741 var thisObject = devtools.DebuggerAgent.formatObjectReference_( | 986 scopeObjectProxy.properties = {}; // TODO(pfeldman): Fix autocomplete. |
| 742 stackFrame.receiver); | 987 switch(scope.type) { |
| 743 // Add variable with name 'this' to the scope. | 988 case ScopeType.Global: |
| 744 scope['this'] = thisObject; | 989 scopeObjectProxy.isDocument = true; |
| 745 | 990 break; |
| 746 var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(stackFrame.line); | 991 case ScopeType.Local: |
| 747 var result = new devtools.CallFrame(); | 992 scopeObjectProxy.isLocal = true; |
| 748 result.sourceID = sourceId; | 993 scopeObjectProxy.thisObject = |
| 749 result.line = line; | 994 devtools.DebuggerAgent.formatObjectProxy_(stackFrame.receiver); |
| 750 result.type = 'function'; | 995 break; |
| 751 result.functionName = funcName; | 996 case ScopeType.With: |
| 752 result.localScope = scope; | 997 scopeObjectProxy.isWithBlock = true; |
| 753 result.scopeChain = [scope]; | 998 break; |
| 754 result.thisObject = thisObject; | 999 case ScopeType.Closure: |
| 755 return result; | 1000 scopeObjectProxy.isClosure = true; |
| 1001 break; |
| 1002 } |
| 1003 scopeChain.push(scopeObjectProxy); |
| 1004 } |
| 1005 return new devtools.CallFrame(stackFrame.index, 'function', funcName, |
| 1006 sourceId, line, scopeChain); |
| 756 }; | 1007 }; |
| 757 | 1008 |
| 758 | 1009 |
| 759 /** | 1010 /** |
| 760 * Collects properties for an object from the debugger response. | 1011 * Collects properties for an object from the debugger response. |
| 761 * @param {Object} object An object from the debugger protocol response. | 1012 * @param {Object} object An object from the debugger protocol response. |
| 762 * @param {Object} result A map to put the properties in. | 1013 * @param {Array.<WebInspector.ObjectPropertyProxy>} result An array to put the |
| 1014 * properties into. |
| 1015 * @param {boolean} noIntrinsic Whether intrinsic properties should be |
| 1016 * included. |
| 763 */ | 1017 */ |
| 764 devtools.DebuggerAgent.formatObjectProperties_ = function(object, result) { | 1018 devtools.DebuggerAgent.formatObjectProperties_ = function(object, result, |
| 765 devtools.DebuggerAgent.propertiesToMap_(object.properties, result); | 1019 noIntrinsic) { |
| 766 result.protoObject = devtools.DebuggerAgent.formatObjectReference_( | 1020 devtools.DebuggerAgent.propertiesToProxies_(object.properties, result); |
| 767 object.protoObject); | 1021 if (noIntrinsic) { |
| 768 result.prototypeObject = devtools.DebuggerAgent.formatObjectReference_( | 1022 return; |
| 769 object.prototypeObject); | 1023 } |
| 770 result.constructorFunction = devtools.DebuggerAgent.formatObjectReference_( | 1024 |
| 771 object.constructorFunction); | 1025 result.push(new WebInspector.ObjectPropertyProxy('__proto__', |
| 1026 devtools.DebuggerAgent.formatObjectProxy_(object.protoObject))); |
| 1027 result.push(new WebInspector.ObjectPropertyProxy('prototype', |
| 1028 devtools.DebuggerAgent.formatObjectProxy_(object.prototypeObject))); |
| 1029 result.push(new WebInspector.ObjectPropertyProxy('constructor', |
| 1030 devtools.DebuggerAgent.formatObjectProxy_(object.constructorFunction))); |
| 772 }; | 1031 }; |
| 773 | 1032 |
| 774 | 1033 |
| 775 /** | 1034 /** |
| 776 * For each property in 'properties' puts its name and user-friendly value into | 1035 * For each property in 'properties' creates its proxy representative. |
| 777 * 'map'. | |
| 778 * @param {Array.<Object>} properties Receiver properties or locals array from | 1036 * @param {Array.<Object>} properties Receiver properties or locals array from |
| 779 * 'backtrace' response. | 1037 * 'backtrace' response. |
| 780 * @param {Object} map Result holder. | 1038 * @param {Array.<WebInspector.ObjectPropertyProxy>} Results holder. |
| 781 */ | 1039 */ |
| 782 devtools.DebuggerAgent.propertiesToMap_ = function(properties, map) { | 1040 devtools.DebuggerAgent.propertiesToProxies_ = function(properties, result) { |
| 783 for (var j = 0; j < properties.length; j++) { | 1041 var map = {}; |
| 784 var nextValue = properties[j]; | 1042 for (var i = 0; i < properties.length; ++i) { |
| 785 // Skip unnamed properties. They may appear e.g. when number of actual | 1043 var property = properties[i]; |
| 786 // parameters is greater the that of formal. In that case the superfluous | 1044 var name = String(property.name); |
| 787 // parameters will be present in the arguments list as elements without | 1045 if (name in map) { |
| 788 // names. | 1046 continue; |
| 789 if (nextValue.name) { | |
| 790 map[nextValue.name] = | |
| 791 devtools.DebuggerAgent.formatObjectReference_(nextValue.value); | |
| 792 } | 1047 } |
| 1048 map[name] = true; |
| 1049 var value = devtools.DebuggerAgent.formatObjectProxy_(property.value); |
| 1050 var propertyProxy = new WebInspector.ObjectPropertyProxy(name, value); |
| 1051 result.push(propertyProxy); |
| 793 } | 1052 } |
| 794 }; | 1053 }; |
| 795 | 1054 |
| 796 | |
| 797 /** | |
| 798 * Puts arguments from the protocol arguments array to the map assigning names | |
| 799 * to the anonymous arguments. | |
| 800 * @param {Array.<Object>} array Arguments array from 'backtrace' response. | |
| 801 * @param {Object} map Result holder. | |
| 802 */ | |
| 803 devtools.DebuggerAgent.argumentsArrayToMap_ = function(array, map) { | |
| 804 for (var j = 0; j < array.length; j++) { | |
| 805 var nextValue = array[j]; | |
| 806 // Skip unnamed properties. They may appear e.g. when number of actual | |
| 807 // parameters is greater the that of formal. In that case the superfluous | |
| 808 // parameters will be present in the arguments list as elements without | |
| 809 // names. | |
| 810 var name = nextValue.name ? nextValue.name : '<arg #' + j + '>'; | |
| 811 map[name] = devtools.DebuggerAgent.formatObjectReference_(nextValue.value); | |
| 812 } | |
| 813 }; | |
| 814 | |
| 815 | 1055 |
| 816 /** | 1056 /** |
| 817 * @param {Object} v An object reference from the debugger response. | 1057 * @param {Object} v An object reference from the debugger response. |
| 818 * @return {*} The value representation expected by ScriptsPanel. | 1058 * @return {*} The value representation expected by ScriptsPanel. |
| 819 */ | 1059 */ |
| 820 devtools.DebuggerAgent.formatObjectReference_ = function(v) { | 1060 devtools.DebuggerAgent.formatObjectProxy_ = function(v) { |
| 1061 var description; |
| 1062 var hasChildren = false; |
| 821 if (v.type == 'object') { | 1063 if (v.type == 'object') { |
| 822 return v; | 1064 description = v.className; |
| 1065 hasChildren = true; |
| 823 } else if (v.type == 'function') { | 1066 } else if (v.type == 'function') { |
| 824 var f = function() {}; | 1067 if (v.source) { |
| 825 f.ref = v.ref; | 1068 description = v.source; |
| 826 return f; | 1069 } else { |
| 1070 description = 'function ' + v.name + '()'; |
| 1071 } |
| 1072 hasChildren = true; |
| 827 } else if (goog.isDef(v.value)) { | 1073 } else if (goog.isDef(v.value)) { |
| 828 return v.value; | 1074 description = v.value; |
| 829 } else if (v.type == 'undefined') { | 1075 } else if (v.type == 'undefined') { |
| 830 return 'undefined'; | 1076 description = 'undefined'; |
| 831 } else if (v.type == 'null') { | 1077 } else if (v.type == 'null') { |
| 832 return 'null'; | 1078 description = 'null'; |
| 833 } else if (v.name) { | |
| 834 return v.name; | |
| 835 } else if (v.className) { | |
| 836 return v.className; | |
| 837 } else { | 1079 } else { |
| 838 return '<unresolved ref: ' + v.ref + ', type: ' + v.type + '>'; | 1080 description = '<unresolved ref: ' + v.ref + ', type: ' + v.type + '>'; |
| 839 } | 1081 } |
| 1082 var proxy = new WebInspector.ObjectProxy(v, [], 0, description, hasChildren); |
| 1083 proxy.type = v.type; |
| 1084 proxy.isV8Ref = true; |
| 1085 return proxy; |
| 840 }; | 1086 }; |
| 841 | 1087 |
| 842 | 1088 |
| 843 /** | 1089 /** |
| 844 * Converts line number from Web Inspector UI(1-based) to v8(0-based). | 1090 * Converts line number from Web Inspector UI(1-based) to v8(0-based). |
| 845 * @param {number} line Resource line number in Web Inspector UI. | 1091 * @param {number} line Resource line number in Web Inspector UI. |
| 846 * @return {number} The line number in v8. | 1092 * @return {number} The line number in v8. |
| 847 */ | 1093 */ |
| 848 devtools.DebuggerAgent.webkitToV8LineNumber_ = function(line) { | 1094 devtools.DebuggerAgent.webkitToV8LineNumber_ = function(line) { |
| 849 return line - 1; | 1095 return line - 1; |
| 850 }; | 1096 }; |
| 851 | 1097 |
| 852 | 1098 |
| 853 /** | 1099 /** |
| 854 * Converts line number from v8(0-based) to Web Inspector UI(1-based). | 1100 * Converts line number from v8(0-based) to Web Inspector UI(1-based). |
| 855 * @param {number} line Resource line number in v8. | 1101 * @param {number} line Resource line number in v8. |
| 856 * @return {number} The line number in Web Inspector. | 1102 * @return {number} The line number in Web Inspector. |
| 857 */ | 1103 */ |
| 858 devtools.DebuggerAgent.v8ToWwebkitLineNumber_ = function(line) { | 1104 devtools.DebuggerAgent.v8ToWwebkitLineNumber_ = function(line) { |
| 859 return line + 1; | 1105 return line + 1; |
| 860 }; | 1106 }; |
| 861 | 1107 |
| 862 | 1108 |
| 863 /** | 1109 /** |
| 864 * @param {number} scriptId Id of the script. | 1110 * @param {number} scriptId Id of the script. |
| 1111 * @param {?string} url Script resource URL if any. |
| 865 * @param {number} lineOffset First line 0-based offset in the containing | 1112 * @param {number} lineOffset First line 0-based offset in the containing |
| 866 * document. | 1113 * document. |
| 1114 * @param {string} contextType Type of the script's context: |
| 1115 * "page" - regular script from html page |
| 1116 * "injected" - extension content script |
| 1117 * @param {bool} opt_isUnresolved If true, script will not be resolved. |
| 867 * @constructor | 1118 * @constructor |
| 868 */ | 1119 */ |
| 869 devtools.ScriptInfo = function(scriptId, lineOffset) { | 1120 devtools.ScriptInfo = function( |
| 1121 scriptId, url, lineOffset, contextType, opt_isUnresolved) { |
| 870 this.scriptId_ = scriptId; | 1122 this.scriptId_ = scriptId; |
| 871 this.lineOffset_ = lineOffset; | 1123 this.lineOffset_ = lineOffset; |
| 1124 this.contextType_ = contextType; |
| 1125 this.url_ = url; |
| 1126 this.isUnresolved_ = opt_isUnresolved; |
| 872 | 1127 |
| 873 this.lineToBreakpointInfo_ = {}; | 1128 this.lineToBreakpointInfo_ = {}; |
| 874 }; | 1129 }; |
| 875 | 1130 |
| 876 | 1131 |
| 877 /** | 1132 /** |
| 878 * @return {number} | 1133 * @return {number} |
| 879 */ | 1134 */ |
| 880 devtools.ScriptInfo.prototype.getLineOffset = function() { | 1135 devtools.ScriptInfo.prototype.getLineOffset = function() { |
| 881 return this.lineOffset_; | 1136 return this.lineOffset_; |
| 882 }; | 1137 }; |
| 883 | 1138 |
| 884 | 1139 |
| 885 /** | 1140 /** |
| 1141 * @return {string} |
| 1142 */ |
| 1143 devtools.ScriptInfo.prototype.getContextType = function() { |
| 1144 return this.contextType_; |
| 1145 }; |
| 1146 |
| 1147 |
| 1148 /** |
| 1149 * @return {?string} |
| 1150 */ |
| 1151 devtools.ScriptInfo.prototype.getUrl = function() { |
| 1152 return this.url_; |
| 1153 }; |
| 1154 |
| 1155 |
| 1156 /** |
| 1157 * @return {?bool} |
| 1158 */ |
| 1159 devtools.ScriptInfo.prototype.isUnresolved = function() { |
| 1160 return this.isUnresolved_; |
| 1161 }; |
| 1162 |
| 1163 |
| 1164 /** |
| 886 * @param {number} line 0-based line number in the script. | 1165 * @param {number} line 0-based line number in the script. |
| 887 * @return {?devtools.BreakpointInfo} Information on a breakpoint at the | 1166 * @return {?devtools.BreakpointInfo} Information on a breakpoint at the |
| 888 * specified line in the script or undefined if there is no breakpoint at | 1167 * specified line in the script or undefined if there is no breakpoint at |
| 889 * that line. | 1168 * that line. |
| 890 */ | 1169 */ |
| 891 devtools.ScriptInfo.prototype.getBreakpointInfo = function(line) { | 1170 devtools.ScriptInfo.prototype.getBreakpointInfo = function(line) { |
| 892 return this.lineToBreakpointInfo_[line]; | 1171 return this.lineToBreakpointInfo_[line]; |
| 893 }; | 1172 }; |
| 894 | 1173 |
| 895 | 1174 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 906 * @param {devtools.BreakpointInfo} breakpoint Breakpoint info to be removed. | 1185 * @param {devtools.BreakpointInfo} breakpoint Breakpoint info to be removed. |
| 907 */ | 1186 */ |
| 908 devtools.ScriptInfo.prototype.removeBreakpointInfo = function(breakpoint) { | 1187 devtools.ScriptInfo.prototype.removeBreakpointInfo = function(breakpoint) { |
| 909 var line = breakpoint.getLine(); | 1188 var line = breakpoint.getLine(); |
| 910 delete this.lineToBreakpointInfo_[line]; | 1189 delete this.lineToBreakpointInfo_[line]; |
| 911 }; | 1190 }; |
| 912 | 1191 |
| 913 | 1192 |
| 914 | 1193 |
| 915 /** | 1194 /** |
| 916 * @param {number} scriptId Id of the owning script. | |
| 917 * @param {number} line Breakpoint 0-based line number in the containing script. | 1195 * @param {number} line Breakpoint 0-based line number in the containing script. |
| 918 * @constructor | 1196 * @constructor |
| 919 */ | 1197 */ |
| 920 devtools.BreakpointInfo = function(sourceId, line) { | 1198 devtools.BreakpointInfo = function(line) { |
| 921 this.sourceId_ = sourceId; | |
| 922 this.line_ = line; | 1199 this.line_ = line; |
| 923 this.v8id_ = -1; | 1200 this.v8id_ = -1; |
| 924 this.removed_ = false; | 1201 this.removed_ = false; |
| 925 }; | 1202 }; |
| 926 | 1203 |
| 927 | 1204 |
| 928 /** | 1205 /** |
| 929 * @return {number} | 1206 * @return {number} |
| 930 */ | 1207 */ |
| 931 devtools.BreakpointInfo.prototype.getSourceId = function(n) { | |
| 932 return this.sourceId_; | |
| 933 }; | |
| 934 | |
| 935 | |
| 936 /** | |
| 937 * @return {number} | |
| 938 */ | |
| 939 devtools.BreakpointInfo.prototype.getLine = function(n) { | 1208 devtools.BreakpointInfo.prototype.getLine = function(n) { |
| 940 return this.line_; | 1209 return this.line_; |
| 941 }; | 1210 }; |
| 942 | 1211 |
| 943 | 1212 |
| 944 /** | 1213 /** |
| 945 * @return {number} Unique identifier of this breakpoint in the v8 debugger. | 1214 * @return {number} Unique identifier of this breakpoint in the v8 debugger. |
| 946 */ | 1215 */ |
| 947 devtools.BreakpointInfo.prototype.getV8Id = function(n) { | 1216 devtools.BreakpointInfo.prototype.getV8Id = function(n) { |
| 948 return this.v8id_; | 1217 return this.v8id_; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 970 * @return {boolean} Whether this breakpoint has been removed from the | 1239 * @return {boolean} Whether this breakpoint has been removed from the |
| 971 * front-end. | 1240 * front-end. |
| 972 */ | 1241 */ |
| 973 devtools.BreakpointInfo.prototype.isRemoved = function() { | 1242 devtools.BreakpointInfo.prototype.isRemoved = function() { |
| 974 return this.removed_; | 1243 return this.removed_; |
| 975 }; | 1244 }; |
| 976 | 1245 |
| 977 | 1246 |
| 978 /** | 1247 /** |
| 979 * Call stack frame data. | 1248 * Call stack frame data. |
| 1249 * @param {string} id CallFrame id. |
| 1250 * @param {string} type CallFrame type. |
| 1251 * @param {string} functionName CallFrame type. |
| 1252 * @param {string} sourceID Source id. |
| 1253 * @param {number} line Source line. |
| 1254 * @param {Array.<Object>} scopeChain Array of scoped objects. |
| 980 * @construnctor | 1255 * @construnctor |
| 981 */ | 1256 */ |
| 982 devtools.CallFrame = function() { | 1257 devtools.CallFrame = function(id, type, functionName, sourceID, line, |
| 983 this.sourceID = null; | 1258 scopeChain) { |
| 984 this.line = null; | 1259 this.id = id; |
| 985 this.type = 'function'; | 1260 this.type = type; |
| 986 this.functionName = null; | 1261 this.functionName = functionName; |
| 987 this.caller = null; | 1262 this.sourceID = sourceID; |
| 988 this.localScope = null; | 1263 this.line = line; |
| 989 this.scopeChain = []; | 1264 this.scopeChain = scopeChain; |
| 990 this.thisObject = {}; | |
| 991 this.frameNumber = null; | |
| 992 }; | 1265 }; |
| 993 | 1266 |
| 994 | 1267 |
| 995 /** | 1268 /** |
| 996 * This method is called by | 1269 * This method issues asynchronous evaluate request, reports result to the |
| 997 * WebInspector.ScriptsPanel.evaluateInSelectedCallFrame. This method issues | 1270 * callback. |
| 998 * asynchronous evaluate request. | |
| 999 * @param {string} expression An expression to be evaluated in the context of | 1271 * @param {string} expression An expression to be evaluated in the context of |
| 1000 * this call frame. | 1272 * this call frame. |
| 1001 * @return {string} User message that the expression is being evaluated. | 1273 * @param {function(Object):undefined} callback Callback to report result to. |
| 1002 */ | 1274 */ |
| 1003 devtools.CallFrame.prototype.evaluate = function(expression) { | 1275 devtools.CallFrame.prototype.evaluate_ = function(expression, callback) { |
| 1004 devtools.tools.getDebuggerAgent().requestEvaluate({ | 1276 devtools.tools.getDebuggerAgent().requestEvaluate({ |
| 1005 'expression': expression, | 1277 'expression': expression, |
| 1006 'frame': this.frameNumber, | 1278 'frame': this.id, |
| 1007 'global': false, | 1279 'global': false, |
| 1008 'disable_break': false | 1280 'disable_break': false, |
| 1009 }, | 1281 'compactFormat': true |
| 1010 devtools.CallFrame.handleEvaluateResponse_); | 1282 }, |
| 1011 return 'evaluating...'; | 1283 function(response) { |
| 1284 var result = {}; |
| 1285 if (response.isSuccess()) { |
| 1286 result.value = devtools.DebuggerAgent.formatObjectProxy_( |
| 1287 response.getBody()); |
| 1288 } else { |
| 1289 result.value = response.getMessage(); |
| 1290 result.isException = true; |
| 1291 } |
| 1292 callback(result); |
| 1293 }); |
| 1012 }; | 1294 }; |
| 1013 | 1295 |
| 1014 | 1296 |
| 1015 /** | |
| 1016 * Handles 'evaluate' response for a call frame | |
| 1017 * @param {devtools.DebuggerMessage} response | |
| 1018 */ | |
| 1019 devtools.CallFrame.handleEvaluateResponse_ = function(response) { | |
| 1020 var body = response.getBody(); | |
| 1021 var value = devtools.DebuggerAgent.formatObjectReference_(body); | |
| 1022 WebInspector.addMessageToConsole(new WebInspector.ConsoleCommandResult( | |
| 1023 value, false /* exception */, null /* commandMessage */)); | |
| 1024 }; | |
| 1025 | |
| 1026 | |
| 1027 /** | 1297 /** |
| 1028 * JSON based commands sent to v8 debugger. | 1298 * JSON based commands sent to v8 debugger. |
| 1029 * @param {string} command Name of the command to execute. | 1299 * @param {string} command Name of the command to execute. |
| 1030 * @param {Object} opt_arguments Command-specific arguments map. | 1300 * @param {Object} opt_arguments Command-specific arguments map. |
| 1031 * @constructor | 1301 * @constructor |
| 1032 */ | 1302 */ |
| 1033 devtools.DebugCommand = function(command, opt_arguments) { | 1303 devtools.DebugCommand = function(command, opt_arguments) { |
| 1034 this.command_ = command; | 1304 this.command_ = command; |
| 1035 this.type_ = 'request'; | 1305 this.type_ = 'request'; |
| 1036 this.seq_ = ++devtools.DebugCommand.nextSeq_; | 1306 this.seq_ = ++devtools.DebugCommand.nextSeq_; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 }; | 1341 }; |
| 1072 | 1342 |
| 1073 | 1343 |
| 1074 /** | 1344 /** |
| 1075 * JSON messages sent from v8 debugger. See protocol definition for more | 1345 * JSON messages sent from v8 debugger. See protocol definition for more |
| 1076 * details: http://code.google.com/p/v8/wiki/DebuggerProtocol | 1346 * details: http://code.google.com/p/v8/wiki/DebuggerProtocol |
| 1077 * @param {string} msg Raw protocol packet as JSON string. | 1347 * @param {string} msg Raw protocol packet as JSON string. |
| 1078 * @constructor | 1348 * @constructor |
| 1079 */ | 1349 */ |
| 1080 devtools.DebuggerMessage = function(msg) { | 1350 devtools.DebuggerMessage = function(msg) { |
| 1081 var jsExpression = '[' + msg + '][0]'; | 1351 this.packet_ = JSON.parse(msg); |
| 1082 this.packet_ = eval(jsExpression); | |
| 1083 this.refs_ = []; | 1352 this.refs_ = []; |
| 1084 if (this.packet_.refs) { | 1353 if (this.packet_.refs) { |
| 1085 for (var i = 0; i < this.packet_.refs.length; i++) { | 1354 for (var i = 0; i < this.packet_.refs.length; i++) { |
| 1086 this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i]; | 1355 this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i]; |
| 1087 } | 1356 } |
| 1088 } | 1357 } |
| 1089 }; | 1358 }; |
| 1090 | 1359 |
| 1091 | 1360 |
| 1092 /** | 1361 /** |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 | 1424 |
| 1156 | 1425 |
| 1157 /** | 1426 /** |
| 1158 * @param {number} handle Object handle. | 1427 * @param {number} handle Object handle. |
| 1159 * @return {?Object} Returns the object with the handle if it was sent in this | 1428 * @return {?Object} Returns the object with the handle if it was sent in this |
| 1160 * message(some objects referenced by handles may be missing in the message). | 1429 * message(some objects referenced by handles may be missing in the message). |
| 1161 */ | 1430 */ |
| 1162 devtools.DebuggerMessage.prototype.lookup = function(handle) { | 1431 devtools.DebuggerMessage.prototype.lookup = function(handle) { |
| 1163 return this.refs_[handle]; | 1432 return this.refs_[handle]; |
| 1164 }; | 1433 }; |
| OLD | NEW |