• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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