mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Do not attempt to call Class.forName in OSS (#43816)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43816 We should not attempt to load generated classes by the Annotation processor in OSS because we simply don't run it, so those classes will fail to load. I'm short-circuiting the logic here. This is sustainability work as we got a report for this in OSS a while ago and I never got the time to work on it. Changelog: [Internal] [Changed] - Do not attempt to call Class.forName in OSS Reviewed By: rshest Differential Revision: D55693479 fbshipit-source-id: 3ec84e2c7940011b48f354058b5099b46065166d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8c62df6396
commit
26cc8cddf9
@@ -1666,6 +1666,12 @@ public class com/facebook/react/bridge/queue/ReactQueueConfigurationSpec$Builder
|
||||
public fun setNativeModulesQueueThreadSpec (Lcom/facebook/react/bridge/queue/MessageQueueThreadSpec;)Lcom/facebook/react/bridge/queue/ReactQueueConfigurationSpec$Builder;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/common/ClassFinder {
|
||||
public static final field INSTANCE Lcom/facebook/react/common/ClassFinder;
|
||||
public static final fun canLoadClassesFromAnnotationProcessors ()Z
|
||||
public static final fun findClass (Ljava/lang/String;)Ljava/lang/Class;
|
||||
}
|
||||
|
||||
public class com/facebook/react/common/ClearableSynchronizedPool : androidx/core/util/Pools$Pool {
|
||||
public fun <init> (I)V
|
||||
public fun acquire ()Ljava/lang/Object;
|
||||
|
||||
+43
-35
@@ -16,6 +16,7 @@ import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactMarker;
|
||||
import com.facebook.react.common.ClassFinder;
|
||||
import com.facebook.react.devsupport.LogBoxModule;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.module.annotations.ReactModuleList;
|
||||
@@ -76,48 +77,21 @@ class CoreModulesPackage extends TurboReactPackage implements ReactPackageLogger
|
||||
|
||||
/**
|
||||
* This method is overridden, since OSS does not run the annotation processor to generate {@link
|
||||
* CoreModulesPackage$$ReactModuleInfoProvider} class. Here we check if it exists. If it does not
|
||||
* exist, we generate one manually in {@link
|
||||
* CoreModulesPackage#getReactModuleInfoByInitialization()} and return that instead.
|
||||
* CoreModulesPackage$$ReactModuleInfoProvider} class. Here we check if it exists with the method
|
||||
* {@link canLoadClassesFromAnnotationProcessors}. If it does not exist, we generate one manually
|
||||
* in {@link CoreModulesPackage#getReactModuleInfoByInitialization()} and return that instead.
|
||||
*/
|
||||
@Override
|
||||
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
||||
if (!ClassFinder.canLoadClassesFromAnnotationProcessors()) {
|
||||
return fallbackForMissingClass();
|
||||
}
|
||||
try {
|
||||
Class<?> reactModuleInfoProviderClass =
|
||||
Class.forName("com.facebook.react.CoreModulesPackage$$ReactModuleInfoProvider");
|
||||
ClassFinder.findClass("com.facebook.react.CoreModulesPackage$$ReactModuleInfoProvider");
|
||||
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// In OSS case, the annotation processor does not run. We fall back on creating this byhand
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
AndroidInfoModule.class,
|
||||
DeviceEventManagerModule.class,
|
||||
DeviceInfoModule.class,
|
||||
DevSettingsModule.class,
|
||||
ExceptionsManagerModule.class,
|
||||
LogBoxModule.class,
|
||||
HeadlessJsTaskSupportModule.class,
|
||||
SourceCodeModule.class,
|
||||
TimingModule.class,
|
||||
UIManagerModule.class,
|
||||
};
|
||||
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
|
||||
return () -> reactModuleInfoMap;
|
||||
return fallbackForMissingClass();
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(
|
||||
"No ReactModuleInfoProvider for CoreModulesPackage$$ReactModuleInfoProvider", e);
|
||||
@@ -127,6 +101,40 @@ class CoreModulesPackage extends TurboReactPackage implements ReactPackageLogger
|
||||
}
|
||||
}
|
||||
|
||||
private ReactModuleInfoProvider fallbackForMissingClass() {
|
||||
// In OSS case, the annotation processor does not run. We fall back on creating this byhand
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
AndroidInfoModule.class,
|
||||
DeviceEventManagerModule.class,
|
||||
DeviceInfoModule.class,
|
||||
DevSettingsModule.class,
|
||||
ExceptionsManagerModule.class,
|
||||
LogBoxModule.class,
|
||||
HeadlessJsTaskSupportModule.class,
|
||||
SourceCodeModule.class,
|
||||
TimingModule.class,
|
||||
UIManagerModule.class,
|
||||
};
|
||||
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
|
||||
return () -> reactModuleInfoMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
||||
switch (name) {
|
||||
|
||||
+28
-20
@@ -11,6 +11,7 @@ import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ModuleSpec;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.common.ClassFinder;
|
||||
import com.facebook.react.devsupport.JSCHeapCapture;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.module.annotations.ReactModuleList;
|
||||
@@ -53,30 +54,15 @@ public class DebugCorePackage extends TurboReactPackage implements ViewManagerOn
|
||||
|
||||
@Override
|
||||
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
||||
if (!ClassFinder.canLoadClassesFromAnnotationProcessors()) {
|
||||
return fallbackForMissingClass();
|
||||
}
|
||||
try {
|
||||
Class<?> reactModuleInfoProviderClass =
|
||||
Class.forName("com.facebook.react.DebugCorePackage$$ReactModuleInfoProvider");
|
||||
ClassFinder.findClass("com.facebook.react.DebugCorePackage$$ReactModuleInfoProvider");
|
||||
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// In OSS case, the annotation processor does not run. We fall back on creating this by hand
|
||||
Class<? extends NativeModule>[] moduleList = new Class[] {JSCHeapCapture.class};
|
||||
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
|
||||
return () -> reactModuleInfoMap;
|
||||
return fallbackForMissingClass();
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(
|
||||
"No ReactModuleInfoProvider for DebugCorePackage$$ReactModuleInfoProvider", e);
|
||||
@@ -86,6 +72,28 @@ public class DebugCorePackage extends TurboReactPackage implements ViewManagerOn
|
||||
}
|
||||
}
|
||||
|
||||
private ReactModuleInfoProvider fallbackForMissingClass() {
|
||||
// In OSS case, the annotation processor does not run. We fall back on creating this by hand
|
||||
Class<? extends NativeModule>[] moduleList = new Class[] {JSCHeapCapture.class};
|
||||
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
|
||||
return () -> reactModuleInfoMap;
|
||||
}
|
||||
|
||||
private static void appendMap(
|
||||
Map<String, ModuleSpec> map, String name, Provider<? extends NativeModule> provider) {
|
||||
map.put(name, ModuleSpec.viewManagerSpec(provider));
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.common
|
||||
|
||||
import com.facebook.react.BuildConfig
|
||||
import kotlin.jvm.Throws
|
||||
|
||||
public object ClassFinder {
|
||||
|
||||
/**
|
||||
* We don't run the ModuleInfoProvider Annotation Processor in OSS, so there is no need to attempt
|
||||
* to call Class.forName() as we know for sure that those classes won't be there.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun canLoadClassesFromAnnotationProcessors(): Boolean = BuildConfig.IS_INTERNAL_BUILD
|
||||
|
||||
@JvmStatic
|
||||
@Throws(ClassNotFoundException::class)
|
||||
public fun findClass(className: String): Class<*>? {
|
||||
if (canLoadClassesFromAnnotationProcessors().not()) {
|
||||
return null
|
||||
}
|
||||
return Class.forName(className)
|
||||
}
|
||||
}
|
||||
+39
-29
@@ -8,10 +8,12 @@
|
||||
package com.facebook.react.runtime;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import com.facebook.react.TurboReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.common.ClassFinder;
|
||||
import com.facebook.react.devsupport.LogBoxModule;
|
||||
import com.facebook.react.devsupport.interfaces.DevSupportManager;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
@@ -74,38 +76,16 @@ class CoreReactPackage extends TurboReactPackage {
|
||||
|
||||
@Override
|
||||
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
||||
if (!ClassFinder.canLoadClassesFromAnnotationProcessors()) {
|
||||
return fallbackForMissingClass();
|
||||
}
|
||||
try {
|
||||
Class<?> reactModuleInfoProviderClass =
|
||||
Class.forName(CoreReactPackage.class.getName() + "$$ReactModuleInfoProvider");
|
||||
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
|
||||
ClassFinder.findClass(CoreReactPackage.class.getName() + "$$ReactModuleInfoProvider");
|
||||
return (ReactModuleInfoProvider)
|
||||
Assertions.assertNotNull(reactModuleInfoProviderClass).newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// In OSS case, the annotation processor does not run. We fall back on creating this byhand
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
AndroidInfoModule.class,
|
||||
DeviceInfoModule.class,
|
||||
SourceCodeModule.class,
|
||||
DevSettingsModule.class,
|
||||
DeviceEventManagerModule.class,
|
||||
LogBoxModule.class,
|
||||
ExceptionsManagerModule.class,
|
||||
};
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
if (reactModule != null) {
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
}
|
||||
return () -> reactModuleInfoMap;
|
||||
return fallbackForMissingClass();
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(
|
||||
"No ReactModuleInfoProvider for "
|
||||
@@ -120,4 +100,34 @@ class CoreReactPackage extends TurboReactPackage {
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private ReactModuleInfoProvider fallbackForMissingClass() {
|
||||
// In OSS case, the annotation processor does not run. We fall back on creating this byhand
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
AndroidInfoModule.class,
|
||||
DeviceInfoModule.class,
|
||||
SourceCodeModule.class,
|
||||
DevSettingsModule.class,
|
||||
DeviceEventManagerModule.class,
|
||||
LogBoxModule.class,
|
||||
ExceptionsManagerModule.class,
|
||||
};
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
if (reactModule != null) {
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
}
|
||||
return () -> reactModuleInfoMap;
|
||||
}
|
||||
}
|
||||
|
||||
+55
-46
@@ -15,6 +15,7 @@ import com.facebook.react.animated.NativeAnimatedModule;
|
||||
import com.facebook.react.bridge.ModuleSpec;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.common.ClassFinder;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.module.annotations.ReactModuleList;
|
||||
import com.facebook.react.module.model.ReactModuleInfo;
|
||||
@@ -252,56 +253,16 @@ public class MainReactPackage extends TurboReactPackage implements ViewManagerOn
|
||||
|
||||
@Override
|
||||
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
||||
if (!ClassFinder.canLoadClassesFromAnnotationProcessors()) {
|
||||
return fallbackForMissingClass();
|
||||
}
|
||||
try {
|
||||
Class<?> reactModuleInfoProviderClass =
|
||||
Class.forName("com.facebook.react.shell.MainReactPackage$$ReactModuleInfoProvider");
|
||||
ClassFinder.findClass(
|
||||
"com.facebook.react.shell.MainReactPackage$$ReactModuleInfoProvider");
|
||||
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// In the OSS case, the annotation processor does not run. We fall back to creating this by
|
||||
// hand
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
AccessibilityInfoModule.class,
|
||||
AppearanceModule.class,
|
||||
AppStateModule.class,
|
||||
BlobModule.class,
|
||||
DevLoadingModule.class,
|
||||
FileReaderModule.class,
|
||||
ClipboardModule.class,
|
||||
DialogModule.class,
|
||||
FrescoModule.class,
|
||||
I18nManagerModule.class,
|
||||
ImageLoaderModule.class,
|
||||
ImageStoreManager.class,
|
||||
IntentModule.class,
|
||||
NativeAnimatedModule.class,
|
||||
NetworkingModule.class,
|
||||
PermissionsModule.class,
|
||||
DevToolsSettingsManagerModule.class,
|
||||
ShareModule.class,
|
||||
StatusBarModule.class,
|
||||
SoundManagerModule.class,
|
||||
ToastModule.class,
|
||||
VibrationModule.class,
|
||||
WebSocketModule.class
|
||||
};
|
||||
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
if (reactModule != null) {
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
}
|
||||
return () -> reactModuleInfoMap;
|
||||
return fallbackForMissingClass();
|
||||
} catch (InstantiationException e) {
|
||||
throw new RuntimeException(
|
||||
"No ReactModuleInfoProvider for"
|
||||
@@ -314,4 +275,52 @@ public class MainReactPackage extends TurboReactPackage implements ViewManagerOn
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private ReactModuleInfoProvider fallbackForMissingClass() {
|
||||
// In the OSS case, the annotation processor does not run.
|
||||
// We fall back to creating this by hand
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
AccessibilityInfoModule.class,
|
||||
AppearanceModule.class,
|
||||
AppStateModule.class,
|
||||
BlobModule.class,
|
||||
DevLoadingModule.class,
|
||||
FileReaderModule.class,
|
||||
ClipboardModule.class,
|
||||
DialogModule.class,
|
||||
FrescoModule.class,
|
||||
I18nManagerModule.class,
|
||||
ImageLoaderModule.class,
|
||||
ImageStoreManager.class,
|
||||
IntentModule.class,
|
||||
NativeAnimatedModule.class,
|
||||
NetworkingModule.class,
|
||||
PermissionsModule.class,
|
||||
DevToolsSettingsManagerModule.class,
|
||||
ShareModule.class,
|
||||
StatusBarModule.class,
|
||||
SoundManagerModule.class,
|
||||
ToastModule.class,
|
||||
VibrationModule.class,
|
||||
WebSocketModule.class
|
||||
};
|
||||
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
if (reactModule != null) {
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.isCxxModule(),
|
||||
ReactModuleInfo.classIsTurboModule(moduleClass)));
|
||||
}
|
||||
}
|
||||
return () -> reactModuleInfoMap;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user