OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project 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 (function (global, utils) { | 5 (function (global, utils) { |
6 "use strict"; | 6 "use strict"; |
7 | 7 |
8 // ---------------------------------------------------------------------------- | 8 // ---------------------------------------------------------------------------- |
9 // Imports | 9 // Imports |
10 | 10 |
11 var FrameMirror = global.FrameMirror; | 11 var FrameMirror = global.FrameMirror; |
12 var GlobalArray = global.Array; | 12 var GlobalArray = global.Array; |
13 var GlobalRegExp = global.RegExp; | 13 var GlobalRegExp = global.RegExp; |
14 var IsNaN = global.isNaN; | 14 var IsNaN = global.isNaN; |
| 15 var JSONParse = global.JSON.parse; |
| 16 var JSONStringify = global.JSON.stringify; |
15 var LookupMirror = global.LookupMirror; | 17 var LookupMirror = global.LookupMirror; |
16 var MakeMirror = global.MakeMirror; | 18 var MakeMirror = global.MakeMirror; |
| 19 var MakeMirrorSerializer = global.MakeMirrorSerializer; |
17 var MathMin = global.Math.min; | 20 var MathMin = global.Math.min; |
18 var Mirror = global.Mirror; | 21 var Mirror = global.Mirror; |
19 var MirrorType; | 22 var MirrorType; |
20 var ParseInt = global.parseInt; | 23 var ParseInt = global.parseInt; |
21 var ValueMirror = global.ValueMirror; | 24 var ValueMirror = global.ValueMirror; |
22 | 25 |
23 utils.Import(function(from) { | 26 utils.Import(function(from) { |
24 MirrorType = from.MirrorType; | 27 MirrorType = from.MirrorType; |
25 }); | 28 }); |
26 | 29 |
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 if (i < 0 || i >= this.frameCount()) { | 860 if (i < 0 || i >= this.frameCount()) { |
858 throw %make_type_error(kDebuggerFrame); | 861 throw %make_type_error(kDebuggerFrame); |
859 } | 862 } |
860 this.selected_frame = i; | 863 this.selected_frame = i; |
861 }; | 864 }; |
862 | 865 |
863 ExecutionState.prototype.selectedFrame = function() { | 866 ExecutionState.prototype.selectedFrame = function() { |
864 return this.selected_frame; | 867 return this.selected_frame; |
865 }; | 868 }; |
866 | 869 |
| 870 ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) { |
| 871 return new DebugCommandProcessor(this, opt_is_running); |
| 872 }; |
| 873 |
| 874 |
867 function MakeBreakEvent(break_id, break_points_hit) { | 875 function MakeBreakEvent(break_id, break_points_hit) { |
868 return new BreakEvent(break_id, break_points_hit); | 876 return new BreakEvent(break_id, break_points_hit); |
869 } | 877 } |
870 | 878 |
871 | 879 |
872 function BreakEvent(break_id, break_points_hit) { | 880 function BreakEvent(break_id, break_points_hit) { |
873 this.frame_ = new FrameMirror(break_id, 0); | 881 this.frame_ = new FrameMirror(break_id, 0); |
874 this.break_points_hit_ = break_points_hit; | 882 this.break_points_hit_ = break_points_hit; |
875 } | 883 } |
876 | 884 |
(...skipping 21 matching lines...) Expand all Loading... |
898 BreakEvent.prototype.sourceLineText = function() { | 906 BreakEvent.prototype.sourceLineText = function() { |
899 return this.frame_.sourceLineText(); | 907 return this.frame_.sourceLineText(); |
900 }; | 908 }; |
901 | 909 |
902 | 910 |
903 BreakEvent.prototype.breakPointsHit = function() { | 911 BreakEvent.prototype.breakPointsHit = function() { |
904 return this.break_points_hit_; | 912 return this.break_points_hit_; |
905 }; | 913 }; |
906 | 914 |
907 | 915 |
| 916 BreakEvent.prototype.toJSONProtocol = function() { |
| 917 var o = { seq: next_response_seq++, |
| 918 type: "event", |
| 919 event: "break", |
| 920 body: { invocationText: this.frame_.invocationText() } |
| 921 }; |
| 922 |
| 923 // Add script related information to the event if available. |
| 924 var script = this.func().script(); |
| 925 if (script) { |
| 926 o.body.sourceLine = this.sourceLine(), |
| 927 o.body.sourceColumn = this.sourceColumn(), |
| 928 o.body.sourceLineText = this.sourceLineText(), |
| 929 o.body.script = MakeScriptObject_(script, false); |
| 930 } |
| 931 |
| 932 // Add an Array of break points hit if any. |
| 933 if (this.breakPointsHit()) { |
| 934 o.body.breakpoints = []; |
| 935 for (var i = 0; i < this.breakPointsHit().length; i++) { |
| 936 // Find the break point number. For break points originating from a |
| 937 // script break point supply the script break point number. |
| 938 var breakpoint = this.breakPointsHit()[i]; |
| 939 var script_break_point = breakpoint.script_break_point(); |
| 940 var number; |
| 941 if (script_break_point) { |
| 942 number = script_break_point.number(); |
| 943 } else { |
| 944 number = breakpoint.number(); |
| 945 } |
| 946 o.body.breakpoints.push(number); |
| 947 } |
| 948 } |
| 949 return JSONStringify(ObjectToProtocolObject_(o)); |
| 950 }; |
| 951 |
| 952 |
908 function MakeExceptionEvent(break_id, exception, uncaught, promise) { | 953 function MakeExceptionEvent(break_id, exception, uncaught, promise) { |
909 return new ExceptionEvent(break_id, exception, uncaught, promise); | 954 return new ExceptionEvent(break_id, exception, uncaught, promise); |
910 } | 955 } |
911 | 956 |
912 | 957 |
913 function ExceptionEvent(break_id, exception, uncaught, promise) { | 958 function ExceptionEvent(break_id, exception, uncaught, promise) { |
914 this.exec_state_ = new ExecutionState(break_id); | 959 this.exec_state_ = new ExecutionState(break_id); |
915 this.exception_ = exception; | 960 this.exception_ = exception; |
916 this.uncaught_ = uncaught; | 961 this.uncaught_ = uncaught; |
917 this.promise_ = promise; | 962 this.promise_ = promise; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 ExceptionEvent.prototype.sourceColumn = function() { | 996 ExceptionEvent.prototype.sourceColumn = function() { |
952 return this.exec_state_.frame(0).sourceColumn(); | 997 return this.exec_state_.frame(0).sourceColumn(); |
953 }; | 998 }; |
954 | 999 |
955 | 1000 |
956 ExceptionEvent.prototype.sourceLineText = function() { | 1001 ExceptionEvent.prototype.sourceLineText = function() { |
957 return this.exec_state_.frame(0).sourceLineText(); | 1002 return this.exec_state_.frame(0).sourceLineText(); |
958 }; | 1003 }; |
959 | 1004 |
960 | 1005 |
| 1006 ExceptionEvent.prototype.toJSONProtocol = function() { |
| 1007 var o = new ProtocolMessage(); |
| 1008 o.event = "exception"; |
| 1009 o.body = { uncaught: this.uncaught_, |
| 1010 exception: MakeMirror(this.exception_) |
| 1011 }; |
| 1012 |
| 1013 // Exceptions might happen whithout any JavaScript frames. |
| 1014 if (this.exec_state_.frameCount() > 0) { |
| 1015 o.body.sourceLine = this.sourceLine(); |
| 1016 o.body.sourceColumn = this.sourceColumn(); |
| 1017 o.body.sourceLineText = this.sourceLineText(); |
| 1018 |
| 1019 // Add script information to the event if available. |
| 1020 var script = this.func().script(); |
| 1021 if (script) { |
| 1022 o.body.script = MakeScriptObject_(script, false); |
| 1023 } |
| 1024 } else { |
| 1025 o.body.sourceLine = -1; |
| 1026 } |
| 1027 |
| 1028 return o.toJSONProtocol(); |
| 1029 }; |
| 1030 |
| 1031 |
961 function MakeCompileEvent(script, type) { | 1032 function MakeCompileEvent(script, type) { |
962 return new CompileEvent(script, type); | 1033 return new CompileEvent(script, type); |
963 } | 1034 } |
964 | 1035 |
965 | 1036 |
966 function CompileEvent(script, type) { | 1037 function CompileEvent(script, type) { |
967 this.script_ = MakeMirror(script); | 1038 this.script_ = MakeMirror(script); |
968 this.type_ = type; | 1039 this.type_ = type; |
969 } | 1040 } |
970 | 1041 |
971 | 1042 |
972 CompileEvent.prototype.eventType = function() { | 1043 CompileEvent.prototype.eventType = function() { |
973 return this.type_; | 1044 return this.type_; |
974 }; | 1045 }; |
975 | 1046 |
976 | 1047 |
977 CompileEvent.prototype.script = function() { | 1048 CompileEvent.prototype.script = function() { |
978 return this.script_; | 1049 return this.script_; |
979 }; | 1050 }; |
980 | 1051 |
981 | 1052 |
| 1053 CompileEvent.prototype.toJSONProtocol = function() { |
| 1054 var o = new ProtocolMessage(); |
| 1055 o.running = true; |
| 1056 switch (this.type_) { |
| 1057 case Debug.DebugEvent.BeforeCompile: |
| 1058 o.event = "beforeCompile"; |
| 1059 break; |
| 1060 case Debug.DebugEvent.AfterCompile: |
| 1061 o.event = "afterCompile"; |
| 1062 break; |
| 1063 case Debug.DebugEvent.CompileError: |
| 1064 o.event = "compileError"; |
| 1065 break; |
| 1066 } |
| 1067 o.body = {}; |
| 1068 o.body.script = this.script_; |
| 1069 |
| 1070 return o.toJSONProtocol(); |
| 1071 }; |
| 1072 |
| 1073 |
982 function MakeScriptObject_(script, include_source) { | 1074 function MakeScriptObject_(script, include_source) { |
983 var o = { id: script.id(), | 1075 var o = { id: script.id(), |
984 name: script.name(), | 1076 name: script.name(), |
985 lineOffset: script.lineOffset(), | 1077 lineOffset: script.lineOffset(), |
986 columnOffset: script.columnOffset(), | 1078 columnOffset: script.columnOffset(), |
987 lineCount: script.lineCount(), | 1079 lineCount: script.lineCount(), |
988 }; | 1080 }; |
989 if (!IS_UNDEFINED(script.data())) { | 1081 if (!IS_UNDEFINED(script.data())) { |
990 o.data = script.data(); | 1082 o.data = script.data(); |
991 } | 1083 } |
(...skipping 17 matching lines...) Expand all Loading... |
1009 | 1101 |
1010 AsyncTaskEvent.prototype.type = function() { | 1102 AsyncTaskEvent.prototype.type = function() { |
1011 return this.type_; | 1103 return this.type_; |
1012 } | 1104 } |
1013 | 1105 |
1014 | 1106 |
1015 AsyncTaskEvent.prototype.id = function() { | 1107 AsyncTaskEvent.prototype.id = function() { |
1016 return this.id_; | 1108 return this.id_; |
1017 } | 1109 } |
1018 | 1110 |
| 1111 |
| 1112 function DebugCommandProcessor(exec_state, opt_is_running) { |
| 1113 this.exec_state_ = exec_state; |
| 1114 this.running_ = opt_is_running || false; |
| 1115 } |
| 1116 |
| 1117 |
| 1118 DebugCommandProcessor.prototype.processDebugRequest = function (request) { |
| 1119 return this.processDebugJSONRequest(request); |
| 1120 }; |
| 1121 |
| 1122 |
| 1123 function ProtocolMessage(request) { |
| 1124 // Update sequence number. |
| 1125 this.seq = next_response_seq++; |
| 1126 |
| 1127 if (request) { |
| 1128 // If message is based on a request this is a response. Fill the initial |
| 1129 // response from the request. |
| 1130 this.type = 'response'; |
| 1131 this.request_seq = request.seq; |
| 1132 this.command = request.command; |
| 1133 } else { |
| 1134 // If message is not based on a request it is a dabugger generated event. |
| 1135 this.type = 'event'; |
| 1136 } |
| 1137 this.success = true; |
| 1138 // Handler may set this field to control debugger state. |
| 1139 this.running = UNDEFINED; |
| 1140 } |
| 1141 |
| 1142 |
| 1143 ProtocolMessage.prototype.setOption = function(name, value) { |
| 1144 if (!this.options_) { |
| 1145 this.options_ = {}; |
| 1146 } |
| 1147 this.options_[name] = value; |
| 1148 }; |
| 1149 |
| 1150 |
| 1151 ProtocolMessage.prototype.failed = function(message, opt_details) { |
| 1152 this.success = false; |
| 1153 this.message = message; |
| 1154 if (IS_OBJECT(opt_details)) { |
| 1155 this.error_details = opt_details; |
| 1156 } |
| 1157 }; |
| 1158 |
| 1159 |
| 1160 ProtocolMessage.prototype.toJSONProtocol = function() { |
| 1161 // Encode the protocol header. |
| 1162 var json = {}; |
| 1163 json.seq= this.seq; |
| 1164 if (this.request_seq) { |
| 1165 json.request_seq = this.request_seq; |
| 1166 } |
| 1167 json.type = this.type; |
| 1168 if (this.event) { |
| 1169 json.event = this.event; |
| 1170 } |
| 1171 if (this.command) { |
| 1172 json.command = this.command; |
| 1173 } |
| 1174 if (this.success) { |
| 1175 json.success = this.success; |
| 1176 } else { |
| 1177 json.success = false; |
| 1178 } |
| 1179 if (this.body) { |
| 1180 // Encode the body part. |
| 1181 var bodyJson; |
| 1182 var serializer = MakeMirrorSerializer(true, this.options_); |
| 1183 if (this.body instanceof Mirror) { |
| 1184 bodyJson = serializer.serializeValue(this.body); |
| 1185 } else if (this.body instanceof GlobalArray) { |
| 1186 bodyJson = []; |
| 1187 for (var i = 0; i < this.body.length; i++) { |
| 1188 if (this.body[i] instanceof Mirror) { |
| 1189 bodyJson.push(serializer.serializeValue(this.body[i])); |
| 1190 } else { |
| 1191 bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer)); |
| 1192 } |
| 1193 } |
| 1194 } else { |
| 1195 bodyJson = ObjectToProtocolObject_(this.body, serializer); |
| 1196 } |
| 1197 json.body = bodyJson; |
| 1198 json.refs = serializer.serializeReferencedObjects(); |
| 1199 } |
| 1200 if (this.message) { |
| 1201 json.message = this.message; |
| 1202 } |
| 1203 if (this.error_details) { |
| 1204 json.error_details = this.error_details; |
| 1205 } |
| 1206 json.running = this.running; |
| 1207 return JSONStringify(json); |
| 1208 }; |
| 1209 |
| 1210 |
| 1211 DebugCommandProcessor.prototype.createResponse = function(request) { |
| 1212 return new ProtocolMessage(request); |
| 1213 }; |
| 1214 |
| 1215 |
| 1216 DebugCommandProcessor.prototype.processDebugJSONRequest = function( |
| 1217 json_request) { |
| 1218 var request; // Current request. |
| 1219 var response; // Generated response. |
| 1220 try { |
| 1221 try { |
| 1222 // Convert the JSON string to an object. |
| 1223 request = JSONParse(json_request); |
| 1224 |
| 1225 // Create an initial response. |
| 1226 response = this.createResponse(request); |
| 1227 |
| 1228 if (!request.type) { |
| 1229 throw %make_error(kDebugger, 'Type not specified'); |
| 1230 } |
| 1231 |
| 1232 if (request.type != 'request') { |
| 1233 throw %make_error(kDebugger, |
| 1234 "Illegal type '" + request.type + "' in request"); |
| 1235 } |
| 1236 |
| 1237 if (!request.command) { |
| 1238 throw %make_error(kDebugger, 'Command not specified'); |
| 1239 } |
| 1240 |
| 1241 if (request.arguments) { |
| 1242 var args = request.arguments; |
| 1243 // TODO(yurys): remove request.arguments.compactFormat check once |
| 1244 // ChromeDevTools are switched to 'inlineRefs' |
| 1245 if (args.inlineRefs || args.compactFormat) { |
| 1246 response.setOption('inlineRefs', true); |
| 1247 } |
| 1248 if (!IS_UNDEFINED(args.maxStringLength)) { |
| 1249 response.setOption('maxStringLength', args.maxStringLength); |
| 1250 } |
| 1251 } |
| 1252 |
| 1253 var key = request.command.toLowerCase(); |
| 1254 var handler = DebugCommandProcessor.prototype.dispatch_[key]; |
| 1255 if (IS_FUNCTION(handler)) { |
| 1256 %_Call(handler, this, request, response); |
| 1257 } else { |
| 1258 throw %make_error(kDebugger, |
| 1259 'Unknown command "' + request.command + '" in request'); |
| 1260 } |
| 1261 } catch (e) { |
| 1262 // If there is no response object created one (without command). |
| 1263 if (!response) { |
| 1264 response = this.createResponse(); |
| 1265 } |
| 1266 response.success = false; |
| 1267 response.message = TO_STRING(e); |
| 1268 } |
| 1269 |
| 1270 // Return the response as a JSON encoded string. |
| 1271 try { |
| 1272 if (!IS_UNDEFINED(response.running)) { |
| 1273 // Response controls running state. |
| 1274 this.running_ = response.running; |
| 1275 } |
| 1276 response.running = this.running_; |
| 1277 return response.toJSONProtocol(); |
| 1278 } catch (e) { |
| 1279 // Failed to generate response - return generic error. |
| 1280 return '{"seq":' + response.seq + ',' + |
| 1281 '"request_seq":' + request.seq + ',' + |
| 1282 '"type":"response",' + |
| 1283 '"success":false,' + |
| 1284 '"message":"Internal error: ' + TO_STRING(e) + '"}'; |
| 1285 } |
| 1286 } catch (e) { |
| 1287 // Failed in one of the catch blocks above - most generic error. |
| 1288 return '{"seq":0,"type":"response","success":false,"message":"Internal error
"}'; |
| 1289 } |
| 1290 }; |
| 1291 |
| 1292 |
| 1293 DebugCommandProcessor.prototype.continueRequest_ = function(request, response) { |
| 1294 // Check for arguments for continue. |
| 1295 if (request.arguments) { |
| 1296 var action = Debug.StepAction.StepIn; |
| 1297 |
| 1298 // Pull out arguments. |
| 1299 var stepaction = request.arguments.stepaction; |
| 1300 |
| 1301 // Get the stepaction argument. |
| 1302 if (stepaction) { |
| 1303 if (stepaction == 'in') { |
| 1304 action = Debug.StepAction.StepIn; |
| 1305 } else if (stepaction == 'next') { |
| 1306 action = Debug.StepAction.StepNext; |
| 1307 } else if (stepaction == 'out') { |
| 1308 action = Debug.StepAction.StepOut; |
| 1309 } else { |
| 1310 throw %make_error(kDebugger, |
| 1311 'Invalid stepaction argument "' + stepaction + '".'); |
| 1312 } |
| 1313 } |
| 1314 |
| 1315 // Set up the VM for stepping. |
| 1316 this.exec_state_.prepareStep(action); |
| 1317 } |
| 1318 |
| 1319 // VM should be running after executing this request. |
| 1320 response.running = true; |
| 1321 }; |
| 1322 |
| 1323 |
| 1324 DebugCommandProcessor.prototype.breakRequest_ = function(request, response) { |
| 1325 // Ignore as break command does not do anything when broken. |
| 1326 }; |
| 1327 |
| 1328 |
| 1329 DebugCommandProcessor.prototype.setBreakPointRequest_ = |
| 1330 function(request, response) { |
| 1331 // Check for legal request. |
| 1332 if (!request.arguments) { |
| 1333 response.failed('Missing arguments'); |
| 1334 return; |
| 1335 } |
| 1336 |
| 1337 // Pull out arguments. |
| 1338 var type = request.arguments.type; |
| 1339 var target = request.arguments.target; |
| 1340 var line = request.arguments.line; |
| 1341 var column = request.arguments.column; |
| 1342 var enabled = IS_UNDEFINED(request.arguments.enabled) ? |
| 1343 true : request.arguments.enabled; |
| 1344 var condition = request.arguments.condition; |
| 1345 var groupId = request.arguments.groupId; |
| 1346 |
| 1347 // Check for legal arguments. |
| 1348 if (!type || IS_UNDEFINED(target)) { |
| 1349 response.failed('Missing argument "type" or "target"'); |
| 1350 return; |
| 1351 } |
| 1352 |
| 1353 // Either function or script break point. |
| 1354 var break_point_number; |
| 1355 if (type == 'function') { |
| 1356 // Handle function break point. |
| 1357 if (!IS_STRING(target)) { |
| 1358 response.failed('Argument "target" is not a string value'); |
| 1359 return; |
| 1360 } |
| 1361 var f; |
| 1362 try { |
| 1363 // Find the function through a global evaluate. |
| 1364 f = this.exec_state_.evaluateGlobal(target).value(); |
| 1365 } catch (e) { |
| 1366 response.failed('Error: "' + TO_STRING(e) + |
| 1367 '" evaluating "' + target + '"'); |
| 1368 return; |
| 1369 } |
| 1370 if (!IS_FUNCTION(f)) { |
| 1371 response.failed('"' + target + '" does not evaluate to a function'); |
| 1372 return; |
| 1373 } |
| 1374 |
| 1375 // Set function break point. |
| 1376 break_point_number = Debug.setBreakPoint(f, line, column, condition); |
| 1377 } else if (type == 'handle') { |
| 1378 // Find the object pointed by the specified handle. |
| 1379 var handle = ParseInt(target, 10); |
| 1380 var mirror = LookupMirror(handle); |
| 1381 if (!mirror) { |
| 1382 return response.failed('Object #' + handle + '# not found'); |
| 1383 } |
| 1384 if (!mirror.isFunction()) { |
| 1385 return response.failed('Object #' + handle + '# is not a function'); |
| 1386 } |
| 1387 |
| 1388 // Set function break point. |
| 1389 break_point_number = Debug.setBreakPoint(mirror.value(), |
| 1390 line, column, condition); |
| 1391 } else if (type == 'script') { |
| 1392 // set script break point. |
| 1393 break_point_number = |
| 1394 Debug.setScriptBreakPointByName(target, line, column, condition, |
| 1395 groupId); |
| 1396 } else if (type == 'scriptId') { |
| 1397 break_point_number = |
| 1398 Debug.setScriptBreakPointById(target, line, column, condition, groupId); |
| 1399 } else if (type == 'scriptRegExp') { |
| 1400 break_point_number = |
| 1401 Debug.setScriptBreakPointByRegExp(target, line, column, condition, |
| 1402 groupId); |
| 1403 } else { |
| 1404 response.failed('Illegal type "' + type + '"'); |
| 1405 return; |
| 1406 } |
| 1407 |
| 1408 // Set additional break point properties. |
| 1409 var break_point = Debug.findBreakPoint(break_point_number); |
| 1410 if (!enabled) { |
| 1411 Debug.disableBreakPoint(break_point_number); |
| 1412 } |
| 1413 |
| 1414 // Add the break point number to the response. |
| 1415 response.body = { type: type, |
| 1416 breakpoint: break_point_number }; |
| 1417 |
| 1418 // Add break point information to the response. |
| 1419 if (break_point instanceof ScriptBreakPoint) { |
| 1420 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) { |
| 1421 response.body.type = 'scriptId'; |
| 1422 response.body.script_id = break_point.script_id(); |
| 1423 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) { |
| 1424 response.body.type = 'scriptName'; |
| 1425 response.body.script_name = break_point.script_name(); |
| 1426 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) { |
| 1427 response.body.type = 'scriptRegExp'; |
| 1428 response.body.script_regexp = break_point.script_regexp_object().source; |
| 1429 } else { |
| 1430 throw %make_error(kDebugger, |
| 1431 "Unexpected breakpoint type: " + break_point.type()); |
| 1432 } |
| 1433 response.body.line = break_point.line(); |
| 1434 response.body.column = break_point.column(); |
| 1435 response.body.actual_locations = break_point.actual_locations(); |
| 1436 } else { |
| 1437 response.body.type = 'function'; |
| 1438 response.body.actual_locations = [break_point.actual_location]; |
| 1439 } |
| 1440 }; |
| 1441 |
| 1442 |
| 1443 DebugCommandProcessor.prototype.changeBreakPointRequest_ = function( |
| 1444 request, response) { |
| 1445 // Check for legal request. |
| 1446 if (!request.arguments) { |
| 1447 response.failed('Missing arguments'); |
| 1448 return; |
| 1449 } |
| 1450 |
| 1451 // Pull out arguments. |
| 1452 var break_point = TO_NUMBER(request.arguments.breakpoint); |
| 1453 var enabled = request.arguments.enabled; |
| 1454 var condition = request.arguments.condition; |
| 1455 |
| 1456 // Check for legal arguments. |
| 1457 if (!break_point) { |
| 1458 response.failed('Missing argument "breakpoint"'); |
| 1459 return; |
| 1460 } |
| 1461 |
| 1462 // Change enabled state if supplied. |
| 1463 if (!IS_UNDEFINED(enabled)) { |
| 1464 if (enabled) { |
| 1465 Debug.enableBreakPoint(break_point); |
| 1466 } else { |
| 1467 Debug.disableBreakPoint(break_point); |
| 1468 } |
| 1469 } |
| 1470 |
| 1471 // Change condition if supplied |
| 1472 if (!IS_UNDEFINED(condition)) { |
| 1473 Debug.changeBreakPointCondition(break_point, condition); |
| 1474 } |
| 1475 }; |
| 1476 |
| 1477 |
| 1478 DebugCommandProcessor.prototype.clearBreakPointGroupRequest_ = function( |
| 1479 request, response) { |
| 1480 // Check for legal request. |
| 1481 if (!request.arguments) { |
| 1482 response.failed('Missing arguments'); |
| 1483 return; |
| 1484 } |
| 1485 |
| 1486 // Pull out arguments. |
| 1487 var group_id = request.arguments.groupId; |
| 1488 |
| 1489 // Check for legal arguments. |
| 1490 if (!group_id) { |
| 1491 response.failed('Missing argument "groupId"'); |
| 1492 return; |
| 1493 } |
| 1494 |
| 1495 var cleared_break_points = []; |
| 1496 var new_script_break_points = []; |
| 1497 for (var i = 0; i < script_break_points.length; i++) { |
| 1498 var next_break_point = script_break_points[i]; |
| 1499 if (next_break_point.groupId() == group_id) { |
| 1500 cleared_break_points.push(next_break_point.number()); |
| 1501 next_break_point.clear(); |
| 1502 } else { |
| 1503 new_script_break_points.push(next_break_point); |
| 1504 } |
| 1505 } |
| 1506 script_break_points = new_script_break_points; |
| 1507 |
| 1508 // Add the cleared break point numbers to the response. |
| 1509 response.body = { breakpoints: cleared_break_points }; |
| 1510 }; |
| 1511 |
| 1512 |
| 1513 DebugCommandProcessor.prototype.clearBreakPointRequest_ = function( |
| 1514 request, response) { |
| 1515 // Check for legal request. |
| 1516 if (!request.arguments) { |
| 1517 response.failed('Missing arguments'); |
| 1518 return; |
| 1519 } |
| 1520 |
| 1521 // Pull out arguments. |
| 1522 var break_point = TO_NUMBER(request.arguments.breakpoint); |
| 1523 |
| 1524 // Check for legal arguments. |
| 1525 if (!break_point) { |
| 1526 response.failed('Missing argument "breakpoint"'); |
| 1527 return; |
| 1528 } |
| 1529 |
| 1530 // Clear break point. |
| 1531 Debug.clearBreakPoint(break_point); |
| 1532 |
| 1533 // Add the cleared break point number to the response. |
| 1534 response.body = { breakpoint: break_point }; |
| 1535 }; |
| 1536 |
| 1537 |
| 1538 DebugCommandProcessor.prototype.listBreakpointsRequest_ = function( |
| 1539 request, response) { |
| 1540 var array = []; |
| 1541 for (var i = 0; i < script_break_points.length; i++) { |
| 1542 var break_point = script_break_points[i]; |
| 1543 |
| 1544 var description = { |
| 1545 number: break_point.number(), |
| 1546 line: break_point.line(), |
| 1547 column: break_point.column(), |
| 1548 groupId: break_point.groupId(), |
| 1549 active: break_point.active(), |
| 1550 condition: break_point.condition(), |
| 1551 actual_locations: break_point.actual_locations() |
| 1552 }; |
| 1553 |
| 1554 if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) { |
| 1555 description.type = 'scriptId'; |
| 1556 description.script_id = break_point.script_id(); |
| 1557 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptName) { |
| 1558 description.type = 'scriptName'; |
| 1559 description.script_name = break_point.script_name(); |
| 1560 } else if (break_point.type() == Debug.ScriptBreakPointType.ScriptRegExp) { |
| 1561 description.type = 'scriptRegExp'; |
| 1562 description.script_regexp = break_point.script_regexp_object().source; |
| 1563 } else { |
| 1564 throw %make_error(kDebugger, |
| 1565 "Unexpected breakpoint type: " + break_point.type()); |
| 1566 } |
| 1567 array.push(description); |
| 1568 } |
| 1569 |
| 1570 response.body = { |
| 1571 breakpoints: array, |
| 1572 breakOnExceptions: Debug.isBreakOnException(), |
| 1573 breakOnUncaughtExceptions: Debug.isBreakOnUncaughtException() |
| 1574 }; |
| 1575 }; |
| 1576 |
| 1577 |
| 1578 DebugCommandProcessor.prototype.disconnectRequest_ = |
| 1579 function(request, response) { |
| 1580 Debug.disableAllBreakPoints(); |
| 1581 this.continueRequest_(request, response); |
| 1582 }; |
| 1583 |
| 1584 |
| 1585 DebugCommandProcessor.prototype.setExceptionBreakRequest_ = |
| 1586 function(request, response) { |
| 1587 // Check for legal request. |
| 1588 if (!request.arguments) { |
| 1589 response.failed('Missing arguments'); |
| 1590 return; |
| 1591 } |
| 1592 |
| 1593 // Pull out and check the 'type' argument: |
| 1594 var type = request.arguments.type; |
| 1595 if (!type) { |
| 1596 response.failed('Missing argument "type"'); |
| 1597 return; |
| 1598 } |
| 1599 |
| 1600 // Initialize the default value of enable: |
| 1601 var enabled; |
| 1602 if (type == 'all') { |
| 1603 enabled = !Debug.isBreakOnException(); |
| 1604 } else if (type == 'uncaught') { |
| 1605 enabled = !Debug.isBreakOnUncaughtException(); |
| 1606 } |
| 1607 |
| 1608 // Pull out and check the 'enabled' argument if present: |
| 1609 if (!IS_UNDEFINED(request.arguments.enabled)) { |
| 1610 enabled = request.arguments.enabled; |
| 1611 if ((enabled != true) && (enabled != false)) { |
| 1612 response.failed('Illegal value for "enabled":"' + enabled + '"'); |
| 1613 } |
| 1614 } |
| 1615 |
| 1616 // Now set the exception break state: |
| 1617 if (type == 'all') { |
| 1618 %ChangeBreakOnException(Debug.ExceptionBreak.Caught, enabled); |
| 1619 } else if (type == 'uncaught') { |
| 1620 %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, enabled); |
| 1621 } else { |
| 1622 response.failed('Unknown "type":"' + type + '"'); |
| 1623 } |
| 1624 |
| 1625 // Add the cleared break point number to the response. |
| 1626 response.body = { 'type': type, 'enabled': enabled }; |
| 1627 }; |
| 1628 |
| 1629 |
| 1630 DebugCommandProcessor.prototype.backtraceRequest_ = function( |
| 1631 request, response) { |
| 1632 // Get the number of frames. |
| 1633 var total_frames = this.exec_state_.frameCount(); |
| 1634 |
| 1635 // Create simple response if there are no frames. |
| 1636 if (total_frames == 0) { |
| 1637 response.body = { |
| 1638 totalFrames: total_frames |
| 1639 }; |
| 1640 return; |
| 1641 } |
| 1642 |
| 1643 // Default frame range to include in backtrace. |
| 1644 var from_index = 0; |
| 1645 var to_index = kDefaultBacktraceLength; |
| 1646 |
| 1647 // Get the range from the arguments. |
| 1648 if (request.arguments) { |
| 1649 if (request.arguments.fromFrame) { |
| 1650 from_index = request.arguments.fromFrame; |
| 1651 } |
| 1652 if (request.arguments.toFrame) { |
| 1653 to_index = request.arguments.toFrame; |
| 1654 } |
| 1655 if (request.arguments.bottom) { |
| 1656 var tmp_index = total_frames - from_index; |
| 1657 from_index = total_frames - to_index; |
| 1658 to_index = tmp_index; |
| 1659 } |
| 1660 if (from_index < 0 || to_index < 0) { |
| 1661 return response.failed('Invalid frame number'); |
| 1662 } |
| 1663 } |
| 1664 |
| 1665 // Adjust the index. |
| 1666 to_index = MathMin(total_frames, to_index); |
| 1667 |
| 1668 if (to_index <= from_index) { |
| 1669 var error = 'Invalid frame range'; |
| 1670 return response.failed(error); |
| 1671 } |
| 1672 |
| 1673 // Create the response body. |
| 1674 var frames = []; |
| 1675 for (var i = from_index; i < to_index; i++) { |
| 1676 frames.push(this.exec_state_.frame(i)); |
| 1677 } |
| 1678 response.body = { |
| 1679 fromFrame: from_index, |
| 1680 toFrame: to_index, |
| 1681 totalFrames: total_frames, |
| 1682 frames: frames |
| 1683 }; |
| 1684 }; |
| 1685 |
| 1686 |
| 1687 DebugCommandProcessor.prototype.frameRequest_ = function(request, response) { |
| 1688 // No frames no source. |
| 1689 if (this.exec_state_.frameCount() == 0) { |
| 1690 return response.failed('No frames'); |
| 1691 } |
| 1692 |
| 1693 // With no arguments just keep the selected frame. |
| 1694 if (request.arguments) { |
| 1695 var index = request.arguments.number; |
| 1696 if (index < 0 || this.exec_state_.frameCount() <= index) { |
| 1697 return response.failed('Invalid frame number'); |
| 1698 } |
| 1699 |
| 1700 this.exec_state_.setSelectedFrame(request.arguments.number); |
| 1701 } |
| 1702 response.body = this.exec_state_.frame(); |
| 1703 }; |
| 1704 |
| 1705 |
| 1706 DebugCommandProcessor.prototype.resolveFrameFromScopeDescription_ = |
| 1707 function(scope_description) { |
| 1708 // Get the frame for which the scope or scopes are requested. |
| 1709 // With no frameNumber argument use the currently selected frame. |
| 1710 if (scope_description && !IS_UNDEFINED(scope_description.frameNumber)) { |
| 1711 var frame_index = scope_description.frameNumber; |
| 1712 if (frame_index < 0 || this.exec_state_.frameCount() <= frame_index) { |
| 1713 throw %make_type_error(kDebuggerFrame); |
| 1714 } |
| 1715 return this.exec_state_.frame(frame_index); |
| 1716 } else { |
| 1717 return this.exec_state_.frame(); |
| 1718 } |
| 1719 }; |
| 1720 |
| 1721 |
| 1722 // Gets scope host object from request. It is either a function |
| 1723 // ('functionHandle' argument must be specified) or a stack frame |
| 1724 // ('frameNumber' may be specified and the current frame is taken by default). |
| 1725 DebugCommandProcessor.prototype.resolveScopeHolder_ = |
| 1726 function(scope_description) { |
| 1727 if (scope_description && "functionHandle" in scope_description) { |
| 1728 if (!IS_NUMBER(scope_description.functionHandle)) { |
| 1729 throw %make_error(kDebugger, 'Function handle must be a number'); |
| 1730 } |
| 1731 var function_mirror = LookupMirror(scope_description.functionHandle); |
| 1732 if (!function_mirror) { |
| 1733 throw %make_error(kDebugger, 'Failed to find function object by handle'); |
| 1734 } |
| 1735 if (!function_mirror.isFunction()) { |
| 1736 throw %make_error(kDebugger, |
| 1737 'Value of non-function type is found by handle'); |
| 1738 } |
| 1739 return function_mirror; |
| 1740 } else { |
| 1741 // No frames no scopes. |
| 1742 if (this.exec_state_.frameCount() == 0) { |
| 1743 throw %make_error(kDebugger, 'No scopes'); |
| 1744 } |
| 1745 |
| 1746 // Get the frame for which the scopes are requested. |
| 1747 var frame = this.resolveFrameFromScopeDescription_(scope_description); |
| 1748 return frame; |
| 1749 } |
| 1750 } |
| 1751 |
| 1752 |
| 1753 DebugCommandProcessor.prototype.scopesRequest_ = function(request, response) { |
| 1754 var scope_holder = this.resolveScopeHolder_(request.arguments); |
| 1755 |
| 1756 // Fill all scopes for this frame or function. |
| 1757 var total_scopes = scope_holder.scopeCount(); |
| 1758 var scopes = []; |
| 1759 for (var i = 0; i < total_scopes; i++) { |
| 1760 scopes.push(scope_holder.scope(i)); |
| 1761 } |
| 1762 response.body = { |
| 1763 fromScope: 0, |
| 1764 toScope: total_scopes, |
| 1765 totalScopes: total_scopes, |
| 1766 scopes: scopes |
| 1767 }; |
| 1768 }; |
| 1769 |
| 1770 |
| 1771 DebugCommandProcessor.prototype.scopeRequest_ = function(request, response) { |
| 1772 // Get the frame or function for which the scope is requested. |
| 1773 var scope_holder = this.resolveScopeHolder_(request.arguments); |
| 1774 |
| 1775 // With no scope argument just return top scope. |
| 1776 var scope_index = 0; |
| 1777 if (request.arguments && !IS_UNDEFINED(request.arguments.number)) { |
| 1778 scope_index = TO_NUMBER(request.arguments.number); |
| 1779 if (scope_index < 0 || scope_holder.scopeCount() <= scope_index) { |
| 1780 return response.failed('Invalid scope number'); |
| 1781 } |
| 1782 } |
| 1783 |
| 1784 response.body = scope_holder.scope(scope_index); |
| 1785 }; |
| 1786 |
| 1787 |
| 1788 // Reads value from protocol description. Description may be in form of type |
| 1789 // (for singletons), raw value (primitive types supported in JSON), |
| 1790 // string value description plus type (for primitive values) or handle id. |
| 1791 // Returns raw value or throws exception. |
| 1792 DebugCommandProcessor.resolveValue_ = function(value_description) { |
| 1793 if ("handle" in value_description) { |
| 1794 var value_mirror = LookupMirror(value_description.handle); |
| 1795 if (!value_mirror) { |
| 1796 throw %make_error(kDebugger, "Failed to resolve value by handle, ' #" + |
| 1797 value_description.handle + "# not found"); |
| 1798 } |
| 1799 return value_mirror.value(); |
| 1800 } else if ("stringDescription" in value_description) { |
| 1801 if (value_description.type == MirrorType.BOOLEAN_TYPE) { |
| 1802 return TO_BOOLEAN(value_description.stringDescription); |
| 1803 } else if (value_description.type == MirrorType.NUMBER_TYPE) { |
| 1804 return TO_NUMBER(value_description.stringDescription); |
| 1805 } if (value_description.type == MirrorType.STRING_TYPE) { |
| 1806 return TO_STRING(value_description.stringDescription); |
| 1807 } else { |
| 1808 throw %make_error(kDebugger, "Unknown type"); |
| 1809 } |
| 1810 } else if ("value" in value_description) { |
| 1811 return value_description.value; |
| 1812 } else if (value_description.type == MirrorType.UNDEFINED_TYPE) { |
| 1813 return UNDEFINED; |
| 1814 } else if (value_description.type == MirrorType.NULL_TYPE) { |
| 1815 return null; |
| 1816 } else { |
| 1817 throw %make_error(kDebugger, "Failed to parse value description"); |
| 1818 } |
| 1819 }; |
| 1820 |
| 1821 |
| 1822 DebugCommandProcessor.prototype.setVariableValueRequest_ = |
| 1823 function(request, response) { |
| 1824 if (!request.arguments) { |
| 1825 response.failed('Missing arguments'); |
| 1826 return; |
| 1827 } |
| 1828 |
| 1829 if (IS_UNDEFINED(request.arguments.name)) { |
| 1830 response.failed('Missing variable name'); |
| 1831 } |
| 1832 var variable_name = request.arguments.name; |
| 1833 |
| 1834 var scope_description = request.arguments.scope; |
| 1835 |
| 1836 // Get the frame or function for which the scope is requested. |
| 1837 var scope_holder = this.resolveScopeHolder_(scope_description); |
| 1838 |
| 1839 if (IS_UNDEFINED(scope_description.number)) { |
| 1840 response.failed('Missing scope number'); |
| 1841 } |
| 1842 var scope_index = TO_NUMBER(scope_description.number); |
| 1843 |
| 1844 var scope = scope_holder.scope(scope_index); |
| 1845 |
| 1846 var new_value = |
| 1847 DebugCommandProcessor.resolveValue_(request.arguments.newValue); |
| 1848 |
| 1849 scope.setVariableValue(variable_name, new_value); |
| 1850 |
| 1851 var new_value_mirror = MakeMirror(new_value); |
| 1852 |
| 1853 response.body = { |
| 1854 newValue: new_value_mirror |
| 1855 }; |
| 1856 }; |
| 1857 |
| 1858 |
| 1859 DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) { |
| 1860 if (!request.arguments) { |
| 1861 return response.failed('Missing arguments'); |
| 1862 } |
| 1863 |
| 1864 // Pull out arguments. |
| 1865 var expression = request.arguments.expression; |
| 1866 var frame = request.arguments.frame; |
| 1867 var global = request.arguments.global; |
| 1868 |
| 1869 // The expression argument could be an integer so we convert it to a |
| 1870 // string. |
| 1871 try { |
| 1872 expression = TO_STRING(expression); |
| 1873 } catch(e) { |
| 1874 return response.failed('Failed to convert expression argument to string'); |
| 1875 } |
| 1876 |
| 1877 // Check for legal arguments. |
| 1878 if (!IS_UNDEFINED(frame) && global) { |
| 1879 return response.failed('Arguments "frame" and "global" are exclusive'); |
| 1880 } |
| 1881 |
| 1882 // Global evaluate. |
| 1883 if (global) { |
| 1884 // Evaluate in the native context. |
| 1885 response.body = this.exec_state_.evaluateGlobal(expression); |
| 1886 return; |
| 1887 } |
| 1888 |
| 1889 // No frames no evaluate in frame. |
| 1890 if (this.exec_state_.frameCount() == 0) { |
| 1891 return response.failed('No frames'); |
| 1892 } |
| 1893 |
| 1894 // Check whether a frame was specified. |
| 1895 if (!IS_UNDEFINED(frame)) { |
| 1896 var frame_number = TO_NUMBER(frame); |
| 1897 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) { |
| 1898 return response.failed('Invalid frame "' + frame + '"'); |
| 1899 } |
| 1900 // Evaluate in the specified frame. |
| 1901 response.body = this.exec_state_.frame(frame_number).evaluate(expression); |
| 1902 return; |
| 1903 } else { |
| 1904 // Evaluate in the selected frame. |
| 1905 response.body = this.exec_state_.frame().evaluate(expression); |
| 1906 return; |
| 1907 } |
| 1908 }; |
| 1909 |
| 1910 |
| 1911 DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) { |
| 1912 if (!request.arguments) { |
| 1913 return response.failed('Missing arguments'); |
| 1914 } |
| 1915 |
| 1916 // Pull out arguments. |
| 1917 var handles = request.arguments.handles; |
| 1918 |
| 1919 // Check for legal arguments. |
| 1920 if (IS_UNDEFINED(handles)) { |
| 1921 return response.failed('Argument "handles" missing'); |
| 1922 } |
| 1923 |
| 1924 // Set 'includeSource' option for script lookup. |
| 1925 if (!IS_UNDEFINED(request.arguments.includeSource)) { |
| 1926 var includeSource = TO_BOOLEAN(request.arguments.includeSource); |
| 1927 response.setOption('includeSource', includeSource); |
| 1928 } |
| 1929 |
| 1930 // Lookup handles. |
| 1931 var mirrors = {}; |
| 1932 for (var i = 0; i < handles.length; i++) { |
| 1933 var handle = handles[i]; |
| 1934 var mirror = LookupMirror(handle); |
| 1935 if (!mirror) { |
| 1936 return response.failed('Object #' + handle + '# not found'); |
| 1937 } |
| 1938 mirrors[handle] = mirror; |
| 1939 } |
| 1940 response.body = mirrors; |
| 1941 }; |
| 1942 |
| 1943 |
| 1944 DebugCommandProcessor.prototype.referencesRequest_ = |
| 1945 function(request, response) { |
| 1946 if (!request.arguments) { |
| 1947 return response.failed('Missing arguments'); |
| 1948 } |
| 1949 |
| 1950 // Pull out arguments. |
| 1951 var type = request.arguments.type; |
| 1952 var handle = request.arguments.handle; |
| 1953 |
| 1954 // Check for legal arguments. |
| 1955 if (IS_UNDEFINED(type)) { |
| 1956 return response.failed('Argument "type" missing'); |
| 1957 } |
| 1958 if (IS_UNDEFINED(handle)) { |
| 1959 return response.failed('Argument "handle" missing'); |
| 1960 } |
| 1961 if (type != 'referencedBy' && type != 'constructedBy') { |
| 1962 return response.failed('Invalid type "' + type + '"'); |
| 1963 } |
| 1964 |
| 1965 // Lookup handle and return objects with references the object. |
| 1966 var mirror = LookupMirror(handle); |
| 1967 if (mirror) { |
| 1968 if (type == 'referencedBy') { |
| 1969 response.body = mirror.referencedBy(); |
| 1970 } else { |
| 1971 response.body = mirror.constructedBy(); |
| 1972 } |
| 1973 } else { |
| 1974 return response.failed('Object #' + handle + '# not found'); |
| 1975 } |
| 1976 }; |
| 1977 |
| 1978 |
| 1979 DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) { |
| 1980 // No frames no source. |
| 1981 if (this.exec_state_.frameCount() == 0) { |
| 1982 return response.failed('No source'); |
| 1983 } |
| 1984 |
| 1985 var from_line; |
| 1986 var to_line; |
| 1987 var frame = this.exec_state_.frame(); |
| 1988 if (request.arguments) { |
| 1989 // Pull out arguments. |
| 1990 from_line = request.arguments.fromLine; |
| 1991 to_line = request.arguments.toLine; |
| 1992 |
| 1993 if (!IS_UNDEFINED(request.arguments.frame)) { |
| 1994 var frame_number = TO_NUMBER(request.arguments.frame); |
| 1995 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) { |
| 1996 return response.failed('Invalid frame "' + frame + '"'); |
| 1997 } |
| 1998 frame = this.exec_state_.frame(frame_number); |
| 1999 } |
| 2000 } |
| 2001 |
| 2002 // Get the script selected. |
| 2003 var script = frame.func().script(); |
| 2004 if (!script) { |
| 2005 return response.failed('No source'); |
| 2006 } |
| 2007 |
| 2008 var raw_script = script.value(); |
| 2009 |
| 2010 // Sanitize arguments and remove line offset. |
| 2011 var line_offset = raw_script.line_offset; |
| 2012 var line_count = %ScriptLineCount(raw_script); |
| 2013 from_line = IS_UNDEFINED(from_line) ? 0 : from_line - line_offset; |
| 2014 to_line = IS_UNDEFINED(to_line) ? line_count : to_line - line_offset; |
| 2015 |
| 2016 if (from_line < 0) from_line = 0; |
| 2017 if (to_line > line_count) to_line = line_count; |
| 2018 |
| 2019 if (from_line >= line_count || to_line < 0 || from_line > to_line) { |
| 2020 return response.failed('Invalid line interval'); |
| 2021 } |
| 2022 |
| 2023 // Fill in the response. |
| 2024 |
| 2025 response.body = {}; |
| 2026 response.body.fromLine = from_line + line_offset; |
| 2027 response.body.toLine = to_line + line_offset; |
| 2028 response.body.fromPosition = %ScriptLineStartPosition(raw_script, from_line); |
| 2029 response.body.toPosition = |
| 2030 (to_line == 0) ? 0 : %ScriptLineEndPosition(raw_script, to_line - 1); |
| 2031 response.body.totalLines = %ScriptLineCount(raw_script); |
| 2032 |
| 2033 response.body.source = %_SubString(raw_script.source, |
| 2034 response.body.fromPosition, |
| 2035 response.body.toPosition); |
| 2036 }; |
| 2037 |
| 2038 |
| 2039 DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) { |
| 2040 var types = ScriptTypeFlag(Debug.ScriptType.Normal); |
| 2041 var includeSource = false; |
| 2042 var idsToInclude = null; |
| 2043 if (request.arguments) { |
| 2044 // Pull out arguments. |
| 2045 if (!IS_UNDEFINED(request.arguments.types)) { |
| 2046 types = TO_NUMBER(request.arguments.types); |
| 2047 if (IsNaN(types) || types < 0) { |
| 2048 return response.failed('Invalid types "' + |
| 2049 request.arguments.types + '"'); |
| 2050 } |
| 2051 } |
| 2052 |
| 2053 if (!IS_UNDEFINED(request.arguments.includeSource)) { |
| 2054 includeSource = TO_BOOLEAN(request.arguments.includeSource); |
| 2055 response.setOption('includeSource', includeSource); |
| 2056 } |
| 2057 |
| 2058 if (IS_ARRAY(request.arguments.ids)) { |
| 2059 idsToInclude = {}; |
| 2060 var ids = request.arguments.ids; |
| 2061 for (var i = 0; i < ids.length; i++) { |
| 2062 idsToInclude[ids[i]] = true; |
| 2063 } |
| 2064 } |
| 2065 |
| 2066 var filterStr = null; |
| 2067 var filterNum = null; |
| 2068 if (!IS_UNDEFINED(request.arguments.filter)) { |
| 2069 var num = TO_NUMBER(request.arguments.filter); |
| 2070 if (!IsNaN(num)) { |
| 2071 filterNum = num; |
| 2072 } |
| 2073 filterStr = request.arguments.filter; |
| 2074 } |
| 2075 } |
| 2076 |
| 2077 // Collect all scripts in the heap. |
| 2078 var scripts = Debug.scripts(); |
| 2079 |
| 2080 response.body = []; |
| 2081 |
| 2082 for (var i = 0; i < scripts.length; i++) { |
| 2083 if (idsToInclude && !idsToInclude[scripts[i].id]) { |
| 2084 continue; |
| 2085 } |
| 2086 if (filterStr || filterNum) { |
| 2087 var script = scripts[i]; |
| 2088 var found = false; |
| 2089 if (filterNum && !found) { |
| 2090 if (script.id && script.id === filterNum) { |
| 2091 found = true; |
| 2092 } |
| 2093 } |
| 2094 if (filterStr && !found) { |
| 2095 if (script.name && script.name.indexOf(filterStr) >= 0) { |
| 2096 found = true; |
| 2097 } |
| 2098 } |
| 2099 if (!found) continue; |
| 2100 } |
| 2101 if (types & ScriptTypeFlag(scripts[i].type)) { |
| 2102 response.body.push(MakeMirror(scripts[i])); |
| 2103 } |
| 2104 } |
| 2105 }; |
| 2106 |
| 2107 |
| 2108 DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) { |
| 2109 response.running = false; |
| 2110 }; |
| 2111 |
| 2112 |
| 2113 // TODO(5510): remove this. |
| 2114 DebugCommandProcessor.prototype.versionRequest_ = function(request, response) { |
| 2115 response.body = { |
| 2116 V8Version: %GetV8Version() |
| 2117 }; |
| 2118 }; |
| 2119 |
| 2120 |
| 2121 DebugCommandProcessor.prototype.changeLiveRequest_ = function( |
| 2122 request, response) { |
| 2123 if (!request.arguments) { |
| 2124 return response.failed('Missing arguments'); |
| 2125 } |
| 2126 var script_id = request.arguments.script_id; |
| 2127 var preview_only = !!request.arguments.preview_only; |
| 2128 |
| 2129 var the_script = scriptById(script_id); |
| 2130 if (!the_script) { |
| 2131 response.failed('Script not found'); |
| 2132 return; |
| 2133 } |
| 2134 |
| 2135 var change_log = new GlobalArray(); |
| 2136 |
| 2137 if (!IS_STRING(request.arguments.new_source)) { |
| 2138 throw "new_source argument expected"; |
| 2139 } |
| 2140 |
| 2141 var new_source = request.arguments.new_source; |
| 2142 |
| 2143 var result_description; |
| 2144 try { |
| 2145 result_description = Debug.LiveEdit.SetScriptSource(the_script, |
| 2146 new_source, preview_only, change_log); |
| 2147 } catch (e) { |
| 2148 if (e instanceof Debug.LiveEdit.Failure && "details" in e) { |
| 2149 response.failed(e.message, e.details); |
| 2150 return; |
| 2151 } |
| 2152 throw e; |
| 2153 } |
| 2154 response.body = {change_log: change_log, result: result_description}; |
| 2155 |
| 2156 if (!preview_only && !this.running_ && result_description.stack_modified) { |
| 2157 response.body.stepin_recommended = true; |
| 2158 } |
| 2159 }; |
| 2160 |
| 2161 |
| 2162 DebugCommandProcessor.prototype.restartFrameRequest_ = function( |
| 2163 request, response) { |
| 2164 if (!request.arguments) { |
| 2165 return response.failed('Missing arguments'); |
| 2166 } |
| 2167 var frame = request.arguments.frame; |
| 2168 |
| 2169 // No frames to evaluate in frame. |
| 2170 if (this.exec_state_.frameCount() == 0) { |
| 2171 return response.failed('No frames'); |
| 2172 } |
| 2173 |
| 2174 var frame_mirror; |
| 2175 // Check whether a frame was specified. |
| 2176 if (!IS_UNDEFINED(frame)) { |
| 2177 var frame_number = TO_NUMBER(frame); |
| 2178 if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) { |
| 2179 return response.failed('Invalid frame "' + frame + '"'); |
| 2180 } |
| 2181 // Restart specified frame. |
| 2182 frame_mirror = this.exec_state_.frame(frame_number); |
| 2183 } else { |
| 2184 // Restart selected frame. |
| 2185 frame_mirror = this.exec_state_.frame(); |
| 2186 } |
| 2187 |
| 2188 var result_description = frame_mirror.restart(); |
| 2189 response.body = {result: result_description}; |
| 2190 }; |
| 2191 |
| 2192 |
| 2193 DebugCommandProcessor.prototype.debuggerFlagsRequest_ = function(request, |
| 2194 response) { |
| 2195 // Check for legal request. |
| 2196 if (!request.arguments) { |
| 2197 response.failed('Missing arguments'); |
| 2198 return; |
| 2199 } |
| 2200 |
| 2201 // Pull out arguments. |
| 2202 var flags = request.arguments.flags; |
| 2203 |
| 2204 response.body = { flags: [] }; |
| 2205 if (!IS_UNDEFINED(flags)) { |
| 2206 for (var i = 0; i < flags.length; i++) { |
| 2207 var name = flags[i].name; |
| 2208 var debugger_flag = debugger_flags[name]; |
| 2209 if (!debugger_flag) { |
| 2210 continue; |
| 2211 } |
| 2212 if ('value' in flags[i]) { |
| 2213 debugger_flag.setValue(flags[i].value); |
| 2214 } |
| 2215 response.body.flags.push({ name: name, value: debugger_flag.getValue() }); |
| 2216 } |
| 2217 } else { |
| 2218 for (var name in debugger_flags) { |
| 2219 var value = debugger_flags[name].getValue(); |
| 2220 response.body.flags.push({ name: name, value: value }); |
| 2221 } |
| 2222 } |
| 2223 }; |
| 2224 |
| 2225 |
| 2226 DebugCommandProcessor.prototype.v8FlagsRequest_ = function(request, response) { |
| 2227 var flags = request.arguments.flags; |
| 2228 if (!flags) flags = ''; |
| 2229 %SetFlags(flags); |
| 2230 }; |
| 2231 |
| 2232 |
| 2233 DebugCommandProcessor.prototype.gcRequest_ = function(request, response) { |
| 2234 var type = request.arguments.type; |
| 2235 if (!type) type = 'all'; |
| 2236 |
| 2237 var before = %GetHeapUsage(); |
| 2238 %CollectGarbage(type); |
| 2239 var after = %GetHeapUsage(); |
| 2240 |
| 2241 response.body = { "before": before, "after": after }; |
| 2242 }; |
| 2243 |
| 2244 |
| 2245 DebugCommandProcessor.prototype.dispatch_ = (function() { |
| 2246 var proto = DebugCommandProcessor.prototype; |
| 2247 return { |
| 2248 "continue": proto.continueRequest_, |
| 2249 "break" : proto.breakRequest_, |
| 2250 "setbreakpoint" : proto.setBreakPointRequest_, |
| 2251 "changebreakpoint": proto.changeBreakPointRequest_, |
| 2252 "clearbreakpoint": proto.clearBreakPointRequest_, |
| 2253 "clearbreakpointgroup": proto.clearBreakPointGroupRequest_, |
| 2254 "disconnect": proto.disconnectRequest_, |
| 2255 "setexceptionbreak": proto.setExceptionBreakRequest_, |
| 2256 "listbreakpoints": proto.listBreakpointsRequest_, |
| 2257 "backtrace": proto.backtraceRequest_, |
| 2258 "frame": proto.frameRequest_, |
| 2259 "scopes": proto.scopesRequest_, |
| 2260 "scope": proto.scopeRequest_, |
| 2261 "setvariablevalue": proto.setVariableValueRequest_, |
| 2262 "evaluate": proto.evaluateRequest_, |
| 2263 "lookup": proto.lookupRequest_, |
| 2264 "references": proto.referencesRequest_, |
| 2265 "source": proto.sourceRequest_, |
| 2266 "scripts": proto.scriptsRequest_, |
| 2267 "suspend": proto.suspendRequest_, |
| 2268 "version": proto.versionRequest_, |
| 2269 "changelive": proto.changeLiveRequest_, |
| 2270 "restartframe": proto.restartFrameRequest_, |
| 2271 "flags": proto.debuggerFlagsRequest_, |
| 2272 "v8flag": proto.v8FlagsRequest_, |
| 2273 "gc": proto.gcRequest_, |
| 2274 }; |
| 2275 })(); |
| 2276 |
| 2277 |
| 2278 // Check whether the previously processed command caused the VM to become |
| 2279 // running. |
| 2280 DebugCommandProcessor.prototype.isRunning = function() { |
| 2281 return this.running_; |
| 2282 }; |
| 2283 |
| 2284 |
| 2285 DebugCommandProcessor.prototype.systemBreak = function(cmd, args) { |
| 2286 return %SystemBreak(); |
| 2287 }; |
| 2288 |
| 2289 |
| 2290 /** |
| 2291 * Convert an Object to its debugger protocol representation. The representation |
| 2292 * may be serilized to a JSON object using JSON.stringify(). |
| 2293 * This implementation simply runs through all string property names, converts |
| 2294 * each property value to a protocol value and adds the property to the result |
| 2295 * object. For type "object" the function will be called recursively. Note that |
| 2296 * circular structures will cause infinite recursion. |
| 2297 * @param {Object} object The object to format as protocol object. |
| 2298 * @param {MirrorSerializer} mirror_serializer The serializer to use if any |
| 2299 * mirror objects are encountered. |
| 2300 * @return {Object} Protocol object value. |
| 2301 */ |
| 2302 function ObjectToProtocolObject_(object, mirror_serializer) { |
| 2303 var content = {}; |
| 2304 for (var key in object) { |
| 2305 // Only consider string keys. |
| 2306 if (typeof key == 'string') { |
| 2307 // Format the value based on its type. |
| 2308 var property_value_json = ValueToProtocolValue_(object[key], |
| 2309 mirror_serializer); |
| 2310 // Add the property if relevant. |
| 2311 if (!IS_UNDEFINED(property_value_json)) { |
| 2312 content[key] = property_value_json; |
| 2313 } |
| 2314 } |
| 2315 } |
| 2316 |
| 2317 return content; |
| 2318 } |
| 2319 |
| 2320 |
| 2321 /** |
| 2322 * Convert an array to its debugger protocol representation. It will convert |
| 2323 * each array element to a protocol value. |
| 2324 * @param {Array} array The array to format as protocol array. |
| 2325 * @param {MirrorSerializer} mirror_serializer The serializer to use if any |
| 2326 * mirror objects are encountered. |
| 2327 * @return {Array} Protocol array value. |
| 2328 */ |
| 2329 function ArrayToProtocolArray_(array, mirror_serializer) { |
| 2330 var json = []; |
| 2331 for (var i = 0; i < array.length; i++) { |
| 2332 json.push(ValueToProtocolValue_(array[i], mirror_serializer)); |
| 2333 } |
| 2334 return json; |
| 2335 } |
| 2336 |
| 2337 |
| 2338 /** |
| 2339 * Convert a value to its debugger protocol representation. |
| 2340 * @param {*} value The value to format as protocol value. |
| 2341 * @param {MirrorSerializer} mirror_serializer The serializer to use if any |
| 2342 * mirror objects are encountered. |
| 2343 * @return {*} Protocol value. |
| 2344 */ |
| 2345 function ValueToProtocolValue_(value, mirror_serializer) { |
| 2346 // Format the value based on its type. |
| 2347 var json; |
| 2348 switch (typeof value) { |
| 2349 case 'object': |
| 2350 if (value instanceof Mirror) { |
| 2351 json = mirror_serializer.serializeValue(value); |
| 2352 } else if (IS_ARRAY(value)){ |
| 2353 json = ArrayToProtocolArray_(value, mirror_serializer); |
| 2354 } else { |
| 2355 json = ObjectToProtocolObject_(value, mirror_serializer); |
| 2356 } |
| 2357 break; |
| 2358 |
| 2359 case 'boolean': |
| 2360 case 'string': |
| 2361 case 'number': |
| 2362 json = value; |
| 2363 break; |
| 2364 |
| 2365 default: |
| 2366 json = null; |
| 2367 } |
| 2368 return json; |
| 2369 } |
| 2370 |
| 2371 |
1019 // ------------------------------------------------------------------- | 2372 // ------------------------------------------------------------------- |
1020 // Exports | 2373 // Exports |
1021 | 2374 |
1022 utils.InstallConstants(global, [ | 2375 utils.InstallConstants(global, [ |
1023 "Debug", Debug, | 2376 "Debug", Debug, |
| 2377 "DebugCommandProcessor", DebugCommandProcessor, |
1024 "BreakEvent", BreakEvent, | 2378 "BreakEvent", BreakEvent, |
1025 "CompileEvent", CompileEvent, | 2379 "CompileEvent", CompileEvent, |
1026 "BreakPoint", BreakPoint, | 2380 "BreakPoint", BreakPoint, |
1027 ]); | 2381 ]); |
1028 | 2382 |
1029 // Functions needed by the debugger runtime. | 2383 // Functions needed by the debugger runtime. |
1030 utils.InstallFunctions(utils, DONT_ENUM, [ | 2384 utils.InstallFunctions(utils, DONT_ENUM, [ |
1031 "MakeExecutionState", MakeExecutionState, | 2385 "MakeExecutionState", MakeExecutionState, |
1032 "MakeExceptionEvent", MakeExceptionEvent, | 2386 "MakeExceptionEvent", MakeExceptionEvent, |
1033 "MakeBreakEvent", MakeBreakEvent, | 2387 "MakeBreakEvent", MakeBreakEvent, |
1034 "MakeCompileEvent", MakeCompileEvent, | 2388 "MakeCompileEvent", MakeCompileEvent, |
1035 "MakeAsyncTaskEvent", MakeAsyncTaskEvent, | 2389 "MakeAsyncTaskEvent", MakeAsyncTaskEvent, |
1036 "IsBreakPointTriggered", IsBreakPointTriggered, | 2390 "IsBreakPointTriggered", IsBreakPointTriggered, |
1037 ]); | 2391 ]); |
1038 | 2392 |
1039 }) | 2393 }) |
OLD | NEW |