Skip to content

Commit 6480aae

Browse files
authored
feat(inspector): implement console in the runtime. fix console logs in devtools inspector (#884) (#894)
* update the __consoleMessage callback by implementing devtools log agent * add c++ utf16 string to protocol utf16 string conversion method * feat: implement the console API in the runtime Remove the console.ts/js implementation from the tns-core-modules and instead bootstrap the console prototype with log, warn, dir, trace, time, timeEnd, info, assert callbacks. * chore: remove references to __console global callback * fix: encoding problem with utf16 strings used in console * refactor console.assert to use console.log string building logic when assertion fails * fix console.dir() implementation to display the values of object properties * fix console logging implementation to print out a message on circular references JSON.stringify fails to resolve
1 parent 5f61f42 commit 6480aae

19 files changed

+602
-848
lines changed

test-app/runtime/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ add_library( # Sets the name of the library. When it's built you can find it wit
7373
src/main/cpp/ObjectManager.cpp
7474
src/main/cpp/V8GlobalHelpers.cpp
7575
src/main/cpp/MetadataTreeNode.cpp
76+
src/main/cpp/console/Console.cpp
7677

7778
# Inspector source (we build it because we've customized it a bit)
7879
src/main/cpp/v8_inspector/src/inspector/string-16.cc
@@ -105,6 +106,7 @@ add_library( # Sets the name of the library. When it's built you can find it wit
105106
src/main/cpp/v8_inspector/src/inspector/injected-script-native.cc
106107
src/main/cpp/v8_inspector/src/inspector/v8-inspector-session-impl.cc
107108
src/main/cpp/v8_inspector/src/inspector/v8-debugger-agent-impl.cc
109+
src/main/cpp/v8_inspector/src/inspector/v8-log-agent-impl.cpp
108110
src/main/cpp/v8_inspector/src/inspector/injected-script.cc
109111
src/main/cpp/v8_inspector/src/inspector/protocol/Overlay.cpp
110112
src/main/cpp/v8_inspector/src/inspector/protocol/Log.cpp

test-app/runtime/src/main/cpp/CallbackHandlers.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,6 @@ void CallbackHandlers::Init(Isolate* isolate) {
5858

5959
assert(INIT_WORKER_METHOD_ID != nullptr);
6060

61-
Local<Object> json = isolate->GetCurrentContext()->Global()->Get(String::NewFromUtf8(isolate, "JSON"))->ToObject();
62-
Local<Function> stringify = json->Get(String::NewFromUtf8(isolate, "stringify")).As<Function>();
63-
64-
auto persistentStringify = new Persistent<Function>(isolate, stringify);
65-
66-
isolateToJsonStringify.insert({isolate, persistentStringify});
67-
6861
MetadataNode::Init(isolate);
6962

7063
MethodCache::Init();
@@ -1381,8 +1374,6 @@ void CallbackHandlers::TerminateWorkerThread(Isolate* isolate) {
13811374
int CallbackHandlers::nextWorkerId = 0;
13821375
std::map<int, Persistent<Object>*> CallbackHandlers::id2WorkerMap;
13831376

1384-
std::map<Isolate*, Persistent<Function>*> CallbackHandlers::isolateToJsonStringify;
1385-
13861377
short CallbackHandlers::MAX_JAVA_STRING_ARRAY_LENGTH = 100;
13871378
jclass CallbackHandlers::RUNTIME_CLASS = nullptr;
13881379
jclass CallbackHandlers::JAVA_LANG_STRING = nullptr;

test-app/runtime/src/main/cpp/CallbackHandlers.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class CallbackHandlers {
2626
*/
2727
static std::map<int, v8::Persistent<v8::Object>*> id2WorkerMap;
2828

29-
static std::map<v8::Isolate*, v8::Persistent<v8::Function>*> isolateToJsonStringify;
30-
3129
static int nextWorkerId;
3230

3331
static void Init(v8::Isolate* isolate);

test-app/runtime/src/main/cpp/JsV8InspectorClient.cpp

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <sstream>
33
#include <assert.h>
44
#include <include/libplatform/libplatform.h>
5+
#include <v8_inspector/src/inspector/v8-log-agent-impl.h>
56
#include "Runtime.h"
67
#include "NativeScriptException.h"
78

@@ -198,41 +199,6 @@ JsV8InspectorClient* JsV8InspectorClient::GetInstance() {
198199
return instance;
199200
}
200201

201-
202-
void JsV8InspectorClient::sendToFrontEndCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
203-
204-
if ((instance == nullptr) || (instance->connection == nullptr)) {
205-
return;
206-
}
207-
208-
try {
209-
if ((args.Length() > 0) && args[0]->IsString()) {
210-
std::string message = ArgConverter::ConvertToString(args[0]->ToString());
211-
212-
std:
213-
string level = "log";
214-
if (args.Length() > 1 && args[1]->IsString()) {
215-
level = ArgConverter::ConvertToString(args[1]->ToString());
216-
}
217-
218-
JEnv env;
219-
JniLocalRef str(env.NewStringUTF(message.c_str()));
220-
JniLocalRef lev(env.NewStringUTF(level.c_str()));
221-
env.CallStaticVoidMethod(inspectorClass, sendToDevToolsConsoleMethod, instance->connection, (jstring) str, (jstring)lev);
222-
}
223-
} catch (NativeScriptException& e) {
224-
e.ReThrowToV8();
225-
} catch (std::exception e) {
226-
stringstream ss;
227-
ss << "Error: c++ exception: " << e.what() << endl;
228-
NativeScriptException nsEx(ss.str());
229-
nsEx.ReThrowToV8();
230-
} catch (...) {
231-
NativeScriptException nsEx(std::string("Error: c++ exception!"));
232-
nsEx.ReThrowToV8();
233-
}
234-
}
235-
236202
void MessageHandler(v8::Local<v8::Message> message, v8::Local<v8::Value> exception) {
237203
// v8::Isolate *isolate = v8::Isolate::GetCurrent();
238204
// v8::Local<v8::Context> context = isolate->GetEnteredContext();

test-app/runtime/src/main/cpp/JsV8InspectorClient.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ class JsV8InspectorClient : V8InspectorClient, v8_inspector::V8Inspector::Channe
3333
void sendProtocolNotification(const v8_inspector::StringView& message) override;
3434
void flushProtocolNotifications() override;
3535

36-
static void sendToFrontEndCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
37-
3836
void runMessageLoopOnPause(int context_group_id) override;
3937
void quitMessageLoopOnPause() override;
4038
v8::Local<v8::Context> ensureDefaultContextInGroup(int contextGroupId) override;
4139

4240
static void attachInspectorCallbacks(v8::Isolate* isolate, v8::Local<v8::ObjectTemplate>& globalObjectTemplate);
4341
static void InspectorIsConnectedGetterCallback(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info);
42+
static bool inspectorIsConnected() {
43+
return JsV8InspectorClient::GetInstance()->isConnected;
44+
}
4445

4546
std::unique_ptr<V8Inspector> inspector_;
4647
v8::Isolate* isolate_;

test-app/runtime/src/main/cpp/Runtime.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "include/zipconf.h"
2323
#include <sstream>
2424
#include <dlfcn.h>
25+
#include <console/Console.h>
2526
#include "NetworkDomainCallbackHandlers.h"
2627
#include "sys/system_properties.h"
2728
#include "JsV8InspectorClient.h"
@@ -500,7 +501,6 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
500501

501502
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__log"), FunctionTemplate::New(isolate, CallbackHandlers::LogMethodCallback));
502503
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__dumpReferenceTables"), FunctionTemplate::New(isolate, CallbackHandlers::DumpReferenceTablesMethodCallback));
503-
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__consoleMessage"), FunctionTemplate::New(isolate, JsV8InspectorClient::sendToFrontEndCallback));
504504
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__enableVerboseLogging"), FunctionTemplate::New(isolate, CallbackHandlers::EnableVerboseLoggingMethodCallback));
505505
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__disableVerboseLogging"), FunctionTemplate::New(isolate, CallbackHandlers::DisableVerboseLoggingMethodCallback));
506506
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__exit"), FunctionTemplate::New(isolate, CallbackHandlers::ExitMethodCallback));
@@ -572,6 +572,12 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
572572
global->ForceSet(ArgConverter::ConvertToV8String(isolate, "self"), global, readOnlyFlags);
573573
}
574574

575+
/*
576+
* Attach 'console' object to the global object
577+
*/
578+
v8::Local<v8::Object> console = Console::createConsole(context, filesPath);
579+
global->ForceSet(context, ArgConverter::ConvertToV8String(isolate, "console"), console, readOnlyFlags);
580+
575581
ArgConverter::Init(isolate);
576582

577583
CallbackHandlers::Init(isolate);

test-app/runtime/src/main/cpp/Util.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,10 @@ u16string Util::ConvertFromUtf8ToUtf16(const string& str) {
109109
auto utf16String = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().from_bytes(str);
110110

111111
return utf16String;
112-
}
112+
}
113+
114+
uint16_t* Util::ConvertFromUtf8ToProtocolUtf16(const string& str) {
115+
auto utf16String = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().from_bytes(str);
116+
117+
return (uint16_t*)utf16String.c_str();
118+
}

test-app/runtime/src/main/cpp/Util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class Util {
2121
static std::string ReplaceAll(std::string& str, const std::string& from, const std::string& to);
2222

2323
static std::u16string ConvertFromUtf8ToUtf16(const std::string& str);
24+
25+
static std::uint16_t* ConvertFromUtf8ToProtocolUtf16(const std::string& str);
2426
};
2527
}
2628

test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@ string tns::ConvertToString(const Local<v8::String>& s) {
1919
}
2020

2121
Local<String> tns::JsonStringifyObject(Isolate* isolate, Handle<v8::Value> value) {
22+
v8::HandleScope scope(isolate);
23+
2224
if (value.IsEmpty()) {
2325
return String::Empty(isolate);
2426
}
2527

26-
auto stringifyFunction = CallbackHandlers::isolateToJsonStringify.find(isolate)->second;
27-
auto func = Local<Function>::New(isolate, *stringifyFunction);
28-
Local<Value> args[] = { value };
28+
v8::Local<v8::String> resultString;
29+
v8::TryCatch tc;
30+
auto success = v8::JSON::Stringify(isolate->GetCurrentContext(), value->ToObject(isolate)).ToLocal(&resultString);
2931

30-
auto result = func->Call(Undefined(isolate), 1, args);
32+
if (!success && tc.HasCaught()) {
33+
auto message = tc.Message()->Get();
34+
resultString = v8::String::Concat(ArgConverter::ConvertToV8String(isolate, "Couldn't convert object to a JSON string: "), message);
35+
}
3136

32-
return result->ToString(isolate);
37+
return resultString;
3338
}
3439

3540
jstring tns::ConvertToJavaString(const Local<Value>& value) {

0 commit comments

Comments
 (0)