Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
9 changes: 7 additions & 2 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -921,9 +921,14 @@ public abstract interface class com/facebook/react/bridge/JavaScriptModule {
}

public final class com/facebook/react/bridge/JavaScriptModuleRegistry {
public static final field Companion Lcom/facebook/react/bridge/JavaScriptModuleRegistry$Companion;
public fun <init> ()V
public static fun getJSModuleName (Ljava/lang/Class;)Ljava/lang/String;
public fun getJavaScriptModule (Lcom/facebook/react/bridge/CatalystInstance;Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule;
public static final fun getJSModuleName (Ljava/lang/Class;)Ljava/lang/String;
public final fun getJavaScriptModule (Lcom/facebook/react/bridge/CatalystInstance;Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule;
}

public final class com/facebook/react/bridge/JavaScriptModuleRegistry$Companion {
public final fun getJSModuleName (Ljava/lang/Class;)Ljava/lang/String;
}

public final class com/facebook/react/bridge/JsonWriterHelper {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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.bridge

import com.facebook.react.common.build.ReactBuildConfig
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

/**
* Class responsible for holding all the [JavaScriptModule]s. Uses Java proxy objects to dispatch
* method calls on JavaScriptModules to the bridge using the corresponding module and method ids so
* the proper function is executed in JavaScript.
*/
public class JavaScriptModuleRegistry {

private val moduleInstances: MutableMap<Class<out JavaScriptModule>, JavaScriptModule> = HashMap()

@Synchronized
public fun <T : JavaScriptModule> getJavaScriptModule(
@Suppress("DEPRECATION") instance: CatalystInstance,
moduleInterface: Class<T>
): T {
val module = moduleInstances[moduleInterface]
if (module != null) {
@Suppress("UNCHECKED_CAST")
return module as T
}

val proxy =
Proxy.newProxyInstance(
moduleInterface.classLoader,
arrayOf<Class<*>>(moduleInterface),
JavaScriptModuleInvocationHandler(instance, moduleInterface)) as JavaScriptModule

moduleInstances[moduleInterface] = proxy
@Suppress("UNCHECKED_CAST")
return proxy as T
}

private class JavaScriptModuleInvocationHandler(
@Suppress("DEPRECATION") private val catalystInstance: CatalystInstance,
private val moduleInterface: Class<out JavaScriptModule>
) : InvocationHandler {

private var name: String? = null

init {
if (ReactBuildConfig.DEBUG) {
val methodNames = mutableSetOf<String>()
for (method in moduleInterface.declaredMethods) {
if (!methodNames.add(method.name)) {
throw AssertionError(
"Method overloading is unsupported: ${moduleInterface.name}#${method.name}")
}
}
}
}

private fun getJSModuleName(): String {
// Getting the class name every call is expensive, so cache it
return name ?: getJSModuleName(moduleInterface).also { name = it }
}

public override fun invoke(proxy: Any, method: Method, args: Array<Any?>?): Any? {
val jsArgs = if (args != null) Arguments.fromJavaArgs(args) else WritableNativeArray()
catalystInstance.callFunction(getJSModuleName(), method.name, jsArgs)
return null
}
}

public companion object {
/**
* With proguard obfuscation turned on, proguard apparently (poorly) emulates inner classes or
* something because Class#getSimpleName() no longer strips the outer class name. We manually
* strip it here if necessary.
*/
@JvmStatic
public fun getJSModuleName(jsModuleInterface: Class<out JavaScriptModule>): String {
var name = jsModuleInterface.simpleName
val dollarSignIndex = name.lastIndexOf('$')
if (dollarSignIndex != -1) {
name = name.substring(dollarSignIndex + 1)
}
return name
}
}
}
Loading