Skip to content

Commit 2097278

Browse files
cortinicofacebook-github-bot
authored andcommitted
Update the template to load the correct JS engine at runtime. (#35095)
Summary: Pull Request resolved: #35095 This change will make sure that we load the correct JS engine at runtime, by using the BuildConfig flag that RNGP sets for us. This will solve a lot of noise in adb logcat for users seeing stacktraces mentioning failing to load `jscexecutor` library. This is also a breaking change, but as the API was not widely used nor advertised in the template, we should be fine by just mentioning this in the release notes. Changelog: [Android] [Changed] - Update the template to load the correct JS engine at runtime Reviewed By: cipolleschi Differential Revision: D40710597 fbshipit-source-id: d59a7a52b22a9bf273ea89094c6620c3ecf6eb00
1 parent 3f77736 commit 2097278

File tree

8 files changed

+75
-44
lines changed

8 files changed

+75
-44
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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;
9+
10+
/**
11+
* An enum that specifies the algorithm to use when loading theJS Engine. {@link #JSC} will load
12+
* JavaScriptCore first and fail if it is not available. {@link #HERMES} will load Hermes first and
13+
* fail if it is not available.
14+
*/
15+
public enum JSEngineResolutionAlgorithm {
16+
JSC,
17+
HERMES
18+
}

ReactAndroid/src/main/java/com/facebook/react/JSInterpreter.java

Lines changed: 0 additions & 18 deletions
This file was deleted.

ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import android.app.Application;
1515
import android.content.Context;
1616
import androidx.annotation.Nullable;
17+
import com.facebook.common.logging.FLog;
1718
import com.facebook.hermes.reactexecutor.HermesExecutor;
1819
import com.facebook.hermes.reactexecutor.HermesExecutorFactory;
1920
import com.facebook.infer.annotation.Assertions;
@@ -40,6 +41,8 @@
4041
/** Builder class for {@link ReactInstanceManager} */
4142
public class ReactInstanceManagerBuilder {
4243

44+
private static final String TAG = ReactInstanceManagerBuilder.class.getSimpleName();
45+
4346
private final List<ReactPackage> mPackages = new ArrayList<>();
4447

4548
private @Nullable String mJSBundleAssetUrl;
@@ -64,7 +67,7 @@ public class ReactInstanceManagerBuilder {
6467
private @Nullable Map<String, RequestHandler> mCustomPackagerCommandHandlers;
6568
private @Nullable ReactPackageTurboModuleManagerDelegate.Builder mTMMDelegateBuilder;
6669
private @Nullable SurfaceDelegateFactory mSurfaceDelegateFactory;
67-
private JSInterpreter jsInterpreter = JSInterpreter.OLD_LOGIC;
70+
private JSEngineResolutionAlgorithm jsEngineResolutionAlgorithm = null;
6871

6972
/* package protected */ ReactInstanceManagerBuilder() {}
7073

@@ -118,28 +121,12 @@ public ReactInstanceManagerBuilder setJSBundleLoader(JSBundleLoader jsBundleLoad
118121
}
119122

120123
/**
121-
* Sets the jsEngine as JSC or HERMES as per the setJsEngineAsHermes call Uses the enum {@link
122-
* JSInterpreter}
123-
*
124-
* @param jsInterpreter
125-
*/
126-
private void setJSEngine(JSInterpreter jsInterpreter) {
127-
this.jsInterpreter = jsInterpreter;
128-
}
129-
130-
/**
131-
* Utility setter to set the required JSEngine as HERMES or JSC Defaults to OLD_LOGIC if not
132-
* called by the host app
133-
*
134-
* @param hermesEnabled hermesEnabled = true sets the JS Engine as HERMES and JSC otherwise
124+
* Sets the JS Engine to load as either Hermes or JSC. If not set, the default is JSC with a
125+
* Hermes fallback.
135126
*/
136-
public ReactInstanceManagerBuilder setJsEngineAsHermes(boolean hermesEnabled) {
137-
if (hermesEnabled) {
138-
setJSEngine(JSInterpreter.HERMES);
139-
} else {
140-
setJSEngine(JSInterpreter.JSC);
141-
}
142-
return this;
127+
private void setJSEngineResolutionAlgorithm(
128+
@Nullable JSEngineResolutionAlgorithm jsEngineResolutionAlgorithm) {
129+
this.jsEngineResolutionAlgorithm = jsEngineResolutionAlgorithm;
143130
}
144131

145132
/**
@@ -365,7 +352,11 @@ private JavaScriptExecutorFactory getDefaultJSExecutorFactory(
365352

366353
// if nothing is specified, use old loading method
367354
// else load the required engine
368-
if (jsInterpreter == JSInterpreter.OLD_LOGIC) {
355+
if (jsEngineResolutionAlgorithm == null) {
356+
FLog.w(
357+
TAG,
358+
"You're not setting the JS Engine Resolution Algorithm. "
359+
+ "We'll try to load JSC first, and if it fails we'll fallback to Hermes");
369360
try {
370361
// If JSC is included, use it as normal
371362
initializeSoLoaderIfNecessary(applicationContext);
@@ -378,7 +369,7 @@ private JavaScriptExecutorFactory getDefaultJSExecutorFactory(
378369
HermesExecutor.loadLibrary();
379370
return new HermesExecutorFactory();
380371
}
381-
} else if (jsInterpreter == JSInterpreter.HERMES) {
372+
} else if (jsEngineResolutionAlgorithm == JSEngineResolutionAlgorithm.HERMES) {
382373
HermesExecutor.loadLibrary();
383374
return new HermesExecutorFactory();
384375
} else {

ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,12 @@ protected String getJSMainModuleName() {
190190
* default ones, you'll want to include more packages here.
191191
*/
192192
protected abstract List<ReactPackage> getPackages();
193+
194+
/**
195+
* Returns the {@link JSEngineResolutionAlgorithm} to be used when loading the JS engine. If null,
196+
* will try to load JSC first and fallback to Hermes if JSC is not available.
197+
*/
198+
protected @Nullable JSEngineResolutionAlgorithm getJSEngineResolutionAlgorithm() {
199+
return null;
200+
}
193201
}

ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
package com.facebook.react.defaults
99

1010
import android.app.Application
11+
import com.facebook.react.JSEngineResolutionAlgorithm
1112
import com.facebook.react.ReactNativeHost
1213
import com.facebook.react.ReactPackageTurboModuleManagerDelegate
1314
import com.facebook.react.bridge.JSIModulePackage
@@ -20,8 +21,10 @@ import com.facebook.react.bridge.JSIModulePackage
2021
* providing the default TurboModuleManagerDelegateBuilder and the default JSIModulePackage,
2122
* provided the name of the dynamic library to load.
2223
*/
23-
abstract class DefaultReactNativeHost protected constructor(application: Application) :
24-
ReactNativeHost(application) {
24+
abstract class DefaultReactNativeHost
25+
protected constructor(
26+
application: Application,
27+
) : ReactNativeHost(application) {
2528

2629
override fun getReactPackageTurboModuleManagerDelegateBuilder():
2730
ReactPackageTurboModuleManagerDelegate.Builder? =
@@ -38,6 +41,13 @@ abstract class DefaultReactNativeHost protected constructor(application: Applica
3841
null
3942
}
4043

44+
override fun getJSEngineResolutionAlgorithm(): JSEngineResolutionAlgorithm? =
45+
when (isHermesEnabled) {
46+
true -> JSEngineResolutionAlgorithm.HERMES
47+
false -> JSEngineResolutionAlgorithm.JSC
48+
null -> null
49+
}
50+
4151
/**
4252
* Returns whether the user wants to use the New Architecture or not.
4353
*
@@ -48,4 +58,14 @@ abstract class DefaultReactNativeHost protected constructor(application: Applica
4858
*/
4959
protected open val isNewArchEnabled: Boolean
5060
get() = false
61+
62+
/**
63+
* Returns whether the user wants to use Hermes.
64+
*
65+
* If true, the app will load the Hermes engine, and fail if not found. If false, the app will
66+
* load the JSC engine, and fail if not found. If null, the app will attempt to load JSC first and
67+
* fallback to Hermes if not found.
68+
*/
69+
protected open val isHermesEnabled: Boolean?
70+
get() = null
5171
}

packages/rn-tester/android/app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,11 @@ android {
138138
productFlavors {
139139
hermes {
140140
dimension "vm"
141+
buildConfigField("boolean", "IS_HERMES_ENABLED_IN_FLAVOR", "true")
141142
}
142143
jsc {
143144
dimension "vm"
145+
buildConfigField("boolean", "IS_HERMES_ENABLED_IN_FLAVOR", "false")
144146
}
145147
}
146148

packages/rn-tester/android/app/src/main/java/com/facebook/react/uiapp/RNTesterApplication.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ public List<ViewManager> createViewManagers(
115115
protected boolean isNewArchEnabled() {
116116
return true;
117117
}
118+
119+
@Override
120+
protected Boolean isHermesEnabled() {
121+
return BuildConfig.IS_HERMES_ENABLED_IN_FLAVOR;
122+
}
118123
};
119124

120125
@Override

template/android/app/src/main/java/com/helloworld/MainApplication.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ protected String getJSMainModuleName() {
3737
protected boolean isNewArchEnabled() {
3838
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
3939
}
40+
41+
@Override
42+
protected Boolean isHermesEnabled() {
43+
return BuildConfig.IS_HERMES_ENABLED;
44+
}
4045
};
4146

4247
@Override

0 commit comments

Comments
 (0)