Removed all functions for parsing the debugger command line commands. The core debugger should only support the JSON protocol. Expect these functions to re-appear in d8.

Added processDebugRequest to the debugger which will only process a JSON request. Use that function in the debugger.
Review URL: http://codereview.chromium.org/11395

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@824 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2008-11-24 10:31:22 +00:00
parent 95d1d40077
commit acb4ff9955
2 changed files with 33 additions and 342 deletions

View File

@ -891,324 +891,13 @@ function DebugCommandProcessor(exec_state) {
};
// Convenience function for C debugger code to process a text command. This
// function converts the text command to a JSON request, performs the request
// and converts the request to a text result for display. The result is an
// object containing the text result and the intermediate results.
DebugCommandProcessor.prototype.processDebugCommand = function (command) {
var request;
var response;
var text_result;
var running;
request = this.commandToJSONRequest(command);
response = this.processDebugJSONRequest(request);
text_result = this.responseToText(response);
running = this.isRunning(response);
return { "request" : request,
"response" : response,
"text_result" : text_result,
"running" : running };
DebugCommandProcessor.prototype.processDebugRequest = function (request) {
return this.processDebugJSONRequest(request);
}
// Converts a text command to a JSON request.
DebugCommandProcessor.prototype.commandToJSONRequest = function(cmd_line) {
// If the wery first character is a { assume that a JSON request have been
// entered as a command. Converting that to a JSON request is trivial.
if (cmd_line && cmd_line.length > 0 && cmd_line.charAt(0) == '{') {
return cmd_line;
}
// Trim string for leading and trailing whitespace.
cmd_line = cmd_line.replace(/^\s+|\s+$/g, "");
// Find the command.
var pos = cmd_line.indexOf(" ");
var cmd;
var args;
if (pos == -1) {
cmd = cmd_line;
args = "";
} else {
cmd = cmd_line.slice(0, pos);
args = cmd_line.slice(pos).replace(/^\s+|\s+$/g, "");
}
// Switch on command.
if (cmd == 'continue' || cmd == 'c') {
return this.continueCommandToJSONRequest_(args);
} else if (cmd == 'step' || cmd == 's') {
return this.stepCommandToJSONRequest_(args);
} else if (cmd == 'backtrace' || cmd == 'bt') {
return this.backtraceCommandToJSONRequest_(args);
} else if (cmd == 'frame' || cmd == 'f') {
return this.frameCommandToJSONRequest_(args);
} else if (cmd == 'print' || cmd == 'p') {
return this.printCommandToJSONRequest_(args);
} else if (cmd == 'source') {
return this.sourceCommandToJSONRequest_(args);
} else if (cmd == 'scripts') {
return this.scriptsCommandToJSONRequest_(args);
} else if (cmd[0] == '{') {
return cmd_line;
} else {
throw new Error('Unknown command "' + cmd + '"');
}
};
// Create a JSON request for the continue command.
DebugCommandProcessor.prototype.continueCommandToJSONRequest_ = function(args) {
var request = this.createRequest('continue');
return request.toJSONProtocol();
};
// Create a JSON request for the step command.
DebugCommandProcessor.prototype.stepCommandToJSONRequest_ = function(args) {
// Requesting a step is through the continue command with additional
// arguments.
var request = this.createRequest('continue');
request.arguments = {};
// Process arguments if any.
if (args && args.length > 0) {
args = args.split(/\s*[ ]+\s*/g);
if (args.length > 2) {
throw new Error('Invalid step arguments.');
}
if (args.length > 0) {
// Get step count argument if any.
if (args.length == 2) {
request.arguments.stepcount = %ToNumber(args[1]);
}
// Get the step action.
if (args[0] == 'in' || args[0] == 'i') {
request.arguments.stepaction = 'in';
} else if (args[0] == 'min' || args[0] == 'm') {
request.arguments.stepaction = 'min';
} else if (args[0] == 'next' || args[0] == 'n') {
request.arguments.stepaction = 'next';
} else if (args[0] == 'out' || args[0] == 'o') {
request.arguments.stepaction = 'out';
} else {
throw new Error('Invalid step argument "' + args[0] + '".');
}
}
} else {
// Default is step next.
request.arguments.stepaction = 'next';
}
return request.toJSONProtocol();
};
// Create a JSON request for the backtrace command.
DebugCommandProcessor.prototype.backtraceCommandToJSONRequest_ = function(args) {
// Build a backtrace request from the text command.
var request = this.createRequest('backtrace');
args = args.split(/\s*[ ]+\s*/g);
if (args.length == 2) {
request.arguments = {};
request.arguments.fromFrame = %ToNumber(args[0]);
request.arguments.toFrame = %ToNumber(args[1]) + 1;
}
return request.toJSONProtocol();
};
// Create a JSON request for the frame command.
DebugCommandProcessor.prototype.frameCommandToJSONRequest_ = function(args) {
// Build a frame request from the text command.
var request = this.createRequest('frame');
args = args.split(/\s*[ ]+\s*/g);
if (args.length > 0 && args[0].length > 0) {
request.arguments = {};
request.arguments.number = args[0];
}
return request.toJSONProtocol();
};
// Create a JSON request for the print command.
DebugCommandProcessor.prototype.printCommandToJSONRequest_ = function(args) {
// Build a evaluate request from the text command.
var request = this.createRequest('evaluate');
if (args.length == 0) {
throw new Error('Missing expression.');
}
request.arguments = {};
request.arguments.expression = args;
return request.toJSONProtocol();
};
// Create a JSON request for the source command.
DebugCommandProcessor.prototype.sourceCommandToJSONRequest_ = function(args) {
// Build a evaluate request from the text command.
var request = this.createRequest('source');
// Default is one line before and two lines after current location.
var before = 1;
var after = 2;
// Parse the arguments.
args = args.split(/\s*[ ]+\s*/g);
if (args.length > 1 && args[0].length > 0 && args[1].length > 0) {
before = %ToNumber(args[0]);
after = %ToNumber(args[1]);
} else if (args.length > 0 && args[0].length > 0) {
after = %ToNumber(args[0]);
}
// Request source arround current source location.
request.arguments = {};
request.arguments.fromLine = this.exec_state_.frame().sourceLine() - before;
if (request.arguments.fromLine < 0) {
request.arguments.fromLine = 0
}
request.arguments.toLine = this.exec_state_.frame().sourceLine() + after + 1;
return request.toJSONProtocol();
};
// Create a JSON request for the scripts command.
DebugCommandProcessor.prototype.scriptsCommandToJSONRequest_ = function(args) {
// Build a evaluate request from the text command.
var request = this.createRequest('scripts');
// Process arguments if any.
if (args && args.length > 0) {
args = args.split(/\s*[ ]+\s*/g);
if (args.length > 1) {
throw new Error('Invalid scripts arguments.');
}
request.arguments = {};
if (args[0] == 'natives') {
request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Native);
} else if (args[0] == 'extensions') {
request.arguments.types = ScriptTypeFlag(Debug.ScriptType.Extension);
} else if (args[0] == 'all') {
request.arguments.types =
ScriptTypeFlag(Debug.ScriptType.Normal) |
ScriptTypeFlag(Debug.ScriptType.Native) |
ScriptTypeFlag(Debug.ScriptType.Extension);
} else {
throw new Error('Invalid argument "' + args[0] + '".');
}
}
return request.toJSONProtocol();
};
// Convert a JSON response to text for display in a text based debugger.
DebugCommandProcessor.prototype.responseToText = function(json_response) {
try {
// Convert the JSON string to an object.
response = %CompileString('(' + json_response + ')', 0, false)();
if (!response.success) {
return response.message;
}
if (response.command == 'backtrace') {
var body = response.body;
var result = 'Frames #' + body.fromFrame + ' to #' +
(body.toFrame - 1) + ' of ' + body.totalFrames + '\n';
for (i = 0; i < body.frames.length; i++) {
if (i != 0) result += '\n';
result += body.frames[i].text;
}
return result;
} else if (response.command == 'frame') {
return SourceUnderline(response.body.sourceLineText,
response.body.column);
} else if (response.command == 'evaluate') {
return response.body.text;
} else if (response.command == 'source') {
// Get the source from the response.
var source = response.body.source;
// Get rid of last line terminator.
var remove_count = 0;
if (source[source.length - 1] == '\n') remove_count++;
if (source[source.length - 2] == '\r') remove_count++;
if (remove_count > 0) source = source.substring(0, source.length - remove_count);
return source;
} else if (response.command == 'scripts') {
var result = '';
for (i = 0; i < response.body.length; i++) {
if (i != 0) result += '\n';
if (response.body[i].name) {
result += response.body[i].name;
} else {
result += '[unnamed] ';
var sourceStart = response.body[i].sourceStart;
if (sourceStart.length > 40) {
sourceStart = sourceStart.substring(0, 37) + '...';
}
result += sourceStart;
}
result += ' (lines: ';
result += response.body[i].sourceLines;
result += ', length: ';
result += response.body[i].sourceLength;
if (response.body[i].type == Debug.ScriptType.Native) {
result += ', native';
} else if (response.body[i].type == Debug.ScriptType.Extension) {
result += ', extension';
}
result += ')';
}
return result;
}
} catch (e) {
return 'Error: "' + %ToString(e) + '" formatting response';
}
};
function SourceUnderline(source_text, position) {
if (IS_UNDEFINED(source_text)) {
return;
}
// Create an underline with a caret pointing to the source position. If the
// source contains a tab character the underline will have a tab character in
// the same place otherwise the underline will have a space character.
var underline = '';
for (var i = 0; i < position; i++) {
if (source_text[i] == '\t') {
underline += '\t';
} else {
underline += ' ';
}
}
underline += '^';
// Return the source line text with the underline beneath.
return source_text + '\n' + underline;
}
function FrameSourceUnderline(frame) {
var location = frame.sourceLocation();
if (location) {
return SourceUnderline(location.sourceText(), location.position - location.start);
}
DebugCommandProcessor.prototype.responseIsRunning = function (response) {
return this.isRunning(response);
}

View File

@ -1769,10 +1769,10 @@ void DebugMessageThread::DebugEvent(v8::DebugEvent event,
host_running_ = false;
SetEventJSONFromEvent(event_data);
// Wait for commands from the debugger.
// Wait for requests from the debugger.
while (true) {
command_received_->Wait();
Logger::DebugTag("Get command from command queue, in interactive loop.");
Logger::DebugTag("Got request from command queue, in interactive loop.");
Vector<uint16_t> command = command_queue_.Get();
ASSERT(!host_running_);
if (!Debugger::debugger_active()) {
@ -1780,52 +1780,54 @@ void DebugMessageThread::DebugEvent(v8::DebugEvent event,
return;
}
// Invoke the JavaScript to convert the debug command line to a JSON
// request, invoke the JSON request and convert the JSON response to a text
// representation.
// Invoke the JavaScript to process the debug request.
v8::Local<v8::String> fun_name;
v8::Local<v8::Function> fun;
v8::Local<v8::Value> args[1];
v8::Local<v8::Value> request;
v8::TryCatch try_catch;
fun_name = v8::String::New("processDebugCommand");
fun_name = v8::String::New("processDebugRequest");
fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
args[0] = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
request = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
command.length());
v8::Local<v8::Value> result_val = fun->Call(cmd_processor, 1, args);
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { request };
v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
// Get the result of the command.
v8::Local<v8::String> result_string;
// Get the response.
v8::Local<v8::String> response;
bool running = false;
if (!try_catch.HasCaught()) {
// Get the result as an object.
v8::Local<v8::Object> result = v8::Object::Cast(*result_val);
// Get response string.
if (!response_val->IsUndefined()) {
response = v8::String::Cast(*response_val);
} else {
response = v8::String::New("");
}
// Log the JSON request/response.
if (FLAG_trace_debug_json) {
PrintLn(result->Get(v8::String::New("request")));
PrintLn(result->Get(v8::String::New("response")));
PrintLn(request);
PrintLn(response);
}
// Get the running state.
running = result->Get(v8::String::New("running"))->ToBoolean()->Value();
// Get result text.
v8::Local<v8::Value> text_result =
result->Get(v8::String::New("response"));
if (!text_result->IsUndefined()) {
result_string = text_result->ToString();
} else {
result_string = v8::String::New("");
fun_name = v8::String::New("isRunning");
fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { response };
v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
if (!try_catch.HasCaught()) {
running = running_val->ToBoolean()->Value();
}
} else {
// In case of failure the result text is the exception text.
result_string = try_catch.Exception()->ToString();
response = try_catch.Exception()->ToString();
}
// Convert text result to C string.
v8::String::Value val(result_string);
v8::String::Value val(response);
Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
result_string->Length());
response->Length());
// Set host_running_ correctly for nested debugger evaluations.
host_running_ = running;