Commit 20a9e9b0 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

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
parent c81043b2
...@@ -46,8 +46,19 @@ void HandleDebugEvent(DebugEvent event, ...@@ -46,8 +46,19 @@ void HandleDebugEvent(DebugEvent event,
TryCatch try_catch; 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. // 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) { if (details->Length() == 0) {
// Empty string is used to signal not to process this event. // Empty string is used to signal not to process this event.
return; return;
......
...@@ -232,7 +232,7 @@ Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) { ...@@ -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; HandleScope handle_scope;
Context::Scope context_scope(utility_context_); Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global(); Handle<Object> global = utility_context_->Global();
......
...@@ -88,7 +88,7 @@ class Shell: public i::AllStatic { ...@@ -88,7 +88,7 @@ class Shell: public i::AllStatic {
static int Main(int argc, char* argv[]); static int Main(int argc, char* argv[]);
static Handle<Array> GetCompletions(Handle<String> text, static Handle<Array> GetCompletions(Handle<String> text,
Handle<String> full); 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<Value> DebugCommandToJSONRequest(Handle<String> command);
static Handle<Object> DebugResponseDetails(Handle<String> response); static Handle<Object> DebugResponseDetails(Handle<String> response);
......
...@@ -103,66 +103,54 @@ var trace_compile = false; // Tracing all compile events? ...@@ -103,66 +103,54 @@ var trace_compile = false; // Tracing all compile events?
function DebugEventToText(event) { function DebugEventToText(event) {
switch (event.eventType()) { // Convert the JSON string to an object.
case Debug.DebugEvent.Break: var response = new ProtocolPackage(event);
// Build the break details.
var details = ''; // Build the text.
if (event.breakPointsHit()) { var body = response.body();
var details = '';
switch (response.event()) {
case 'break':
if (body.breakpoints) {
details += 'breakpoint'; details += 'breakpoint';
if (event.breakPointsHit().length > 1) { if (body.breakpoints.length > 1) {
details += 's'; details += 's';
} }
details += ' #'; details += ' #';
for (var i = 0; i < event.breakPointsHit().length; i++) { for (var i = 0; i < body.breakpoints.length; i++) {
if (i > 0) { if (i > 0) {
details += ', #'; details += ', #';
} }
// Find the break point number. For break points originating from a details += body.breakpoints[i];
// 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();
}
} }
} else { } else {
details += 'break'; details += 'break';
} }
details += ' in '; details += ' in ';
details += event.executionState().frame(0).invocationText(); details += body.invocationText;
details += ' at '; details += ', ';
details += event.executionState().frame(0).sourceAndPositionText(); details += SourceInfo(body);
details += '\n' details += '\n';
if (event.func().script()) { details += SourceUnderline(body.sourceLineText, body.sourceColumn);
details += FrameSourceUnderline(event.executionState().frame(0)); Debug.State.currentSourceLine = body.sourceLine;
}
Debug.State.currentSourceLine =
event.executionState().frame(0).sourceLine();
Debug.State.currentFrame = 0; Debug.State.currentFrame = 0;
return details; return details;
case Debug.DebugEvent.Exception: case 'exception':
var details = ''; if (body.uncaught) {
if (event.uncaught_) {
details += 'Uncaught: '; details += 'Uncaught: ';
} else { } else {
details += 'Exception: '; details += 'Exception: ';
} }
details += '"'; details += '"';
details += event.exception(); details += body.exception.text;
details += '"'; details += '"';
if (event.executionState().frameCount() > 0) { if (body.sourceLine >= 0) {
details += '"'; details += ', ';
details += event.exception(); details += SourceInfo(body);
details += ' at ';
details += event.executionState().frame(0).sourceAndPositionText();
details += '\n'; details += '\n';
details += FrameSourceUnderline(event.executionState().frame(0)); details += SourceUnderline(body.sourceLineText, body.sourceColumn);
Debug.State.currentSourceLine = Debug.State.currentSourceLine = body.sourceLine;
event.executionState().frame(0).sourceLine();
Debug.State.currentFrame = 0; Debug.State.currentFrame = 0;
} else { } else {
details += ' (empty stack)'; details += ' (empty stack)';
...@@ -170,11 +158,18 @@ function DebugEventToText(event) { ...@@ -170,11 +158,18 @@ function DebugEventToText(event) {
Debug.State.currentFrame = kNoFrame; Debug.State.currentFrame = kNoFrame;
} }
return details; 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) { if (trace_compile) {
details = 'Source ' + event.script().name() + ' compiled:\n' details = 'Source ' + event.script().name() + ' compiled:\n'
var source = event.script().source(); var source = body.script.source;
if (!(source[source.length - 1] == '\n')) { if (!(source[source.length - 1] == '\n')) {
details += source; details += source;
} else { } else {
...@@ -185,11 +180,29 @@ function DebugEventToText(event) { ...@@ -185,11 +180,29 @@ function DebugEventToText(event) {
return ''; return '';
} }
} }
return 'Unknown debug event ' + response.event();
return 'Unknown debug event ' + event.eventType();
}; };
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) { function SourceUnderline(source_text, position) {
if (!source_text) { if (!source_text) {
return; return;
...@@ -213,15 +226,6 @@ function SourceUnderline(source_text, position) { ...@@ -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. // Converts a text command to a JSON request.
function DebugCommandToJSONRequest(cmd_line) { function DebugCommandToJSONRequest(cmd_line) {
return new DebugRequest(cmd_line).JSONRequest(); return new DebugRequest(cmd_line).JSONRequest();
......
...@@ -871,28 +871,32 @@ ExceptionEvent.prototype.sourceLineText = function() { ...@@ -871,28 +871,32 @@ ExceptionEvent.prototype.sourceLineText = function() {
ExceptionEvent.prototype.toJSONProtocol = function() { ExceptionEvent.prototype.toJSONProtocol = function() {
var o = { seq: next_response_seq++, var o = new ProtocolMessage();
type: "event", o.event = "exception";
event: "exception", o.body = { uncaught: this.uncaught_,
body: { uncaught: this.uncaught_, exception: MakeMirror(this.exception_)
exception: MakeMirror(this.exception_), }
sourceLine: this.sourceLine(),
sourceColumn: this.sourceColumn(), // Exceptions might happen whithout any JavaScript frames.
sourceLineText: this.sourceLineText(), 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(); // Add script information to the event if available.
if (script) { var script = this.func().script();
o.body.script = { name: script.name(), if (script) {
lineOffset: script.lineOffset(), o.body.script = { name: script.name(),
columnOffset: script.columnOffset(), lineOffset: script.lineOffset(),
lineCount: script.lineCount() 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() { ...@@ -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) { function MakeNewFunctionEvent(func) {
return new NewFunctionEvent(func); return new NewFunctionEvent(func);
} }
...@@ -963,24 +986,32 @@ DebugCommandProcessor.prototype.processDebugRequest = function (request) { ...@@ -963,24 +986,32 @@ DebugCommandProcessor.prototype.processDebugRequest = function (request) {
} }
function ResponsePacket(request) { function ProtocolMessage(request) {
// Build the initial response from the request. // Update sequence number.
this.seq = next_response_seq++; this.seq = next_response_seq++;
this.type = 'response';
if (request) this.request_seq = request.seq; if (request) {
if (request) this.command = request.command; // 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.success = true;
this.running = false; this.running = false;
} }
ResponsePacket.prototype.failed = function(message) { ProtocolMessage.prototype.failed = function(message) {
this.success = false; this.success = false;
this.message = message; this.message = message;
} }
ResponsePacket.prototype.toJSONProtocol = function() { ProtocolMessage.prototype.toJSONProtocol = function() {
// Encode the protocol header. // Encode the protocol header.
var json = '{'; var json = '{';
json += '"seq":' + this.seq; json += '"seq":' + this.seq;
...@@ -988,6 +1019,9 @@ ResponsePacket.prototype.toJSONProtocol = function() { ...@@ -988,6 +1019,9 @@ ResponsePacket.prototype.toJSONProtocol = function() {
json += ',"request_seq":' + this.request_seq; json += ',"request_seq":' + this.request_seq;
} }
json += ',"type":"' + this.type + '"'; json += ',"type":"' + this.type + '"';
if (this.event) {
json += ',"event":' + StringToJSON_(this.event);
}
if (this.command) { if (this.command) {
json += ',"command":' + StringToJSON_(this.command); json += ',"command":' + StringToJSON_(this.command);
} }
...@@ -1033,7 +1067,7 @@ ResponsePacket.prototype.toJSONProtocol = function() { ...@@ -1033,7 +1067,7 @@ ResponsePacket.prototype.toJSONProtocol = function() {
DebugCommandProcessor.prototype.createResponse = function(request) { DebugCommandProcessor.prototype.createResponse = function(request) {
return new ResponsePacket(request); return new ProtocolMessage(request);
}; };
...@@ -1652,7 +1686,9 @@ function SimpleObjectToJSON_(object, mirror_serializer) { ...@@ -1652,7 +1686,9 @@ function SimpleObjectToJSON_(object, mirror_serializer) {
var property_value_json; var property_value_json;
switch (typeof property_value) { switch (typeof property_value) {
case 'object': 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) property_value_json = property_value.toJSONProtocol(true)
} else if (IS_ARRAY(property_value)){ } else if (IS_ARRAY(property_value)){
property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer); property_value_json = SimpleArrayToJSON_(property_value, mirror_serializer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment