| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Simple interactive debugger shell that connects to the Dart VM's debugger | 5 // Simple interactive debugger shell that connects to the Dart VM's debugger |
| 6 // connection port. | 6 // connection port. |
| 7 | 7 |
| 8 import "dart:convert"; | 8 import "dart:convert"; |
| 9 import "dart:io"; | 9 import "dart:io"; |
| 10 import "dart:async"; | 10 import "dart:async"; |
| 11 | 11 |
| 12 import "ddbg/lib/commando.dart"; | 12 import "ddbg/lib/commando.dart"; |
| 13 | 13 |
| 14 class TargetIsolate { |
| 15 int id; |
| 16 // The location of the last paused event. |
| 17 Map pausedLocation = null; |
| 18 |
| 19 TargetIsolate(this.id); |
| 20 bool get isPaused => pausedLocation != null; |
| 21 } |
| 22 |
| 23 Map<int, TargetIsolate> targetIsolates= new Map<int, TargetIsolate>(); |
| 14 | 24 |
| 15 Map<int, Completer> outstandingCommands; | 25 Map<int, Completer> outstandingCommands; |
| 16 | 26 |
| 17 Socket vmSock; | 27 Socket vmSock; |
| 18 String vmData; | 28 String vmData; |
| 19 Commando cmdo; | 29 Commando cmdo; |
| 20 var vmSubscription; | 30 var vmSubscription; |
| 21 int seqNum = 0; | 31 int seqNum = 0; |
| 22 int isolate_id = -1; | |
| 23 | 32 |
| 24 Process targetProcess; | 33 Process targetProcess; |
| 25 | 34 |
| 26 final verbose = false; | 35 final verbose = false; |
| 27 final printMessages = false; | 36 final printMessages = false; |
| 28 | 37 |
| 29 // The location of the last paused event. | 38 TargetIsolate currentIsolate; |
| 30 Map pausedLocation = null; | 39 TargetIsolate mainIsolate; |
| 31 | 40 |
| 32 | 41 |
| 33 void printHelp() { | 42 void printHelp() { |
| 34 print(""" | 43 print(""" |
| 35 q Quit debugger shell | 44 q Quit debugger shell |
| 36 bt Show backtrace | 45 bt Show backtrace |
| 37 r Resume execution | 46 r Resume execution |
| 38 s Single step | 47 s Single step |
| 39 so Step over | 48 so Step over |
| 40 si Step into | 49 si Step into |
| 41 sbp [<file>] <line> Set breakpoint | 50 sbp [<file>] <line> Set breakpoint |
| 42 rbp <id> Remove breakpoint with given id | 51 rbp <id> Remove breakpoint with given id |
| 43 po <id> Print object info for given id | 52 po <id> Print object info for given id |
| 44 eval obj <id> <expr> Evaluate expr on object id | 53 eval obj <id> <expr> Evaluate expr on object id |
| 45 eval cls <id> <expr> Evaluate expr on class id | 54 eval cls <id> <expr> Evaluate expr on class id |
| 46 eval lib <id> <expr> Evaluate expr in toplevel of library id | 55 eval lib <id> <expr> Evaluate expr in toplevel of library id |
| 47 pl <id> <idx> [<len>] Print list element/slice | 56 pl <id> <idx> [<len>] Print list element/slice |
| 48 pc <id> Print class info for given id | 57 pc <id> Print class info for given id |
| 49 ll List loaded libraries | 58 ll List loaded libraries |
| 50 plib <id> Print library info for given library id | 59 plib <id> Print library info for given library id |
| 51 slib <id> <true|false> Set library id debuggable | 60 slib <id> <true|false> Set library id debuggable |
| 52 pg <id> Print all global variables visible within given library id | 61 pg <id> Print all global variables visible within given library id |
| 53 ls <lib_id> List loaded scripts in library | 62 ls <lib_id> List loaded scripts in library |
| 54 gs <lib_id> <script_url> Get source text of script in library | 63 gs <lib_id> <script_url> Get source text of script in library |
| 55 tok <lib_id> <script_url> Get line and token table of script in library | 64 tok <lib_id> <script_url> Get line and token table of script in library |
| 56 epi <none|all|unhandled> Set exception pause info | 65 epi <none|all|unhandled> Set exception pause info |
| 57 li List ids of all isolates in the VM | 66 li List ids of all isolates in the VM |
| 67 sci <id> Set current target isolate |
| 58 i <id> Interrupt execution of given isolate id | 68 i <id> Interrupt execution of given isolate id |
| 59 h Print help | 69 h Print help |
| 60 """); | 70 """); |
| 61 } | 71 } |
| 62 | 72 |
| 63 | 73 |
| 74 String formatLocation(Map location) { |
| 75 if (location == null) return ""; |
| 76 var fileName = location["url"].split("/").last; |
| 77 return "file: $fileName lib: ${location['libraryId']} token: ${location['token
Offset']}"; |
| 78 } |
| 79 |
| 80 |
| 64 void quitShell() { | 81 void quitShell() { |
| 65 vmSubscription.cancel(); | 82 vmSubscription.cancel(); |
| 66 vmSock.close(); | 83 vmSock.close(); |
| 67 cmdo.done(); | 84 cmdo.done(); |
| 68 } | 85 } |
| 69 | 86 |
| 70 | 87 |
| 71 Future sendCmd(Map<String, dynamic> cmd) { | 88 Future sendCmd(Map<String, dynamic> cmd) { |
| 72 var completer = new Completer(); | 89 var completer = new Completer(); |
| 73 int id = cmd["id"]; | 90 int id = cmd["id"]; |
| 74 outstandingCommands[id] = completer; | 91 outstandingCommands[id] = completer; |
| 75 if (verbose) { | 92 if (verbose) { |
| 76 print("sending: '${JSON.encode(cmd)}'"); | 93 print("sending: '${JSON.encode(cmd)}'"); |
| 77 } | 94 } |
| 78 vmSock.write(JSON.encode(cmd)); | 95 vmSock.write(JSON.encode(cmd)); |
| 79 return completer.future; | 96 return completer.future; |
| 80 } | 97 } |
| 81 | 98 |
| 82 | 99 |
| 100 bool checkCurrentIsolate() { |
| 101 if (currentIsolate != null) { |
| 102 return true; |
| 103 } |
| 104 print("Need valid current isolate"); |
| 105 return false; |
| 106 } |
| 107 |
| 108 |
| 109 bool checkPaused() { |
| 110 if (!checkCurrentIsolate()) return false; |
| 111 if (currentIsolate.isPaused) return true; |
| 112 print("Current isolate must be paused"); |
| 113 return false; |
| 114 } |
| 115 |
| 83 typedef void HandlerType(Map response); | 116 typedef void HandlerType(Map response); |
| 84 | 117 |
| 85 HandlerType showPromptAfter(void handler(Map response)) { | 118 HandlerType showPromptAfter(void handler(Map response)) { |
| 86 // Hide the command prompt immediately. | 119 // Hide the command prompt immediately. |
| 87 return (response) { | 120 return (response) { |
| 88 handler(response); | 121 handler(response); |
| 89 cmdo.show(); | 122 cmdo.show(); |
| 90 }; | 123 }; |
| 91 } | 124 } |
| 92 | 125 |
| 93 | 126 |
| 94 void processCommand(String cmdLine) { | 127 void processCommand(String cmdLine) { |
| 95 | 128 |
| 96 void huh() { | 129 void huh() { |
| 97 print("'$cmdLine' not understood, try h for help"); | 130 print("'$cmdLine' not understood, try h for help"); |
| 98 } | 131 } |
| 99 | 132 |
| 100 seqNum++; | 133 seqNum++; |
| 101 cmdLine = cmdLine.trim(); | 134 cmdLine = cmdLine.trim(); |
| 102 var args = cmdLine.split(' '); | 135 var args = cmdLine.split(' '); |
| 103 if (args.length == 0) { | 136 if (args.length == 0) { |
| 104 return; | 137 return; |
| 105 } | 138 } |
| 106 var command = args[0]; | 139 var command = args[0]; |
| 107 var simple_commands = | 140 var resume_commands = |
| 108 { 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'}; | 141 { 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'}; |
| 109 if (simple_commands[command] != null) { | 142 if (resume_commands[command] != null) { |
| 143 if (!checkPaused()) return; |
| 110 var cmd = { "id": seqNum, | 144 var cmd = { "id": seqNum, |
| 111 "command": simple_commands[command], | 145 "command": resume_commands[command], |
| 112 "params": { "isolateId" : isolate_id } }; | 146 "params": { "isolateId" : currentIsolate.id } }; |
| 113 cmdo.hide(); | 147 cmdo.hide(); |
| 114 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); | 148 sendCmd(cmd).then(showPromptAfter(handleResumedResponse)); |
| 115 } else if (command == "bt") { | 149 } else if (command == "bt") { |
| 116 var cmd = { "id": seqNum, | 150 var cmd = { "id": seqNum, |
| 117 "command": "getStackTrace", | 151 "command": "getStackTrace", |
| 118 "params": { "isolateId" : isolate_id } }; | 152 "params": { "isolateId" : currentIsolate.id } }; |
| 119 cmdo.hide(); | 153 cmdo.hide(); |
| 120 sendCmd(cmd).then(showPromptAfter(handleStackTraceResponse)); | 154 sendCmd(cmd).then(showPromptAfter(handleStackTraceResponse)); |
| 121 } else if (command == "ll") { | 155 } else if (command == "ll") { |
| 122 var cmd = { "id": seqNum, | 156 var cmd = { "id": seqNum, |
| 123 "command": "getLibraries", | 157 "command": "getLibraries", |
| 124 "params": { "isolateId" : isolate_id } }; | 158 "params": { "isolateId" : currentIsolate.id } }; |
| 125 cmdo.hide(); | 159 cmdo.hide(); |
| 126 sendCmd(cmd).then(showPromptAfter(handleGetLibraryResponse)); | 160 sendCmd(cmd).then(showPromptAfter(handleGetLibraryResponse)); |
| 127 } else if (command == "sbp" && args.length >= 2) { | 161 } else if (command == "sbp" && args.length >= 2) { |
| 128 var url, line; | 162 var url, line; |
| 129 if (args.length == 2 && pausedLocation != null) { | 163 if (args.length == 2 && currentIsolate.pausedLocation != null) { |
| 130 url = pausedLocation["url"]; | 164 url = currentIsolate.pausedLocation["url"]; |
| 131 assert(url != null); | 165 assert(url != null); |
| 132 line = int.parse(args[1]); | 166 line = int.parse(args[1]); |
| 133 } else { | 167 } else { |
| 134 url = args[1]; | 168 url = args[1]; |
| 135 line = int.parse(args[2]); | 169 line = int.parse(args[2]); |
| 136 } | 170 } |
| 137 var cmd = { "id": seqNum, | 171 var cmd = { "id": seqNum, |
| 138 "command": "setBreakpoint", | 172 "command": "setBreakpoint", |
| 139 "params": { "isolateId" : isolate_id, | 173 "params": { "isolateId" : currentIsolate.id, |
| 140 "url": url, | 174 "url": url, |
| 141 "line": line }}; | 175 "line": line }}; |
| 142 cmdo.hide(); | 176 cmdo.hide(); |
| 143 sendCmd(cmd).then(showPromptAfter(handleSetBpResponse)); | 177 sendCmd(cmd).then(showPromptAfter(handleSetBpResponse)); |
| 144 } else if (command == "rbp" && args.length == 2) { | 178 } else if (command == "rbp" && args.length == 2) { |
| 145 var cmd = { "id": seqNum, | 179 var cmd = { "id": seqNum, |
| 146 "command": "removeBreakpoint", | 180 "command": "removeBreakpoint", |
| 147 "params": { "isolateId" : isolate_id, | 181 "params": { "isolateId" : currentIsolate.id, |
| 148 "breakpointId": int.parse(args[1]) } }; | 182 "breakpointId": int.parse(args[1]) } }; |
| 149 cmdo.hide(); | 183 cmdo.hide(); |
| 150 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); | 184 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); |
| 151 } else if (command == "ls" && args.length == 2) { | 185 } else if (command == "ls" && args.length == 2) { |
| 152 var cmd = { "id": seqNum, | 186 var cmd = { "id": seqNum, |
| 153 "command": "getScriptURLs", | 187 "command": "getScriptURLs", |
| 154 "params": { "isolateId" : isolate_id, | 188 "params": { "isolateId" : currentIsolate.id, |
| 155 "libraryId": int.parse(args[1]) } }; | 189 "libraryId": int.parse(args[1]) } }; |
| 156 cmdo.hide(); | 190 cmdo.hide(); |
| 157 sendCmd(cmd).then(showPromptAfter(handleGetScriptsResponse)); | 191 sendCmd(cmd).then(showPromptAfter(handleGetScriptsResponse)); |
| 158 } else if (command == "eval" && args.length > 3) { | 192 } else if (command == "eval" && args.length > 3) { |
| 159 var expr = args.getRange(3, args.length).join(" "); | 193 var expr = args.getRange(3, args.length).join(" "); |
| 160 var target = args[1]; | 194 var target = args[1]; |
| 161 if (target == "obj") { | 195 if (target == "obj") { |
| 162 target = "objectId"; | 196 target = "objectId"; |
| 163 } else if (target == "cls") { | 197 } else if (target == "cls") { |
| 164 target = "classId"; | 198 target = "classId"; |
| 165 } else if (target == "lib") { | 199 } else if (target == "lib") { |
| 166 target = "libraryId"; | 200 target = "libraryId"; |
| 167 } else { | 201 } else { |
| 168 huh(); | 202 huh(); |
| 169 return; | 203 return; |
| 170 } | 204 } |
| 171 var cmd = { "id": seqNum, | 205 var cmd = { "id": seqNum, |
| 172 "command": "evaluateExpr", | 206 "command": "evaluateExpr", |
| 173 "params": { "isolateId": isolate_id, | 207 "params": { "isolateId": currentIsolate.id, |
| 174 target: int.parse(args[2]), | 208 target: int.parse(args[2]), |
| 175 "expression": expr } }; | 209 "expression": expr } }; |
| 176 cmdo.hide(); | 210 cmdo.hide(); |
| 177 sendCmd(cmd).then(showPromptAfter(handleEvalResponse)); | 211 sendCmd(cmd).then(showPromptAfter(handleEvalResponse)); |
| 178 } else if (command == "po" && args.length == 2) { | 212 } else if (command == "po" && args.length == 2) { |
| 179 var cmd = { "id": seqNum, | 213 var cmd = { "id": seqNum, |
| 180 "command": "getObjectProperties", | 214 "command": "getObjectProperties", |
| 181 "params": { "isolateId" : isolate_id, | 215 "params": { "isolateId" : currentIsolate.id, |
| 182 "objectId": int.parse(args[1]) } }; | 216 "objectId": int.parse(args[1]) } }; |
| 183 cmdo.hide(); | 217 cmdo.hide(); |
| 184 sendCmd(cmd).then(showPromptAfter(handleGetObjPropsResponse)); | 218 sendCmd(cmd).then(showPromptAfter(handleGetObjPropsResponse)); |
| 185 } else if (command == "pl" && args.length >= 3) { | 219 } else if (command == "pl" && args.length >= 3) { |
| 186 var cmd; | 220 var cmd; |
| 187 if (args.length == 3) { | 221 if (args.length == 3) { |
| 188 cmd = { "id": seqNum, | 222 cmd = { "id": seqNum, |
| 189 "command": "getListElements", | 223 "command": "getListElements", |
| 190 "params": { "isolateId" : isolate_id, | 224 "params": { "isolateId" : currentIsolate.id, |
| 191 "objectId": int.parse(args[1]), | 225 "objectId": int.parse(args[1]), |
| 192 "index": int.parse(args[2]) } }; | 226 "index": int.parse(args[2]) } }; |
| 193 } else { | 227 } else { |
| 194 cmd = { "id": seqNum, | 228 cmd = { "id": seqNum, |
| 195 "command": "getListElements", | 229 "command": "getListElements", |
| 196 "params": { "isolateId" : isolate_id, | 230 "params": { "isolateId" : currentIsolate.id, |
| 197 "objectId": int.parse(args[1]), | 231 "objectId": int.parse(args[1]), |
| 198 "index": int.parse(args[2]), | 232 "index": int.parse(args[2]), |
| 199 "length": int.parse(args[3]) } }; | 233 "length": int.parse(args[3]) } }; |
| 200 } | 234 } |
| 201 cmdo.hide(); | 235 cmdo.hide(); |
| 202 sendCmd(cmd).then(showPromptAfter(handleGetListResponse)); | 236 sendCmd(cmd).then(showPromptAfter(handleGetListResponse)); |
| 203 } else if (command == "pc" && args.length == 2) { | 237 } else if (command == "pc" && args.length == 2) { |
| 204 var cmd = { "id": seqNum, | 238 var cmd = { "id": seqNum, |
| 205 "command": "getClassProperties", | 239 "command": "getClassProperties", |
| 206 "params": { "isolateId" : isolate_id, | 240 "params": { "isolateId" : currentIsolate.id, |
| 207 "classId": int.parse(args[1]) } }; | 241 "classId": int.parse(args[1]) } }; |
| 208 cmdo.hide(); | 242 cmdo.hide(); |
| 209 sendCmd(cmd).then(showPromptAfter(handleGetClassPropsResponse)); | 243 sendCmd(cmd).then(showPromptAfter(handleGetClassPropsResponse)); |
| 210 } else if (command == "plib" && args.length == 2) { | 244 } else if (command == "plib" && args.length == 2) { |
| 211 var cmd = { "id": seqNum, | 245 var cmd = { "id": seqNum, |
| 212 "command": "getLibraryProperties", | 246 "command": "getLibraryProperties", |
| 213 "params": {"isolateId" : isolate_id, | 247 "params": {"isolateId" : currentIsolate.id, |
| 214 "libraryId": int.parse(args[1]) } }; | 248 "libraryId": int.parse(args[1]) } }; |
| 215 cmdo.hide(); | 249 cmdo.hide(); |
| 216 sendCmd(cmd).then(showPromptAfter(handleGetLibraryPropsResponse)); | 250 sendCmd(cmd).then(showPromptAfter(handleGetLibraryPropsResponse)); |
| 217 } else if (command == "slib" && args.length == 3) { | 251 } else if (command == "slib" && args.length == 3) { |
| 218 var cmd = { "id": seqNum, | 252 var cmd = { "id": seqNum, |
| 219 "command": "setLibraryProperties", | 253 "command": "setLibraryProperties", |
| 220 "params": {"isolateId" : isolate_id, | 254 "params": {"isolateId" : currentIsolate.id, |
| 221 "libraryId": int.parse(args[1]), | 255 "libraryId": int.parse(args[1]), |
| 222 "debuggingEnabled": args[2] } }; | 256 "debuggingEnabled": args[2] } }; |
| 223 cmdo.hide(); | 257 cmdo.hide(); |
| 224 sendCmd(cmd).then(showPromptAfter(handleSetLibraryPropsResponse)); | 258 sendCmd(cmd).then(showPromptAfter(handleSetLibraryPropsResponse)); |
| 225 } else if (command == "pg" && args.length == 2) { | 259 } else if (command == "pg" && args.length == 2) { |
| 226 var cmd = { "id": seqNum, | 260 var cmd = { "id": seqNum, |
| 227 "command": "getGlobalVariables", | 261 "command": "getGlobalVariables", |
| 228 "params": { "isolateId" : isolate_id, | 262 "params": { "isolateId" : currentIsolate.id, |
| 229 "libraryId": int.parse(args[1]) } }; | 263 "libraryId": int.parse(args[1]) } }; |
| 230 cmdo.hide(); | 264 cmdo.hide(); |
| 231 sendCmd(cmd).then(showPromptAfter(handleGetGlobalVarsResponse)); | 265 sendCmd(cmd).then(showPromptAfter(handleGetGlobalVarsResponse)); |
| 232 } else if (command == "gs" && args.length == 3) { | 266 } else if (command == "gs" && args.length == 3) { |
| 233 var cmd = { "id": seqNum, | 267 var cmd = { "id": seqNum, |
| 234 "command": "getScriptSource", | 268 "command": "getScriptSource", |
| 235 "params": { "isolateId" : isolate_id, | 269 "params": { "isolateId" : currentIsolate.id, |
| 236 "libraryId": int.parse(args[1]), | 270 "libraryId": int.parse(args[1]), |
| 237 "url": args[2] } }; | 271 "url": args[2] } }; |
| 238 cmdo.hide(); | 272 cmdo.hide(); |
| 239 sendCmd(cmd).then(showPromptAfter(handleGetSourceResponse)); | 273 sendCmd(cmd).then(showPromptAfter(handleGetSourceResponse)); |
| 240 } else if (command == "tok" && args.length == 3) { | 274 } else if (command == "tok" && args.length == 3) { |
| 241 var cmd = { "id": seqNum, | 275 var cmd = { "id": seqNum, |
| 242 "command": "getLineNumberTable", | 276 "command": "getLineNumberTable", |
| 243 "params": { "isolateId" : isolate_id, | 277 "params": { "isolateId" : currentIsolate.id, |
| 244 "libraryId": int.parse(args[1]), | 278 "libraryId": int.parse(args[1]), |
| 245 "url": args[2] } }; | 279 "url": args[2] } }; |
| 246 cmdo.hide(); | 280 cmdo.hide(); |
| 247 sendCmd(cmd).then(showPromptAfter(handleGetLineTableResponse)); | 281 sendCmd(cmd).then(showPromptAfter(handleGetLineTableResponse)); |
| 248 } else if (command == "epi" && args.length == 2) { | 282 } else if (command == "epi" && args.length == 2) { |
| 249 var cmd = { "id": seqNum, | 283 var cmd = { "id": seqNum, |
| 250 "command": "setPauseOnException", | 284 "command": "setPauseOnException", |
| 251 "params": { "isolateId" : isolate_id, | 285 "params": { "isolateId" : currentIsolate.id, |
| 252 "exceptions": args[1] } }; | 286 "exceptions": args[1] } }; |
| 253 cmdo.hide(); | 287 cmdo.hide(); |
| 254 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); | 288 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); |
| 255 } else if (command == "li") { | 289 } else if (command == "li") { |
| 256 var cmd = { "id": seqNum, "command": "getIsolateIds" }; | 290 var cmd = { "id": seqNum, "command": "getIsolateIds" }; |
| 257 cmdo.hide(); | 291 cmdo.hide(); |
| 258 sendCmd(cmd).then(showPromptAfter(handleGetIsolatesResponse)); | 292 sendCmd(cmd).then(showPromptAfter(handleGetIsolatesResponse)); |
| 293 } else if (command == "sci" && args.length == 2) { |
| 294 var id = int.parse(args[1]); |
| 295 if (targetIsolates[id] != null) { |
| 296 currentIsolate = targetIsolates[id]; |
| 297 print("Setting current target isolate to $id"); |
| 298 } else { |
| 299 print("$id is not a valid isolate id"); |
| 300 } |
| 259 } else if (command == "i" && args.length == 2) { | 301 } else if (command == "i" && args.length == 2) { |
| 260 var cmd = { "id": seqNum, | 302 var cmd = { "id": seqNum, |
| 261 "command": "interrupt", | 303 "command": "interrupt", |
| 262 "params": { "isolateId": int.parse(args[1]) } }; | 304 "params": { "isolateId": int.parse(args[1]) } }; |
| 263 cmdo.hide(); | 305 cmdo.hide(); |
| 264 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); | 306 sendCmd(cmd).then(showPromptAfter(handleGenericResponse)); |
| 265 } else if (command == "q") { | 307 } else if (command == "q") { |
| 266 quitShell(); | 308 quitShell(); |
| 267 } else if (command == "h") { | 309 } else if (command == "h") { |
| 268 printHelp(); | 310 printHelp(); |
| 269 } else { | 311 } else { |
| 270 huh(); | 312 huh(); |
| 271 } | 313 } |
| 272 } | 314 } |
| 273 | 315 |
| 274 | 316 |
| 275 String remoteObject(value) { | 317 String remoteObject(value) { |
| 276 var kind = value["kind"]; | 318 var kind = value["kind"]; |
| 277 var text = value["text"]; | 319 var text = value["text"]; |
| 278 var id = value["objectId"]; | 320 var id = value["objectId"]; |
| 279 if (kind == "string") { | 321 if (kind == "string") { |
| 280 return "(string, id $id) '$text'"; | 322 return "(string, id $id) '$text'"; |
| 281 } else if (kind == "list") { | 323 } else if (kind == "list") { |
| 282 var len = value["length"]; | 324 var len = value["length"]; |
| 283 return "(list, id $id, len $len) $text"; | 325 return "(list, id $id, len $len) $text"; |
| 284 } else if (kind == "object") { | 326 } else if (kind == "object") { |
| 285 return "(obj, id $id) $text"; | 327 return "(obj, id $id) $text"; |
| 286 } else if (kind == "function") { | 328 } else if (kind == "function") { |
| 287 var location = value['location'] != null | 329 var location = formatLocation(value['location']); |
| 288 ? ", file '${value['location']['url']}'" | |
| 289 ", token pos ${value['location']['tokenOffset']}" | |
| 290 : ""; | |
| 291 var name = value['name']; | 330 var name = value['name']; |
| 292 var signature = value['signature']; | 331 var signature = value['signature']; |
| 293 return "(closure ${name}${signature} $location)"; | 332 return "(closure ${name}${signature} $location)"; |
| 294 } else { | 333 } else { |
| 295 return "$text"; | 334 return "$text"; |
| 296 } | 335 } |
| 297 } | 336 } |
| 298 | 337 |
| 299 | 338 |
| 300 printNamedObject(obj) { | 339 printNamedObject(obj) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 | 443 |
| 405 handleGetLineTableResponse(Map response) { | 444 handleGetLineTableResponse(Map response) { |
| 406 Map result = response["result"]; | 445 Map result = response["result"]; |
| 407 var info = result["lines"]; | 446 var info = result["lines"]; |
| 408 print("Line info table:\n$info"); | 447 print("Line info table:\n$info"); |
| 409 } | 448 } |
| 410 | 449 |
| 411 | 450 |
| 412 void handleGetIsolatesResponse(Map response) { | 451 void handleGetIsolatesResponse(Map response) { |
| 413 Map result = response["result"]; | 452 Map result = response["result"]; |
| 414 print("Isolates: ${result["isolateIds"]}"); | 453 List ids = result["isolateIds"]; |
| 454 assert(ids != null); |
| 455 print("List of isolates:"); |
| 456 for (int id in ids) { |
| 457 TargetIsolate isolate = targetIsolates[id]; |
| 458 var state = (isolate != null) ? "running" : "<unknown isolate>"; |
| 459 if (isolate != null && isolate.isPaused) { |
| 460 var loc = formatLocation(isolate.pausedLocation); |
| 461 state = "paused at $loc"; |
| 462 } |
| 463 var marker = " "; |
| 464 if (currentIsolate != null && id == currentIsolate.id) { |
| 465 marker = "*"; |
| 466 } |
| 467 print("$marker $id $state"); |
| 468 } |
| 415 } | 469 } |
| 416 | 470 |
| 417 | 471 |
| 418 void handleGetLibraryResponse(Map response) { | 472 void handleGetLibraryResponse(Map response) { |
| 419 Map result = response["result"]; | 473 Map result = response["result"]; |
| 420 List libs = result["libraries"]; | 474 List libs = result["libraries"]; |
| 421 print("Loaded libraries:"); | 475 print("Loaded libraries:"); |
| 422 print(libs); | 476 print(libs); |
| 423 for (int i = 0; i < libs.length; i++) { | 477 for (int i = 0; i < libs.length; i++) { |
| 424 print(" ${libs[i]["id"]} ${libs[i]["url"]}"); | 478 print(" ${libs[i]["id"]} ${libs[i]["url"]}"); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 449 print("Set BP $id"); | 503 print("Set BP $id"); |
| 450 } | 504 } |
| 451 | 505 |
| 452 | 506 |
| 453 void handleGenericResponse(Map response) { | 507 void handleGenericResponse(Map response) { |
| 454 if (response["error"] != null) { | 508 if (response["error"] != null) { |
| 455 print("Error: ${response["error"]}"); | 509 print("Error: ${response["error"]}"); |
| 456 } | 510 } |
| 457 } | 511 } |
| 458 | 512 |
| 513 void handleResumedResponse(Map response) { |
| 514 if (response["error"] != null) { |
| 515 print("Error: ${response["error"]}"); |
| 516 return; |
| 517 } |
| 518 assert(currentIsolate != null); |
| 519 currentIsolate.pausedLocation = null; |
| 520 } |
| 521 |
| 459 | 522 |
| 460 void handleStackTraceResponse(Map response) { | 523 void handleStackTraceResponse(Map response) { |
| 461 Map result = response["result"]; | 524 Map result = response["result"]; |
| 462 List callFrames = result["callFrames"]; | 525 List callFrames = result["callFrames"]; |
| 463 assert(callFrames != null); | 526 assert(callFrames != null); |
| 464 printStackTrace(callFrames); | 527 printStackTrace(callFrames); |
| 465 } | 528 } |
| 466 | 529 |
| 467 | 530 |
| 468 void printStackFrame(frame_num, Map frame) { | 531 void printStackFrame(frame_num, Map frame) { |
| 469 var fname = frame["functionName"]; | 532 var fname = frame["functionName"]; |
| 470 var libId = frame["location"]["libraryId"]; | 533 var loc = formatLocation(frame["location"]); |
| 471 var url = frame["location"]["url"]; | 534 print("$frame_num $fname ($loc)"); |
| 472 var toff = frame["location"]["tokenOffset"]; | |
| 473 print("$frame_num $fname (url: $url token: $toff lib: $libId)"); | |
| 474 List locals = frame["locals"]; | 535 List locals = frame["locals"]; |
| 475 for (int i = 0; i < locals.length; i++) { | 536 for (int i = 0; i < locals.length; i++) { |
| 476 printNamedObject(locals[i]); | 537 printNamedObject(locals[i]); |
| 477 } | 538 } |
| 478 } | 539 } |
| 479 | 540 |
| 480 | 541 |
| 481 void printStackTrace(List frames) { | 542 void printStackTrace(List frames) { |
| 482 for (int i = 0; i < frames.length; i++) { | 543 for (int i = 0; i < frames.length; i++) { |
| 483 printStackFrame(i, frames[i]); | 544 printStackFrame(i, frames[i]); |
| 484 } | 545 } |
| 485 } | 546 } |
| 486 | 547 |
| 487 | 548 |
| 488 void handlePausedEvent(msg) { | 549 void handlePausedEvent(msg) { |
| 489 assert(msg["params"] != null); | 550 assert(msg["params"] != null); |
| 490 var reason = msg["params"]["reason"]; | 551 var reason = msg["params"]["reason"]; |
| 491 isolate_id = msg["params"]["isolateId"]; | 552 int isolateId = msg["params"]["isolateId"]; |
| 492 assert(isolate_id != null); | 553 assert(isolateId != null); |
| 493 pausedLocation = msg["params"]["location"]; | 554 var isolate = targetIsolates[isolateId]; |
| 494 assert(pausedLocation != null); | 555 assert(isolate != null); |
| 556 assert(!isolate.isPaused); |
| 557 var location = msg["params"]["location"];; |
| 558 assert(location != null); |
| 559 isolate.pausedLocation = location; |
| 495 if (reason == "breakpoint") { | 560 if (reason == "breakpoint") { |
| 496 print("Isolate $isolate_id paused on breakpoint"); | 561 print("Isolate $isolateId paused on breakpoint"); |
| 497 print("location: $pausedLocation"); | 562 print("location: ${formatLocation(location)}"); |
| 498 } else if (reason == "interrupted") { | 563 } else if (reason == "interrupted") { |
| 499 print("Isolate $isolate_id paused due to an interrupt"); | 564 print("Isolate $isolateId paused due to an interrupt"); |
| 565 print("location: ${formatLocation(location)}"); |
| 500 } else { | 566 } else { |
| 501 assert(reason == "exception"); | 567 assert(reason == "exception"); |
| 502 var excObj = msg["params"]["exception"]; | 568 var excObj = msg["params"]["exception"]; |
| 503 print("Isolate $isolate_id paused on exception"); | 569 print("Isolate $isolateId paused on exception"); |
| 504 print(remoteObject(excObj)); | 570 print(remoteObject(excObj)); |
| 505 } | 571 } |
| 506 } | 572 } |
| 507 | 573 |
| 574 void handleIsolateEvent(msg) { |
| 575 Map params = msg["params"]; |
| 576 assert(params != null); |
| 577 var isolateId = params["id"]; |
| 578 var reason = params["reason"]; |
| 579 if (reason == "created") { |
| 580 print("Isolate $isolateId has been created."); |
| 581 assert(targetIsolates[isolateId] == null); |
| 582 targetIsolates[isolateId] = new TargetIsolate(isolateId); |
| 583 if (mainIsolate == null) { |
| 584 mainIsolate = targetIsolates[isolateId]; |
| 585 currentIsolate = mainIsolate; |
| 586 print("Current isolate set to ${currentIsolate.id}."); |
| 587 } |
| 588 } else { |
| 589 assert(reason == "shutdown"); |
| 590 var isolate = targetIsolates.remove(isolateId); |
| 591 assert(isolate != null); |
| 592 if (isolate == mainIsolate) { |
| 593 mainIsolate = null; |
| 594 print("Main isolate ${isolate.id} has terminated."); |
| 595 } else { |
| 596 print("Isolate ${isolate.id} has terminated."); |
| 597 } |
| 598 if (isolate == currentIsolate) { |
| 599 currentIsolate = mainIsolate; |
| 600 if (currentIsolate == null && !targetIsolates.isEmpty) { |
| 601 currentIsolate = targetIsolates.first; |
| 602 } |
| 603 if (currentIsolate != null) { |
| 604 print("Setting current isolate to ${currentIsolate.id}."); |
| 605 } else { |
| 606 print("All isolates have terminated."); |
| 607 } |
| 608 } |
| 609 } |
| 610 } |
| 508 | 611 |
| 509 void processVmMessage(String jsonString) { | 612 void processVmMessage(String jsonString) { |
| 510 var msg = JSON.decode(jsonString); | 613 var msg = JSON.decode(jsonString); |
| 511 if (msg == null) { | 614 if (msg == null) { |
| 512 return; | 615 return; |
| 513 } | 616 } |
| 514 var event = msg["event"]; | 617 var event = msg["event"]; |
| 618 if (event == "isolate") { |
| 619 cmdo.hide(); |
| 620 handleIsolateEvent(msg); |
| 621 cmdo.show(); |
| 622 return; |
| 623 } |
| 515 if (event == "paused") { | 624 if (event == "paused") { |
| 516 cmdo.hide(); | 625 cmdo.hide(); |
| 517 handlePausedEvent(msg); | 626 handlePausedEvent(msg); |
| 518 cmdo.show(); | 627 cmdo.show(); |
| 519 return; | 628 return; |
| 520 } | 629 } |
| 521 if (event == "breakpointResolved") { | 630 if (event == "breakpointResolved") { |
| 522 Map params = msg["params"]; | 631 Map params = msg["params"]; |
| 523 assert(params != null); | 632 assert(params != null); |
| 633 var isolateId = params["isolateId"]; |
| 634 var location = formatLocation(params["location"]); |
| 524 cmdo.hide(); | 635 cmdo.hide(); |
| 525 print("BP ${params["breakpointId"]} resolved and " | 636 print("BP ${params["breakpointId"]} resolved in isolate $isolateId" |
| 526 "set at line ${params["line"]}."); | 637 " at $location."); |
| 527 cmdo.show(); | 638 cmdo.show(); |
| 528 return; | 639 return; |
| 529 } | 640 } |
| 530 if (event == "isolate") { | |
| 531 Map params = msg["params"]; | |
| 532 assert(params != null); | |
| 533 cmdo.hide(); | |
| 534 print("Isolate ${params["id"]} has been ${params["reason"]}."); | |
| 535 cmdo.show(); | |
| 536 return; | |
| 537 } | |
| 538 if (msg["id"] != null) { | 641 if (msg["id"] != null) { |
| 539 var id = msg["id"]; | 642 var id = msg["id"]; |
| 540 if (outstandingCommands.containsKey(id)) { | 643 if (outstandingCommands.containsKey(id)) { |
| 541 var completer = outstandingCommands.remove(id); | 644 var completer = outstandingCommands.remove(id); |
| 542 if (msg["error"] != null) { | 645 if (msg["error"] != null) { |
| 543 print("VM says: ${msg["error"]}"); | 646 print("VM says: ${msg["error"]}"); |
| 544 // TODO(turnidge): Rework how hide/show happens. For now we | 647 // TODO(turnidge): Rework how hide/show happens. For now we |
| 545 // show here explicitly. | 648 // show here explicitly. |
| 546 cmdo.show(); | 649 cmdo.show(); |
| 547 } else { | 650 } else { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 print('Program exited with code $exitCode.'); | 837 print('Program exited with code $exitCode.'); |
| 735 } | 838 } |
| 736 }); | 839 }); |
| 737 | 840 |
| 738 debuggerMain(); | 841 debuggerMain(); |
| 739 }); | 842 }); |
| 740 } else { | 843 } else { |
| 741 debuggerMain(); | 844 debuggerMain(); |
| 742 } | 845 } |
| 743 } | 846 } |
| OLD | NEW |