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:
parent
95d1d40077
commit
acb4ff9955
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
56
src/debug.cc
56
src/debug.cc
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user