Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions test-app/app/src/main/java/com/tns/NativeScriptRuntime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.tns;

public final class NativeScriptRuntime {
private NativeScriptRuntime() {
}

public static boolean reloadApplication() {
return RuntimeHelper.reloadApplication();
}

public static boolean reloadApplication(String baseDir) {
return RuntimeHelper.reloadApplication();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
}
53 changes: 52 additions & 1 deletion test-app/app/src/main/java/com/tns/RuntimeHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;

Expand All @@ -24,6 +26,9 @@ private RuntimeHelper() {
}

private static AndroidJsV8Inspector v8Inspector;
private static Context applicationContext;
private static BroadcastReceiver timezoneChangedReceiver;
private static boolean reloadScheduled;

// hasErrorIntent tells you if there was an event (with an uncaught
// exception) raised from ErrorReport
Expand Down Expand Up @@ -59,6 +64,9 @@ private static boolean hasErrorIntent(Context context) {
}

public static Runtime initRuntime(Context context) {
Context appContext = context.getApplicationContext();
applicationContext = appContext != null ? appContext : context;

if (Runtime.isInitialized()) {
return Runtime.getCurrentRuntime();
}
Expand Down Expand Up @@ -237,6 +245,40 @@ public static Runtime initRuntime(Context context) {
}
}

public static synchronized boolean reloadApplication() {
final Context context = applicationContext;
if (context == null || reloadScheduled) {
return false;
}

reloadScheduled = true;

new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
try {
Runtime.destroyMainRuntime();

Runtime runtime = initRuntime(context);
if (runtime == null) {
throw new IllegalStateException("NativeScript runtime reload failed to initialize a new runtime.");
}

runtime.run();
} catch (Throwable e) {
Log.e(logTag, "NativeScript runtime reload failed.", e);
throw new RuntimeException("NativeScript runtime reload failed.", e);
} finally {
synchronized (RuntimeHelper.class) {
reloadScheduled = false;
}
}
}
});

return true;
}

private static void waitForLiveSync(Context context) {
boolean needToWait = false;

Expand Down Expand Up @@ -295,7 +337,16 @@ public void onReceive(Context context, Intent intent) {
}
};

context.registerReceiver(timezoneReceiver, timezoneFilter);
if (timezoneChangedReceiver != null) {
try {
context.unregisterReceiver(timezoneChangedReceiver);
} catch (IllegalArgumentException e) {
// Already unregistered.
}
}

timezoneChangedReceiver = timezoneReceiver;
context.registerReceiver(timezoneChangedReceiver, timezoneFilter);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

public static void initLiveSync(Application app) {
Expand Down
123 changes: 122 additions & 1 deletion test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,127 @@ extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeIdLegacy(JNIEnv*
return getCurrentRuntimeIdCritical_impl();
}

extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerGlobalOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jstring msg) {
// Worker Thread runtime
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
// TODO: Pete: Log message informing the developer of the failure
}

auto isolate = runtime->GetIsolate();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handleScope(isolate);
auto context = runtime->GetContext();
v8::Context::Scope context_scope(context);

CallbackHandlers::WorkerGlobalOnMessageCallback(isolate, msg);
}

extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerObjectOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jint workerId, jstring msg) {
// Main Thread runtime
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
// TODO: Pete: Log message informing the developer of the failure
}

auto isolate = runtime->GetIsolate();

v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handleScope(isolate);
auto context = runtime->GetContext();
v8::Context::Scope context_scope(context);

CallbackHandlers::WorkerObjectOnMessageCallback(isolate, workerId, msg);
}

extern "C" JNIEXPORT void Java_com_tns_Runtime_TerminateWorkerCallback(JNIEnv* env, jobject obj, jint runtimeId) {
// Worker Thread runtime
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
// TODO: Pete: Log message informing the developer of the failure
return;
}

auto isolate = runtime->GetIsolate();

{
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handleScope(isolate);

CallbackHandlers::TerminateWorkerThread(isolate);

runtime->DestroyRuntime();
}

isolate->Dispose();

delete runtime;
}

