OLD | NEW |
| (Empty) |
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 | |
10 void PrintPrompt(bool is_running) { | |
11 const char* prompt = is_running? "> " : "dbg> "; | |
12 printf("%s", prompt); | |
13 fflush(stdout); | |
14 } | |
15 | |
16 | |
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(isolate); | |
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", NewStringType::kNormal) | |
33 .ToLocalChecked(); | |
34 Local<Object> event_data = event_details.GetEventData(); | |
35 Local<Function> to_json_fun = | |
36 Local<Function>::Cast(event_data->Get(isolate->GetCurrentContext(), | |
37 to_json_fun_name).ToLocalChecked()); | |
38 Local<Value> event_json; | |
39 if (!to_json_fun->Call(isolate->GetCurrentContext(), event_data, 0, NULL) | |
40 .ToLocal(&event_json)) { | |
41 Shell::ReportException(isolate, &try_catch); | |
42 return; | |
43 } | |
44 | |
45 // Print the event details. | |
46 Local<Object> details = | |
47 Shell::DebugMessageDetails(isolate, Local<String>::Cast(event_json)); | |
48 if (try_catch.HasCaught()) { | |
49 Shell::ReportException(isolate, &try_catch); | |
50 return; | |
51 } | |
52 String::Utf8Value str( | |
53 details->Get(isolate->GetCurrentContext(), | |
54 String::NewFromUtf8(isolate, "text", NewStringType::kNormal) | |
55 .ToLocalChecked()).ToLocalChecked()); | |
56 if (str.length() == 0) { | |
57 // Empty string is used to signal not to process this event. | |
58 return; | |
59 } | |
60 printf("%s\n", *str); | |
61 | |
62 // Get the debug command processor. | |
63 Local<String> fun_name = | |
64 String::NewFromUtf8(isolate, "debugCommandProcessor", | |
65 NewStringType::kNormal).ToLocalChecked(); | |
66 Local<Object> exec_state = event_details.GetExecutionState(); | |
67 Local<Function> fun = Local<Function>::Cast( | |
68 exec_state->Get(isolate->GetCurrentContext(), fun_name).ToLocalChecked()); | |
69 Local<Value> cmd_processor_value; | |
70 if (!fun->Call(isolate->GetCurrentContext(), exec_state, 0, NULL) | |
71 .ToLocal(&cmd_processor_value)) { | |
72 Shell::ReportException(isolate, &try_catch); | |
73 return; | |
74 } | |
75 Local<Object> cmd_processor = Local<Object>::Cast(cmd_processor_value); | |
76 | |
77 static const int kBufferSize = 256; | |
78 bool running = false; | |
79 while (!running) { | |
80 char command[kBufferSize]; | |
81 PrintPrompt(running); | |
82 char* str = fgets(command, kBufferSize, stdin); | |
83 if (str == NULL) break; | |
84 | |
85 // Ignore empty commands. | |
86 if (strlen(command) == 0) continue; | |
87 | |
88 TryCatch try_catch(isolate); | |
89 | |
90 // Convert the debugger command to a JSON debugger request. | |
91 Local<Value> request = Shell::DebugCommandToJSONRequest( | |
92 isolate, String::NewFromUtf8(isolate, command, NewStringType::kNormal) | |
93 .ToLocalChecked()); | |
94 if (try_catch.HasCaught()) { | |
95 Shell::ReportException(isolate, &try_catch); | |
96 continue; | |
97 } | |
98 | |
99 // If undefined is returned the command was handled internally and there is | |
100 // no JSON to send. | |
101 if (request->IsUndefined()) { | |
102 continue; | |
103 } | |
104 | |
105 Local<String> fun_name; | |
106 Local<Function> fun; | |
107 // All the functions used below take one argument. | |
108 static const int kArgc = 1; | |
109 Local<Value> args[kArgc]; | |
110 | |
111 // Invoke the JavaScript to convert the debug command line to a JSON | |
112 // request, invoke the JSON request and convert the JSON respose to a text | |
113 // representation. | |
114 fun_name = String::NewFromUtf8(isolate, "processDebugRequest", | |
115 NewStringType::kNormal).ToLocalChecked(); | |
116 fun = Local<Function>::Cast(cmd_processor->Get(isolate->GetCurrentContext(), | |
117 fun_name).ToLocalChecked()); | |
118 args[0] = request; | |
119 Local<Value> response_val; | |
120 if (!fun->Call(isolate->GetCurrentContext(), cmd_processor, kArgc, args) | |
121 .ToLocal(&response_val)) { | |
122 Shell::ReportException(isolate, &try_catch); | |
123 continue; | |
124 } | |
125 Local<String> response = Local<String>::Cast(response_val); | |
126 | |
127 // Convert the debugger response into text details and the running state. | |
128 Local<Object> response_details = | |
129 Shell::DebugMessageDetails(isolate, response); | |
130 if (try_catch.HasCaught()) { | |
131 Shell::ReportException(isolate, &try_catch); | |
132 continue; | |
133 } | |
134 String::Utf8Value text_str( | |
135 response_details->Get(isolate->GetCurrentContext(), | |
136 String::NewFromUtf8(isolate, "text", | |
137 NewStringType::kNormal) | |
138 .ToLocalChecked()).ToLocalChecked()); | |
139 if (text_str.length() > 0) { | |
140 printf("%s\n", *text_str); | |
141 } | |
142 running = response_details->Get(isolate->GetCurrentContext(), | |
143 String::NewFromUtf8(isolate, "running", | |
144 NewStringType::kNormal) | |
145 .ToLocalChecked()) | |
146 .ToLocalChecked() | |
147 ->ToBoolean(isolate->GetCurrentContext()) | |
148 .ToLocalChecked() | |
149 ->Value(); | |
150 } | |
151 } | |
152 | |
153 } // namespace v8 | |
OLD | NEW |