Skip to content

Commit d3c52cb

Browse files
authored
fix: refactor console.log implementation a bit (#1741)
1 parent 1c0214a commit d3c52cb

File tree

6 files changed

+75
-54
lines changed

6 files changed

+75
-54
lines changed

test-app/app/src/main/assets/app/mainpage.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,5 @@ require("./tests/kotlin/enums/testEnumsSupport");
6767
require("./tests/kotlin/access/testInternalLanguageFeaturesSupport");
6868
require("./tests/testPackagePrivate");
6969
require("./tests/kotlin/properties/testPropertiesSupport.js");
70-
require('./tests/testNativeTimers');
70+
require('./tests/testNativeTimers');
71+
require("./tests/console/logTests.js");
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
describe("Test JSONObject conversions", () => {
2+
it("console.log with number param should not crash", () => {
3+
console.log(123);
4+
});
5+
6+
it("console.log with string param should not crash", () => {
7+
console.log("123");
8+
});
9+
10+
it("console.log with object param should not crash", () => {
11+
console.log({ num: 123 });
12+
});
13+
14+
it("console.log with function param should not crash", () => {
15+
console.log(function() {});
16+
});
17+
18+
it("console.log with arrow function param should not crash", () => {
19+
console.log(() => {});
20+
});
21+
22+
it("console.log with primitive array param should not crash", () => {
23+
console.log([1, 2, 3]);
24+
});
25+
26+
it("console.log with object array param should not crash", () => {
27+
console.log([{
28+
num: 123
29+
}]);
30+
});
31+
});

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,16 +1091,18 @@ CallbackHandlers::WorkerObjectPostMessageCallback(const v8::FunctionCallbackInfo
10911091
ArgConverter::ConvertToV8String(isolate, "workerId"),
10921092
jsId);
10931093

1094-
Local<String> msg = tns::JsonStringifyObject(isolate, args[0], false);
10951094
auto context = isolate->GetCurrentContext();
1095+
auto objToStringify = args[0]->ToObject(context).ToLocalChecked();
1096+
std::string msg = tns::JsonStringifyObject(isolate, objToStringify, false);
1097+
10961098
// get worker's ID that is associated on the other side - in Java
10971099
auto id = jsId->Int32Value(context).ToChecked();
10981100

10991101
JEnv env;
11001102
auto mId = env.GetStaticMethodID(RUNTIME_CLASS, "sendMessageFromMainToWorker",
11011103
"(ILjava/lang/String;)V");
11021104

1103-
auto jmsg = ArgConverter::ConvertToJavaString(msg);
1105+
jstring jmsg = env.NewStringUTF(msg.c_str());
11041106
JniLocalRef jmsgRef(jmsg);
11051107

11061108
env.CallStaticVoidMethod(RUNTIME_CLASS, mId, id, (jstring) jmsgRef);
@@ -1190,13 +1192,15 @@ CallbackHandlers::WorkerGlobalPostMessageCallback(const v8::FunctionCallbackInfo
11901192
return;
11911193
}
11921194

1193-
Local<String> msg = tns::JsonStringifyObject(isolate, args[0], false);
1195+
auto context = isolate->GetCurrentContext();
1196+
auto objToStringify = args[0]->ToObject(context).ToLocalChecked();
1197+
std::string msg = tns::JsonStringifyObject(isolate, objToStringify, false);
11941198

11951199
JEnv env;
11961200
auto mId = env.GetStaticMethodID(RUNTIME_CLASS, "sendMessageFromWorkerToMain",
11971201
"(Ljava/lang/String;)V");
11981202

1199-
auto jmsg = ArgConverter::ConvertToJavaString(msg);
1203+
auto jmsg = env.NewStringUTF(msg.c_str());
12001204
JniLocalRef jmsgRef(jmsg);
12011205

12021206
env.CallStaticVoidMethod(RUNTIME_CLASS, mId, (jstring) jmsgRef);

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ Local<Function> GetSmartJSONStringifyFunction(Isolate* isolate) {
6666
return smartStringifyPersistentFunction->Get(isolate);
6767
}
6868

69-
Local<String> tns::JsonStringifyObject(Isolate* isolate, Handle<v8::Value> value, bool handleCircularReferences) {
69+
std::string tns::JsonStringifyObject(Isolate* isolate, v8::Local<v8::Object> value, bool handleCircularReferences) {
7070
if (value.IsEmpty()) {
71-
return String::Empty(isolate);
71+
return "";
7272
}
7373

7474
auto context = isolate->GetCurrentContext();
@@ -80,25 +80,28 @@ Local<String> tns::JsonStringifyObject(Isolate* isolate, Handle<v8::Value> value
8080
v8::Local<v8::Value> resultValue;
8181
v8::TryCatch tc(isolate);
8282

83-
Local<Value> args[] = { value->ToObject(context).ToLocalChecked() };
84-
auto success = smartJSONStringifyFunction->Call(context, Undefined(isolate), 1, args).ToLocal(&resultValue);
83+
Local<Value> args[] = { value };
84+
auto success = smartJSONStringifyFunction
85+
->Call(context, Undefined(isolate), 1, args)
86+
.ToLocal(&resultValue);
8587

8688
if (success && !tc.HasCaught()) {
87-
return resultValue->ToString(context).ToLocalChecked();
89+
auto res = resultValue.As<v8::String>();
90+
return ArgConverter::ConvertToString(res);
8891
}
8992
}
9093
}
9194
}
9295

9396
v8::Local<v8::String> resultString;
9497
v8::TryCatch tc(isolate);
95-
auto success = v8::JSON::Stringify(context, value->ToObject(context).ToLocalChecked()).ToLocal(&resultString);
98+
auto success = v8::JSON::Stringify(context, value).ToLocal(&resultString);
9699

97100
if (!success && tc.HasCaught()) {
98101
throw NativeScriptException(tc);
99102
}
100103

101-
return resultString;
104+
return ArgConverter::ConvertToString(resultString);
102105
}
103106