extern "C" JNIEXPORT void Java_com_tns_Runtime_TerminateRuntimeCallback(JNIEnv* env, jobject obj, jint runtimeId) {
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
// TODO: Pete: Log message informing the developer of the failure
return;
}

auto isolate = runtime->GetIsolate();

{
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handleScope(isolate);

runtime->DestroyRuntime();
}

isolate->Dispose();

delete runtime;
}

extern "C" JNIEXPORT void Java_com_tns_Runtime_ClearWorkerPersistent(JNIEnv* env, jobject obj, jint runtimeId, jint workerId) {
// Worker Thread runtime
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
// TODO: Pete: Log message informing the developer of the failure
}

auto isolate = runtime->GetIsolate();

v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handleScope(isolate);
auto context = runtime->GetContext();
v8::Context::Scope context_scope(context);

CallbackHandlers::ClearWorkerPersistent(workerId);
}

extern "C" JNIEXPORT void Java_com_tns_Runtime_CallWorkerObjectOnErrorHandleMain(JNIEnv* env, jobject obj, jint runtimeId, jint workerId, jstring message, jstring stackTrace, jstring filename, jint lineno, jstring threadName) {
// Main Thread runtime
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
// TODO: Pete: Log message informing the developer of the failure
}

auto isolate = runtime->GetIsolate();
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handleScope(isolate);
auto context = runtime->GetContext();
v8::Context::Scope context_scope(context);

try {
CallbackHandlers::CallWorkerObjectOnErrorHandle(isolate, workerId, message, stackTrace, filename, lineno, threadName);
} catch (NativeScriptException& e) {
e.ReThrowToJava();
}
}
extern "C" JNIEXPORT void Java_com_tns_Runtime_ResetDateTimeConfigurationCache(JNIEnv* _env, jobject obj, jint runtimeId) {
auto runtime = TryGetRuntime(runtimeId);
if (runtime == nullptr) {
Expand All @@ -360,4 +481,4 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_ResetDateTimeConfigurationCache(J

auto isolate = runtime->GetIsolate();
isolate->DateTimeConfigurationChangeNotification(Isolate::TimeZoneDetection::kRedetect);
}
}
45 changes: 45 additions & 0 deletions test-app/runtime/src/main/java/com/tns/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ public static void SetManualInstrumentationMode(String mode) {
}
}

private static native void WorkerGlobalOnMessageCallback(int runtimeId, String message);

private static native void WorkerObjectOnMessageCallback(int runtimeId, int workerId, String message);

private static native void TerminateWorkerCallback(int runtimeId);

private static native void TerminateRuntimeCallback(int runtimeId);

private static native void ClearWorkerPersistent(int runtimeId, int workerId);

private static native void CallWorkerObjectOnErrorHandleMain(int runtimeId, int workerId, String message, String stackTrace, String filename, int lineno, String threadName) throws NativeScriptException;
private static native void ResetDateTimeConfigurationCache(int runtimeId);

void passUncaughtExceptionToJs(Throwable ex, String message, String fullStackTrace, String jsStackTrace) {
Expand Down Expand Up @@ -454,6 +465,40 @@ public static boolean isInitialized() {
return (runtime != null) ? runtime.isInitializedImpl() : false;
}

static void destroyMainRuntime() {
Runtime runtime = Runtime.getCurrentRuntime();
if (runtime == null) {
return;
}

if (runtime.workerId != 0) {
throw new NativeScriptException("Only the main NativeScript runtime can be destroyed with destroyMainRuntime().");
}

runtime.isTerminating = true;
runtime.terminateWorkers();
GcListener.unsubscribe(runtime);
runtimeCache.remove(runtime.runtimeId);
pendingWorkerMessages.clear();
currentRuntime.remove();

TerminateRuntimeCallback(runtime.runtimeId);
}

private void terminateWorkers() {
for (Handler workerHandler : new ArrayList<>(workerIdToHandler.values())) {
if (workerHandler == null) {
continue;
}

Message msg = Message.obtain();
msg.arg1 = MessageType.TerminateThread;
workerHandler.sendMessageAtFrontOfQueue(msg);
}

workerIdToHandler.clear();
}
Comment thread
NathanWalker marked this conversation as resolved.
Outdated

public int getWorkerId() {
return workerId;
}
Expand Down