From 36ab7afb9e1ce60d373a278b63887f2214f14556 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 27 Sep 2019 19:07:58 +0100 Subject: [PATCH] Improve JavaScript debugging in d8 Adds ability to pause JavaScript debugger from d8 by defining a global function `handleInspectorMessage` which should block waiting for a new inspector message, and `send` it afterwards. Additionally, adds a simple helper script that, when invoked via `websocketd` as per instructions, can be used for debugging `d8` using Chrome DevTools (inspecting script sources, pausing, stepping over, etc.). Change-Id: Iee75fb4e3f2ccc8c8552c804fefaefb233d6b089 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1829221 Reviewed-by: Yang Guo Commit-Queue: Ingvar Stepanyan Cr-Commit-Position: refs/heads/master@{#64040} --- src/d8/d8.cc | 28 ++++++++++++++++++++++++++++ tools/inspect-d8.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tools/inspect-d8.js diff --git a/src/d8/d8.cc b/src/d8/d8.cc index 9fd67013d0..80beb851b8 100644 --- a/src/d8/d8.cc +++ b/src/d8/d8.cc @@ -2502,6 +2502,33 @@ class InspectorClient : public v8_inspector::V8InspectorClient { context_.Reset(isolate_, context); } + void runMessageLoopOnPause(int contextGroupId) override { + v8::Isolate::AllowJavascriptExecutionScope allow_script(isolate_); + v8::HandleScope handle_scope(isolate_); + Local callback_name = + v8::String::NewFromUtf8(isolate_, "handleInspectorMessage", + v8::NewStringType::kNormal) + .ToLocalChecked(); + Local context = context_.Get(isolate_); + Local callback = + context->Global()->Get(context, callback_name).ToLocalChecked(); + if (!callback->IsFunction()) return; + + v8::TryCatch try_catch(isolate_); + is_paused = true; + + while (is_paused) { + USE(Local::Cast(callback)->Call(context, Undefined(isolate_), 0, + {})); + if (try_catch.HasCaught()) { + Shell::ReportException(isolate_, &try_catch); + is_paused = false; + } + } + } + + void quitMessageLoopOnPause() override { is_paused = false; } + private: static v8_inspector::V8InspectorSession* GetSession(Local context) { InspectorClient* inspector_client = static_cast( @@ -2540,6 +2567,7 @@ class InspectorClient : public v8_inspector::V8InspectorClient { std::unique_ptr inspector_; std::unique_ptr session_; std::unique_ptr channel_; + bool is_paused = false; Global context_; Isolate* isolate_; }; diff --git a/tools/inspect-d8.js b/tools/inspect-d8.js new file mode 100644 index 0000000000..b87a7586b2 --- /dev/null +++ b/tools/inspect-d8.js @@ -0,0 +1,30 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This helper allows to debug d8 using Chrome DevTools. +// +// It runs a simple REPL for inspector messages and relies on +// websocketd (https://github.com/joewalnes/websocketd) for the WebSocket +// communication. +// +// You can start a session with a debug build of d8 like: +// +// $ websocketd out/x64.debug/d8 YOUR_SCRIPT.js tools/inspect-d8.js +// +// After that, copy the URL from console and pass it as `ws=` parameter to +// the Chrome DevTools frontend like: +// +// chrome-devtools://devtools/bundled/js_app.html?ws=localhost:80 + +function receive(msg) { + print(msg); +} + +function handleInspectorMessage() { + send(readline()); +} + +while (true) { + handleInspectorMessage(); +}