From 8fcbaf55af2ad672f78fe51b0b874210729e04c7 Mon Sep 17 00:00:00 2001 From: Darin Dimitrov Date: Thu, 27 Jun 2019 14:33:14 +0300 Subject: [PATCH] Use the built-in JSON.stringify for cross workers communication --- CHANGELOG.md | 2 ++ test-app/app/src/main/assets/app/shared | 2 +- .../runtime/src/main/cpp/CallbackHandlers.cpp | 4 +-- .../runtime/src/main/cpp/V8GlobalHelpers.cpp | 27 ++++++++++--------- .../runtime/src/main/cpp/V8GlobalHelpers.h | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 467ee7e51..5de2ddb1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ The application crashed because of an uncaught exception. You can look at "stackTrace" or "nativeException" for more detailed information about the exception. ``` +- [The built-in `JSON.stringify` method is used for cross workers communication](https://github.com/NativeScript/android-runtime/issues/1408). Circular object references are no longer supported and attempting to send such object will throw an exception. + 5.4.0 == diff --git a/test-app/app/src/main/assets/app/shared b/test-app/app/src/main/assets/app/shared index fe68ba3a8..79a384c6d 160000 --- a/test-app/app/src/main/assets/app/shared +++ b/test-app/app/src/main/assets/app/shared @@ -1 +1 @@ -Subproject commit fe68ba3a86daed1dc46d4aa10951f3cf03a0242a +Subproject commit 79a384c6dd1c34f018ac3d42acfde6d759b7bc66 diff --git a/test-app/runtime/src/main/cpp/CallbackHandlers.cpp b/test-app/runtime/src/main/cpp/CallbackHandlers.cpp index f915f782f..14e108ada 100644 --- a/test-app/runtime/src/main/cpp/CallbackHandlers.cpp +++ b/test-app/runtime/src/main/cpp/CallbackHandlers.cpp @@ -992,7 +992,7 @@ CallbackHandlers::WorkerObjectPostMessageCallback(const v8::FunctionCallbackInfo ArgConverter::ConvertToV8String(isolate, "workerId"), jsId); - Local msg = tns::JsonStringifyObject(isolate, args[0])->ToString(isolate); + Local msg = tns::JsonStringifyObject(isolate, args[0], false); auto context = isolate->GetCurrentContext(); // get worker's ID that is associated on the other side - in Java auto id = jsId->Int32Value(context).ToChecked(); @@ -1090,7 +1090,7 @@ CallbackHandlers::WorkerGlobalPostMessageCallback(const v8::FunctionCallbackInfo return; } - Local msg = tns::JsonStringifyObject(isolate, args[0])->ToString(isolate); + Local msg = tns::JsonStringifyObject(isolate, args[0], false); JEnv env; auto mId = env.GetStaticMethodID(RUNTIME_CLASS, "sendMessageFromWorkerToMain", diff --git a/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp b/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp index 7df8b68a9..30d9defe8 100644 --- a/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp +++ b/test-app/runtime/src/main/cpp/V8GlobalHelpers.cpp @@ -66,34 +66,35 @@ Local GetSmartJSONStringifyFunction(Isolate* isolate) { return smartStringifyPersistentFunction->Get(isolate); } -Local tns::JsonStringifyObject(Isolate* isolate, Handle value) { +Local tns::JsonStringifyObject(Isolate* isolate, Handle value, bool handleCircularReferences) { if (value.IsEmpty()) { return String::Empty(isolate); } - Local smartJSONStringifyFunction = GetSmartJSONStringifyFunction(isolate); + if (handleCircularReferences) { + Local smartJSONStringifyFunction = GetSmartJSONStringifyFunction(isolate); - if (!smartJSONStringifyFunction.IsEmpty()) { - if (value->IsObject()) { - v8::Local resultValue; - v8::TryCatch tc(isolate); + if (!smartJSONStringifyFunction.IsEmpty()) { + if (value->IsObject()) { + v8::Local resultValue; + v8::TryCatch tc(isolate); - Local args[] = { value->ToObject(isolate) }; - auto success = smartJSONStringifyFunction->Call(isolate->GetCurrentContext(), Undefined(isolate), 1, args).ToLocal(&resultValue); + Local args[] = { value->ToObject(isolate) }; + auto success = smartJSONStringifyFunction->Call(isolate->GetCurrentContext(), Undefined(isolate), 1, args).ToLocal(&resultValue); - if (success && !tc.HasCaught()) { - return resultValue->ToString(isolate); + if (success && !tc.HasCaught()) { + return resultValue->ToString(isolate); + } } } } v8::Local resultString; v8::TryCatch tc(isolate); - auto success = v8::JSON::Stringify(isolate->GetCurrentContext(), value->ToObject(isolate), ArgConverter::ConvertToV8String(isolate, "2")).ToLocal(&resultString); + auto success = v8::JSON::Stringify(isolate->GetCurrentContext(), value->ToObject(isolate)).ToLocal(&resultString); if (!success && tc.HasCaught()) { - auto message = tc.Message()->Get(); - resultString = v8::String::Concat(isolate, ArgConverter::ConvertToV8String(isolate, "Couldn't convert object to a JSON string: "), message); + throw NativeScriptException(tc); } return resultString; diff --git a/test-app/runtime/src/main/cpp/V8GlobalHelpers.h b/test-app/runtime/src/main/cpp/V8GlobalHelpers.h index 701c171d5..c13e79311 100644 --- a/test-app/runtime/src/main/cpp/V8GlobalHelpers.h +++ b/test-app/runtime/src/main/cpp/V8GlobalHelpers.h @@ -8,7 +8,7 @@ #include namespace tns { -v8::Local JsonStringifyObject(v8::Isolate* isolate, v8::Handle value); +v8::Local JsonStringifyObject(v8::Isolate* isolate, v8::Handle value, bool handleCircularReferences = true); bool V8GetPrivateValue(v8::Isolate* isolate, const v8::Local& obj, const v8::Local& propName, v8::Local& out);