| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 (function() { | |
| 32 | |
| 33 // Monkey patch the ScopeType class defined by the V8 engine. | |
| 34 ScopeType.Instance = 6; | |
| 35 ScopeType.Class = 7; | |
| 36 ScopeType.Library = 8; | |
| 37 | |
| 38 var DartDebug = {}; | |
| 39 | |
| 40 DartDebug.ExecutionState = function(callFrames) | |
| 41 { | |
| 42 this._callFrames = []; | |
| 43 for (var i = 0; i < callFrames.length; ++i) { | |
| 44 this._callFrames.push(new DartDebug.FrameMirror(callFrames[i])); | |
| 45 } | |
| 46 }; | |
| 47 | |
| 48 DartDebug.ExecutionState.prototype = { | |
| 49 frameCount: function() | |
| 50 { | |
| 51 return this._callFrames.length; | |
| 52 }, | |
| 53 | |
| 54 frame: function(index) | |
| 55 { | |
| 56 return this._callFrames[index]; | |
| 57 }, | |
| 58 | |
| 59 prepareStep: function(action, count) | |
| 60 { | |
| 61 if (action === Debug.StepAction.StepIn) | |
| 62 return DartDebug.nativeCallbacks.stepInto(); | |
| 63 if (action === Debug.StepAction.StepNext) | |
| 64 return DartDebug.nativeCallbacks.stepOver(); | |
| 65 if (action === Debug.StepAction.StepOut) | |
| 66 return DartDebug.nativeCallbacks.stepOut(); | |
| 67 } | |
| 68 }; | |
| 69 | |
| 70 DartDebug.EventData = function(exception) | |
| 71 { | |
| 72 this._exception = exception; | |
| 73 }; | |
| 74 | |
| 75 DartDebug.EventData.prototype = { | |
| 76 exception: function() | |
| 77 { | |
| 78 return this._exception; | |
| 79 } | |
| 80 }; | |
| 81 | |
| 82 DartDebug.Script = function(id, scriptData) | |
| 83 { | |
| 84 this.id = id; | |
| 85 this.url = scriptData.scriptURL; | |
| 86 this.source = scriptData.source; | |
| 87 this.line_offset = 0; | |
| 88 this.column_offset = 0; | |
| 89 this.context_data = scriptData.contextData; | |
| 90 this.language = 'Dart'; | |
| 91 this.libraryId = scriptData.libraryId; | |
| 92 }; | |
| 93 | |
| 94 DartDebug.Script.prototype = { | |
| 95 get line_ends() | |
| 96 { | |
| 97 var result = []; | |
| 98 var pos = this.source.indexOf('\n'); | |
| 99 while (pos !== -1) { | |
| 100 result.push(pos); | |
| 101 pos = this.source.indexOf('\n', pos + 1); | |
| 102 } | |
| 103 result.push(this.source.length); | |
| 104 return result; | |
| 105 }, | |
| 106 | |
| 107 nameOrSourceURL: function() | |
| 108 { | |
| 109 return this.url; | |
| 110 } | |
| 111 }; | |
| 112 | |
| 113 DartDebug.FrameMirror = function(callFrame) | |
| 114 { | |
| 115 this._callFrame = callFrame; | |
| 116 this._functionName = callFrame.functionName; | |
| 117 this._scriptId = DartDebug.scriptURLToScriptId[callFrame.scriptURL]; | |
| 118 this._lineNumber = callFrame.lineNumber; | |
| 119 this._columnNumber = callFrame.columnNumber; | |
| 120 this._localScope = new DartDebug.ScopeMirror(callFrame.localScopeProxy, Scop
eType.Local); | |
| 121 this._globalScope = new DartDebug.ScopeMirror(callFrame.libraryProxy, ScopeT
ype.Global); | |
| 122 this._librariesScope = new DartDebug.ScopeMirror(callFrame.librariesProxy, S
copeType.Library); | |
| 123 | |
| 124 this._scopes = [this._localScope]; | |
| 125 if (callFrame.localScopeProxy.this) { | |
| 126 this._classInstanceScope = new DartDebug.ScopeMirror(callFrame.localScop
eProxy.this, ScopeType.Instance); | |
| 127 this._scopes.push(this._classInstanceScope); | |
| 128 } | |
| 129 if (callFrame.classProxy) { | |
| 130 this._classScope = new DartDebug.ScopeMirror(callFrame.classProxy, Scope
Type.Class); | |
| 131 this._scopes.push(this._classScope); | |
| 132 } | |
| 133 this._scopes.push(this._globalScope); | |
| 134 this._scopes.push(this._librariesScope); | |
| 135 }; | |
| 136 | |
| 137 DartDebug.FrameMirror.prototype = { | |
| 138 func: function() | |
| 139 { | |
| 140 var self = this; | |
| 141 return { | |
| 142 name: function() { return self._functionName; }, | |
| 143 inferredName: function() { return self._functionName; }, | |
| 144 script: function() { return { id: function() { return self._scriptId
; } }; } | |
| 145 }; | |
| 146 }, | |
| 147 | |
| 148 sourceLocation: function() | |
| 149 { | |
| 150 return { line: this._lineNumber, column: this._columnNumber }; | |
| 151 }, | |
| 152 | |
| 153 scopeCount: function() | |
| 154 { | |
| 155 return this._scopes.length; | |
| 156 }, | |
| 157 | |
| 158 scope: function(index) | |
| 159 { | |
| 160 return this._scopes[index]; | |
| 161 }, | |
| 162 | |
| 163 allScopes: function(fastAsyncScopes) | |
| 164 { | |
| 165 return this._scopes; | |
| 166 }, | |
| 167 | |
| 168 evaluate: function(expression, disableBreak) | |
| 169 { | |
| 170 var result = DartDebug.nativeCallbacks.invocationTrampoline( | |
| 171 DartDebug.nativeCallbacks.evaluateInScope, | |
| 172 [expression, this._localScope.receiver(), this._callFrame.functionPr
oxy, this._callFrame.localVariables]); | |
| 173 return { value: function() { return result; } }; | |
| 174 }, | |
| 175 | |
| 176 restart: function() { | |
| 177 return false; // Not yet supported by the Dart VM. | |
| 178 }, | |
| 179 | |
| 180 details: function() { | |
| 181 return this.details_; | |
| 182 }, | |
| 183 | |
| 184 get details_() | |
| 185 { | |
| 186 var receiver = this._localScope.receiver(); | |
| 187 var func = this.func(); | |
| 188 var sourceLocation = this.sourceLocation(); | |
| 189 return { | |
| 190 receiver: function() | |
| 191 { | |
| 192 return receiver; | |
| 193 }, | |
| 194 | |
| 195 func: function() | |
| 196 { | |
| 197 return func; | |
| 198 }, | |
| 199 | |
| 200 sourceLocation: function() | |
| 201 { | |
| 202 return sourceLocation; | |
| 203 }, | |
| 204 | |
| 205 isAtReturn: function() | |
| 206 { | |
| 207 // FIXMEDART: actually determine whether we are at a return. | |
| 208 return false; | |
| 209 } | |
| 210 }; | |
| 211 } | |
| 212 }; | |
| 213 | |
| 214 DartDebug.ScopeMirror = function(object, scopeType) | |
| 215 { | |
| 216 this._object = object; | |
| 217 this._scopeType = scopeType; | |
| 218 }; | |
| 219 | |
| 220 DartDebug.ScopeMirror.prototype = { | |
| 221 scopeType: function() | |
| 222 { | |
| 223 return this._scopeType; | |
| 224 }, | |
| 225 | |
| 226 scopeObject: function() | |
| 227 { | |
| 228 var properties = []; | |
| 229 for (var name in this._object) { | |
| 230 if (name !== 'this') | |
| 231 properties.push(new DartDebug.PropertyMirror(name, this._object[
name])); | |
| 232 } | |
| 233 return { properties: function() { return properties; } }; | |
| 234 }, | |
| 235 | |
| 236 get details_() | |
| 237 { | |
| 238 var object = this._object; | |
| 239 var type = this._scopeType; | |
| 240 return { | |
| 241 object: function() { return object; }, | |
| 242 type: function() { return type; } | |
| 243 }; | |
| 244 }, | |
| 245 | |
| 246 details: function() | |
| 247 { | |
| 248 return this.details_; | |
| 249 }, | |
| 250 | |
| 251 receiver: function() | |
| 252 { | |
| 253 return this._object['this']; | |
| 254 } | |
| 255 }; | |
| 256 | |
| 257 DartDebug.PropertyMirror = function(name, value) | |
| 258 { | |
| 259 this._name = name; | |
| 260 this._value = value; | |
| 261 }; | |
| 262 | |
| 263 DartDebug.PropertyMirror.prototype = { | |
| 264 name: function() | |
| 265 { | |
| 266 return this._name; | |
| 267 }, | |
| 268 | |
| 269 get value_() | |
| 270 { | |
| 271 return this._value; | |
| 272 } | |
| 273 }; | |
| 274 | |
| 275 DartDebug.isolates = {}; | |
| 276 | |
| 277 DartDebug.scriptArray = []; | |
| 278 DartDebug.scripts = {}; | |
| 279 DartDebug.scriptURLToScriptId = {}; | |
| 280 DartDebug.lastScriptId = 0; | |
| 281 | |
| 282 DartDebug.breakpoints = {}; | |
| 283 DartDebug.lastBreakpointId = 0; | |
| 284 | |
| 285 DartDebug.registerIsolate = function(isolateHandle) | |
| 286 { | |
| 287 this.isolates[isolateHandle] = true; | |
| 288 }; | |
| 289 | |
| 290 DartDebug.unregisterIsolate = function(isolateHandle) | |
| 291 { | |
| 292 delete this.isolates[isolateHandle]; | |
| 293 if (Object.keys(this.isolates).length) | |
| 294 return; | |
| 295 | |
| 296 // The page was destroyed. | |
| 297 DartDebug.scripts = {}; | |
| 298 DartDebug.scriptArray = []; | |
| 299 DartDebug.scriptURLToScriptId = {}; | |
| 300 DartDebug.libraryScopeCache = {}; | |
| 301 DartDebug.breakpoints = {}; | |
| 302 }; | |
| 303 | |
| 304 DartDebug.isolateLoaded = function(isolateHandle) | |
| 305 { | |
| 306 var isolateScripts = DartDebug.nativeCallbacks.scriptsForIsolate(isolateHand
le); | |
| 307 for (var i = 0; i < isolateScripts.length; ++i) { | |
| 308 var script = DartDebug.registerScript(isolateHandle, isolateScripts[i]); | |
| 309 if (!script) | |
| 310 continue; | |
| 311 var executionState = {}; | |
| 312 var eventData = { script_: { script_: script } }; | |
| 313 DartDebug.nativeCallbacks.handleDebugEvent(Debug.DebugEvent.AfterCompile
, executionState, eventData); | |
| 314 } | |
| 315 DartDebug.nativeCallbacks.setExceptionPauseInfo(isolateHandle, Debug.isBreak
OnException(), Debug.isBreakOnUncaughtException()); | |
| 316 }; | |
| 317 | |
| 318 DartDebug.disable = function() | |
| 319 { | |
| 320 for (var breakpointId in DartDebug.breakpoints) { | |
| 321 var vmBreakpoints = DartDebug.breakpoints[breakpointId].vmBreakpoints; | |
| 322 for (var i = 0; i < vmBreakpoints.length; ++i) | |
| 323 DartDebug.nativeCallbacks.removeBreakpoint(vmBreakpoints[i].isolateH
andle, vmBreakpoints[i].id); | |
| 324 } | |
| 325 for (var isolateHandle in DartDebug.isolates) { | |
| 326 DartDebug.nativeCallbacks.setExceptionPauseInfo(isolateHandle, false, fa
lse); | |
| 327 } | |
| 328 DartDebug.breakpoints = {}; | |
| 329 DartDebug.scripts = {}; | |
| 330 DartDebug.scriptURLToScriptId = {}; | |
| 331 }; | |
| 332 | |
| 333 DartDebug.registerScript = function(isolateHandle, scriptData) | |
| 334 { | |
| 335 if (scriptData.scriptURL in DartDebug.scriptURLToScriptId) | |
| 336 return; | |
| 337 | |
| 338 var scriptId = --this.lastScriptId; | |
| 339 var script = new DartDebug.Script(scriptId, scriptData); | |
| 340 | |
| 341 DartDebug.scripts[scriptId] = script; | |
| 342 DartDebug.scriptArray.push(script); | |
| 343 DartDebug.scriptURLToScriptId[scriptData.scriptURL] = scriptId; | |
| 344 | |
| 345 return script; | |
| 346 }; | |
| 347 | |
| 348 DartDebug.updateExceptionPauseInfo = function() | |
| 349 { | |
| 350 for (var isolateHandle in DartDebug.isolates) | |
| 351 DartDebug.nativeCallbacks.setExceptionPauseInfo(isolateHandle, Debug.isB
reakOnException(), Debug.isBreakOnUncaughtException()); | |
| 352 } | |
| 353 | |
| 354 var originals = {}; | |
| 355 | |
| 356 Debug.dartScripts = function() | |
| 357 { | |
| 358 for (var isolateHandle in DartDebug.isolates) { | |
| 359 var isolateScripts = DartDebug.nativeCallbacks.scriptsForIsolate(isolate
Handle); | |
| 360 for (var i = 0; i < isolateScripts.length; ++i) { | |
| 361 DartDebug.registerScript(isolateHandle, isolateScripts[i]); | |
| 362 } | |
| 363 } | |
| 364 return DartDebug.scriptArray; | |
| 365 }; | |
| 366 | |
| 367 originals.setScriptBreakPointById = Debug.setScriptBreakPointById; | |
| 368 | |
| 369 Debug.setScriptBreakPointById = function(scriptId, lineNumber) | |
| 370 { | |
| 371 var script = DartDebug.scripts[scriptId]; | |
| 372 if (!script) | |
| 373 return originals.setScriptBreakPointById.apply(Debug, arguments); | |
| 374 | |
| 375 var vmBreakpoints = []; | |
| 376 for (var isolateHandle in DartDebug.isolates) { | |
| 377 var vmBreakpointId = DartDebug.nativeCallbacks.setBreakpoint(isolateHand
le, script.url, lineNumber + 1); | |
| 378 if (vmBreakpointId) | |
| 379 vmBreakpoints.push({ id: vmBreakpointId, isolateHandle: isolateHandl
e }); | |
| 380 } | |
| 381 | |
| 382 var breakpointId = 'dart-' + (++DartDebug.lastBreakpointId); | |
| 383 DartDebug.breakpoints[breakpointId] = { vmBreakpoints: vmBreakpoints }; | |
| 384 return breakpointId; | |
| 385 }; | |
| 386 | |
| 387 originals.findBreakPointActualLocations = Debug.findBreakPointActualLocations; | |
| 388 | |
| 389 Debug.findBreakPointActualLocations = function(breakpointId) | |
| 390 { | |
| 391 var breakpoint = DartDebug.breakpoints[breakpointId]; | |
| 392 if (!breakpoint) | |
| 393 return originals.findBreakPointActualLocations.apply(Debug, arguments); | |
| 394 | |
| 395 var locations = []; | |
| 396 var vmBreakpoints = breakpoint.vmBreakpoints; | |
| 397 for (var i = 0; i < vmBreakpoints.length; ++i) { | |
| 398 var lineNumber = DartDebug.nativeCallbacks.getBreakpointLine(vmBreakpoin
ts[i].isolateHandle, vmBreakpoints[i].id); | |
| 399 // FIXME: provide column. | |
| 400 locations.push({ line: lineNumber - 1, column: 0 }); | |
| 401 } | |
| 402 return locations; | |
| 403 } | |
| 404 | |
| 405 originals.findBreakPoint = Debug.findBreakPoint; | |
| 406 | |
| 407 Debug.findBreakPoint = function(breakpointId, remove) | |
| 408 { | |
| 409 var breakpoint = DartDebug.breakpoints[breakpointId]; | |
| 410 if (!breakpoint) | |
| 411 return originals.findBreakPoint.apply(Debug, arguments); | |
| 412 | |
| 413 if (remove) { | |
| 414 var vmBreakpoints = breakpoint.vmBreakpoints; | |
| 415 for (var i = 0; i < vmBreakpoints.length; ++i) | |
| 416 DartDebug.nativeCallbacks.removeBreakpoint(vmBreakpoints[i].isolateH
andle, vmBreakpoints[i].id); | |
| 417 delete DartDebug.breakpoints[breakpointId]; | |
| 418 } | |
| 419 }; | |
| 420 | |
| 421 | |
| 422 originals.setBreakOnException = Debug.setBreakOnException; | |
| 423 | |
| 424 Debug.setBreakOnException = function() | |
| 425 { | |
| 426 originals.setBreakOnException.apply(Debug); | |
| 427 DartDebug.updateExceptionPauseInfo(); | |
| 428 } | |
| 429 | |
| 430 originals.clearBreakOnException = Debug.clearBreakOnException; | |
| 431 | |
| 432 Debug.clearBreakOnException = function() | |
| 433 { | |
| 434 originals.clearBreakOnException.apply(Debug); | |
| 435 DartDebug.updateExceptionPauseInfo(); | |
| 436 } | |
| 437 | |
| 438 originals.setBreakOnUncaughtException = Debug.setBreakOnUncaughtException; | |
| 439 | |
| 440 Debug.setBreakOnUncaughtException = function() | |
| 441 { | |
| 442 originals.setBreakOnUncaughtException.apply(Debug); | |
| 443 DartDebug.updateExceptionPauseInfo(); | |
| 444 } | |
| 445 | |
| 446 originals.clearBreakOnUncaughtException = Debug.clearBreakOnUncaughtException; | |
| 447 | |
| 448 Debug.clearBreakOnUncaughtException = function() | |
| 449 { | |
| 450 originals.clearBreakOnUncaughtException.apply(Debug); | |
| 451 DartDebug.updateExceptionPauseInfo(); | |
| 452 } | |
| 453 | |
| 454 return DartDebug; | |
| 455 | |
| 456 })() | |
| OLD | NEW |