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; | |
17 var LookupMirror = global.LookupMirror; | 15 var LookupMirror = global.LookupMirror; |
18 var MakeMirror = global.MakeMirror; | 16 var MakeMirror = global.MakeMirror; |
19 var MakeMirrorSerializer = global.MakeMirrorSerializer; | |
20 var MathMin = global.Math.min; | 17 var MathMin = global.Math.min; |
21 var Mirror = global.Mirror; | 18 var Mirror = global.Mirror; |
22 var MirrorType; | 19 var MirrorType; |
23 var ParseInt = global.parseInt; | 20 var ParseInt = global.parseInt; |
24 var ValueMirror = global.ValueMirror; | 21 var ValueMirror = global.ValueMirror; |
25 | 22 |
26 utils.Import(function(from) { | 23 utils.Import(function(from) { |
27 MirrorType = from.MirrorType; | 24 MirrorType = from.MirrorType; |
28 }); | 25 }); |
29 | 26 |
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 if (i < 0 || i >= this.frameCount()) { | 857 if (i < 0 || i >= this.frameCount()) { |
861 throw %make_type_error(kDebuggerFrame); | 858 throw %make_type_error(kDebuggerFrame); |
862 } | 859 } |
863 this.selected_frame = i; | 860 this.selected_frame = i; |
864 }; | 861 }; |
865 | 862 |
866 ExecutionState.prototype.selectedFrame = function() { | 863 ExecutionState.prototype.selectedFrame = function() { |
867 return this.selected_frame; | 864 return this.selected_frame; |
868 }; | 865 }; |
869 | 866 |
870 ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) { | |
871 return new DebugCommandProcessor(this, opt_is_running); | |
872 }; | |
873 | |
874 | |
875 function MakeBreakEvent(break_id, break_points_hit) { | 867 function MakeBreakEvent(break_id, break_points_hit) { |
876 return new BreakEvent(break_id, break_points_hit); | 868 return new BreakEvent(break_id, break_points_hit); |
877 } | 869 } |
878 | 870 |
879 | 871 |
880 function BreakEvent(break_id, break_points_hit) { | 872 function BreakEvent(break_id, break_points_hit) { |
881 this.frame_ = new FrameMirror(break_id, 0); | 873 this.frame_ = new FrameMirror(break_id, 0); |
882 this.break_points_hit_ = break_points_hit; | 874 this.break_points_hit_ = break_points_hit; |
883 } | 875 } |
884 | 876 |
(...skipping 21 matching lines...) Expand all Loading... |
906 BreakEvent.prototype.sourceLineText = function() { | 898 BreakEvent.prototype.sourceLineText = function() { |
907 return this.frame_.sourceLineText(); | 899 return this.frame_.sourceLineText(); |
908 }; | 900 }; |
909 | 901 |
910 | 902 |
911 BreakEvent.prototype.breakPointsHit = function() { | 903 BreakEvent.prototype.breakPointsHit = function() { |
912 return this.break_points_hit_; | 904 return this.break_points_hit_; |
913 }; | 905 }; |
914 | 906 |
915 | 907 |
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 | |
953 function MakeExceptionEvent(break_id, exception, uncaught, promise) { | 908 function MakeExceptionEvent(break_id, exception, uncaught, promise) { |
954 return new ExceptionEvent(break_id, exception, uncaught, promise); | 909 return new ExceptionEvent(break_id, exception, uncaught, promise); |
955 } | 910 } |
956 | 911 |
957 | 912 |
958 function ExceptionEvent(break_id, exception, uncaught, promise) { | 913 function ExceptionEvent(break_id, exception, uncaught, promise) { |
959 this.exec_state_ = new ExecutionState(break_id); | 914 this.exec_state_ = new ExecutionState(break_id); |
960 this.exception_ = exception; | 915 this.exception_ = exception; |
961 this.uncaught_ = uncaught; | 916 this.uncaught_ = uncaught; |
962 this.promise_ = promise; | 917 this.promise_ = promise; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 ExceptionEvent.prototype.sourceColumn = function() { | 951 ExceptionEvent.prototype.sourceColumn = function() { |
997 return this.exec_state_.frame(0).sourceColumn(); | 952 return this.exec_state_.frame(0).sourceColumn(); |
998 }; | 953 }; |
999 | 954 |
1000 | 955 |
1001 ExceptionEvent.prototype.sourceLineText = function() { | 956 ExceptionEvent.prototype.sourceLineText = function() { |
1002 return this.exec_state_.frame(0).sourceLineText(); | 957 return this.exec_state_.frame(0).sourceLineText(); |
1003 }; | 958 }; |
1004 | 959 |
1005 | 960 |
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 | |
1032 function MakeCompileEvent(script, type) { | 961 function MakeCompileEvent(script, type) { |
1033 return new CompileEvent(script, type); | 962 return new CompileEvent(script, type); |
1034 } | 963 } |
1035 | 964 |
1036 | 965 |
1037 function CompileEvent(script, type) { | 966 function CompileEvent(script, type) { |
1038 this.script_ = MakeMirror(script); | 967 this.script_ = MakeMirror(script); |
1039 this.type_ = type; | 968 this.type_ = type; |
1040 } | 969 } |
1041 | 970 |
1042 | 971 |
1043 CompileEvent.prototype.eventType = function() { | 972 CompileEvent.prototype.eventType = function() { |
1044 return this.type_; | 973 return this.type_; |
1045 }; | 974 }; |
1046 | 975 |
1047 | 976 |
1048 CompileEvent.prototype.script = function() { | 977 CompileEvent.prototype.script = function() { |
1049 return this.script_; | 978 return this.script_; |
1050 }; | 979 }; |
1051 | 980 |
1052 | 981 |
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 | |
1074 function MakeScriptObject_(script, include_source) { | 982 function MakeScriptObject_(script, include_source) { |
1075 var o = { id: script.id(), | 983 var o = { id: script.id(), |
1076 name: script.name(), | 984 name: script.name(), |
1077 lineOffset: script.lineOffset(), | 985 lineOffset: script.lineOffset(), |
1078 columnOffset: script.columnOffset(), | 986 columnOffset: script.columnOffset(), |
1079 lineCount: script.lineCount(), | 987 lineCount: script.lineCount(), |
1080 }; | 988 }; |
1081 if (!IS_UNDEFINED(script.data())) { | 989 if (!IS_UNDEFINED(script.data())) { |
1082 o.data = script.data(); | 990 o.data = script.data(); |
1083 } | 991 } |
(...skipping 17 matching lines...) Expand all Loading... |
1101 | 1009 |
1102 AsyncTaskEvent.prototype.type = function() { | 1010 AsyncTaskEvent.prototype.type = function() { |
1103 return this.type_; | 1011 return this.type_; |
1104 } | 1012 } |
1105 | 1013 |
1106 | 1014 |
1107 AsyncTaskEvent.prototype.id = function() { | 1015 AsyncTaskEvent.prototype.id = function() { |
1108 return this.id_; | 1016 return this.id_; |
1109 } | 1017 } |
1110 | 1018 |
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 | |
2372 // ------------------------------------------------------------------- | 1019 // ------------------------------------------------------------------- |
2373 // Exports | 1020 // Exports |
2374 | 1021 |
2375 utils.InstallConstants(global, [ | 1022 utils.InstallConstants(global, [ |
2376 "Debug", Debug, | 1023 "Debug", Debug, |
2377 "DebugCommandProcessor", DebugCommandProcessor, | |
2378 "BreakEvent", BreakEvent, | 1024 "BreakEvent", BreakEvent, |
2379 "CompileEvent", CompileEvent, | 1025 "CompileEvent", CompileEvent, |
2380 "BreakPoint", BreakPoint, | 1026 "BreakPoint", BreakPoint, |
2381 ]); | 1027 ]); |
2382 | 1028 |
2383 // Functions needed by the debugger runtime. | 1029 // Functions needed by the debugger runtime. |
2384 utils.InstallFunctions(utils, DONT_ENUM, [ | 1030 utils.InstallFunctions(utils, DONT_ENUM, [ |
2385 "MakeExecutionState", MakeExecutionState, | 1031 "MakeExecutionState", MakeExecutionState, |
2386 "MakeExceptionEvent", MakeExceptionEvent, | 1032 "MakeExceptionEvent", MakeExceptionEvent, |
2387 "MakeBreakEvent", MakeBreakEvent, | 1033 "MakeBreakEvent", MakeBreakEvent, |
2388 "MakeCompileEvent", MakeCompileEvent, | 1034 "MakeCompileEvent", MakeCompileEvent, |
2389 "MakeAsyncTaskEvent", MakeAsyncTaskEvent, | 1035 "MakeAsyncTaskEvent", MakeAsyncTaskEvent, |
2390 "IsBreakPointTriggered", IsBreakPointTriggered, | 1036 "IsBreakPointTriggered", IsBreakPointTriggered, |
2391 ]); | 1037 ]); |
2392 | 1038 |
2393 }) | 1039 }) |
OLD | NEW |