Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Callback;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.interfaces.ReactHost;
import com.facebook.react.modules.core.PermissionListener;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package com.facebook.react

import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.interfaces.ReactHost

@OptIn(UnstableReactNativeAPI::class)
/** Interface that represents an instance of a React Native application */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
import com.facebook.react.interfaces.ReactHost;
import com.facebook.react.interfaces.fabric.ReactSurface;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.interfaces
package com.facebook.react

import android.app.Activity
import android.content.Context
import android.os.Bundle
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.queue.ReactQueueConfiguration
import com.facebook.react.common.LifecycleState
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.devsupport.interfaces.DevSupportManager
import com.facebook.react.interfaces.TaskInterface
import com.facebook.react.interfaces.fabric.ReactSurface
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler

Expand All @@ -25,7 +25,6 @@ import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler
*
* The implementation of this interface should be Thread Safe
*/
@UnstableReactNativeAPI
interface ReactHost {

/** The current [LifecycleState] for React Host */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public interface RCTDeviceEventEmitter extends JavaScriptModule {
private @Nullable JSExceptionHandler mExceptionHandlerWrapper;
private @Nullable WeakReference<Activity> mCurrentActivity;

private @Nullable InteropModuleRegistry mInteropModuleRegistry;
protected @Nullable InteropModuleRegistry mInteropModuleRegistry;
private boolean mIsInitialized = false;

public ReactContext(Context base) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
package com.facebook.react.common.annotations

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@RequiresOptIn(
level = RequiresOptIn.Level.ERROR,
message = "This API is experimental and is likely to change or to be removed in the future")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,41 @@
package com.facebook.react.defaults

import android.content.Context
import com.facebook.react.JSEngineResolutionAlgorithm
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.JSBundleLoader
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.fabric.ComponentFactory
import com.facebook.react.interfaces.ReactHost
import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler
import com.facebook.react.runtime.JSCInstance
import com.facebook.react.runtime.ReactHostImpl
import com.facebook.react.runtime.hermes.HermesInstance

@UnstableReactNativeAPI
/**
* A utility class that allows you to simplify the setup of a [ReactHost] for new apps in Open
* Source.
*
* [ReactHost] is an interface responsible of handling the lifecycle of a React Native app when
* running in bridgeless mode.
*/
object DefaultReactHost {
private var reactHost: ReactHost? = null

/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param packageList the list of [ReactPackage]s to use for creating the [ReactHost]
* @param jsMainModulePath the path to your app's main module on Metro. Usually `index` or
* `index.<platform>`
* @param jsBundleAssetPath the path to the JS bundle relative to the assets directory. Will be
* composed in a `asset://...` URL
* @param isHermesEnabled whether to use Hermes as the JS engine, default to true.
*/
@OptIn(UnstableReactNativeAPI::class)
@JvmStatic
fun getDefaultReactHost(
context: Context,
Expand All @@ -47,13 +68,42 @@ object DefaultReactHost {
// TODO: T164788699 find alternative of accessing ReactHostImpl for initialising reactHost
reactHost =
ReactHostImpl(
context,
defaultReactHostDelegate,
componentFactory,
true,
reactJsExceptionHandler,
true)
context,
defaultReactHostDelegate,
componentFactory,
true,
reactJsExceptionHandler,
true)
.apply {
jsEngineResolutionAlgorithm =
if (isHermesEnabled) {
JSEngineResolutionAlgorithm.HERMES
} else {
JSEngineResolutionAlgorithm.JSC
}
}
}
return reactHost as ReactHost
}

/**
* Util function to create a default [ReactHost] to be used in your application. This method is
* used by the New App template.
*
* This method takes in input a [ReactNativeHost] (bridge-mode) and uses its configuration to
* create an equivalent [ReactHost] (bridgeless-mode).
*
* @param context the Android [Context] to use for creating the [ReactHost]
* @param reactNativeHost the [ReactNativeHost] to use for creating the [ReactHost]
*/
@JvmStatic
fun getDefaultReactHost(
context: Context,
reactNativeHost: ReactNativeHost,
): ReactHost {
require(reactNativeHost is DefaultReactNativeHost) {
"You can call getDefaultReactHost only with instances of DefaultReactNativeHost"
}
return reactNativeHost.toReactHost(context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
package com.facebook.react.defaults

import android.app.Application
import android.content.Context
import com.facebook.react.JSEngineResolutionAlgorithm
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackageTurboModuleManagerDelegate
import com.facebook.react.bridge.JSIModulePackage
Expand Down Expand Up @@ -68,4 +70,18 @@ protected constructor(
*/
protected open val isHermesEnabled: Boolean?
get() = null

/**
* Converts this [ReactNativeHost] (bridge-mode) to a [ReactHost] (bridgeless-mode).
*
* @param context the Android [Context] to use for creating the [ReactHost]
*/
fun toReactHost(context: Context): ReactHost =
DefaultReactHost.getDefaultReactHost(
context,
packages,
jsMainModuleName,
bundleAssetName ?: "index",
isHermesEnabled ?: true,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException;
import com.facebook.react.bridge.ReactSoftExceptionLogger;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.uimanager.events.EventDispatcher;
Expand Down Expand Up @@ -49,6 +50,9 @@ class BridgelessReactContext extends ReactApplicationContext implements EventDis
BridgelessReactContext(Context context, ReactHostImpl host) {
super(context);
mReactHost = host;
if (ReactFeatureFlags.unstable_useFabricInterop) {
initializeInteropModules();
}
}

@Override
Expand Down Expand Up @@ -124,6 +128,10 @@ public BridgelessJSModuleInvocationHandler(

@Override
public <T extends JavaScriptModule> T getJSModule(Class<T> jsInterface) {
if (mInteropModuleRegistry != null
&& mInteropModuleRegistry.shouldReturnInteropModule(jsInterface)) {
return mInteropModuleRegistry.getInteropModule(jsInterface);
}
JavaScriptModule interfaceProxy =
(JavaScriptModule)
Proxy.newProxyInstance(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.facebook.infer.annotation.ThreadSafe;
import com.facebook.react.JSEngineResolutionAlgorithm;
import com.facebook.react.MemoryPressureRouter;
import com.facebook.react.ReactHost;
import com.facebook.react.ReactInstanceEventListener;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.JSBundleLoader;
Expand All @@ -48,7 +49,6 @@
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.fabric.FabricUIManager;
import com.facebook.react.interfaces.ReactHost;
import com.facebook.react.interfaces.TaskInterface;
import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler;
import com.facebook.react.interfaces.fabric.ReactSurface;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/ReactCommon/react/bridging/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct Bridging<
std::shared_ptr<T>,
std::enable_if_t<std::is_base_of_v<jsi::HostObject, T>>> {
static std::shared_ptr<T> fromJs(jsi::Runtime& rt, const jsi::Object& value) {
return value.asHostObject<T>(rt);
return value.getHostObject<T>(rt);
}

static jsi::Object toJs(jsi::Runtime& rt, std::shared_ptr<T> value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ package com.helloworld
import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.flipper.ReactNativeFlipper
import com.facebook.react.interfaces.ReactHost
import com.facebook.soloader.SoLoader

@UnstableReactNativeAPI
class MainApplication : Application(), ReactApplication {

override val reactNativeHost: ReactNativeHost =
Expand All @@ -33,12 +31,7 @@ class MainApplication : Application(), ReactApplication {
}

override val reactHost: ReactHost
get() =
DefaultReactHost.getDefaultReactHost(
context = this,
packageList = PackageList(this).packages,
jsMainModulePath = "index",
isHermesEnabled = BuildConfig.IS_HERMES_ENABLED)
get() = getDefaultReactHost(this.applicationContext, reactNativeHost)

override fun onCreate() {
super.onCreate()
Expand Down
8 changes: 7 additions & 1 deletion packages/rn-tester/NativeComponentExample/js/MyNativeView.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export default function MyNativeView(props: {}): React.Node {
const ref = useRef<React.ElementRef<MyNativeViewType> | null>(null);
const legacyRef = useRef<React.ElementRef<MyLegacyViewType> | null>(null);
const [opacity, setOpacity] = useState(1.0);
const [arrayValues, setArrayValues] = useState([1, 2, 3]);
const [hsba, setHsba] = useState<HSBA>(new HSBA());
const [cornerRadiusIndex, setCornerRadiusIndex] = useState<number>(0);
const [legacyMeasure, setLegacyMeasure] =
Expand All @@ -102,7 +103,7 @@ export default function MyNativeView(props: {}): React.Node {
ref={ref}
style={{flex: 1}}
opacity={opacity}
values={[0, 1, 2, 3, 4]}
values={arrayValues}
onIntArrayChanged={event => {
console.log(event.nativeEvent.values);
console.log(event.nativeEvent.boolValues);
Expand Down Expand Up @@ -154,6 +155,11 @@ export default function MyNativeView(props: {}): React.Node {
title="Set Opacity"
onPress={() => {
setOpacity(Math.random());
setArrayValues([
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100),
Math.floor(Math.random() * 100),
]);
}}
/>
<Button
Expand Down
2 changes: 2 additions & 0 deletions packages/rn-tester/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ android {
versionName "1.0"
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
buildConfigField("String", "JS_MAIN_MODULE_NAME", "\"js/RNTesterApp.android\"")
buildConfigField("String", "BUNDLE_ASSET_NAME", "\"RNTesterApp.android.bundle\"")
}
externalNativeBuild {
cmake {
Expand Down
5 changes: 5 additions & 0 deletions packages/rn-tester/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.facebook.react.uiapp"
xmlns:android="http://schemas.android.com/apk/res/android">

<uses-feature
Expand All @@ -15,6 +16,10 @@
android:name="android.hardware.camera"
android:required="false" />

<uses-sdk
android:minSdkVersion="23"
android:targetSdkVersion="34" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Expand Down
Loading