Make ReactNativeConfig a JNI Class (#42247)

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

With this change I make `ReactNativeConfig` a JNI class loaded at Fabric Loading time.

This removes the default from `EmptyReactNativeConfig.java` and makes sure we do read the defaults from C++ `ReactNativeConfig.cpp` file.

Changelog:
[Internal] [Changed] - Make ReactNativeConfig a JNI Class

Reviewed By: motiz88

Differential Revision: D52696653

fbshipit-source-id: 99d5e37c65e0e59efcee2c857bb94194fb40d87d
This commit is contained in:
Nicola Corti
2024-01-15 10:47:20 -08:00
committed by Facebook GitHub Bot
parent 50157310ba
commit cfef30f386
9 changed files with 140 additions and 18 deletions
+7 -1
View File
@@ -30,10 +30,16 @@
-keepclassmembers class * {
@com.facebook.proguard.annotations.DoNotStrip *;
}
-keep @com.facebook.proguard.annotations.DoNotStripAny class * {
*;
}
-keep @com.facebook.jni.annotations.DoNotStrip class *
-keepclassmembers class * {
@com.facebook.jni.annotations.DoNotStrip *;
}
-keep @com.facebook.jni.annotations.DoNotStripAny class * {
*;
}
-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
void set*(***);
@@ -7,29 +7,34 @@
package com.facebook.react.fabric;
import androidx.annotation.NonNull;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStripAny;
/**
* An empty {@link ReactNativeConfig} that is returning empty responses and false for all the
* requested keys.
* An empty {@link ReactNativeConfig} that is backed by the C++ implementation where the defaults
* are store.
*/
@DoNotStripAny
public class EmptyReactNativeConfig implements ReactNativeConfig {
@Override
public boolean getBool(final String s) {
return false;
@NonNull private final HybridData mHybridData;
private static native HybridData initHybrid();
public EmptyReactNativeConfig() {
mHybridData = initHybrid();
}
@Override
public long getInt64(final String s) {
return 0;
}
public native boolean getBool(final String param);
@Override
public String getString(final String s) {
return "";
}
public native long getInt64(final String param);
@Override
public double getDouble(final String s) {
return 0;
}
public native String getString(final String param);
@Override
public native double getDouble(final String param);
}
@@ -0,0 +1,47 @@
/*
* 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.
*/
#include "JEmptyReactNativeConfig.h"
#include <fbjni/fbjni.h>
#include <react/config/ReactNativeConfig.h>
namespace facebook::react {
jni::local_ref<JEmptyReactNativeConfig::jhybriddata>
JEmptyReactNativeConfig::initHybrid(jni::alias_ref<jclass>) {
return makeCxxInstance();
}
jboolean JEmptyReactNativeConfig::getBool(const jni::alias_ref<jstring> param) {
return reactNativeConfig_.getBool(param->toStdString());
}
jni::local_ref<jstring> JEmptyReactNativeConfig::getString(
const jni::alias_ref<jstring> param) {
return jni::make_jstring(reactNativeConfig_.getString(param->toStdString()));
}
jlong JEmptyReactNativeConfig::getInt64(const jni::alias_ref<jstring> param) {
return reactNativeConfig_.getInt64(param->toStdString());
}
jdouble JEmptyReactNativeConfig::getDouble(
const jni::alias_ref<jstring> param) {
return reactNativeConfig_.getDouble(param->toStdString());
}
void JEmptyReactNativeConfig::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", JEmptyReactNativeConfig::initHybrid),
makeNativeMethod("getBool", JEmptyReactNativeConfig::getBool),
makeNativeMethod("getString", JEmptyReactNativeConfig::getString),
makeNativeMethod("getInt64", JEmptyReactNativeConfig::getInt64),
makeNativeMethod("getDouble", JEmptyReactNativeConfig::getDouble),
});
}
} // namespace facebook::react
@@ -0,0 +1,38 @@
/*
* 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.
*/
#pragma once
#include <fbjni/fbjni.h>
#include <react/config/ReactNativeConfig.h>
#include <react/jni/ReadableNativeMap.h>
#include <memory>
namespace facebook::react {
class JEmptyReactNativeConfig
: public jni::HybridClass<JEmptyReactNativeConfig> {
public:
constexpr static const char* const kJavaDescriptor =
"Lcom/facebook/react/fabric/EmptyReactNativeConfig;";
static void registerNatives();
jboolean getBool(const jni::alias_ref<jstring> param);
jni::local_ref<jstring> getString(const jni::alias_ref<jstring> param);
jlong getInt64(const jni::alias_ref<jstring> param);
jdouble getDouble(const jni::alias_ref<jstring> param);
private:
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>);
const EmptyReactNativeConfig reactNativeConfig_ = EmptyReactNativeConfig();
};
} // namespace facebook::react
@@ -12,6 +12,7 @@
#include "CoreComponentsRegistry.h"
#include "EventBeatManager.h"
#include "EventEmitterWrapper.h"
#include "JEmptyReactNativeConfig.h"
#include "StateWrapperImpl.h"
#include "SurfaceHandlerBinding.h"
@@ -24,5 +25,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
facebook::react::ComponentFactory::registerNatives();
facebook::react::CoreComponentsRegistry::registerNatives();
facebook::react::SurfaceHandlerBinding::registerNatives();
facebook::react::JEmptyReactNativeConfig::registerNatives();
});
}
@@ -15,7 +15,7 @@
namespace facebook::react {
/**
* Implementation of ReactNativeConfig that wraps a FabricMobileConfig Java
* Implementation of ReactNativeConfig that wraps a ReactNativeConfig Java
* object.
*/
class ReactNativeConfigHolder : public ReactNativeConfig {
@@ -12,6 +12,7 @@ import com.facebook.react.bridge.JSBundleLoader
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.defaults.DefaultReactHostDelegate
import com.facebook.react.runtime.hermes.HermesInstance
import com.facebook.testutils.fakes.FakeReactNativeConfig
import com.facebook.testutils.shadows.ShadowSoLoader
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
@@ -36,12 +37,14 @@ class ReactHostDelegateTest {
Mockito.mock(ReactPackageTurboModuleManagerDelegate.Builder::class.java)
val hermesInstance: JSRuntimeFactory = Mockito.mock(HermesInstance::class.java)
val jsMainModulePathMocked = "mockedJSMainModulePath"
val reactNativeConfig = FakeReactNativeConfig()
val delegate =
DefaultReactHostDelegate(
jsMainModulePath = jsMainModulePathMocked,
jsBundleLoader = jsBundleLoader,
jsRuntimeFactory = hermesInstance,
turboModuleManagerDelegateBuilder = turboModuleManagerDelegateBuilderMock)
turboModuleManagerDelegateBuilder = turboModuleManagerDelegateBuilderMock,
reactNativeConfig = reactNativeConfig)
assertThat(delegate.jsMainModulePath).isEqualTo(jsMainModulePathMocked)
}
@@ -0,0 +1,21 @@
/*
* 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.testutils.fakes
import com.facebook.react.fabric.ReactNativeConfig
/** A fake [ReactNativeConfig] that returns default values for all methods without accessing JNI. */
class FakeReactNativeConfig : ReactNativeConfig {
override fun getBool(param: String): Boolean = false
override fun getInt64(param: String): Long = 0L
override fun getString(param: String): String = ""
override fun getDouble(param: String): Double = 0.0
}
@@ -27,7 +27,7 @@ class ReactNativeConfig {
};
/**
* Empty configuration that will provide hardcoded values.
* Empty configuration that will provide hardcoded default values.
*/
class EmptyReactNativeConfig : public ReactNativeConfig {
public: