| 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 |