}
-static void PrintLn(v8::Local<v8::Value> value) {
- v8::Local<v8::String> s = value->ToString();
- ScopedVector<char> data(s->Utf8Length() + 1);
- if (data.start() == NULL) {
- V8::FatalProcessOutOfMemory("PrintLn");
- return;
- }
- s->WriteUtf8(data.start());
- PrintF("%s\n", data.start());
-}
-
-
static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
// Isolate::context() may have been NULL when "script collected" event
force_debugger_active_(false),
message_handler_(NULL),
debugger_unload_pending_(false),
- host_dispatch_handler_(NULL),
debug_message_dispatch_handler_(NULL),
message_dispatch_helper_thread_(NULL),
- host_dispatch_period_(TimeDelta::FromMilliseconds(100)),
agent_(NULL),
command_queue_(isolate->logger(), kQueueInitialSize),
command_received_(0),
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
bool auto_continue) {
- v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
HandleScope scope(isolate_);
if (!isolate_->debug()->Load()) return;
return;
}
- v8::TryCatch try_catch;
-
// DebugCommandProcessor goes here.
- v8::Local<v8::Object> cmd_processor;
- {
- v8::Local<v8::Object> api_exec_state =
- v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
- v8::Local<v8::String> fun_name = v8::String::NewFromUtf8(
- isolate, "debugCommandProcessor");
- v8::Local<v8::Function> fun =
- v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
-
- v8::Handle<v8::Boolean> running = v8::Boolean::New(isolate, auto_continue);
- static const int kArgc = 1;
- v8::Handle<Value> argv[kArgc] = { running };
- cmd_processor = v8::Local<v8::Object>::Cast(
- fun->Call(api_exec_state, kArgc, argv));
- if (try_catch.HasCaught()) {
- PrintLn(try_catch.Exception());
- return;
- }
- }
-
bool running = auto_continue;
+ Handle<Object> cmd_processor_ctor = Object::GetProperty(
+ isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
+ Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
+ Handle<Object> cmd_processor = Execution::Call(
+ isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
+ Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
+ Object::GetProperty(
+ isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
+ Handle<Object> is_running = Object::GetProperty(
+ isolate_, cmd_processor, "isRunning").ToHandleChecked();
+
// Process requests from the debugger.
- while (true) {
+ do {
// Wait for new command in the queue.
- if (Debugger::host_dispatch_handler_) {
- // In case there is a host dispatch - do periodic dispatches.
- if (!command_received_.WaitFor(host_dispatch_period_)) {
- // Timout expired, do the dispatch.
- Debugger::host_dispatch_handler_();
- continue;
- }
- } else {
- // In case there is no host dispatch - just wait.
- command_received_.Wait();
- }
+ command_received_.Wait();
// Get the command from the queue.
CommandMessage command = command_queue_.Get();
return;
}
- // Invoke JavaScript to process the debug request.
- v8::Local<v8::String> fun_name;
- v8::Local<v8::Function> fun;
- v8::Local<v8::Value> request;
- v8::TryCatch try_catch;
- fun_name = v8::String::NewFromUtf8(isolate, "processDebugRequest");
- fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
-
- request = v8::String::NewFromTwoByte(isolate, command.text().start(),
- v8::String::kNormalString,
- command.text().length());
- static const int kArgc = 1;
- v8::Handle<Value> argv[kArgc] = { request };
- v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
-
- // Get the response.
- v8::Local<v8::String> response;
- if (!try_catch.HasCaught()) {
- // Get response string.
- if (!response_val->IsUndefined()) {
- response = v8::Local<v8::String>::Cast(response_val);
+ Vector<const uc16> command_text(
+ const_cast<const uc16*>(command.text().start()),
+ command.text().length());
+ Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
+ command_text).ToHandleChecked();
+ Handle<Object> request_args[] = { request_text };
+ Handle<Object> exception;
+ Handle<Object> answer_value;
+ Handle<String> answer;
+ MaybeHandle<Object> maybe_result = Execution::TryCall(
+ process_debug_request, cmd_processor, 1, request_args, &exception);
+
+ if (maybe_result.ToHandle(&answer_value)) {
+ if (answer_value->IsUndefined()) {
+ answer = isolate_->factory()->empty_string();
} else {
- response = v8::String::NewFromUtf8(isolate, "");
+ answer = Handle<String>::cast(answer_value);
}
// Log the JSON request/response.
if (FLAG_trace_debug_json) {
- PrintLn(request);
- PrintLn(response);
+ PrintF("%s\n", request_text->ToCString().get());
+ PrintF("%s\n", answer->ToCString().get());
}
- // Get the running state.
- fun_name = v8::String::NewFromUtf8(isolate, "isRunning");
- fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
- static const int kArgc = 1;
- v8::Handle<Value> argv[kArgc] = { response };
- v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
- if (!try_catch.HasCaught()) {
- running = running_val->ToBoolean()->Value();
- }
+ Handle<Object> is_running_args[] = { answer };
+ maybe_result = Execution::Call(
+ isolate_, is_running, cmd_processor, 1, is_running_args);
+ running = maybe_result.ToHandleChecked()->IsTrue();
} else {
- // In case of failure the result text is the exception text.
- response = try_catch.Exception()->ToString();
+ answer = Handle<String>::cast(
+ Execution::ToString(isolate_, exception).ToHandleChecked());
}
// Return the result.
MessageImpl message = MessageImpl::NewResponse(
- event,
- running,
- Handle<JSObject>::cast(exec_state),
- Handle<JSObject>::cast(event_data),
- Handle<String>(Utils::OpenHandle(*response)),
- command.client_data());
+ event, running, exec_state, event_data, answer, command.client_data());
InvokeMessageHandler(message);
command.Dispose();
// Return from debug event processing if either the VM is put into the
// running state (through a continue command) or auto continue is active
// and there are no more commands queued.
- if (running && !HasCommands()) {
- return;
- }
- }
+ } while (!running || HasCommands());
}
}
-void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
- TimeDelta period) {
- host_dispatch_handler_ = handler;
- host_dispatch_period_ = period;
-}
-
-
void Debugger::SetDebugMessageDispatchHandler(
v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
}
-/* Test DebuggerHostDispatch */
-/* In this test, the debugger waits for a command on a breakpoint
- * and is dispatching host commands while in the infinite loop.
- */
-
-class HostDispatchV8Thread : public v8::internal::Thread {
- public:
- HostDispatchV8Thread() : Thread("HostDispatchV8Thread") { }
- void Run();
-};
-
-class HostDispatchDebuggerThread : public v8::internal::Thread {
- public:
- HostDispatchDebuggerThread() : Thread("HostDispatchDebuggerThread") { }
- void Run();
-};
-
-Barriers* host_dispatch_barriers;
-
-static void HostDispatchMessageHandler(const v8::Debug::Message& message) {
- static char print_buffer[1000];
- v8::String::Value json(message.GetJSON());
- Utf16ToAscii(*json, json.length(), print_buffer);
-}
-
-
-static void HostDispatchDispatchHandler() {
- host_dispatch_barriers->semaphore_1.Signal();
-}
-
-
-void HostDispatchV8Thread::Run() {
- const char* source_1 = "var y_global = 3;\n"
- "function cat( new_value ) {\n"
- " var x = new_value;\n"
- " y_global = 4;\n"
- " x = 3 * x + 1;\n"
- " y_global = 5;\n"
- " return x;\n"
- "}\n"
- "\n";
- const char* source_2 = "cat(17);\n";
-
- v8::Isolate::Scope isolate_scope(CcTest::isolate());
- DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
-
- // Set up message and host dispatch handlers.
- v8::Debug::SetMessageHandler2(HostDispatchMessageHandler);
- v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */);
-
- CompileRun(source_1);
- host_dispatch_barriers->barrier_1.Wait();
- host_dispatch_barriers->barrier_2.Wait();
- CompileRun(source_2);
-}
-
-
-void HostDispatchDebuggerThread::Run() {
- const int kBufSize = 1000;
- uint16_t buffer[kBufSize];
-
- const char* command_1 = "{\"seq\":101,"
- "\"type\":\"request\","
- "\"command\":\"setbreakpoint\","
- "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
- const char* command_2 = "{\"seq\":102,"
- "\"type\":\"request\","
- "\"command\":\"continue\"}";
-
- v8::Isolate* isolate = CcTest::isolate();
- // v8 thread initializes, runs source_1
- host_dispatch_barriers->barrier_1.Wait();
- // 1: Set breakpoint in cat().
- v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer));
-
- host_dispatch_barriers->barrier_2.Wait();
- // v8 thread starts compiling source_2.
- // Break happens, to run queued commands and host dispatches.
- // Wait for host dispatch to be processed.
- host_dispatch_barriers->semaphore_1.Wait();
- // 2: Continue evaluation
- v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer));
-}
-
-
-TEST(DebuggerHostDispatch) {
- HostDispatchDebuggerThread host_dispatch_debugger_thread;
- HostDispatchV8Thread host_dispatch_v8_thread;
-
- // Create a V8 environment
- Barriers stack_allocated_host_dispatch_barriers;
- host_dispatch_barriers = &stack_allocated_host_dispatch_barriers;
-
- host_dispatch_v8_thread.Start();
- host_dispatch_debugger_thread.Start();
-
- host_dispatch_v8_thread.Join();
- host_dispatch_debugger_thread.Join();
-}
-
-
/* Test DebugMessageDispatch */
/* In this test, the V8 thread waits for a message from the debug thread.
* The DebugMessageDispatchHandler is executed from the debugger thread