Home | History | Annotate | Download | only in src
      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;
     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