OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 NewFunctionEvent.prototype.setBreakPoint = function(p) { | 884 NewFunctionEvent.prototype.setBreakPoint = function(p) { |
885 Debug.setBreakPoint(this.func, p || 0); | 885 Debug.setBreakPoint(this.func, p || 0); |
886 }; | 886 }; |
887 | 887 |
888 | 888 |
889 function DebugCommandProcessor(exec_state) { | 889 function DebugCommandProcessor(exec_state) { |
890 this.exec_state_ = exec_state; | 890 this.exec_state_ = exec_state; |
891 }; | 891 }; |
892 | 892 |
893 | 893 |
894 // Convenience function for C debugger code to process a text command. This | 894 DebugCommandProcessor.prototype.processDebugRequest = function (request) { |
895 // function converts the text command to a JSON request, performs the request | 895 return this.processDebugJSONRequest(request); |
896 // and converts the request to a text result for display. The result is an | |
897 // object containing the text result and the intermediate results. | |
898 DebugCommandProcessor.prototype.processDebugCommand = function (command) { | |
899 var request; | |
900 var response; | |
901 var text_result; | |
902 var running; | |
903 | |
904 request = this.commandToJSONRequest(command); | |
905 response = this.processDebugJSONRequest(request); | |
906 text_result = this.responseToText(response); | |
907 running = this.isRunning(response); | |
908 | |
909 return { "request" : request, | |
910 "response" : response, | |
911 "text_result" : text_result, | |
912 "running" : running }; | |
913 } | 896 } |
914 | 897 |
915 | 898 |
916 // Converts a text command to a JSON request. | 899 DebugCommandProcessor.prototype.responseIsRunning = function (response) { |
917 DebugCommandProcessor.prototype.commandToJSONRequest = function(cmd_line) { | 900 return this.isRunning(response); |
918 // If the wery first character is a { assume that a JSON request have been | |
919 // entered as a command. Converting that to a JSON request is trivial. | |
920 if (cmd_line && cmd_line.length > 0 && cmd_line.charAt(0) == '{') { | |
921 return cmd_line; | |
922 } | |
923 | |
924 // Trim string for leading and trailing whitespace. | |
925 cmd_line = cmd_line.replace(/^\s+|\s+$/g, ""); | |
926 | |
927 // Find the command. | |
928 var pos = cmd_line.indexOf(" "); | |
929 var cmd; | |
930 var args; | |
931 if (pos == -1) { | |
932 cmd = cmd_line; | |
933 args = ""; | |
934 } else { | |
935 cmd = cmd_line.slice(0, pos); | |
936 args = cmd_line.slice(pos).replace(/^\s+|\s+$/g, ""); | |
937 } | |
938 | |
939 // Switch on command. | |
940 if (cmd == 'continue' || cmd == 'c') { | |
941 return this.continueCommandToJSONRequest_(args); | |
942 } else if (cmd == 'step' || cmd == 's') { | |
943 return this.stepCommandToJSONRequest_(args); | |
944 } else if (cmd == 'backtrace' || cmd == 'bt') { | |
945 return this.backtraceCommandToJSONRequest_(args); | |
946 } else if (cmd == 'frame' || cmd == 'f') { | |
947 return this.frameCommandToJSONRequest_(args); | |
948 } else if (cmd == 'print' || cmd == 'p') { | |
949 return this.printCommandToJSONRequest_(args); | |
950 } else if (cmd == 'source') { | |
951 return this.sourceCommandToJSONRequest_(args); | |
952 } else if (cmd == 'scripts') { | |
953 return this.scriptsCommandToJSONRequest_(args); | |
954 } else if (cmd[0] == '{') { | |
955 return cmd_line; | |
956 } else { | |
957 throw new Error('Unknown command "' + cmd + '"'); | |
958 } | |
959 }; | |
960 | |
961 | |
962 // Create a JSON request for the continue command. | |
963 DebugCommandProcessor.prototype.continueCommandToJSONRequest_ = function(args) { | |
964 var request = this.createRequest('continue'); | |
965 return request.toJSONProtocol(); | |
966 }; | |
967 | |
968 | |
969 // Create a JSON request for the step command. | |
970 DebugCommandProcessor.prototype.stepCommandToJSONRequest_ = function(args) { | |
971 // Requesting a step is through the continue command with additional | |
972 // arguments. | |
973 var request = this.createRequest('continue'); | |
974 request.arguments = {}; | |
975 | |
976 // Process arguments if any. | |
977 if (args && args.length > 0) { | |
978 args = args.split(/\s*[ ]+\s*/g); | |
979 | |
980 if (args.length > 2) { | |
981 throw new Error('Invalid step arguments.'); | |
982 } | |
983 | |
984 if (args.length > 0) { | |
985 // Get step count argument if any. | |
986 if (args.length == 2) { | |
987 request.arguments.stepcount = %ToNumber(args[1]); | |
988 } | |
989 | |
990 // Get the step action. | |
991 if (args[0] == 'in' || args[0] == 'i') { | |
992 request.arguments.stepaction = 'in'; | |
993 } else if (args[0] == 'min' || args[0] == 'm') { | |
994 request.arguments.stepaction = 'min'; | |
995 } else if (args[0] == 'next' || args[0] == 'n') { | |
996 request.arguments.stepaction = 'next'; | |
997 } else if (args[0] == 'out' || args[0] == 'o') { | |
998 request.arguments.stepaction = 'out'; | |
999 } else { | |
1000 throw new Error('Invalid step argument "' + args[0] + '".'); | |
1001 } | |
1002 } | |
1003 } else { | |
1004 // Default is step next. | |
1005 request.arguments.stepaction = 'next'; | |
1006 } | |
1007 | |
1008 return request.toJSONProtocol(); | |
1009 }; | |
1010 | |
1011 | |
1012 // Create a JSON request for the backtrace command. | |
1013 DebugCommandProcessor.prototype.backtraceCommandToJSONRequest_ = function(args)
{ | |
1014 // Build a backtrace request from the text command. | |
1015 var request = this.createRequest('backtrace'); | |
1016 args = args.split(/\s*[ ]+\s*/g); | |
1017 if (args.length == 2) { | |
1018 request.arguments = {}; | |
1019 request.arguments.fromFrame = %ToNumber(args[0]); | |
1020 request.arguments.toFrame = %ToNumber(args[1]) + 1; | |
1021 } | |
1022 return request.toJSONProtocol(); | |
1023 }; | |
1024 | |
1025 | |
1026 // Create a JSON request for the frame command. | |
1027 DebugCommandProcessor.prototype.frameCommandToJSONRequest_ = function(args) { | |
1028 // Build a frame request from the text command. | |
1029 var request = this.createRequest('frame'); | |
1030 args = args.split(/\s*[ ]+\s*/g); | |
1031 if (args.length > 0 && args[0].length > 0) { | |
1032 request.arguments = {}; | |
1033 request.arguments.number = args[0]; | |
1034 } | |
1035 return request.toJSONProtocol(); | |
1036 }; | |
1037 | |
1038 | |
1039 // Create a JSON request for the print command. | |
1040 DebugCommandProcessor.prototype.printCommandToJSONRequest_ = function(args) { | |
1041 // Build a evaluate request from the text command. | |
1042 var request = this.createRequest('evaluate'); | |
1043 if (args.length == 0) { | |
1044 throw new Error('Missing expression.'); | |
1045 } | |
1046 | |
1047 request.arguments = {}; | |
1048 request.arguments.expression = args; | |
1049 | |
1050 return request.toJSONProtocol(); | |
1051 }; | |
1052 | |
1053 | |
1054 // Create a JSON request for the source command. | |
1055 DebugCommandProcessor.prototype.sourceCommandToJSONRequest_ = function(args) { | |
1056 // Build a evaluate request from the text command. | |
1057 var request = this.createRequest('source'); | |
1058 | |
1059 // Default is one line before and two lines after current location. | |
1060 var before = 1; | |
1061 var after = 2; | |
1062 | |
1063 // Parse the arguments. | |
1064 args = args.split(/\s*[ ]+\s*/g); | |
1065 if (args.length > 1 && args[0].length > 0 && args[1].length > 0) { | |
1066 before = %ToNumber(args[0]); | |
1067 after = %ToNumber(args[1]); | |
1068 } else if (args.length > 0 && args[0].length > 0) { | |
1069 after = %ToNumber(args[0]); | |
1070 } | |
1071 | |
1072 // Request source arround current source location. | |
1073 request.arguments = {}; | |
1074 request.arguments.fromLine = this.exec_state_.frame().sourceLine() - before; | |
1075 if (request.arguments.fromLine < 0) { | |
1076 request.arguments.fromLine = 0 | |
1077 } | |
1078 request.arguments.toLine = this.exec_state_.frame().sourceLine() + after + 1; | |
1079 | |
1080 return request.toJSONProtocol(); | |
1081 }; | |
1082 | |
1083 | |
1084 // Create a JSON request for the scripts command. | |
1085 DebugCommandProcessor.prototype.scriptsCommandToJSONRequest_ = function(args) { | |
1086 // Build a evaluate request from the text command. | |
1087 var request = this.createRequest('scripts'); | |
1088 | |
1089 // Process arguments if any. | |
1090 if (args && args.length > 0) { | |
1091 args = args.split(/\s*[ ]+\s*/g); | |
1092 | |
1093 if (args.length > 1) { | |
1094 throw new Error('Invalid scripts arguments.'); | |
1095 } | |
1096 | |
1097 request.arguments = {}; | |
1098 if (args[0] == 'natives') { | |
1099 request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Native); | |
1100 } else if (args[0] == 'extensions') { | |
1101 request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Extension); | |
1102 } else if (args[0] == 'all') { | |
1103 request.arguments.types = | |
1104 ScriptTypeFlag(Debug.ScriptType.Normal) | | |
1105 ScriptTypeFlag(Debug.ScriptType.Native) | | |
1106 ScriptTypeFlag(Debug.ScriptType.Extension); | |
1107 } else { | |
1108 throw new Error('Invalid argument "' + args[0] + '".'); | |
1109 } | |
1110 } | |
1111 | |
1112 return request.toJSONProtocol(); | |
1113 }; | |
1114 | |
1115 | |
1116 // Convert a JSON response to text for display in a text based debugger. | |
1117 DebugCommandProcessor.prototype.responseToText = function(json_response) { | |
1118 try { | |
1119 // Convert the JSON string to an object. | |
1120 response = %CompileString('(' + json_response + ')', 0, false)(); | |
1121 | |
1122 if (!response.success) { | |
1123 return response.message; | |
1124 } | |
1125 | |
1126 if (response.command == 'backtrace') { | |
1127 var body = response.body; | |
1128 var result = 'Frames #' + body.fromFrame + ' to #' + | |
1129 (body.toFrame - 1) + ' of ' + body.totalFrames + '\n'; | |
1130 for (i = 0; i < body.frames.length; i++) { | |
1131 if (i != 0) result += '\n'; | |
1132 result += body.frames[i].text; | |
1133 } | |
1134 return result; | |
1135 } else if (response.command == 'frame') { | |
1136 return SourceUnderline(response.body.sourceLineText, | |
1137 response.body.column); | |
1138 } else if (response.command == 'evaluate') { | |
1139 return response.body.text; | |
1140 } else if (response.command == 'source') { | |
1141 // Get the source from the response. | |
1142 var source = response.body.source; | |
1143 | |
1144 // Get rid of last line terminator. | |
1145 var remove_count = 0; | |
1146 if (source[source.length - 1] == '\n') remove_count++; | |
1147 if (source[source.length - 2] == '\r') remove_count++; | |
1148 if (remove_count > 0) source = source.substring(0, source.length - remove_
count); | |
1149 | |
1150 return source; | |
1151 } else if (response.command == 'scripts') { | |
1152 var result = ''; | |
1153 for (i = 0; i < response.body.length; i++) { | |
1154 if (i != 0) result += '\n'; | |
1155 if (response.body[i].name) { | |
1156 result += response.body[i].name; | |
1157 } else { | |
1158 result += '[unnamed] '; | |
1159 var sourceStart = response.body[i].sourceStart; | |
1160 if (sourceStart.length > 40) { | |
1161 sourceStart = sourceStart.substring(0, 37) + '...'; | |
1162 } | |
1163 result += sourceStart; | |
1164 } | |
1165 result += ' (lines: '; | |
1166 result += response.body[i].sourceLines; | |
1167 result += ', length: '; | |
1168 result += response.body[i].sourceLength; | |
1169 if (response.body[i].type == Debug.ScriptType.Native) { | |
1170 result += ', native'; | |
1171 } else if (response.body[i].type == Debug.ScriptType.Extension) { | |
1172 result += ', extension'; | |
1173 } | |
1174 result += ')'; | |
1175 } | |
1176 return result; | |
1177 } | |
1178 } catch (e) { | |
1179 return 'Error: "' + %ToString(e) + '" formatting response'; | |
1180 } | |
1181 }; | |
1182 | |
1183 | |
1184 function SourceUnderline(source_text, position) { | |
1185 if (IS_UNDEFINED(source_text)) { | |
1186 return; | |
1187 } | |
1188 | |
1189 // Create an underline with a caret pointing to the source position. If the | |
1190 // source contains a tab character the underline will have a tab character in | |
1191 // the same place otherwise the underline will have a space character. | |
1192 var underline = ''; | |
1193 for (var i = 0; i < position; i++) { | |
1194 if (source_text[i] == '\t') { | |
1195 underline += '\t'; | |
1196 } else { | |
1197 underline += ' '; | |
1198 } | |
1199 } | |
1200 underline += '^'; | |
1201 | |
1202 // Return the source line text with the underline beneath. | |
1203 return source_text + '\n' + underline; | |
1204 } | |
1205 | |
1206 | |
1207 function FrameSourceUnderline(frame) { | |
1208 var location = frame.sourceLocation(); | |
1209 if (location) { | |
1210 return SourceUnderline(location.sourceText(), location.position - location.s
tart); | |
1211 } | |
1212 } | 901 } |
1213 | 902 |
1214 | 903 |
1215 function RequestPacket(command) { | 904 function RequestPacket(command) { |
1216 this.seq = 0; | 905 this.seq = 0; |
1217 this.type = 'request'; | 906 this.type = 'request'; |
1218 this.command = command; | 907 this.command = command; |
1219 } | 908 } |
1220 | 909 |
1221 | 910 |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1908 json += NumberToJSON_(elem); | 1597 json += NumberToJSON_(elem); |
1909 } else if (IS_STRING(elem)) { | 1598 } else if (IS_STRING(elem)) { |
1910 json += StringToJSON_(elem); | 1599 json += StringToJSON_(elem); |
1911 } else { | 1600 } else { |
1912 json += elem; | 1601 json += elem; |
1913 } | 1602 } |
1914 } | 1603 } |
1915 json += ']'; | 1604 json += ']'; |
1916 return json; | 1605 return json; |
1917 } | 1606 } |
OLD | NEW |