Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: pkg/dartino_compiler/lib/src/debug_service_protocol.dart

Issue 1987673002: Initial Implementation of the vm-service protocol (Closed) Base URL: git@github.com:dartino/sdk.git@master
Patch Set: Keep track of terminated state Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 /// An implementation of the vm service-protocol in terms of a DartinoVmContext.
6 /// Processes are mapped to isolates.
7 // TODO(sigurdm): Handle processes better.
8 // TODO(sigurdm): Find a way to represent fibers.
9 // TODO(sigurdm): Represent remote values.
10 // TODO(sigurdm): Use https://pub.dartlang.org/packages/json_rpc_2 for serving.
11
12 import "dart:async" show Future;
13
14 import 'dart:convert' show JSON;
15
16 import 'dart:io' show File, HttpServer, WebSocket, WebSocketTransformer;
17
18 import 'hub/session_manager.dart' show SessionState;
19
20 import 'guess_configuration.dart' show dartinoVersion;
21
22 import '../debug_state.dart'
23 show BackTrace, BackTraceFrame, Breakpoint, RemoteObject;
24
25 import '../vm_context.dart' show DartinoVmContext, DebugListener;
26
27 import '../dartino_system.dart'
28 show DartinoFunction, DartinoFunctionKind, DartinoSystem;
29
30 import 'debug_info.dart' show DebugInfo, ScopeInfo, SourceLocation;
31
32 import 'dartino_compiler_implementation.dart'
33 show DartinoCompilerImplementation;
34
35 import 'codegen_visitor.dart' show LocalValue;
36
37 import '../program_info.dart' show Configuration;
38
39 import 'package:collection/collection.dart' show binarySearch;
40
41 import 'package:compiler/src/scanner/scanner.dart' show Scanner;
42 import 'package:compiler/src/tokens/token.dart' show Token;
43 import 'package:compiler/src/io/source_file.dart' show SourceFile;
44 import 'package:compiler/src/elements/visitor.dart' show BaseElementVisitor;
45 import 'package:compiler/src/elements/elements.dart'
46 show
47 CompilationUnitElement,
48 Element,
49 FunctionElement,
50 LibraryElement,
51 MemberElement,
52 ScopeContainerElement;
53
54 const bool logging = const bool.fromEnvironment("dartino-log-debug-server");
55
56 //TODO(danrubel): Verify const map values
57 const Map<String, dynamic> dartCoreLibRefDesc = const <String, dynamic>{
58 "type": "@Library",
59 "id": "libraries/dart:core",
60 "fixedId": true,
61 "name": "dart:core",
62 "uri": "dart:core",
63 };
64
65 //TODO(danrubel): Verify correct id
66 const String nullId = "objects/Null";
67
68 //TODO(danrubel): Verify const map values
69 const Map<String, dynamic> nullClassRefDesc = const <String, dynamic>{
70 "type": "@Class",
71 "id": "classes/NullClass",
72 "name": "NullClass",
73 };
74
75 //TODO(danrubel): Verify const map values
76 const Map<String, dynamic> nullRefDesc = const <String, dynamic>{
77 "type": "@Null",
78 "id": nullId,
79 "kind": "Null",
80 "class": nullClassRefDesc,
81 "valueAsString": "null",
82 };
83
84 //TODO(danrubel): Verify const map values
85 const Map<String, dynamic> nullDesc = const <String, dynamic>{
86 "type": "Null",
87 "id": nullId,
88 "kind": "Null",
89 "class": nullClassRefDesc,
90 "valueAsString": "null",
91 };
92
93 class DebugServer {
94 Future<int> serveSingleShot(SessionState state,
95 {int port: 0, Uri snapshotLocation}) async {
96 HttpServer server = await HttpServer.bind("127.0.0.1", port);
97 // The Atom Dartino plugin waits for "localhost:<port-number>"
98 // to determine the observatory port for debugging.
99 print("localhost:${server.port}");
100 WebSocket socket = await server.transform(new WebSocketTransformer()).first;
101 await new DebugConnection(state, socket, snapshotLocation: snapshotLocation)
102 .serve();
103 await state.vmContext.terminate();
104 await server.close();
105 return 0;
106 }
107 }
108
109 class DebugConnection implements DebugListener {
110 final Map<String, bool> streams = new Map<String, bool>();
111
112 DartinoVmContext get vmContext => state.vmContext;
113 final SessionState state;
114 final WebSocket socket;
115 final Uri snapshotLocation;
116
117 final Map<Uri, List<int>> tokenTables = new Map<Uri, List<int>>();
118
119 Map lastPauseEvent;
120
121 DebugConnection(this.state, this.socket, {this.snapshotLocation});
122
123 List<int> makeTokenTable(CompilationUnitElement compilationUnit) {
124 // TODO(sigurdm): Are these cached somewhere?
125 Token t = new Scanner(compilationUnit.script.file).tokenize();
126 List<int> result = new List<int>();
127 while (t.next != t) {
128 result.add(t.charOffset);
129 t = t.next;
130 }
131 return result;
132 }
133
134 void send(Map message) {
135 if (logging) {
136 print("Sending ${JSON.encode(message)}");
137 }
138 socket.add(JSON.encode(message));
139 }
140
141 void setStream(String streamId, bool value) {
142 streams[streamId] = value;
143 }
144
145 Map<String, CompilationUnitElement> scripts =
146 new Map<String, CompilationUnitElement>();
147
148 Map frameDesc(BackTraceFrame frame, int index) {
149 List<Map> vars = new List<Map>();
150 for (ScopeInfo current = frame.scopeInfo();
151 current != ScopeInfo.sentinel;
152 current = current.previous) {
153 vars.add({
154 "type": "BoundVariable",
155 "name": current.name,
156 "value": valueDesc(current.lookup(current.name))
157 });
158 }
159 return {
160 "type": "Frame",
161 "index": index,
162 "function": functionRef(frame.function),
163 "code": {
164 "id": "code-id", //TODO(danrubel): what is the unique id here?
165 "type": "@Code",
166 "name": "code-name", // TODO(sigurdm): How to create a name here?
167 "kind": "Dart",
168 },
169 "location": locationDesc(frame.sourceLocation(), false),
170 "vars": vars,
171 };
172 }
173
174 Map locationDesc(SourceLocation location, bool includeEndToken) {
175 // TODO(sigurdm): Investigate when this happens.
176 if (location == null || location.file == null)
177 return {
178 "type": "SourceLocation",
179 "script": scriptRef(Uri.parse('file:///unknown')),
180 "tokenPos": 0,
181 };
182 Uri uri = location.file.uri;
183 // TODO(sigurdm): Avoid this. The uri should be the same as we get from
184 // `CompilationUnit.script.file.uri`.
185 uri = new File(new File.fromUri(uri).resolveSymbolicLinksSync()).uri;
186
187 int tokenPos =
188 binarySearch(tokenTables[location.file.uri], location.span.begin);
189
190 Map result = {
191 "type": "SourceLocation",
192 "script": scriptRef(location.file.uri),
193 "tokenPos": tokenPos,
194 };
195 if (includeEndToken) {
196 int endTokenPos =
197 binarySearch(tokenTables[location.file.uri], location.span.end);
198 result["endTokenPos"] = endTokenPos;
199 }
200
201 return result;
202 }
203
204 Map isolateRef(int isolateId) {
205 return {
206 "name": "Isolate $isolateId",
207 "id": "isolates/$isolateId",
208 "fixedId": true,
209 "type": "@Isolate",
210 "number": "$isolateId"
211 };
212 }
213
214 Map libraryRef(LibraryElement library) {
215 return {
216 "type": "@Library",
217 "id": "libraries/${library.canonicalUri}",
218 "fixedId": true,
219 "name": "${library.canonicalUri}",
220 "uri": "${library.canonicalUri}",
221 };
222 }
223
224 Map libraryDesc(LibraryElement library) {
225 return {
226 "type": "Library",
227 "id": "libraries/${library.canonicalUri}",
228 "fixedId": true,
229 "name": "${library.canonicalUri}",
230 "uri": "${library.canonicalUri}",
231 // TODO(danrubel): determine proper values for the next entry
232 "debuggable": true,
233 // TODO(sigurdm): The following fields are not used by the atom-debugger.
234 // We might want to include them to get full compatibility with the
235 // observatory.
236 "dependencies": [],
237 "classes": [],
238 "variables": [],
239 "functions": [],
240 "scripts": library.compilationUnits
241 .map((CompilationUnitElement compilationUnit) =>
242 scriptRef(compilationUnit.script.resourceUri))
243 .toList()
244 };
245 }
246
247 Map breakpointDesc(Breakpoint breakpoint) {
248 DebugInfo debugInfo =
249 state.vmContext.debugState.getDebugInfo(breakpoint.function);
250 SourceLocation location = debugInfo.locationFor(breakpoint.bytecodeIndex);
251 return {
252 "type": "Breakpoint",
253 "breakpointNumber": breakpoint.id,
254 "id": "breakpoints/${breakpoint.id}",
255 "fixedId": true,
256 "resolved": true,
257 "location": locationDesc(location, false),
258 };
259 }
260
261 Map scriptRef(Uri uri) {
262 return {
263 "type": "@Script",
264 "id": "scripts/${uri}",
265 "fixedId": true,
266 "uri": "${uri}",
267 "_kind": "script"
268 };
269 }
270
271 Map scriptDesc(CompilationUnitElement compilationUnit) {
272 String text = compilationUnit.script.text;
273 SourceFile file = compilationUnit.script.file;
274 List<List<int>> tokenPosTable = [];
275 List<int> tokenTable = tokenTables[compilationUnit.script.resourceUri];
276 int currentLine = -1;
277 for (int i = 0; i < tokenTable.length; i++) {
278 int line = file.getLine(tokenTable[i]);
279 int column = file.getColumn(line, tokenTable[i]);
280 if (line != currentLine) {
281 currentLine = line;
282 // The debugger lines starts from 1.
283 tokenPosTable.add([currentLine + 1]);
284 }
285 tokenPosTable.last.add(i);
286 tokenPosTable.last.add(column);
287 }
288 return {
289 "type": "Script",
290 "id": "scripts/${compilationUnit.script.resourceUri}",
291 "fixedId": true,
292 "uri": "${compilationUnit.script.resourceUri}",
293 "library": libraryRef(compilationUnit.library),
294 "source": text,
295 "tokenPosTable": tokenPosTable,
296 "lineOffset": 0, // TODO(sigurdm): What is this?
297 "columnOffset": 0, // TODO(sigurdm): What is this?
298 };
299 }
300
301 String functionKind(DartinoFunctionKind kind) {
302 return {
303 DartinoFunctionKind.NORMAL: "RegularFunction",
304 DartinoFunctionKind.LAZY_FIELD_INITIALIZER: "Stub",
305 DartinoFunctionKind.INITIALIZER_LIST: "RegularFunction",
306 DartinoFunctionKind.PARAMETER_STUB: "Stub",
307 DartinoFunctionKind.ACCESSOR: "GetterFunction"
308 }[kind];
309 }
310
311 Map functionRef(DartinoFunction function) {
312 String name = function.name;
313 //TODO(danrubel): Investigate why this happens.
314 if (name == null || name.isEmpty) name = 'unknown';
315 return {
316 "type": "@Function",
317 "id": "functions/${function.functionId}",
318 "fixedId": true,
319 "name": "${name}",
320 // TODO(sigurdm): All kinds of owner.
321 "owner": libraryRef(function?.element?.library ?? state.compiler.mainApp),
322 "static": function.element?.isStatic ?? false,
323 "const": function.element?.isConst ?? false,
324 "_kind": functionKind(function.kind),
325 };
326 }
327
328 Map functionDesc(DartinoFunction function) {
329 FunctionElement element = function.element;
330 return {
331 "type": "Function",
332 "id": "functions/${function.functionId}",
333 // TODO(sigurdm): All kinds of owner.
334 "owner": libraryRef(element.library),
335 "static": element.isStatic,
336 "const": element.isConst,
337 "_kind": functionKind(function.kind),
338 };
339 }
340
341 Map valueDesc(LocalValue lookup) {
342 //TODO(danrubel): Translate local value into description?
343 // Need to return an @InstanceRef or Sentinel
344 return nullRefDesc;
345 }
346
347 initialize(DartinoCompilerImplementation compiler) {
348 for (LibraryElement library in compiler.libraryLoader.libraries) {
349 cacheScripts(LibraryElement library) {
350 for (CompilationUnitElement compilationUnit
351 in library.compilationUnits) {
352 Uri uri = compilationUnit.script.file.uri;
353 scripts["scripts/$uri"] = compilationUnit;
354 tokenTables[uri] = makeTokenTable(compilationUnit);
355 }
356 }
357 cacheScripts(library);
358 if (library.isPatched) {
359 cacheScripts(library.patch);
360 }
361 }
362 }
363
364 serve() async {
365 vmContext.listeners.add(this);
366
367 await vmContext.initialize(state, snapshotLocation: snapshotLocation);
368
369 initialize(state.compiler.compiler);
370
371 await for (var message in socket) {
372 if (message is! String) throw "Expected String";
373 var decodedMessage = JSON.decode(message);
374 if (logging) {
375 print("Received $decodedMessage");
376 }
377
378 if (decodedMessage is! Map) throw "Expected Map";
379 var id = decodedMessage['id'];
380 void sendResult(Map result) {
381 Map message = {"jsonrpc": "2.0", "result": result, "id": id};
382 send(message);
383 }
384 void sendError(Map error) {
385 Map message = {"jsonrpc": "2.0", "error": error, "id": id};
386 send(message);
387 }
388 switch (decodedMessage["method"]) {
389 case "streamListen":
390 setStream(decodedMessage["params"]["streamId"], true);
391 sendResult({"type": "Success"});
392 break;
393 case "streamCancel":
394 setStream(decodedMessage["streamId"], false);
395 sendResult({"type": "Success"});
396 break;
397 case "getVersion":
398 sendResult({"type": "Version", "major": 3, "minor": 4});
399 break;
400 case "getVM":
401 List<int> isolates = await state.vmContext.processes();
402 sendResult({
403 "type": "VM",
404 "name": "dartino-vm",
405 "architectureBits": {
406 Configuration.Offset64BitsDouble: 64,
407 Configuration.Offset64BitsFloat: 64,
408 Configuration.Offset32BitsDouble: 32,
409 Configuration.Offset32BitsFloat: 32,
410 }[vmContext.configuration],
411 // TODO(sigurdm): Can we give a better description?
412 "targetCPU": "${vmContext.configuration}",
413 // TODO(sigurdm): Can we give a better description?
414 "hostCPU": "${vmContext.configuration}",
415 "version": "$dartinoVersion",
416 // TODO(sigurdm): Can we say something meaningful?
417 "pid": 0,
418 // TODO(sigurdm): Implement a startTime for devices with a clock.
419 "startTime": 0,
420 "isolates": isolates.map(isolateRef).toList()
421 });
422 break;
423 case "getIsolate":
424 String isolateIdString = decodedMessage["params"]["isolateId"];
425 int isolateId = int.parse(
426 isolateIdString.substring(isolateIdString.indexOf("/") + 1));
427
428 sendResult({
429 "type": "Isolate",
430 "runnable": true,
431 "livePorts": 0,
432 "startTime": 0,
433 "name": "Isolate $isolateId",
434 "number": "$isolateId",
435 // TODO(sigurdm): This seems to be required by the observatory.
436 "_originNumber": "$isolateId",
437 "breakpoints":
438 state.vmContext.breakpoints().map(breakpointDesc).toList(),
439 "rootLib": libraryRef(state.compiler.compiler.mainApp),
440 "id": "$isolateIdString",
441 "libraries": state.compiler.compiler.libraryLoader.libraries
442 .map(libraryRef)
443 .toList(),
444 "pauseEvent": lastPauseEvent,
445 // TODO(danrubel): determine proper values for these 2 entries
446 "pauseOnExit": false,
447 "exceptionPauseMode": "Unhandled",
448 // Needed by observatory.
449 "_debuggerSettings": {"_exceptions": "unhandled"},
450 });
451 break;
452 case "addBreakpoint":
453 String scriptId = decodedMessage["params"]["scriptId"];
454 Uri uri = scripts[scriptId].script.resourceUri;
455 int line = decodedMessage["params"]["line"];
456 int column = decodedMessage["params"]["column"] ?? 1;
457 // TODO(sigurdm): Use the isolateId.
458 Breakpoint breakpoint =
459 await state.vmContext.setFileBreakpoint(uri, line, column);
460 if (breakpoint != null) {
461 sendResult({
462 "type": "Breakpoint",
463 "id": "breakpoints/${breakpoint.id}",
464 "breakpointNumber": breakpoint.id,
465 "resolved": true,
466 "location": locationDesc(
467 breakpoint.location(vmContext.debugState), false),
468 });
469 } else {
470 sendError({"code": 102, "message": "Cannot add breakpoint"});
471 }
472 break;
473 case "removeBreakpoint":
474 String breakpointId = decodedMessage["params"]["breakpointId"];
475 int id =
476 int.parse(breakpointId.substring(breakpointId.indexOf("/") + 1));
477 if (vmContext.isRunning || vmContext.isTerminated) {
478 sendError({"code": 106, "message": "Isolate must be paused"});
479 break;
480 }
481 Breakpoint breakpoint = await vmContext.deleteBreakpoint(id);
482 if (breakpoint == null) {
483 // TODO(sigurdm): Is this the right message?
484 sendError({"code": 102, "message": "Cannot remove breakpoint"});
485 } else {
486 sendResult({"type": "Success"});
487 }
488 break;
489 case "getObject":
490 // TODO(sigurdm): should not be ignoring the isolate id.
491 String id = decodedMessage["params"]["objectId"];
492 int slashIndex = id.indexOf('/');
493 switch (id.substring(0, slashIndex)) {
494 case "libraries":
495 String uri = id.substring(slashIndex + 1);
496 sendResult(libraryDesc(state.compiler.compiler.libraryLoader
497 .lookupLibrary(Uri.parse(uri))));
498 break;
499 case "scripts":
500 sendResult(scriptDesc(scripts[id]));
501 break;
502 case "functions":
503 sendResult(functionDesc(vmContext.dartinoSystem.functionsById[
504 int.parse(id.substring(slashIndex + 1))]));
505 break;
506 case "objects":
507 if (id == nullId) {
508 sendResult(nullDesc);
509 } else {
510 //TODO(danrubel): Need to return an Instance description
511 // or Sentinel for the given @InstanceRef
512 throw 'Unknown object: $id';
513 }
514 break;
515 default:
516 throw "Unsupported object type $id";
517 }
518 break;
519 case "getStack":
520 String isolateIdString = decodedMessage["params"]["isolateId"];
521 int isolateId = int.parse(
522 isolateIdString.substring(isolateIdString.indexOf("/") + 1));
523 BackTrace backTrace =
524 await state.vmContext.backTrace(processId: isolateId);
525 List frames = [];
526 int index = 0;
527 for (BackTraceFrame frame in backTrace.frames) {
528 frames.add(frameDesc(frame, index));
529 index++;
530 }
531
532 sendResult({"type": "Stack", "frames": frames, "messages": [],});
533 break;
534 case "getSourceReport":
535 String scriptId = decodedMessage["params"]["scriptId"];
536 CompilationUnitElement compilationUnit = scripts[scriptId];
537 Uri scriptUri = compilationUnit.script.file.uri;
538 List<int> tokenTable = tokenTables[scriptUri];
539
540 // We do not support coverage.
541 assert(decodedMessage["params"]["reports"]
542 .contains("PossibleBreakpoints"));
543 int tokenPos = decodedMessage["params"]["tokenPos"] ?? 0;
544 int endTokenPos =
545 decodedMessage["params"]["endTokenPos"] ?? tokenTable.length - 1;
546 int startPos = tokenTable[tokenPos];
547 int endPos = tokenTable[endTokenPos];
548 List<int> possibleBreakpoints = new List<int>();
549 DartinoSystem system = state.compilationResults.last.system;
550 for (FunctionElement function
551 in FunctionsFinder.findNestedFunctions(compilationUnit)) {
552 DartinoFunction dartinoFunction =
553 system.functionsByElement[function];
554 if (dartinoFunction == null) break;
555 DebugInfo info = state.compiler
556 .createDebugInfo(system.functionsByElement[function], system);
557 if (info == null) break;
558 for (SourceLocation location in info.locations) {
559 // TODO(sigurdm): Investigate these.
560 if (location == null || location.span == null) continue;
561 int position = location.span.begin;
562 if (!(position >= startPos && position <= endPos)) continue;
563 possibleBreakpoints.add(binarySearch(tokenTable, position));
564 }
565 }
566 Map range = {
567 "scriptIndex": 0,
568 "compiled": true,
569 "startPos": tokenPos,
570 "endPos": endTokenPos,
571 "possibleBreakpoints": possibleBreakpoints,
572 "callSites": [],
573 };
574 sendResult({
575 "type": "SourceReport",
576 "ranges": [range],
577 "scripts": [scriptRef(scriptUri)],
578 });
579 break;
580 case "resume":
581 // TODO(sigurdm): use isolateId.
582 String stepOption = decodedMessage["params"]["step"];
583 switch (stepOption) {
584 case "Into":
585 // TODO(sigurdm): avoid needing await here.
586 await vmContext.step();
587 sendResult({"type": "Success"});
588 break;
589 case "Over":
590 // TODO(sigurdm): avoid needing await here.
591 await vmContext.stepOver();
592 sendResult({"type": "Success"});
593 break;
594 case "Out":
595 // TODO(sigurdm): avoid needing await here.
596 await vmContext.stepOut();
597 sendResult({"type": "Success"});
598 break;
599 case "OverAsyncSuspension":
600 sendError({
601 "code": 100,
602 "message": "Feature is disabled",
603 "data": {
604 "details":
605 "Stepping over async suspensions is not implemented",
606 }
607 });
608 break;
609 default:
610 assert(stepOption == null);
611 if (vmContext.isScheduled) {
612 // TODO(sigurdm): Ensure other commands are not issued during
613 // this.
614 vmContext.cont();
615 } else {
616 vmContext.startRunning();
617 }
618 sendResult({"type": "Success"});
619 }
620 break;
621 case "setExceptionPauseMode":
622 // TODO(sigurdm): implement exception-pause-mode.
623 sendResult({"type": "Success"});
624 break;
625 case "pause":
626 await vmContext.interrupt();
627 sendResult({"type": "Success"});
628 break;
629 case "addBreakpointWithScriptUri":
630 // TODO(sigurdm): Use the isolateId.
631 String scriptUri = decodedMessage["params"]["scriptUri"];
632 int line = decodedMessage["params"]["line"] ?? 1;
633 int column = decodedMessage["params"]["column"] ?? 1;
634 if (vmContext.isRunning) {
635 sendError({"code": 102, "message": "Cannot add breakpoint"});
636 break;
637 }
638 Breakpoint breakpoint = await vmContext.setFileBreakpoint(
639 Uri.parse(scriptUri), line, column);
640 if (breakpoint == null) {
641 sendError({"code": 102, "message": "Cannot add breakpoint"});
642 } else {
643 sendResult({
644 "type": "Breakpoint",
645 "id": "breakpoints/${breakpoint.id}",
646 "breakpointNumber": breakpoint.id,
647 "resolved": true,
648 "location": locationDesc(
649 breakpoint.location(vmContext.debugState), false),
650 });
651 }
652 break;
653 default:
654 sendError({
655 "code": 100,
656 "message": "Feature is disabled",
657 "data": {
658 "details":
659 "Request type ${decodedMessage["method"]} not implemented",
660 }
661 });
662 if (logging) {
663 print("Unhandled request type: ${decodedMessage["method"]}");
664 }
665 }
666 }
667 }
668
669 void streamNotify(String streamId, Map event) {
670 if (streams[streamId] ?? false) {
671 send({
672 "method": "streamNotify",
673 "params": {"streamId": streamId, "event": event,},
674 "jsonrpc": "2.0",
675 });
676 }
677 }
678
679 @override
680 breakpointAdded(int processId, Breakpoint breakpoint) {
681 streamNotify("Debug", {
682 "type": "Event",
683 "kind": "BreakpointAdded",
684 "isolate": isolateRef(processId),
685 "timestamp": new DateTime.now().millisecondsSinceEpoch,
686 "breakpoint": breakpointDesc(breakpoint),
687 });
688 }
689
690 @override
691 breakpointRemoved(int processId, Breakpoint breakpoint) {
692 streamNotify("Debug", {
693 "type": "Event",
694 "kind": "BreakpointRemoved",
695 "isolate": isolateRef(processId),
696 "timestamp": new DateTime.now().millisecondsSinceEpoch,
697 "breakpoint": breakpointDesc(breakpoint),
698 });
699 }
700
701 @override
702 gc(int processId) {
703 // TODO(sigurdm): Implement gc notification.
704 }
705
706 @override
707 lostConnection() {
708 socket.close();
709 }
710
711 @override
712 pauseBreakpoint(
713 int processId, BackTraceFrame topFrame, Breakpoint breakpoint) {
714 //TODO(danrubel): are there any other breakpoints
715 // at which we are currently paused for a PauseBreakpoint event?
716 List<Breakpoint> pauseBreakpoints = <Breakpoint>[];
717 pauseBreakpoints.add(breakpoint);
718 Map event = {
719 "type": "Event",
720 "kind": "PauseBreakpoint",
721 "isolate": isolateRef(processId),
722 "timestamp": new DateTime.now().millisecondsSinceEpoch,
723 "topFrame": frameDesc(topFrame, 0),
724 "atAsyncSuspension": false,
725 "breakpoint": breakpointDesc(breakpoint),
726 "pauseBreakpoints":
727 new List.from(pauseBreakpoints.map((bp) => breakpointDesc(bp))),
728 };
729 lastPauseEvent = event;
730 streamNotify("Debug", event);
731 }
732
733 @override
734 pauseException(int processId, BackTraceFrame topFrame, RemoteObject thrown) {
735 Map event = {
736 "type": "Event",
737 "kind": "PauseException",
738 "isolate": isolateRef(processId),
739 "timestamp": new DateTime.now().millisecondsSinceEpoch,
740 "topFrame": frameDesc(topFrame, 0),
741 "atAsyncSuspension": false,
742 // TODO(sigurdm): pass thrown as an instance.
743 };
744 streamNotify("Debug", event);
745 }
746
747 @override
748 pauseExit(int processId, BackTraceFrame topFrame) {
749 // TODO(sigurdm): implement pauseExit
750 }
751
752 @override
753 pauseInterrupted(int processId, BackTraceFrame topFrame) {
754 Map event = {
755 "type": "Event",
756 "kind": "PauseInterrupted",
757 "isolate": isolateRef(processId),
758 "timestamp": new DateTime.now().millisecondsSinceEpoch,
759 "topFrame": frameDesc(topFrame, 0),
760 "atAsyncSuspension": false,
761 };
762 lastPauseEvent = event;
763 streamNotify("Debug", event);
764 }
765
766 @override
767 pauseStart(int processId) {
768 Map event = {
769 "type": "Event",
770 "kind": "PauseStart",
771 "isolate": isolateRef(processId),
772 "timestamp": new DateTime.now().millisecondsSinceEpoch,
773 };
774 lastPauseEvent = event;
775 streamNotify("Debug", event);
776 }
777
778 @override
779 processExit(int processId) {
780 streamNotify("Isolate", {
781 "type": "Event",
782 "kind": "IsolateExit",
783 "isolate": isolateRef(processId),
784 "timestamp": new DateTime.now().millisecondsSinceEpoch,
785 });
786 socket.close();
787 }
788
789 @override
790 processRunnable(int processId) {
791 Map event = {
792 "type": "Event",
793 "kind": "IsolateRunnable",
794 "isolate": isolateRef(processId),
795 "timestamp": new DateTime.now().millisecondsSinceEpoch,
796 };
797 streamNotify("Isolate", event);
798 }
799
800 @override
801 processStart(int processId) {
802 streamNotify("Isolate", {
803 "type": "Event",
804 "kind": "IsolateStart",
805 "isolate": isolateRef(processId),
806 "timestamp": new DateTime.now().millisecondsSinceEpoch,
807 });
808 }
809
810 @override
811 resume(int processId) {
812 Map event = {
813 "type": "Event",
814 "kind": "Resume",
815 "isolate": isolateRef(processId),
816 "timestamp": new DateTime.now().millisecondsSinceEpoch,
817 };
818 BackTraceFrame topFrame = vmContext.debugState.topFrame;
819 if (topFrame != null) {
820 event["topFrame"] = frameDesc(vmContext.debugState.topFrame, 0);
821 }
822 lastPauseEvent = event;
823 streamNotify("Debug", event);
824 }
825
826 @override
827 writeStdErr(int processId, List<int> data) {
828 Map event = {
829 "type": "Event",
830 "kind": "WriteEvent",
831 "bytes": new String.fromCharCodes(data),
832 };
833 streamNotify("Stderr", event);
834 }
835
836 @override
837 writeStdOut(int processId, List<int> data) {
838 Map event = {
839 "type": "Event",
840 "kind": "WriteEvent",
841 "bytes": new String.fromCharCodes(data),
842 };
843 streamNotify("Stdout", event);
844 }
845
846 @override
847 terminated() {}
848 }
849
850 class FunctionsFinder extends BaseElementVisitor {
851 final List<FunctionElement> result = new List<FunctionElement>();
852
853 FunctionsFinder();
854
855 static List<FunctionElement> findNestedFunctions(
856 CompilationUnitElement element) {
857 FunctionsFinder finder = new FunctionsFinder();
858 finder.visit(element);
859 return finder.result;
860 }
861
862 visit(Element e, [arg]) => e.accept(this, arg);
863
864 visitElement(Element e, _) {}
865
866 visitFunctionElement(FunctionElement element, _) {
867 result.add(element);
868 MemberElement memberContext = element.memberContext;
869 if (memberContext == element) {
870 memberContext.nestedClosures.forEach(visit);
871 }
872 }
873
874 visitScopeContainerElement(ScopeContainerElement e, _) {
875 e.forEachLocalMember(visit);
876 }
877
878 visitCompilationUnitElement(CompilationUnitElement e, _) {
879 e.forEachLocalMember(visit);
880 }
881 }
OLDNEW
« no previous file with comments | « pkg/dartino_compiler/lib/debug_state.dart ('k') | pkg/dartino_compiler/lib/src/hub/sentence_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698