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 |