Skip to content

Commit 90c565a

Browse files
committed
fix(console): prioritize array printing before object printing in order to properly transform array entries
1 parent 593c75f commit 90c565a

File tree

1 file changed

+49
-10
lines changed

1 file changed

+49
-10
lines changed

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

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const v8::Local<v8::String> transformJSObject(v8::Isolate* isolate, v8::Local<v8
7676
auto objToString = object->ToString(isolate);
7777
v8::Local<v8::String> resultString;
7878

79-
auto hasCustomToStringImplementation = !objToString->SameValue(ArgConverter::ConvertToV8String(isolate, "[object Object]"));
79+
auto hasCustomToStringImplementation = ArgConverter::ConvertToString(objToString).find("[object Object]") == std::string::npos;
8080

8181
if (hasCustomToStringImplementation) {
8282
resultString = objToString;
@@ -87,6 +87,52 @@ const v8::Local<v8::String> transformJSObject(v8::Isolate* isolate, v8::Local<v8
8787
return resultString;
8888
}
8989

90+
const v8::Local<v8::String> buildStringFromArg(v8::Isolate* isolate, const v8::Local<v8::Value>& val) {
91+
v8::Local<v8::String> argString;
92+
if (val->IsFunction()) {
93+
val->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
94+
} else if (val->IsArray()) {
95+
auto cachedSelf = val;
96+
auto array = val->ToObject();
97+
auto arrayEntryKeys = array->GetPropertyNames(isolate->GetCurrentContext()).ToLocalChecked();
98+
auto context = isolate->GetCurrentContext();
99+
100+
auto arrayLength = arrayEntryKeys->Length();
101+
102+
argString = ArgConverter::ConvertToV8String(isolate, "[");
103+
104+
for (int i = 0; i < arrayLength; i++) {
105+
auto propertyName = arrayEntryKeys->Get(context, i).ToLocalChecked();
106+
107+
auto propertyValue = array->Get(context, propertyName).ToLocalChecked();
108+
109+
// avoid bottomless recursion with cyclic reference to the same array
110+
if (propertyValue->StrictEquals(cachedSelf)) {
111+
argString = v8::String::Concat(argString, ArgConverter::ConvertToV8String(isolate, "[Circular]"));
112+
continue;
113+
}
114+
115+
auto objectString = buildStringFromArg(isolate, propertyValue);
116+
117+
argString = v8::String::Concat(argString, objectString);
118+
119+
if (i != arrayLength - 1) {
120+
argString = v8::String::Concat(argString, ArgConverter::ConvertToV8String(isolate, ", "));
121+
}
122+
}
123+
124+
argString = v8::String::Concat(argString, ArgConverter::ConvertToV8String(isolate, "]"));
125+
} else if (val->IsObject()) {
126+
v8::Local<v8::Object> obj = val.As<v8::Object>();
127+
128+
argString = transformJSObject(isolate, obj);
129+
} else {
130+
val->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
131+
}
132+
133+
return argString;
134+
}
135+
90136
const std::string buildLogString(const v8::FunctionCallbackInfo<v8::Value>& info, int startingIndex = 0) {
91137
auto isolate = info.GetIsolate();
92138

@@ -98,15 +144,8 @@ const std::string buildLogString(const v8::FunctionCallbackInfo<v8::Value>& info
98144
if (argLen) {
99145
for (int i = startingIndex; i < argLen; i++) {
100146
v8::Local<v8::String> argString;
101-
if (info[i]->IsFunction()) {
102-
info[i]->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
103-
} else if (info[i]->IsObject()) {
104-
v8::Local<v8::Object> obj = info[i].As<v8::Object>();
105-
106-
argString = transformJSObject(isolate, obj);
107-
} else {
108-
info[i]->ToDetailString(isolate->GetCurrentContext()).ToLocal(&argString);
109-
}
147+
148+
argString = buildStringFromArg(isolate, info[i]);
110149

111150
// separate args with a space
112151
if (i != 0) {

0 commit comments

Comments
 (0)