104107
bool tns::V8GetPrivateValue(Isolate* isolate, const Local<Object>& obj, const Local<String>& propName, Local<Value>& out) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <map>
99

1010
namespace tns {
11-
v8::Local<v8::String> JsonStringifyObject(v8::Isolate* isolate, v8::Handle<v8::Value> value, bool handleCircularReferences = true);
11+
std::string JsonStringifyObject(v8::Isolate* isolate, v8::Handle<v8::Object> value, bool handleCircularReferences = true);
1212

1313
bool V8GetPrivateValue(v8::Isolate* isolate, const v8::Local<v8::Object>& obj, const v8::Local<v8::String>& propName, v8::Local<v8::Value>& out);
1414

test-app/runtime/src/main/cpp/console/Console.cpp

Lines changed: 23 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -72,105 +72,89 @@ void Console::sendToDevToolsFrontEnd(v8::Isolate* isolate, const std::string& me
7272
}
7373
}
7474

75-
const v8::Local<v8::String> transformJSObject(v8::Isolate* isolate, v8::Local<v8::Object> object) {
75+
std::string transformJSObject(v8::Isolate* isolate, v8::Local<v8::Object> object) {
7676
auto context = isolate->GetCurrentContext();
7777
auto objToString = object->ToString(context).ToLocalChecked();
78-
v8::Local<v8::String> resultString;
78+
auto objToCppString = ArgConverter::ConvertToString(objToString);
7979

80-
auto hasCustomToStringImplementation = ArgConverter::ConvertToString(objToString).find("[object Object]") == std::string::npos;
80+
auto hasCustomToStringImplementation = objToCppString.find("[object Object]") == std::string::npos;
8181

8282
if (hasCustomToStringImplementation) {
83-
resultString = objToString;
83+
return objToCppString;
8484
} else {
85-
v8::HandleScope scope(isolate);
86-
resultString = JsonStringifyObject(isolate, object);
85+
return JsonStringifyObject(isolate, object);
8786
}
88-
89-
return resultString;
9087
}
9188

92-
const v8::Local<v8::String> buildStringFromArg(v8::Isolate* isolate, const v8::Local<v8::Value>& val) {
93-
v8::Local<v8::String> argString;
89+
std::string buildStringFromArg(v8::Isolate* isolate, const v8::Local<v8::Value>& val) {
9490
if (val->IsFunction()) {
95-
val->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
91+
auto v8FunctionString = val->ToDetailString(isolate->GetCurrentContext()).ToLocalChecked();
92+
return ArgConverter::ConvertToString(v8FunctionString);
9693
} else if (val->IsArray()) {
9794
auto context = isolate->GetCurrentContext();
9895
auto cachedSelf = val;
9996
auto array = val->ToObject(context).ToLocalChecked();
10097
auto arrayEntryKeys = array->GetPropertyNames(isolate->GetCurrentContext()).ToLocalChecked();
10198

10299
auto arrayLength = arrayEntryKeys->Length();
103-
104-
argString = ArgConverter::ConvertToV8String(isolate, "[");
100+
std::string argString = "[";
105101

106102
for (int i = 0; i < arrayLength; i++) {
107103
auto propertyName = arrayEntryKeys->Get(context, i).ToLocalChecked();
108-
109104
auto propertyValue = array->Get(context, propertyName).ToLocalChecked();
110105

111106
// avoid bottomless recursion with cyclic reference to the same array
112107
if (propertyValue->StrictEquals(cachedSelf)) {
113-
argString = v8::String::Concat(isolate, argString, ArgConverter::ConvertToV8String(isolate, "[Circular]"));
108+
argString.append("[Circular]");
114109
continue;
115110
}
116111

117112
auto objectString = buildStringFromArg(isolate, propertyValue);
118-
119-
argString = v8::String::Concat(isolate, argString, objectString);
113+
argString.append(objectString);
120114

121115
if (i != arrayLength - 1) {
122-
argString = v8::String::Concat(isolate, argString, ArgConverter::ConvertToV8String(isolate, ", "));
116+
argString.append(", ");
123117
}
124118
}
125119

126-
argString = v8::String::Concat(isolate, argString, ArgConverter::ConvertToV8String(isolate, "]"));
120+
return argString.append("]");
127121
} else if (val->IsObject()) {
128122
v8::Local<v8::Object> obj = val.As<v8::Object>();
129-
130-
argString = transformJSObject(isolate, obj);
123+
return transformJSObject(isolate, obj);
131124
} else {
132-
val->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
125+
auto v8DefaultToString = val->ToDetailString(isolate->GetCurrentContext()).ToLocalChecked();
126+
return ArgConverter::ConvertToString(v8DefaultToString);
133127
}
134-
135-
return argString;
136128
}
137129

138-
const std::string buildLogString(const v8::FunctionCallbackInfo<v8::Value>& info, int startingIndex = 0) {
130+
std::string buildLogString(const v8::FunctionCallbackInfo<v8::Value>& info, int startingIndex = 0) {
139131
auto isolate = info.GetIsolate();
140-
141132
v8::HandleScope scope(isolate);
142-
143133
std::stringstream ss;
144134

145135
auto argLen = info.Length();
146136
if (argLen) {
147137
for (int i = startingIndex; i < argLen; i++) {
148-
v8::Local<v8::String> argString;
149-
150-
argString = buildStringFromArg(isolate, info[i]);
151-
152138
// separate args with a space
153139
if (i != 0) {
154140
ss << " ";
155141
}
156-
157-
ss << ArgConverter::ConvertToString(argString);
142+
143+
std::string argString = buildStringFromArg(isolate, info[i]);
144+
ss << argString;
158145
}
159146
} else {
160147
ss << std::endl;
161148
}
162149

163-
std::string stringResult = ss.str();
164-
165-
return stringResult;
150+
return ss.str();
166151
}
167152

168153
void Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
169154
try {
170155
auto isolate = info.GetIsolate();
171156

172157
auto argLen = info.Length();
173-
auto context = isolate->GetCurrentContext();
174158
auto expressionPasses = argLen && info[0]->BooleanValue(isolate);
175159

176160
if (!expressionPasses) {
@@ -307,13 +291,11 @@ void Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
307291
if (propIsFunction) {
308292
ss << "()";
309293
} else if (propertyValue->IsArray()) {
310-
auto stringResult = buildStringFromArg(isolate, propertyValue);
311-
std::string jsonStringifiedArray = ArgConverter::ConvertToString(stringResult);
294+
std::string jsonStringifiedArray = buildStringFromArg(isolate, propertyValue);
312295
ss << ": " << jsonStringifiedArray;
313296
} else if (propertyValue->IsObject()) {
314297
auto obj = propertyValue->ToObject(context).ToLocalChecked();
315-
auto objString = transformJSObject(isolate, obj);
316-
std::string jsonStringifiedObject = ArgConverter::ConvertToString(objString);
298+
auto jsonStringifiedObject = transformJSObject(isolate, obj);
317299
// if object prints out as the error string for circular references, replace with #CR instead for brevity
318300
if (jsonStringifiedObject.find("circular structure") != std::string::npos) {
319301
jsonStringifiedObject = "#CR";

0 commit comments

Comments
 (0)