Skip to content

Commit 1908b3d

Browse files
fabriziocuccifacebook-github-bot
authored andcommitted
Kotlinify JavaScriptModuleRegistry (#51164)
Summary: Pull Request resolved: #51164 As per title. Changelog: [Internal] Reviewed By: javache Differential Revision: D74326679 fbshipit-source-id: ecd15fda9ea8686b65171c462e7e82dc9609377b
1 parent 84253c4 commit 1908b3d

File tree

3 files changed

+100
-104
lines changed

3 files changed

+100
-104
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -921,9 +921,14 @@ public abstract interface class com/facebook/react/bridge/JavaScriptModule {
921921
}
922922

923923
public final class com/facebook/react/bridge/JavaScriptModuleRegistry {
924+
public static final field Companion Lcom/facebook/react/bridge/JavaScriptModuleRegistry$Companion;
924925
public fun <init> ()V
925-
public static fun getJSModuleName (Ljava/lang/Class;)Ljava/lang/String;
926-
public fun getJavaScriptModule (Lcom/facebook/react/bridge/CatalystInstance;Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule;
926+
public static final fun getJSModuleName (Ljava/lang/Class;)Ljava/lang/String;
927+
public final fun getJavaScriptModule (Lcom/facebook/react/bridge/CatalystInstance;Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule;
928+
}
929+
930+
public final class com/facebook/react/bridge/JavaScriptModuleRegistry$Companion {
931+
public final fun getJSModuleName (Ljava/lang/Class;)Ljava/lang/String;
927932
}
928933

929934
public final class com/facebook/react/bridge/JsonWriterHelper {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaScriptModuleRegistry.java

Lines changed: 0 additions & 102 deletions
This file was deleted.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.bridge
9+
10+
import com.facebook.react.common.build.ReactBuildConfig
11+
import java.lang.reflect.InvocationHandler
12+
import java.lang.reflect.Method
13+
import java.lang.reflect.Proxy
14+
15+
/**
16+
* Class responsible for holding all the [JavaScriptModule]s. Uses Java proxy objects to dispatch
17+
* method calls on JavaScriptModules to the bridge using the corresponding module and method ids so
18+
* the proper function is executed in JavaScript.
19+
*/
20+
public class JavaScriptModuleRegistry {
21+
22+
private val moduleInstances: MutableMap<Class<out JavaScriptModule>, JavaScriptModule> = HashMap()
23+
24+
@Synchronized
25+
public fun <T : JavaScriptModule> getJavaScriptModule(
26+
@Suppress("DEPRECATION") instance: CatalystInstance,
27+
moduleInterface: Class<T>
28+
): T {
29+
val module = moduleInstances[moduleInterface]
30+
if (module != null) {
31+
@Suppress("UNCHECKED_CAST")
32+
return module as T
33+
}
34+
35+
val proxy =
36+
Proxy.newProxyInstance(
37+
moduleInterface.classLoader,
38+
arrayOf<Class<*>>(moduleInterface),
39+
JavaScriptModuleInvocationHandler(instance, moduleInterface)) as JavaScriptModule
40+
41+
moduleInstances[moduleInterface] = proxy
42+
@Suppress("UNCHECKED_CAST")
43+
return proxy as T
44+
}
45+
46+
private class JavaScriptModuleInvocationHandler(
47+
@Suppress("DEPRECATION") private val catalystInstance: CatalystInstance,
48+
private val moduleInterface: Class<out JavaScriptModule>
49+
) : InvocationHandler {
50+
51+
private var name: String? = null
52+
53+
init {
54+
if (ReactBuildConfig.DEBUG) {
55+
val methodNames = mutableSetOf<String>()
56+
for (method in moduleInterface.declaredMethods) {
57+
if (!methodNames.add(method.name)) {
58+
throw AssertionError(
59+
"Method overloading is unsupported: ${moduleInterface.name}#${method.name}")
60+
}
61+
}
62+
}
63+
}
64+
65+
private fun getJSModuleName(): String {
66+
// Getting the class name every call is expensive, so cache it
67+
return name ?: getJSModuleName(moduleInterface).also { name = it }
68+
}
69+
70+
public override fun invoke(proxy: Any, method: Method, args: Array<Any?>?): Any? {
71+
val jsArgs = if (args != null) Arguments.fromJavaArgs(args) else WritableNativeArray()
72+
catalystInstance.callFunction(getJSModuleName(), method.name, jsArgs)
73+
return null
74+
}
75+
}
76+
77+
public companion object {
78+
/**
79+
* With proguard obfuscation turned on, proguard apparently (poorly) emulates inner classes or
80+
* something because Class#getSimpleName() no longer strips the outer class name. We manually
81+
* strip it here if necessary.
82+
*/
83+
@JvmStatic
84+
public fun getJSModuleName(jsModuleInterface: Class<out JavaScriptModule>): String {
85+
var name = jsModuleInterface.simpleName
86+
val dollarSignIndex = name.lastIndexOf('$')
87+
if (dollarSignIndex != -1) {
88+
name = name.substring(dollarSignIndex + 1)
89+
}
90+
return name
91+
}
92+
}
93+
}

0 commit comments

Comments
 (0)