Convert TurboModuleManager.java to Kotlin (#50706)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50706

Convert Java to Kotlin

Changelog:
[Internal]

Reviewed By: cortinico

Differential Revision: D72771539

fbshipit-source-id: 2646987d12bfed35a1692b96a8548a0952fc41d7
This commit is contained in:
Alan Lee
2025-04-14 10:40:32 -07:00
committed by Facebook GitHub Bot
parent 309ccb8b60
commit f9c318b05d
2 changed files with 405 additions and 480 deletions
@@ -1,480 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.internal.turbomodule.core;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.CxxModuleWrapper;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.RuntimeExecutor;
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry;
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
import com.facebook.react.turbomodule.core.NativeMethodCallInvokerHolderImpl;
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder;
import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.soloader.SoLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This is the main class and entry point for TurboModules. Note that this is a hybrid class, and
* has a C++ counterpart This class installs the JSI bindings. It also implements the method to get
* a Java module, that the C++ counterpart calls.
*/
@Nullsafe(Nullsafe.Mode.LOCAL)
public class TurboModuleManager implements TurboModuleRegistry {
private static final String TAG = "TurboModuleManager";
private final List<String> mEagerInitModuleNames;
private final ModuleProvider mTurboModuleProvider;
private final ModuleProvider mLegacyModuleProvider;
private final @Nullable TurboModuleManagerDelegate mDelegate;
static {
SoLoader.loadLibrary("turbomodulejsijni");
}
// Prevents the creation of new TurboModules once cleanup as been initiated.
private final Object mModuleCleanupLock = new Object();
@GuardedBy("mModuleCleanupLock")
private boolean mModuleCleanupStarted = false;
// List of TurboModules that have been, or are currently being, instantiated
@GuardedBy("mModuleCleanupLock")
private final Map<String, ModuleHolder> mModuleHolders = new HashMap<>();
@DoNotStrip
@SuppressWarnings("unused")
private final HybridData mHybridData;
public TurboModuleManager(
RuntimeExecutor runtimeExecutor,
@Nullable final TurboModuleManagerDelegate delegate,
CallInvokerHolder jsCallInvokerHolder,
NativeMethodCallInvokerHolder nativeMethodCallInvokerHolder) {
mDelegate = delegate;
mHybridData =
initHybrid(
runtimeExecutor,
(CallInvokerHolderImpl) jsCallInvokerHolder,
(NativeMethodCallInvokerHolderImpl) nativeMethodCallInvokerHolder,
delegate);
installJSIBindings(shouldEnableLegacyModuleInterop());
mEagerInitModuleNames =
delegate == null ? Collections.emptyList() : delegate.getEagerInitModuleNames();
ModuleProvider nullProvider = moduleName -> null;
mTurboModuleProvider =
delegate == null
? nullProvider
: moduleName -> (NativeModule) delegate.getModule(moduleName);
mLegacyModuleProvider =
delegate == null || !shouldEnableLegacyModuleInterop()
? nullProvider
: moduleName -> {
NativeModule nativeModule = delegate.getLegacyModule(moduleName);
if (nativeModule != null) {
// TurboModuleManagerDelegate.getLegacyModule must never return a TurboModule
Assertions.assertCondition(
!(nativeModule instanceof TurboModule),
"NativeModule \"" + moduleName + "\" is a TurboModule");
return nativeModule;
}
return null;
};
}
private boolean isTurboModule(String moduleName) {
return mDelegate != null && mDelegate.unstable_isModuleRegistered(moduleName);
}
private boolean isLegacyModule(String moduleName) {
return mDelegate != null && mDelegate.unstable_isLegacyModuleRegistered(moduleName);
}
private boolean shouldEnableLegacyModuleInterop() {
return mDelegate != null && mDelegate.unstable_shouldEnableLegacyModuleInterop();
}
@Override
public List<String> getEagerInitModuleNames() {
return mEagerInitModuleNames;
}
// used from TurboModuleManager.cpp
@SuppressWarnings("unused")
@DoNotStrip
private static List<TurboModuleInteropUtils.MethodDescriptor> getMethodDescriptorsFromModule(
NativeModule module) {
return TurboModuleInteropUtils.getMethodDescriptorsFromModule(module);
}
// used from TurboModuleManager.cpp
@SuppressWarnings("unused")
@DoNotStrip
@Nullable
private NativeModule getLegacyJavaModule(String moduleName) {
/*
* This API is invoked from global.nativeModuleProxy.
* Only call getModule if the native module is a legacy module.
*/
if (!isLegacyModule(moduleName)) {
return null;
}
final NativeModule module = getModule(moduleName);
return !(module instanceof CxxModuleWrapper) && !(module instanceof TurboModule)
? module
: null;
}
// used from TurboModuleManager.cpp
@SuppressWarnings("unused")
@DoNotStrip
@Nullable
private CxxModuleWrapper getLegacyCxxModule(String moduleName) {
/*
* This API is invoked from global.nativeModuleProxy.
* Only call getModule if the native module is a legacy module.
*/
if (!isLegacyModule(moduleName)) {
return null;
}
final NativeModule module = getModule(moduleName);
return module instanceof CxxModuleWrapper && !(module instanceof TurboModule)
? (CxxModuleWrapper) module
: null;
}
// used from TurboModuleManager.cpp
@SuppressWarnings("unused")
@DoNotStrip
@Nullable
private CxxModuleWrapper getTurboLegacyCxxModule(String moduleName) {
/*
* This API is invoked from global.__turboModuleProxy.
* Only call getModule if the native module is a turbo module.
*/
if (!isTurboModule(moduleName)) {
return null;
}
final NativeModule module = getModule(moduleName);
return module instanceof CxxModuleWrapper && module instanceof TurboModule
? (CxxModuleWrapper) module
: null;
}
// used from TurboModuleManager.cpp
@SuppressWarnings("unused")
@DoNotStrip
@Nullable
private TurboModule getTurboJavaModule(String moduleName) {
/*
* This API is invoked from global.__turboModuleProxy.
* Only call getModule if the native module is a turbo module.
*/
if (!isTurboModule(moduleName)) {
return null;
}
final NativeModule module = getModule(moduleName);
return !(module instanceof CxxModuleWrapper) && module instanceof TurboModule
? (TurboModule) module
: null;
}
/**
* Return the NativeModule instance that corresponds to the provided moduleName.
*
* <p>This method: - Creates and initializes the module if it doesn't already exist. - Returns
* null after TurboModuleManager has been torn down.
*/
@Nullable
public NativeModule getModule(String moduleName) {
ModuleHolder moduleHolder;
synchronized (mModuleCleanupLock) {
if (mModuleCleanupStarted) {
/*
* Always return null after cleanup has started, so that getNativeModule(moduleName) returns null.
*/
FLog.e(
TAG,
"getModule(): Tried to get module \"%s\", but TurboModuleManager was tearing down"
+ " (legacy: %b, turbo: %b)",
moduleName,
isLegacyModule(moduleName),
isTurboModule(moduleName));
return null;
}
/*
* TODO(T64619790): Should we populate mModuleHolders ahead of time, to avoid having
* * to control concurrent access to it?
*/
if (!mModuleHolders.containsKey(moduleName)) {
mModuleHolders.put(moduleName, new ModuleHolder());
}
moduleHolder = mModuleHolders.get(moduleName);
}
if (moduleHolder == null) {
FLog.e(TAG, "getModule(): Tried to get module \"%s\", but moduleHolder was null", moduleName);
return null;
}
TurboModulePerfLogger.moduleCreateStart(moduleName, moduleHolder.getModuleId());
NativeModule module = getOrCreateModule(moduleName, moduleHolder, true);
if (module != null) {
TurboModulePerfLogger.moduleCreateEnd(moduleName, moduleHolder.getModuleId());
} else {
TurboModulePerfLogger.moduleCreateFail(moduleName, moduleHolder.getModuleId());
}
return module;
}
/**
* Given a ModuleHolder, and the TurboModule's moduleName, return the TurboModule instance.
*
* <p>Use the ModuleHolder to ensure that if n threads race to create TurboModule x, then only the
* first thread creates x. All n - 1 other threads wait until the x is created and initialized.
*/
@Nullable
private NativeModule getOrCreateModule(
String moduleName, ModuleHolder moduleHolder, boolean shouldPerfLog) {
boolean shouldCreateModule = false;
synchronized (moduleHolder) {
if (moduleHolder.isDoneCreatingModule()) {
if (shouldPerfLog) {
TurboModulePerfLogger.moduleCreateCacheHit(moduleName, moduleHolder.getModuleId());
}
return moduleHolder.getModule();
}
if (!moduleHolder.isCreatingModule()) {
// Only one thread gets here
shouldCreateModule = true;
moduleHolder.startCreatingModule();
}
}
if (shouldCreateModule) {
TurboModulePerfLogger.moduleCreateConstructStart(moduleName, moduleHolder.getModuleId());
NativeModule nativeModule = mTurboModuleProvider.getModule(moduleName);
if (nativeModule == null) {
nativeModule = mLegacyModuleProvider.getModule(moduleName);
}
TurboModulePerfLogger.moduleCreateConstructEnd(moduleName, moduleHolder.getModuleId());
TurboModulePerfLogger.moduleCreateSetUpStart(moduleName, moduleHolder.getModuleId());
if (nativeModule != null) {
synchronized (moduleHolder) {
moduleHolder.setModule(nativeModule);
}
/*
* TurboModuleManager is initialized after ReactApplicationContext has been set up.
* NativeModules should be initialized after ReactApplicationContext has been set up.
* Therefore, we should initialize on the TurboModule now.
*/
nativeModule.initialize();
} else {
FLog.e(
TAG,
"getOrCreateModule(): Unable to create module \"%s\" (legacy: %b, turbo: %b)",
moduleName,
isLegacyModule(moduleName),
isTurboModule(moduleName));
}
TurboModulePerfLogger.moduleCreateSetUpEnd(moduleName, moduleHolder.getModuleId());
synchronized (moduleHolder) {
moduleHolder.endCreatingModule();
moduleHolder.notifyAll();
}
return nativeModule;
}
synchronized (moduleHolder) {
boolean wasInterrupted = false;
while (moduleHolder.isCreatingModule()) {
try {
// Wait until TurboModule is created and initialized
moduleHolder.wait();
} catch (InterruptedException e) {
wasInterrupted = true;
}
}
if (wasInterrupted) {
/*
* TurboModules should ideally be quick to create and initialize. Therefore,
* we wait until the TurboModule is done initializing before re-interrupting the
* current thread.
*/
Thread.currentThread().interrupt();
}
return moduleHolder.getModule();
}
}
/** Which NativeModules have been created? */
public Collection<NativeModule> getModules() {
final List<ModuleHolder> moduleHolders = new ArrayList<>();
synchronized (mModuleCleanupLock) {
moduleHolders.addAll(mModuleHolders.values());
}
final List<NativeModule> modules = new ArrayList<>();
for (final ModuleHolder moduleHolder : moduleHolders) {
synchronized (moduleHolder) {
// No need to wait for the TurboModule to finish being created and initialized
if (moduleHolder.getModule() != null) {
modules.add(moduleHolder.getModule());
}
}
}
return modules;
}
public boolean hasModule(String moduleName) {
ModuleHolder moduleHolder;
synchronized (mModuleCleanupLock) {
moduleHolder = mModuleHolders.get(moduleName);
}
if (moduleHolder != null) {
synchronized (moduleHolder) {
if (moduleHolder.getModule() != null) {
return true;
}
}
}
return false;
}
private native HybridData initHybrid(
RuntimeExecutor runtimeExecutor,
CallInvokerHolderImpl jsCallInvokerHolder,
NativeMethodCallInvokerHolderImpl nativeMethodCallInvoker,
@Nullable TurboModuleManagerDelegate tmmDelegate);
private native void installJSIBindings(boolean shouldCreateLegacyModules);
@Override
public void invalidate() {
/*
* Halt the production of new TurboModules.
*
* <p>After this point, mModuleHolders will not be accessed by TurboModuleManager.
* Therefore, it won't be modified.
*
* <p>The ModuleHolders in mModuleHolders, however, can still be populated with newly
* created TurboModules.
*/
synchronized (mModuleCleanupLock) {
mModuleCleanupStarted = true;
}
for (final Map.Entry<String, ModuleHolder> moduleHolderEntry : mModuleHolders.entrySet()) {
final String moduleName = moduleHolderEntry.getKey();
final ModuleHolder moduleHolder = moduleHolderEntry.getValue();
/**
* ReactNative could start tearing down before this particular TurboModule has been fully
* initialized. In this case, we should wait for initialization to complete, before destroying
* the TurboModule.
*/
final NativeModule nativeModule = getOrCreateModule(moduleName, moduleHolder, false);
if (nativeModule != null) {
nativeModule.invalidate();
}
}
mModuleHolders.clear();
// Delete the native part of this hybrid class.
mHybridData.resetNative();
}
private static class ModuleHolder {
private volatile @Nullable NativeModule mModule = null;
private volatile boolean mIsTryingToCreate = false;
private volatile boolean mIsDoneCreatingModule = false;
private static volatile int sHolderCount = 0;
private volatile int mModuleId;
public ModuleHolder() {
mModuleId = sHolderCount;
sHolderCount += 1;
}
int getModuleId() {
return mModuleId;
}
void setModule(NativeModule module) {
mModule = module;
}
@Nullable
NativeModule getModule() {
return mModule;
}
void startCreatingModule() {
mIsTryingToCreate = true;
}
void endCreatingModule() {
mIsTryingToCreate = false;
mIsDoneCreatingModule = true;
}
boolean isDoneCreatingModule() {
return mIsDoneCreatingModule;
}
boolean isCreatingModule() {
return mIsTryingToCreate;
}
}
private interface ModuleProvider {
@Nullable
NativeModule getModule(String name);
}
}
@@ -0,0 +1,405 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.internal.turbomodule.core
import androidx.annotation.GuardedBy
import com.facebook.common.logging.FLog
import com.facebook.jni.HybridData
import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.bridge.CxxModuleWrapper
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.RuntimeExecutor
import com.facebook.react.common.annotations.FrameworkAPI
import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
import com.facebook.react.turbomodule.core.NativeMethodCallInvokerHolderImpl
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder
import com.facebook.react.turbomodule.core.interfaces.TurboModule
import com.facebook.soloader.SoLoader
import kotlin.concurrent.Volatile
/**
* This is the main class and entry point for TurboModules. Note that this is a hybrid class, and
* has a C++ counterpart This class installs the JSI bindings. It also implements the method to get
* a Java module, that the C++ counterpart calls.
*/
@OptIn(FrameworkAPI::class)
public class TurboModuleManager(
runtimeExecutor: RuntimeExecutor,
private val delegate: TurboModuleManagerDelegate?,
jsCallInvokerHolder: CallInvokerHolder,
nativeMethodCallInvokerHolder: NativeMethodCallInvokerHolder
) : TurboModuleRegistry {
public override val eagerInitModuleNames: List<String>
private val turboModuleProvider: ModuleProvider
private val legacyModuleProvider: ModuleProvider
// Prevents the creation of new TurboModules once cleanup as been initiated.
private val moduleCleanupLock = Object()
@GuardedBy("moduleCleanupLock") private var moduleCleanupStarted = false
// List of TurboModules that have been, or are currently being, instantiated
@GuardedBy("moduleCleanupLock") private val moduleHolders = mutableMapOf<String, ModuleHolder>()
@Suppress("NoHungarianNotation")
@DoNotStrip
private val mHybridData: HybridData =
initHybrid(
runtimeExecutor,
jsCallInvokerHolder as CallInvokerHolderImpl,
nativeMethodCallInvokerHolder as NativeMethodCallInvokerHolderImpl,
delegate)
init {
installJSIBindings(shouldEnableLegacyModuleInterop())
eagerInitModuleNames = delegate?.eagerInitModuleNames ?: emptyList()
val nullProvider: ModuleProvider = ModuleProvider { _: String -> null }
turboModuleProvider =
if (delegate == null) nullProvider
else
ModuleProvider { moduleName: String -> delegate.getModule(moduleName) as NativeModule? }
legacyModuleProvider =
if (delegate == null || !shouldEnableLegacyModuleInterop()) nullProvider
else
ModuleProvider { moduleName: String ->
val nativeModule = delegate.getLegacyModule(moduleName)
if (nativeModule != null) {
// TurboModuleManagerDelegate.getLegacyModule must never return a TurboModule
require(nativeModule !is TurboModule) {
"NativeModule \"$moduleName\" is a TurboModule"
}
return@ModuleProvider nativeModule
}
null
}
}
private fun isTurboModule(moduleName: String): Boolean =
delegate?.unstable_isModuleRegistered(moduleName) == true
private fun isLegacyModule(moduleName: String): Boolean =
delegate?.unstable_isLegacyModuleRegistered(moduleName) == true
private fun shouldEnableLegacyModuleInterop(): Boolean =
delegate?.unstable_shouldEnableLegacyModuleInterop() == true
// used from TurboModuleManager.cpp
@Suppress("unused")
@DoNotStrip
private fun getLegacyJavaModule(moduleName: String): NativeModule? {
/*
* This API is invoked from global.nativeModuleProxy.
* Only call getModule if the native module is a legacy module.
*/
if (!isLegacyModule(moduleName)) {
return null
}
val module = getModule(moduleName)
return if (module !is CxxModuleWrapper && module !is TurboModule) module else null
}
// used from TurboModuleManager.cpp
@Suppress("unused")
@DoNotStrip
private fun getLegacyCxxModule(moduleName: String): CxxModuleWrapper? {
/*
* This API is invoked from global.nativeModuleProxy.
* Only call getModule if the native module is a legacy module.
*/
if (!isLegacyModule(moduleName)) {
return null
}
val module = getModule(moduleName)
return if (module is CxxModuleWrapper && module !is TurboModule) module else null
}
// used from TurboModuleManager.cpp
@Suppress("unused")
@DoNotStrip
private fun getTurboLegacyCxxModule(moduleName: String): CxxModuleWrapper? {
/*
* This API is invoked from global.__turboModuleProxy.
* Only call getModule if the native module is a turbo module.
*/
if (!isTurboModule(moduleName)) {
return null
}
val module = getModule(moduleName)
return if (module is CxxModuleWrapper && module is TurboModule) module else null
}
// used from TurboModuleManager.cpp
@Suppress("unused")
@DoNotStrip
private fun getTurboJavaModule(moduleName: String): TurboModule? {
/*
* This API is invoked from global.__turboModuleProxy.
* Only call getModule if the native module is a turbo module.
*/
if (!isTurboModule(moduleName)) {
return null
}
val module = getModule(moduleName)
return if (module !is CxxModuleWrapper && module is TurboModule) module else null
}
/**
* Return the NativeModule instance that corresponds to the provided moduleName.
*
* This method: - Creates and initializes the module if it doesn't already exist. - Returns null
* after TurboModuleManager has been torn down.
*/
override fun getModule(moduleName: String): NativeModule? {
val moduleHolder: ModuleHolder?
synchronized(moduleCleanupLock) {
if (moduleCleanupStarted) {
/*
* Always return null after cleanup has started, so that getNativeModule(moduleName) returns null.
*/
FLog.e(
TAG,
"getModule(): Tried to get module \"%s\", but TurboModuleManager was tearing down (legacy: %b, turbo: %b)",
moduleName,
isLegacyModule(moduleName),
isTurboModule(moduleName))
return null
}
/*
* TODO(T64619790): Should we populate moduleHolders ahead of time, to avoid having
* * to control concurrent access to it?
*/
if (!moduleHolders.containsKey(moduleName)) {
moduleHolders[moduleName] = ModuleHolder()
}
moduleHolder = moduleHolders[moduleName]
}
if (moduleHolder == null) {
FLog.e(TAG, "getModule(): Tried to get module \"%s\", but moduleHolder was null", moduleName)
return null
}
TurboModulePerfLogger.moduleCreateStart(moduleName, moduleHolder.moduleId)
val module = getOrCreateModule(moduleName, moduleHolder, true)
if (module != null) {
TurboModulePerfLogger.moduleCreateEnd(moduleName, moduleHolder.moduleId)
} else {
TurboModulePerfLogger.moduleCreateFail(moduleName, moduleHolder.moduleId)
}
return module
}
/**
* Given a ModuleHolder, and the TurboModule's moduleName, return the TurboModule instance.
*
* Use the ModuleHolder to ensure that if n threads race to create TurboModule x, then only the
* first thread creates x. All n - 1 other threads wait until the x is created and initialized.
*/
private fun getOrCreateModule(
moduleName: String,
moduleHolder: ModuleHolder,
shouldPerfLog: Boolean
): NativeModule? {
var shouldCreateModule = false
synchronized(moduleHolder) {
if (moduleHolder.isDoneCreatingModule) {
if (shouldPerfLog) {
TurboModulePerfLogger.moduleCreateCacheHit(moduleName, moduleHolder.moduleId)
}
return moduleHolder.module
}
if (!moduleHolder.isCreatingModule) {
// Only one thread gets here
shouldCreateModule = true
moduleHolder.startCreatingModule()
}
}
if (shouldCreateModule) {
TurboModulePerfLogger.moduleCreateConstructStart(moduleName, moduleHolder.moduleId)
var nativeModule = turboModuleProvider.getModule(moduleName)
if (nativeModule == null) {
nativeModule = legacyModuleProvider.getModule(moduleName)
}
TurboModulePerfLogger.moduleCreateConstructEnd(moduleName, moduleHolder.moduleId)
TurboModulePerfLogger.moduleCreateSetUpStart(moduleName, moduleHolder.moduleId)
if (nativeModule != null) {
synchronized(moduleHolder) { moduleHolder.module = nativeModule }
/*
* TurboModuleManager is initialized after ReactApplicationContext has been set up.
* NativeModules should be initialized after ReactApplicationContext has been set up.
* Therefore, we should initialize on the TurboModule now.
*/
nativeModule.initialize()
} else {
FLog.e(
TAG,
"getOrCreateModule(): Unable to create module \"%s\" (legacy: %b, turbo: %b)",
moduleName,
isLegacyModule(moduleName),
isTurboModule(moduleName))
}
TurboModulePerfLogger.moduleCreateSetUpEnd(moduleName, moduleHolder.moduleId)
synchronized(moduleHolder) {
moduleHolder.endCreatingModule()
(moduleHolder as Object).notifyAll()
}
return nativeModule
}
synchronized(moduleHolder) {
var wasInterrupted = false
while (moduleHolder.isCreatingModule) {
try {
// Wait until TurboModule is created and initialized
(moduleHolder as Object).wait()
} catch (e: InterruptedException) {
wasInterrupted = true
}
}
if (wasInterrupted) {
/*
* TurboModules should ideally be quick to create and initialize. Therefore,
* we wait until the TurboModule is done initializing before re-interrupting the
* current thread.
*/
Thread.currentThread().interrupt()
}
return moduleHolder.module
}
}
public override val modules: Collection<NativeModule>
get() {
val holders = synchronized(moduleCleanupLock) { this.moduleHolders.values.toList() }
val moduleList = holders.mapNotNull { holder -> synchronized(holders) { holder.module } }
return moduleList
}
override fun hasModule(moduleName: String): Boolean {
val moduleHolder = synchronized(moduleCleanupLock) { moduleHolders[moduleName] ?: return false }
return synchronized(moduleHolder) { moduleHolder.module != null }
}
private external fun initHybrid(
runtimeExecutor: RuntimeExecutor,
jsCallInvokerHolder: CallInvokerHolderImpl,
nativeMethodCallInvoker: NativeMethodCallInvokerHolderImpl,
tmmDelegate: TurboModuleManagerDelegate?
): HybridData
private external fun installJSIBindings(shouldCreateLegacyModules: Boolean)
override fun invalidate() {
/*
* Halt the production of new TurboModules.
*
* <p>After this point, mModuleHolders will not be accessed by TurboModuleManager.
* Therefore, it won't be modified.
*
* <p>The ModuleHolders in mModuleHolders, however, can still be populated with newly
* created TurboModules.
*/
synchronized(moduleCleanupLock) { moduleCleanupStarted = true }
for ((moduleName, moduleHolder) in moduleHolders) {
/**
* ReactNative could start tearing down before this particular TurboModule has been fully
* initialized. In this case, we should wait for initialization to complete, before destroying
* the TurboModule.
*/
val nativeModule = getOrCreateModule(moduleName, moduleHolder, false)
nativeModule?.invalidate()
}
moduleHolders.clear()
// Delete the native part of this hybrid class.
mHybridData.resetNative()
}
private class ModuleHolder {
@Volatile var module: NativeModule? = null
@Volatile
var isCreatingModule: Boolean = false
private set
@Volatile
var isDoneCreatingModule: Boolean = false
private set
@Volatile
var moduleId: Int
private set
init {
moduleId = holderCount
holderCount += 1
}
fun startCreatingModule() {
isCreatingModule = true
}
fun endCreatingModule() {
isCreatingModule = false
isDoneCreatingModule = true
}
companion object {
@Volatile private var holderCount = 0
}
}
private fun interface ModuleProvider {
fun getModule(name: String): NativeModule?
}
public companion object {
private const val TAG = "TurboModuleManager"
init {
SoLoader.loadLibrary("turbomodulejsijni")
}
// used from TurboModuleManager.cpp
@JvmStatic
@Suppress("unused")
@DoNotStrip
private fun getMethodDescriptorsFromModule(
module: NativeModule
): List<TurboModuleInteropUtils.MethodDescriptor> =
TurboModuleInteropUtils.getMethodDescriptorsFromModule(module)
}
}