diff --git a/android/src/main/cpp/OnLoad.cpp b/android/src/main/cpp/OnLoad.cpp index d68d96f..443c3cd 100644 --- a/android/src/main/cpp/OnLoad.cpp +++ b/android/src/main/cpp/OnLoad.cpp @@ -12,11 +12,11 @@ #include #include #include +#include #include #include #include -#include "MainLoopRegistry.h" #include "V8ExecutorFactory.h" #include "V8Runtime.h" #include "V8RuntimeConfig.h" @@ -92,8 +92,16 @@ class V8ExecutorHolder std::move(config))); } - static void onMainLoopIdle(jni::alias_ref) { - MainLoopRegistry::GetInstance()->OnMainLoopIdle(); + static void onMainLoopIdle( + jni::alias_ref, + jni::alias_ref + runtimeExecutor) { + runtimeExecutor->cthis()->get()([](jsi::Runtime &runtime) { + auto v8Runtime = dynamic_cast(&runtime); + if (v8Runtime) { + v8Runtime->OnMainLoopIdle(); + } + }); } static void registerNatives() { diff --git a/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Executor.java b/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Executor.java index 644b261..54290d8 100644 --- a/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Executor.java +++ b/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Executor.java @@ -12,6 +12,7 @@ import android.os.Build; import com.facebook.jni.HybridData; import com.facebook.react.bridge.JavaScriptExecutor; +import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.soloader.SoLoader; import io.csie.kudo.reactnative.v8.BuildConfig; @@ -56,5 +57,6 @@ private static native HybridData initHybrid( int codecacheMode, String codecacheDir); - /* package */ static native void onMainLoopIdle(); + /* package */ static native void onMainLoopIdle( + RuntimeExecutor runtimeExecutor); } diff --git a/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Module.java b/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Module.java index 697c9c5..7ce1d0f 100644 --- a/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Module.java +++ b/android/src/main/java/io/csie/kudo/reactnative/v8/executor/V8Module.java @@ -6,6 +6,7 @@ import android.os.SystemClock; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.UiThreadUtil; public class V8Module @@ -54,7 +55,10 @@ public boolean queueIdle() { if (getReactApplicationContext().hasActiveReactInstance() && SystemClock.uptimeMillis() - mLastMainLoopIdleCallbackTime > MAIN_LOOP_IDLE_THROTTLE) { - V8Executor.onMainLoopIdle(); + final RuntimeExecutor runtimeExecutor = getReactApplicationContext() + .getCatalystInstance() + .getRuntimeExecutor(); + V8Executor.onMainLoopIdle(runtimeExecutor); mLastMainLoopIdleCallbackTime = SystemClock.uptimeMillis(); } return true; diff --git a/src/v8runtime/MainLoopRegistry.cpp b/src/v8runtime/MainLoopRegistry.cpp deleted file mode 100644 index e3a4243..0000000 --- a/src/v8runtime/MainLoopRegistry.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) Kudo Chien. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "MainLoopRegistry.h" - -namespace rnv8 { - -// static -MainLoopRegistry *MainLoopRegistry::GetInstance() { - static MainLoopRegistry instance; - return &instance; -} - -void MainLoopRegistry::RegisterCallback(Callback callback) { - std::lock_guard lock(mutex_); - callbacks_.push_back(std::move(callback)); -} - -void MainLoopRegistry::UnregisterCallback(const Callback &callback) { - std::lock_guard lock(mutex_); - callbacks_.erase( - std::remove_if( - callbacks_.begin(), - callbacks_.end(), - [&callback](const Callback ®istered_callback) { - return callback.target_type() == - registered_callback.target_type() && - callback.target() == - registered_callback.target(); - }), - callbacks_.end()); -} - -void MainLoopRegistry::OnMainLoopIdle() { - std::lock_guard lock(mutex_); - for (const auto &callback : callbacks_) { - callback(); - } -} - -} // namespace rnv8 diff --git a/src/v8runtime/MainLoopRegistry.h b/src/v8runtime/MainLoopRegistry.h deleted file mode 100644 index 7aab283..0000000 --- a/src/v8runtime/MainLoopRegistry.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) Kudo Chien. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace rnv8 { - -class MainLoopRegistry { - public: - using Callback = std::function; - - static MainLoopRegistry *GetInstance(); - - public: - void RegisterCallback(Callback callback); - - void UnregisterCallback(const Callback &callback); - - void OnMainLoopIdle(); - - private: - MainLoopRegistry() = default; - ~MainLoopRegistry() = default; - - MainLoopRegistry(const MainLoopRegistry &) = delete; - MainLoopRegistry &operator=(const MainLoopRegistry &) = delete; - - std::vector callbacks_; - std::mutex mutex_; -}; - -} // namespace rnv8 diff --git a/src/v8runtime/V8Runtime.cpp b/src/v8runtime/V8Runtime.cpp index 93decf5..7b48397 100644 --- a/src/v8runtime/V8Runtime.cpp +++ b/src/v8runtime/V8Runtime.cpp @@ -82,70 +82,73 @@ V8Runtime::V8Runtime( config_->deviceName); inspectorClient_->ConnectToReactFrontend(); } - mainLoopIdleCallback_ = std::bind(&V8Runtime::OnMainLoopIdle, this); - MainLoopRegistry::GetInstance()->RegisterCallback(mainLoopIdleCallback_); } V8Runtime::V8Runtime( const V8Runtime *v8Runtime, - std::unique_ptr config, - bool sharedGlobalContext) + std::unique_ptr config) : config_(std::move(config)) { - if (!sharedGlobalContext) { - arrayBufferAllocator_.reset( - v8::ArrayBuffer::Allocator::NewDefaultAllocator()); - v8::Isolate::CreateParams createParams; - createParams.array_buffer_allocator = arrayBufferAllocator_.get(); - if (v8Runtime->config_->snapshotBlob) { - snapshotBlob_ = std::make_unique(); - snapshotBlob_->data = v8Runtime->config_->snapshotBlob->c_str(); - snapshotBlob_->raw_size = - static_cast(v8Runtime->config_->snapshotBlob->size()); - createParams.snapshot_blob = snapshotBlob_.get(); - } - config_->codecacheMode = V8RuntimeConfig::CodecacheMode::kNone; + arrayBufferAllocator_.reset( + v8::ArrayBuffer::Allocator::NewDefaultAllocator()); + v8::Isolate::CreateParams createParams; + createParams.array_buffer_allocator = arrayBufferAllocator_.get(); + if (v8Runtime->config_->snapshotBlob) { + snapshotBlob_ = std::make_unique(); + snapshotBlob_->data = v8Runtime->config_->snapshotBlob->c_str(); + snapshotBlob_->raw_size = + static_cast(v8Runtime->config_->snapshotBlob->size()); + createParams.snapshot_blob = snapshotBlob_.get(); + } + config_->codecacheMode = V8RuntimeConfig::CodecacheMode::kNone; - isolate_ = v8::Isolate::New(createParams); + isolate_ = v8::Isolate::New(createParams); #if defined(__ANDROID__) - if (!v8Runtime->config_->timezoneId.empty()) { - isolate_->DateTimeConfigurationChangeNotification( - v8::Isolate::TimeZoneDetection::kCustom, - v8Runtime->config_->timezoneId.c_str()); - } + if (!v8Runtime->config_->timezoneId.empty()) { + isolate_->DateTimeConfigurationChangeNotification( + v8::Isolate::TimeZoneDetection::kCustom, + v8Runtime->config_->timezoneId.c_str()); + } #endif - v8::Locker locker(isolate_); - v8::Isolate::Scope scopedIsolate(isolate_); - v8::HandleScope scopedHandle(isolate_); - context_.Reset(isolate_, CreateGlobalContext(isolate_)); - v8::Context::Scope scopedContext(context_.Get(isolate_)); - jsQueue_ = v8Runtime->jsQueue_; - mainLoopIdleCallback_ = std::bind(&V8Runtime::OnMainLoopIdle, this); - MainLoopRegistry::GetInstance()->RegisterCallback(mainLoopIdleCallback_); - } else { - isSharedRuntime_ = true; - isolate_ = v8Runtime->isolate_; - jsQueue_ = v8Runtime->jsQueue_; + v8::Locker locker(isolate_); + v8::Isolate::Scope scopedIsolate(isolate_); + v8::HandleScope scopedHandle(isolate_); + context_.Reset(isolate_, CreateGlobalContext(isolate_)); + v8::Context::Scope scopedContext(context_.Get(isolate_)); + jsQueue_ = v8Runtime->jsQueue_; - v8::Locker locker(isolate_); - v8::Isolate::Scope scopedIsolate(isolate_); - v8::HandleScope scopedHandle(isolate_); - context_.Reset(isolate_, CreateGlobalContext(isolate_)); - - auto localContext = context_.Get(isolate_); - localContext->SetSecurityToken( - v8Runtime->context_.Get(isolate_)->GetSecurityToken()); - - bool inheritProtoResult = - localContext->Global() - ->GetPrototype() - .As() - ->SetPrototype( - localContext, - v8Runtime->context_.Get(isolate_)->Global()->GetPrototype()) - .FromJust(); - if (!inheritProtoResult) { - LOG(ERROR) << "Unable to inherit prototype from parent shared runtime."; - } + if (config_->enableInspector) { + inspectorClient_ = std::make_shared( + jsQueue_, + context_.Get(isolate_), + config_->appName, + config_->deviceName); + inspectorClient_->ConnectToReactFrontend(); + } + +#if 0 // Experimental shared global context + isSharedRuntime_ = true; + isolate_ = v8Runtime->isolate_; + jsQueue_ = v8Runtime->jsQueue_; + + v8::Locker locker(isolate_); + v8::Isolate::Scope scopedIsolate(isolate_); + v8::HandleScope scopedHandle(isolate_); + context_.Reset(isolate_, CreateGlobalContext(isolate_)); + + auto localContext = context_.Get(isolate_); + localContext->SetSecurityToken( + v8Runtime->context_.Get(isolate_)->GetSecurityToken()); + + bool inheritProtoResult = + localContext->Global() + ->GetPrototype() + .As() + ->SetPrototype( + localContext, + v8Runtime->context_.Get(isolate_)->Global()->GetPrototype()) + .FromJust(); + if (!inheritProtoResult) { + LOG(ERROR) << "Unable to inherit prototype from parent shared runtime."; } if (config_->enableInspector) { @@ -156,11 +159,10 @@ V8Runtime::V8Runtime( config_->deviceName); inspectorClient_->ConnectToReactFrontend(); } +#endif } V8Runtime::~V8Runtime() { - MainLoopRegistry::GetInstance()->UnregisterCallback(mainLoopIdleCallback_); - mainLoopIdleCallback_ = nullptr; { v8::Locker locker(isolate_); v8::Isolate::Scope scopedIsolate(isolate_); @@ -311,10 +313,6 @@ V8Runtime::LoadCodeCacheIfNeeded(const std::string &sourceURL) { return nullptr; } - if (sourceURL.empty()) { - return nullptr; - } - if (config_->codecacheMode == V8RuntimeConfig::CodecacheMode::kNone) { return nullptr; } @@ -349,10 +347,6 @@ bool V8Runtime::SaveCodeCacheIfNeeded( return false; } - if (sourceURL.empty()) { - return false; - } - if (cachedData && !cachedData->rejected) { return false; } @@ -462,14 +456,7 @@ jsi::Value V8Runtime::evaluatePreparedJavaScript( #if REACT_NATIVE_MINOR_VERSION >= 75 || \ (REACT_NATIVE_MINOR_VERSION >= 74 && REACT_NATIVE_PATCH_VERSION >= 3) void V8Runtime::queueMicrotask(const jsi::Function &callback) { - v8::Locker locker(isolate_); - v8::Isolate::Scope scopedIsolate(isolate_); - v8::HandleScope scopedHandle(isolate_); - v8::Context::Scope scopedContext(context_.Get(isolate_)); - - v8::Local v8Function = - JSIV8ValueConverter::ToV8Function(*this, callback); - isolate_->EnqueueMicrotask(v8Function); + // TODO: add this when we revisit new architecture support } #endif // REACT_NATIVE_MINOR_VERSION >= 75 || (REACT_NATIVE_MINOR_VERSION >= 74 // && REACT_NATIVE_PATCH_VERSION >= 3 diff --git a/src/v8runtime/V8Runtime.h b/src/v8runtime/V8Runtime.h index 28a05a4..7528488 100644 --- a/src/v8runtime/V8Runtime.h +++ b/src/v8runtime/V8Runtime.h @@ -8,7 +8,6 @@ #pragma once #include -#include "MainLoopRegistry.h" #include "V8RuntimeConfig.h" #include "jsi/jsi.h" #include "libplatform/libplatform.h" @@ -27,8 +26,7 @@ class V8Runtime : public facebook::jsi::Runtime { std::shared_ptr jsQueue); V8Runtime( const V8Runtime *v8Runtime, - std::unique_ptr config, - bool sharedGlobalContext = false); + std::unique_ptr config); ~V8Runtime(); // Calling this function when the platform main runloop is idle @@ -279,7 +277,6 @@ class V8Runtime : public facebook::jsi::Runtime { std::shared_ptr inspectorClient_; bool isSharedRuntime_ = false; std::shared_ptr jsQueue_; - MainLoopRegistry::Callback mainLoopIdleCallback_; }; } // namespace rnv8