1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/d8.h"
6 #include "src/d8-debug.h"
7
8 namespace v8 {
9
PrintPrompt(bool is_running)10 void PrintPrompt(bool is_running) {
11 const char* prompt = is_running? "> " : "dbg> ";
12 printf("%s", prompt);
13 fflush(stdout);
14 }
15
16
HandleDebugEvent(const Debug::EventDetails & event_details)17 void HandleDebugEvent(const Debug::EventDetails& event_details) {
18 // TODO(svenpanne) There should be a way to retrieve this in the callback.
19 Isolate* isolate = Isolate::GetCurrent();
20 HandleScope scope(isolate);
21
22 DebugEvent event = event_details.GetEvent();
23 // Check for handled event.
24 if (event != Break && event != Exception && event != AfterCompile) {
25 return;
26 }
27
28 TryCatch try_catch;
29
30 // Get the toJSONProtocol function on the event and get the JSON format.
31 Local<String> to_json_fun_name =
32 String::NewFromUtf8(isolate, "toJSONProtocol");
33 Handle<Object> event_data = event_details.GetEventData();
34 Local<Function> to_json_fun =
35 Local<Function>::Cast(event_data->Get(to_json_fun_name));
36 Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
37 if (try_catch.HasCaught()) {
38 Shell::ReportException(isolate, &try_catch);
39 return;
40 }
41
42 // Print the event details.
43 Handle<Object> details =
44 Shell::DebugMessageDetails(isolate, Handle<String>::Cast(event_json));
45 if (try_catch.HasCaught()) {
46 Shell::ReportException(isolate, &try_catch);
47 return;
48 }
49 String::Utf8Value str(details->Get(String::NewFromUtf8(isolate, "text")));
50 if (str.length() == 0) {
51 // Empty string is used to signal not to process this event.
52 return;
53 }
54 printf("%s\n", *str);
55
56 // Get the debug command processor.
57 Local<String> fun_name =
58 String::NewFromUtf8(isolate, "debugCommandProcessor");
59 Handle<Object> exec_state = event_details.GetExecutionState();
60 Local<Function> fun = Local<Function>::Cast(exec_state->Get(fun_name));
61 Local<Object> cmd_processor =
62 Local<Object>::Cast(fun->Call(exec_state, 0, NULL));
63 if (try_catch.HasCaught()) {
64 Shell::ReportException(isolate, &try_catch);
65 return;
66 }
67
68 static const int kBufferSize = 256;
69 bool running = false;
70 while (!running) {
71 char command[kBufferSize];
72 PrintPrompt(running);
73 char* str = fgets(command, kBufferSize, stdin);
74 if (str == NULL) break;
75
76 // Ignore empty commands.
77 if (strlen(command) == 0) continue;
78
79 TryCatch try_catch;
80
81 // Convert the debugger command to a JSON debugger request.
82 Handle<Value> request = Shell::DebugCommandToJSONRequest(
83 isolate, String::NewFromUtf8(isolate, command));
84 if (try_catch.HasCaught()) {
85 Shell::ReportException(isolate, &try_catch);
86 continue;
87 }
88
89 // If undefined is returned the command was handled internally and there is
90 // no JSON to send.
91 if (request->IsUndefined()) {
92 continue;
93 }
94
95 Handle<String> fun_name;
96 Handle<Function> fun;
97 // All the functions used below take one argument.
98 static const int kArgc = 1;
99 Handle<Value> args[kArgc];
100
101 // Invoke the JavaScript to convert the debug command line to a JSON
102 // request, invoke the JSON request and convert the JSON respose to a text
103 // representation.
104 fun_name = String::NewFromUtf8(isolate, "processDebugRequest");
105 fun = Handle<Function>::Cast(cmd_processor->Get(fun_name));
106 args[0] = request;
107 Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args);
108 if (try_catch.HasCaught()) {
109 Shell::ReportException(isolate, &try_catch);
110 continue;
111 }
112 Handle<String> response = Handle<String>::Cast(response_val);
113
114 // Convert the debugger response into text details and the running state.
115 Handle<Object> response_details =
116 Shell::DebugMessageDetails(isolate, response);
117 if (try_catch.HasCaught()) {
118 Shell::ReportException(isolate, &try_catch);
119 continue;
120 }
121 String::Utf8Value text_str(
122 response_details->Get(String::NewFromUtf8(isolate, "text")));
123 if (text_str.length() > 0) {
124 printf("%s\n", *text_str);
125 }
126 running = response_details->Get(String::NewFromUtf8(isolate, "running"))
127 ->ToBoolean()
128 ->Value();
129 }
130 }
131
132 } // namespace v8
133