Change the D8 JavaScript debugger to fully use the JSON protocol.

The D8 debugger frontend now only processes JSON messages. Before the debugger events was passed as objects.

Changed the debugger events JSON generation to use the same serailizer as the responses to requests. This provides correct serialization of mirror objects in debugger events. Renamed ResponsePacket to ProtocolMessage as it is not only used for responses.
Review URL: http://codereview.chromium.org/27202

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1374 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2009-02-26 11:55:35 +00:00
parent c81043b259
commit 20a9e9b013
5 changed files with 135 additions and 84 deletions

View File

@ -46,8 +46,19 @@ void HandleDebugEvent(DebugEvent event,
TryCatch try_catch;
// Get the toJSONProtocol function on the event and get the JSON format.
Local<String> to_json_fun_name = String::New("toJSONProtocol");
Local<Function> to_json_fun =
Function::Cast(*event_data->Get(to_json_fun_name));
Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
if (try_catch.HasCaught()) {
Shell::ReportException(&try_catch);
return;
}
// Print the event details.
Handle<String> details = Shell::DebugEventToText(event_data);
Handle<String> details =
Shell::DebugEventToText(Handle<String>::Cast(event_json));
if (details->Length() == 0) {
// Empty string is used to signal not to process this event.
return;

View File

@ -232,7 +232,7 @@ Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
}
Handle<String> Shell::DebugEventToText(Handle<Object> event) {
Handle<String> Shell::DebugEventToText(Handle<String> event) {
HandleScope handle_scope;
Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global();

View File

@ -88,7 +88,7 @@ class Shell: public i::AllStatic {
static int Main(int argc, char* argv[]);
static Handle<Array> GetCompletions(Handle<String> text,
Handle<String> full);
static Handle<String> DebugEventToText(Handle<Object> event);
static Handle<String> DebugEventToText(Handle<String> event);
static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
static Handle<Object> DebugResponseDetails(Handle<String> response);

106
src/d8.js
View File

@ -103,66 +103,54 @@ var trace_compile = false; // Tracing all compile events?
function DebugEventToText(event) {
switch (event.eventType()) {
case Debug.DebugEvent.Break:
// Build the break details.
var details = '';
if (event.breakPointsHit()) {
// Convert the JSON string to an object.
var response = new ProtocolPackage(event);
// Build the text.
var body = response.body();
var details = '';
switch (response.event()) {
case 'break':
if (body.breakpoints) {
details += 'breakpoint';
if (event.breakPointsHit().length > 1) {
if (body.breakpoints.length > 1) {
details += 's';
}
details += ' #';
for (var i = 0; i < event.breakPointsHit().length; i++) {
for (var i = 0; i < body.breakpoints.length; i++) {
if (i > 0) {
details += ', #';
}
// Find the break point number. For break points originating from a
// script break point display the script break point number.
var break_point = event.breakPointsHit()[i];
var script_break_point = break_point.script_break_point();
if (script_break_point) {
details += script_break_point.number();
} else {
details += break_point.number();
}
details += body.breakpoints[i];
}
} else {
details += 'break';
}
details += ' in ';
details += event.executionState().frame(0).invocationText();
details += ' at ';
details += event.executionState().frame(0).sourceAndPositionText();
details += '\n'
if (event.func().script()) {
details += FrameSourceUnderline(event.executionState().frame(0));
}
Debug.State.currentSourceLine =
event.executionState().frame(0).sourceLine();
details += body.invocationText;
details += ', ';
details += SourceInfo(body);
details += '\n';
details += SourceUnderline(body.sourceLineText, body.sourceColumn);
Debug.State.currentSourceLine = body.sourceLine;
Debug.State.currentFrame = 0;
return details;
case Debug.DebugEvent.Exception:
var details = '';
if (event.uncaught_) {
case 'exception':
if (body.uncaught) {
details += 'Uncaught: ';
} else {
details += 'Exception: ';
}
details += '"';
details += event.exception();
details += body.exception.text;
details += '"';
if (event.executionState().frameCount() > 0) {
details += '"';
details += event.exception();
details += ' at ';
details += event.executionState().frame(0).sourceAndPositionText();
if (body.sourceLine >= 0) {
details += ', ';
details += SourceInfo(body);
details += '\n';
details += FrameSourceUnderline(event.executionState().frame(0));
Debug.State.currentSourceLine =
event.executionState().frame(0).sourceLine();
details += SourceUnderline(body.sourceLineText, body.sourceColumn);
Debug.State.currentSourceLine = body.sourceLine;
Debug.State.currentFrame = 0;
} else {
details += ' (empty stack)';
@ -171,10 +159,17 @@ function DebugEventToText(event) {
}
return details;
case Debug.DebugEvent.AfterCompile:
case 'exception':
if (trace_compile) {
details = 'Source ' + body.script.name + ' compiled:\n'
} else {
return '';
}
case 'afterCompile':
if (trace_compile) {
details = 'Source ' + event.script().name() + ' compiled:\n'
var source = event.script().source();
var source = body.script.source;
if (!(source[source.length - 1] == '\n')) {
details += source;
} else {
@ -185,11 +180,29 @@ function DebugEventToText(event) {
return '';
}
}
return 'Unknown debug event ' + event.eventType();
return 'Unknown debug event ' + response.event();
};
function SourceInfo(body) {
var result = '';
if (body.script) {
if (body.script.name) {
result += body.script.name;
} else {
result += '[unnamed]';
}
}
result += ' line ';
result += body.sourceLine + 1;
result += ' column ';
result += body.sourceColumn + 1;
return result;
}
function SourceUnderline(source_text, position) {
if (!source_text) {
return;
@ -213,15 +226,6 @@ function SourceUnderline(source_text, position) {
};
function FrameSourceUnderline(frame) {
var location = frame.sourceLocation();
if (location) {
return SourceUnderline(location.sourceText(),
location.position - location.start);
}
};
// Converts a text command to a JSON request.
function DebugCommandToJSONRequest(cmd_line) {
return new DebugRequest(cmd_line).JSONRequest();

View File

@ -871,28 +871,32 @@ ExceptionEvent.prototype.sourceLineText = function() {
ExceptionEvent.prototype.toJSONProtocol = function() {
var o = { seq: next_response_seq++,
type: "event",
event: "exception",
body: { uncaught: this.uncaught_,
exception: MakeMirror(this.exception_),
sourceLine: this.sourceLine(),
sourceColumn: this.sourceColumn(),
sourceLineText: this.sourceLineText(),
}
}
var o = new ProtocolMessage();
o.event = "exception";
o.body = { uncaught: this.uncaught_,
exception: MakeMirror(this.exception_)
}
// Add script information to the event if available.
var script = this.func().script();
if (script) {
o.body.script = { name: script.name(),
lineOffset: script.lineOffset(),
columnOffset: script.columnOffset(),
lineCount: script.lineCount()
};
// Exceptions might happen whithout any JavaScript frames.
if (this.exec_state_.frameCount() > 0) {
o.body.sourceLine = this.sourceLine();
o.body.sourceColumn = this.sourceColumn();
o.body.sourceLineText = this.sourceLineText();
// Add script information to the event if available.
var script = this.func().script();
if (script) {
o.body.script = { name: script.name(),
lineOffset: script.lineOffset(),
columnOffset: script.columnOffset(),
lineCount: script.lineCount()
};
}
} else {
o.body.sourceLine = -1;
}
return SimpleObjectToJSON_(o);
return o.toJSONProtocol();
};
@ -927,6 +931,25 @@ CompileEvent.prototype.script = function() {
};
CompileEvent.prototype.toJSONProtocol = function() {
var o = new ProtocolMessage();
if (this.before_) {
o.event = "beforeCompile";
} else {
o.event = "afterCompile";
}
o.body = {};
o.body.script = { name: this.script_.name(),
lineOffset: this.script_.lineOffset(),
columnOffset: this.script_.columnOffset(),
lineCount: this.script_.lineCount(),
source: this.script_.source()
};
return o.toJSONProtocol();
}
function MakeNewFunctionEvent(func) {
return new NewFunctionEvent(func);
}
@ -963,24 +986,32 @@ DebugCommandProcessor.prototype.processDebugRequest = function (request) {
}
function ResponsePacket(request) {
// Build the initial response from the request.
function ProtocolMessage(request) {
// Update sequence number.
this.seq = next_response_seq++;
this.type = 'response';
if (request) this.request_seq = request.seq;
if (request) this.command = request.command;
if (request) {
// If message is based on a request this is a response. Fill the initial
// response from the request.
this.type = 'response';
this.request_seq = request.seq;
this.command = request.command;
} else {
// If message is not based on a request it is a dabugger generated event.
this.type = 'event';
}
this.success = true;
this.running = false;
}
ResponsePacket.prototype.failed = function(message) {
ProtocolMessage.prototype.failed = function(message) {
this.success = false;
this.message = message;
}
ResponsePacket.prototype.toJSONProtocol = function() {
ProtocolMessage.prototype.toJSONProtocol = function() {
// Encode the protocol header.
var json = '{';
json += '"seq":' + this.seq;
@ -988,6 +1019,9 @@ ResponsePacket.prototype.toJSONProtocol = function() {
json += ',"request_seq":' + this.request_seq;
}
json += ',"type":"' + this.type + '"';
if (this.event) {
json += ',"event":' + StringToJSON_(this.event);
}
if (this.command) {
json += ',"command":' + StringToJSON_(this.command);
}
@ -1033,7 +1067,7 @@ ResponsePacket.prototype.toJSONProtocol = function() {
DebugCommandProcessor.prototype.createResponse = function(request) {
return new ResponsePacket(request);
return new ProtocolMessage(request);
};
@ -1652,7 +1686,9 @@ function SimpleObjectToJSON_(object, mirror_serializer) {
var property_value_json;
switch (typeof property_value) {
case 'object':
if (typeof property_value.toJSONProtocol == 'function') {
if (property_value instanceof Mirror) {
property_value_json = mirror_serializer.serializeValue(property_value);
} else if (typeof property_value.toJSONProtocol == 'function') {
property_value_json = property_value.toJSONProtocol(true)
} else if (IS_ARRAY(property_value)){
property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer);