Skip to content

Commit

Permalink
fix: Implement console.log inspector with Runtime protocol
Browse files Browse the repository at this point in the history
Console messages used to be implemented with the Log protocol, which is no
longer part of V8. The Runtime protocol provides an equivalent API,
Runtime.consoleAPICalled.

The Runtime protocol is part of the generated public sources, but the V8
inspector's RuntimeAgent is not. So, for now, we make use of V8's private
API, casting V8Inspector* to V8InspectorImpl* and V8InspectorSession* to
V8InspectorSessionImpl* in order to access their methods (for which we
pulled in the corresponding V8 header files in the V8 sources update,
earlier on this branch.)
  • Loading branch information
ptomato committed Mar 8, 2023
1 parent f357ce6 commit 2c4337b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 163 deletions.
26 changes: 20 additions & 6 deletions test-app/runtime/src/main/cpp/JsV8InspectorClient.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#include "JsV8InspectorClient.h"
#include <assert.h>
#include <include/libplatform/libplatform.h>
#include <src/inspector/v8-console-message.h>
#include <src/inspector/v8-inspector-impl.h>
#include <src/inspector/v8-inspector-session-impl.h>
#include <src/inspector/v8-runtime-agent-impl.h>
#include <src/inspector/v8-stack-trace-impl.h>

#include "Runtime.h"
#include "NativeScriptException.h"

#include "ArgConverter.h"
// #include "DOMDomainCallbackHandlers.h"
// #include "LogAgentImpl.h"
// #include "NetworkDomainCallbackHandlers.h"

using namespace std;
Expand Down Expand Up @@ -232,17 +237,26 @@ void JsV8InspectorClient::sendToFrontEndCallback(const v8::FunctionCallbackInfo<
}
}

void JsV8InspectorClient::consoleLogCallback(Isolate* isolate, const string& message, const string& logLevel) {
void JsV8InspectorClient::consoleLogCallback(Isolate* isolate, ConsoleAPIType method, const std::vector<v8::Local<v8::Value>>& args) {
if (!inspectorIsConnected()) {
return;
}

auto stack = v8::StackTrace::CurrentStackTrace(isolate, 1, v8::StackTrace::StackTraceOptions::kDetailed);
// Note, here we access private V8 API
auto* impl = reinterpret_cast<v8_inspector::V8InspectorImpl*>(instance->inspector_.get());
auto* session = reinterpret_cast<v8_inspector::V8InspectorSessionImpl*>(instance->session_.get());

std::unique_ptr<V8StackTraceImpl> stack = impl->debugger()->captureStackTrace(false);

v8::Local<v8::Context> context = instance->context_.Get(instance->isolate_);
const int contextId = V8ContextInfo::executionContextId(context);

auto frame = stack->GetFrame(isolate, 0);
std::unique_ptr<v8_inspector::V8ConsoleMessage> msg =
v8_inspector::V8ConsoleMessage::createForConsoleAPI(
context, contextId, contextGroupId, impl, instance->currentTimeMS(),
method, args, String16{}, std::move(stack));

// will be no-op in non-debuggable builds
// v8_inspector::V8LogAgentImpl::EntryAdded(message, logLevel, ArgConverter::ConvertToString(frame->GetScriptNameOrSourceURL()), frame->GetLineNumber());
session->runtimeAgent()->messageAdded(msg.get());
}

void JsV8InspectorClient::attachInspectorCallbacks(Isolate* isolate,
Expand Down
7 changes: 3 additions & 4 deletions test-app/runtime/src/main/cpp/JsV8InspectorClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
#define JSV8INSPECTORCLIENT_H_

#include <string>
#include <vector>
#include <src/inspector/v8-console-message.h>
#include "v8.h"
#include "JEnv.h"
#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-inspector-session-impl.h"
#include "v8-inspector.h"
#include "src/inspector/protocol/Forward.h"

using namespace v8_inspector;

Expand All @@ -28,7 +27,7 @@ class JsV8InspectorClient : V8InspectorClient, v8_inspector::V8Inspector::Channe
void flushProtocolNotifications() override;

static void sendToFrontEndCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
static void consoleLogCallback(v8::Isolate* isolate, const std::string& message, const std::string& logLevel);
static void consoleLogCallback(v8::Isolate* isolate, ConsoleAPIType method, const std::vector<v8::Local<v8::Value>>& args);

// Overrides of V8InspectorClient
void runMessageLoopOnPause(int context_group_id) override;
Expand Down
90 changes: 0 additions & 90 deletions test-app/runtime/src/main/cpp/LogAgentImpl.cpp

This file was deleted.

49 changes: 0 additions & 49 deletions test-app/runtime/src/main/cpp/LogAgentImpl.h

This file was deleted.

45 changes: 33 additions & 12 deletions test-app/runtime/src/main/cpp/console/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
#include <chrono>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <V8GlobalHelpers.h>
#include <NativeScriptException.h>

#include "ArgConverter.h"
#include "Console.h"

namespace tns {
Expand Down Expand Up @@ -66,10 +70,27 @@ void Console::sendToADBLogcat(const std::string& message, android_LogPriority lo
}
}

void Console::sendToDevToolsFrontEnd(v8::Isolate* isolate, const std::string& message, const std::string& logLevel) {
if (m_callback != nullptr) {
m_callback(isolate, message, logLevel);
void Console::sendToDevToolsFrontEnd(v8::Isolate* isolate, ConsoleAPIType method, const v8::FunctionCallbackInfo<v8::Value>& args) {
if (!m_callback) {
return;
}

std::vector<v8::Local<v8::Value>> arg_vector;
unsigned nargs = args.Length();
arg_vector.reserve(nargs);
for (unsigned ix = 0; ix < nargs; ix++)
arg_vector.push_back(args[ix]);

m_callback(isolate, method, arg_vector);
}

void Console::sendToDevToolsFrontEnd(v8::Isolate* isolate, ConsoleAPIType method, const std::string& message) {
if (!m_callback) {
return;
}

std::vector<v8::Local<v8::Value>> args{ArgConverter::ConvertToV8String(isolate, message)};
m_callback(isolate, method, args);
}

std::string transformJSObject(v8::Isolate* isolate, v8::Local<v8::Object> object) {
Expand Down Expand Up @@ -170,7 +191,7 @@ void Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {

std::string log = assertionError.str();
sendToADBLogcat(log, ANDROID_LOG_ERROR);
sendToDevToolsFrontEnd(isolate, log, "error");
sendToDevToolsFrontEnd(isolate, ConsoleAPIType::kAssert, info);
}
} catch (NativeScriptException& e) {
e.ReThrowToV8();
Expand All @@ -191,7 +212,7 @@ void Console::errorCallback(const v8::FunctionCallbackInfo <v8::Value>& info) {
log += buildLogString(info);

sendToADBLogcat(log, ANDROID_LOG_ERROR);
sendToDevToolsFrontEnd(info.GetIsolate(), log, "error");
sendToDevToolsFrontEnd(info.GetIsolate(), ConsoleAPIType::kError, info);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand All @@ -211,7 +232,7 @@ void Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
log += buildLogString(info);

sendToADBLogcat(log, ANDROID_LOG_INFO);
sendToDevToolsFrontEnd(info.GetIsolate(), log, "info");
sendToDevToolsFrontEnd(info.GetIsolate(), ConsoleAPIType::kInfo, info);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand All @@ -231,7 +252,7 @@ void Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
log += buildLogString(info);

sendToADBLogcat(log, ANDROID_LOG_INFO);
sendToDevToolsFrontEnd(info.GetIsolate(), log, "info");
sendToDevToolsFrontEnd(info.GetIsolate(), ConsoleAPIType::kLog, info);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand All @@ -251,7 +272,7 @@ void Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
log += buildLogString(info);

sendToADBLogcat(log, ANDROID_LOG_WARN);
sendToDevToolsFrontEnd(info.GetIsolate(), log, "warning");
sendToDevToolsFrontEnd(info.GetIsolate(), ConsoleAPIType::kWarning, info);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand Down Expand Up @@ -325,7 +346,7 @@ void Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
std::string log = ss.str();

sendToADBLogcat(log, ANDROID_LOG_INFO);
sendToDevToolsFrontEnd(isolate, log, "info");
sendToDevToolsFrontEnd(isolate, ConsoleAPIType::kDir, info);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand Down Expand Up @@ -406,7 +427,7 @@ void Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {

std::string log = ss.str();
__android_log_write(ANDROID_LOG_ERROR, LOG_TAG, log.c_str());
sendToDevToolsFrontEnd(isolate, log, "error");
sendToDevToolsFrontEnd(isolate, ConsoleAPIType::kTrace, info);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand Down Expand Up @@ -480,7 +501,7 @@ void Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
std::string warning = std::string("No such label '" + label + "' for console.timeEnd()");

__android_log_write(ANDROID_LOG_WARN, LOG_TAG, warning.c_str());
sendToDevToolsFrontEnd(isolate, warning, "warning");
sendToDevToolsFrontEnd(isolate, ConsoleAPIType::kWarning, warning);

return;
}
Expand All @@ -499,7 +520,7 @@ void Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
std::string log = ss.str();

__android_log_write(ANDROID_LOG_INFO, LOG_TAG, log.c_str());
sendToDevToolsFrontEnd(isolate, log, "info");
sendToDevToolsFrontEnd(isolate, ConsoleAPIType::kTimeEnd, log);
} catch (NativeScriptException& e) {
e.ReThrowToV8();
} catch (std::exception e) {
Expand Down
10 changes: 8 additions & 2 deletions test-app/runtime/src/main/cpp/console/Console.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

#include <include/v8.h>
#include <string>
#include <vector>
#include <ArgConverter.h>
#include <android/log.h>

#include <src/inspector/v8-console-message.h>

namespace tns {

typedef void (*ConsoleCallback)(v8::Isolate* isolate, const std::string& message, const std::string& logLevel);
typedef void (*ConsoleCallback)(v8::Isolate* isolate, v8_inspector::ConsoleAPIType method, const std::vector<v8::Local<v8::Value>>& args);

class Console {
public:
Expand All @@ -31,6 +34,8 @@ class Console {
static void onDisposeIsolate(v8::Isolate* isolate);

private:
using ConsoleAPIType = v8_inspector::ConsoleAPIType;

static int m_maxLogcatObjectSize;
static ConsoleCallback m_callback;
static const char* LOG_TAG;
Expand All @@ -54,7 +59,8 @@ class Console {
}

static void sendToADBLogcat(const std::string& log, android_LogPriority logPriority);
static void sendToDevToolsFrontEnd(v8::Isolate* isolate, const std::string& message, const std::string& logLevel);
static void sendToDevToolsFrontEnd(v8::Isolate* isolate, ConsoleAPIType method, const v8::FunctionCallbackInfo<v8::Value>& args);
static void sendToDevToolsFrontEnd(v8::Isolate* isolate, ConsoleAPIType method, const std::string& args);
};

}
Expand Down

0 comments on commit 2c4337b

Please sign in to comment.