1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "d8.h"
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "d8-debug.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug-agent.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockstatic bool was_running = true;
389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid PrintPrompt(bool is_running) {
409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  const char* prompt = is_running? "> " : "dbg> ";
419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  was_running = is_running;
429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  printf("%s", prompt);
436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  fflush(stdout);
446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid PrintPrompt() {
489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  PrintPrompt(was_running);
499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid HandleDebugEvent(DebugEvent event,
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Handle<Object> exec_state,
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Handle<Object> event_data,
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Handle<Value> data) {
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope scope;
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for handled event.
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (event != Break && event != Exception && event != AfterCompile) {
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TryCatch try_catch;
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the toJSONProtocol function on the event and get the JSON format.
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> to_json_fun_name = String::New("toJSONProtocol");
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> to_json_fun =
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Function::Cast(*event_data->Get(to_json_fun_name));
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_catch.HasCaught()) {
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Shell::ReportException(&try_catch);
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print the event details.
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> details =
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::DebugMessageDetails(Handle<String>::Cast(event_json));
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_catch.HasCaught()) {
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Shell::ReportException(&try_catch);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String::Utf8Value str(details->Get(String::New("text")));
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (str.length() == 0) {
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Empty string is used to signal not to process this event.
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printf("%s\n", *str);
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the debug command processor.
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<String> fun_name = String::New("debugCommandProcessor");
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Function> fun = Function::Cast(*exec_state->Get(fun_name));
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Local<Object> cmd_processor =
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Object::Cast(*fun->Call(exec_state, 0, NULL));
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_catch.HasCaught()) {
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Shell::ReportException(&try_catch);
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 256;
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool running = false;
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!running) {
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char command[kBufferSize];
1039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    PrintPrompt(running);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* str = fgets(command, kBufferSize, stdin);
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (str == NULL) break;
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Ignore empty commands.
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (strlen(command) == 0) continue;
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TryCatch try_catch;
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Convert the debugger command to a JSON debugger request.
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Value> request =
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Shell::DebugCommandToJSONRequest(String::New(command));
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (try_catch.HasCaught()) {
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::ReportException(&try_catch);
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If undefined is returned the command was handled internally and there is
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // no JSON to send.
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (request->IsUndefined()) {
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> fun_name;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Function> fun;
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // All the functions used below take one argument.
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kArgc = 1;
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Value> args[kArgc];
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Invoke the JavaScript to convert the debug command line to a JSON
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // request, invoke the JSON request and convert the JSON respose to a text
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // representation.
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fun_name = String::New("processDebugRequest");
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fun = Handle<Function>::Cast(cmd_processor->Get(fun_name));
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    args[0] = request;
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args);
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (try_catch.HasCaught()) {
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::ReportException(&try_catch);
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> response = Handle<String>::Cast(response_val);
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Convert the debugger response into text details and the running state.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Object> response_details = Shell::DebugMessageDetails(response);
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (try_catch.HasCaught()) {
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::ReportException(&try_catch);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    String::Utf8Value text_str(response_details->Get(String::New("text")));
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (text_str.length() > 0) {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      printf("%s\n", *text_str);
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    running =
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        response_details->Get(String::New("running"))->ToBoolean()->Value();
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RunRemoteDebugger(int port) {
16244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RemoteDebugger debugger(i::Isolate::Current(), port);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  debugger.Run();
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::Run() {
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool ok;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that socket support is initialized.
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = i::Socket::Setup();
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("Unable to initialize socket support %d\n", i::Socket::LastError());
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Connect to the debugger agent.
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  conn_ = i::OS::CreateSocket();
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kPortStrSize = 6;
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char port_str[kPortStrSize];
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = conn_->Connect("localhost", port_str);
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) {
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("Unable to connect to debug agent %d\n", i::Socket::LastError());
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Start the receiver thread.
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ReceiverThread receiver(isolate_, this);
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  receiver.Start();
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Start the keyboard thread.
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  KeyboardThread keyboard(isolate_, this);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  keyboard.Start();
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  PrintPrompt();
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Process events received from debugged VM and from the keyboard.
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool terminate = false;
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!terminate) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    event_available_->Wait();
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RemoteDebuggerEvent* event = GetEvent();
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (event->type()) {
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case RemoteDebuggerEvent::kMessage:
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        HandleMessageReceived(event->data());
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case RemoteDebuggerEvent::kKeyboard:
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        HandleKeyboardCommand(event->data());
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case RemoteDebuggerEvent::kDisconnect:
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        terminate = true;
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UNREACHABLE();
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    delete event;
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Wait for the receiver thread to end.
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  receiver.Join();
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::MessageReceived(i::SmartPointer<char> message) {
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RemoteDebuggerEvent* event =
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message);
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddEvent(event);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::KeyboardCommand(i::SmartPointer<char> command) {
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RemoteDebuggerEvent* event =
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command);
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddEvent(event);
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::ConnectionClosed() {
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RemoteDebuggerEvent* event =
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect,
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              i::SmartPointer<char>());
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddEvent(event);
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::ScopedLock lock(event_access_);
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (head_ == NULL) {
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(tail_ == NULL);
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    head_ = event;
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tail_ = event;
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(tail_ != NULL);
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tail_->set_next(event);
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tail_ = event;
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  event_available_->Signal();
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRemoteDebuggerEvent* RemoteDebugger::GetEvent() {
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::ScopedLock lock(event_access_);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(head_ != NULL);
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RemoteDebuggerEvent* result = head_;
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  head_ = head_->next();
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (head_ == NULL) {
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(tail_ == result);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tail_ = NULL;
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::HandleMessageReceived(char* message) {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope scope;
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print the event details.
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TryCatch try_catch;
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> details =
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message)));
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_catch.HasCaught()) {
2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Shell::ReportException(&try_catch);
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    PrintPrompt();
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String::Utf8Value str(details->Get(String::New("text")));
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (str.length() == 0) {
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Empty string is used to signal not to process this event.
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*str != NULL) {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("%s\n", *str);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    printf("???\n");
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
2979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  bool is_running = details->Get(String::New("running"))->ToBoolean()->Value();
2989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  PrintPrompt(is_running);
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RemoteDebugger::HandleKeyboardCommand(char* command) {
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope scope;
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the debugger command to a JSON debugger request.
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TryCatch try_catch;
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Value> request =
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Shell::DebugCommandToJSONRequest(String::New(command));
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (try_catch.HasCaught()) {
3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    v8::String::Utf8Value exception(try_catch.Exception());
3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    const char* exception_string = Shell::ToCString(exception);
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    printf("%s\n", exception_string);
3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    PrintPrompt();
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If undefined is returned the command was handled internally and there is
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // no JSON to send.
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (request->IsUndefined()) {
3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    PrintPrompt();
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send the JSON debugger request.
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request));
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ReceiverThread::Run() {
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Receive the connect message (with empty body).
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  i::SmartPointer<char> message =
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(*message == NULL);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Receive a message.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    i::SmartPointer<char> message =
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (*message == NULL) {
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      remote_debugger_->ConnectionClosed();
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the message to the main thread.
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    remote_debugger_->MessageReceived(message);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid KeyboardThread::Run() {
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 256;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // read keyboard input.
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char command[kBufferSize];
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* str = fgets(command, kBufferSize, stdin);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (str == NULL) {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Pass the keyboard command to the main thread.
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    remote_debugger_->KeyboardCommand(
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        i::SmartPointer<char>(i::StrDup(command)));
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace v8
368