Skip to content

Commit bbe02de

Browse files
cipolleschireact-native-bot
authored andcommitted
Use Hermes V1 as default engine (#54989)
Summary: This change makes Hermes V1 the default engine for React Native for both platforms. This change needs to land before the branch cut of react native 0.84 bypass-github-export-checks ## Changelog: [iOS][Changed] - Make Hermes V1 the default engine for iOS Pull Request resolved: #54989 Test Plan: 1. Run `bundle exec pod install` and verified that Hermes V1 is used when building from source <img height="480" alt="Simulator Screenshot - iPhone 17 Pro - 2025-12-29 at 11 28 44" src="https://github.com/user-attachments/assets/0889f16c-f2ee-4a0e-9a4d-529dd82c8283" /> 2. Run `prebuild-ios -s` and verified that the scripts downloads the Hermes V1 tarball <img width="831" height="324" alt="Screenshot 2025-12-29 at 10 37 53" src="https://github.com/user-attachments/assets/9a60565e-1e13-4967-a4a4-dd079e6b040f" /> 3. GHA and nightlies Reviewed By: vzaidman, cortinico, huntie Differential Revision: D89881943 Pulled By: cipolleschi fbshipit-source-id: 958b6d31bd4230ba4a5c7fee2bffc19e03dcbc89
1 parent e4be8c4 commit bbe02de

14 files changed

Lines changed: 103 additions & 39 deletions

File tree

.github/workflows/prebuild-ios-core.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ jobs:
5050
shell: bash
5151
run: |
5252
if [ "${{ inputs.use-hermes-nightly }}" == "true" ]; then
53-
HERMES_VERSION="nightly"
53+
# We are not publishing nightly versions of Hermes V1 yet.
54+
# For now, we can use the latest version of Hermes V1 published on maven and npm.
55+
HERMES_VERSION="latest-v1"
5456
else
55-
HERMES_VERSION=$(sed -n 's/^HERMES_VERSION_NAME=//p' packages/react-native/sdks/hermes-engine/version.properties)
57+
HERMES_VERSION=$(sed -n 's/^HERMES_V1_VERSION_NAME=//p' packages/react-native/sdks/hermes-engine/version.properties)
5658
fi
5759
echo "Using Hermes version: $HERMES_VERSION"
5860
echo "HERMES_VERSION=$HERMES_VERSION" >> $GITHUB_ENV

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ react.internal.useHermesStable=true
2626
react.internal.useHermesNightly=false
2727

2828
# Controls whether to use Hermes 1.0. Clean and rebuild when changing.
29-
hermesV1Enabled=false
29+
hermesV1Enabled=true

packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,5 @@ abstract class PrivateReactExtension @Inject constructor(project: Project) {
5959
val codegenDir: DirectoryProperty =
6060
objects.directoryProperty().convention(root.dir("node_modules/@react-native/codegen"))
6161

62-
val hermesV1Enabled: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
62+
val hermesV1Enabled: Property<Boolean> = objects.property(Boolean::class.java).convention(true)
6363
}

packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ internal object DependencyUtils {
113113
fun configureDependencies(
114114
project: Project,
115115
coordinates: Coordinates,
116-
hermesV1Enabled: Boolean = false,
116+
hermesV1Enabled: Boolean = true,
117117
) {
118118
if (
119119
coordinates.versionString.isBlank() ||
@@ -149,7 +149,7 @@ internal object DependencyUtils {
149149

150150
internal fun getDependencySubstitutions(
151151
coordinates: Coordinates,
152-
hermesV1Enabled: Boolean = false,
152+
hermesV1Enabled: Boolean = true,
153153
): List<Triple<String, String, String>> {
154154
val dependencySubstitution = mutableListOf<Triple<String, String, String>>()
155155
val hermesVersion =

packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/ProjectUtils.kt

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ internal object ProjectUtils {
2929

3030
const val HERMES_FALLBACK = true
3131

32+
const val HERMES_V1_ENABLED_FALLBACK = true
33+
3234
internal fun Project.isNewArchEnabled(): Boolean = true
3335

3436
internal val Project.isHermesEnabled: Boolean
@@ -73,14 +75,20 @@ internal object ProjectUtils {
7375

7476
internal val Project.isHermesV1Enabled: Boolean
7577
get() =
76-
(project.hasProperty(HERMES_V1_ENABLED) &&
77-
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
78-
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
79-
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
80-
(project.extraProperties.has(HERMES_V1_ENABLED) &&
81-
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
82-
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
83-
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
78+
if (
79+
project.hasProperty(HERMES_V1_ENABLED) || project.hasProperty(SCOPED_HERMES_V1_ENABLED)
80+
) {
81+
(project.hasProperty(HERMES_V1_ENABLED) &&
82+
project.property(HERMES_V1_ENABLED).toString().toBoolean()) ||
83+
(project.hasProperty(SCOPED_HERMES_V1_ENABLED) &&
84+
project.property(SCOPED_HERMES_V1_ENABLED).toString().toBoolean()) ||
85+
(project.extraProperties.has(HERMES_V1_ENABLED) &&
86+
project.extraProperties.get(HERMES_V1_ENABLED).toString().toBoolean()) ||
87+
(project.extraProperties.has(SCOPED_HERMES_V1_ENABLED) &&
88+
project.extraProperties.get(SCOPED_HERMES_V1_ENABLED).toString().toBoolean())
89+
} else {
90+
HERMES_V1_ENABLED_FALLBACK
91+
}
8492

8593
internal fun Project.needsCodegenFromPackageJson(rootProperty: DirectoryProperty): Boolean {
8694
val parsedPackageJson = readPackageJsonFile(this, rootProperty)

packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/DependencyUtilsTest.kt

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ class DependencyUtilsTest {
290290
assertThat(forcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
291291
.isTrue()
292292
assertThat(forcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:4.5.6" })
293+
.isFalse()
294+
assertThat(forcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
293295
.isTrue()
294296
}
295297

@@ -325,10 +327,14 @@ class DependencyUtilsTest {
325327
assertThat(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
326328
.isTrue()
327329
assertThat(appForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:4.5.6" })
330+
.isFalse()
331+
assertThat(appForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
328332
.isTrue()
329333
assertThat(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
330334
.isTrue()
331335
assertThat(libForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:4.5.6" })
336+
.isFalse()
337+
assertThat(libForcedModules.any { it.toString() == "com.facebook.hermes:hermes-android:7.8.9" })
332338
.isTrue()
333339
}
334340

@@ -384,12 +390,20 @@ class DependencyUtilsTest {
384390
assertThat(
385391
appForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:4.5.6" }
386392
)
393+
.isFalse()
394+
assertThat(
395+
appForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
396+
)
387397
.isTrue()
388398
assertThat(libForcedModules.any { it.toString() == "io.github.test:react-android:1.2.3" })
389399
.isTrue()
390400
assertThat(
391401
libForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:4.5.6" }
392402
)
403+
.isFalse()
404+
assertThat(
405+
libForcedModules.any { it.toString() == "io.github.test.hermes:hermes-android:7.8.9" }
406+
)
393407
.isTrue()
394408
}
395409

@@ -430,7 +444,7 @@ class DependencyUtilsTest {
430444
}
431445

432446
@Test
433-
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withClassicHermes() {
447+
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withHermesV1() {
434448
val dependencySubstitutions =
435449
getDependencySubstitutions(DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"))
436450

@@ -442,7 +456,7 @@ class DependencyUtilsTest {
442456
)
443457
.isEqualTo(dependencySubstitutions[0].third)
444458
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
445-
assertThat("com.facebook.hermes:hermes-android:0.42.0")
459+
assertThat("com.facebook.hermes:hermes-android:0.43.0")
446460
.isEqualTo(dependencySubstitutions[1].second)
447461
assertThat(
448462
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
@@ -451,7 +465,7 @@ class DependencyUtilsTest {
451465
}
452466

453467
@Test
454-
fun getDependencySubstitutions_withDefaultGroup_substitutesCorrectly_withHermesV1() {
468+
fun getDependencySubstitutions_withDefaultGroupAndFallback_substitutesCorrectly_withClassicHermes() {
455469
val dependencySubstitutions =
456470
getDependencySubstitutions(
457471
DependencyUtils.Coordinates("0.42.0", "0.42.0", "0.43.0"),
@@ -475,7 +489,7 @@ class DependencyUtilsTest {
475489
}
476490

477491
@Test
478-
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withClassicHermes() {
492+
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withHermesV1() {
479493
val dependencySubstitutions =
480494
getDependencySubstitutions(
481495
DependencyUtils.Coordinates(
@@ -494,14 +508,14 @@ class DependencyUtilsTest {
494508
)
495509
.isEqualTo(dependencySubstitutions[0].third)
496510
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
497-
assertThat("io.github.test.hermes:hermes-android:0.42.0")
511+
assertThat("io.github.test.hermes:hermes-android:0.43.0")
498512
.isEqualTo(dependencySubstitutions[1].second)
499513
assertThat(
500514
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
501515
)
502516
.isEqualTo(dependencySubstitutions[1].third)
503517
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[2].first)
504-
assertThat("io.github.test.hermes:hermes-android:0.42.0")
518+
assertThat("io.github.test.hermes:hermes-android:0.43.0")
505519
.isEqualTo(dependencySubstitutions[2].second)
506520
assertThat("The hermes-android artifact was moved to com.facebook.hermes publishing group.")
507521
.isEqualTo(dependencySubstitutions[2].third)
@@ -510,14 +524,14 @@ class DependencyUtilsTest {
510524
assertThat("The react-android dependency was modified to use the correct Maven group.")
511525
.isEqualTo(dependencySubstitutions[3].third)
512526
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[4].first)
513-
assertThat("io.github.test.hermes:hermes-android:0.42.0")
527+
assertThat("io.github.test.hermes:hermes-android:0.43.0")
514528
.isEqualTo(dependencySubstitutions[4].second)
515529
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
516530
.isEqualTo(dependencySubstitutions[4].third)
517531
}
518532

519533
@Test
520-
fun getDependencySubstitutions_withCustomGroup_substitutesCorrectly_withHermesV1() {
534+
fun getDependencySubstitutions_withCustomGroupAndFallbackToClassicHermes_substitutesCorrectly_withClassicHermes() {
521535
val dependencySubstitutions =
522536
getDependencySubstitutions(
523537
DependencyUtils.Coordinates(
@@ -527,7 +541,7 @@ class DependencyUtilsTest {
527541
"io.github.test",
528542
"io.github.test.hermes",
529543
),
530-
hermesV1Enabled = true,
544+
hermesV1Enabled = false,
531545
)
532546

533547
assertThat("com.facebook.react:react-native").isEqualTo(dependencySubstitutions[0].first)
@@ -537,14 +551,14 @@ class DependencyUtilsTest {
537551
)
538552
.isEqualTo(dependencySubstitutions[0].third)
539553
assertThat("com.facebook.react:hermes-engine").isEqualTo(dependencySubstitutions[1].first)
540-
assertThat("io.github.test.hermes:hermes-android:0.43.0")
554+
assertThat("io.github.test.hermes:hermes-android:0.42.0")
541555
.isEqualTo(dependencySubstitutions[1].second)
542556
assertThat(
543557
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210."
544558
)
545559
.isEqualTo(dependencySubstitutions[1].third)
546560
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[2].first)
547-
assertThat("io.github.test.hermes:hermes-android:0.43.0")
561+
assertThat("io.github.test.hermes:hermes-android:0.42.0")
548562
.isEqualTo(dependencySubstitutions[2].second)
549563
assertThat("The hermes-android artifact was moved to com.facebook.hermes publishing group.")
550564
.isEqualTo(dependencySubstitutions[2].third)
@@ -553,7 +567,7 @@ class DependencyUtilsTest {
553567
assertThat("The react-android dependency was modified to use the correct Maven group.")
554568
.isEqualTo(dependencySubstitutions[3].third)
555569
assertThat("com.facebook.react:hermes-android").isEqualTo(dependencySubstitutions[4].first)
556-
assertThat("io.github.test.hermes:hermes-android:0.43.0")
570+
assertThat("io.github.test.hermes:hermes-android:0.42.0")
557571
.isEqualTo(dependencySubstitutions[4].second)
558572
assertThat("The hermes-android dependency was modified to use the correct Maven group.")
559573
.isEqualTo(dependencySubstitutions[4].third)

packages/gradle-plugin/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/ProjectUtilsTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ class ProjectUtilsTest {
117117
}
118118

119119
@Test
120-
fun isHermesV1Enabled_returnsFalseByDefault() {
121-
assertThat(createProject().isHermesV1Enabled).isFalse()
120+
fun isHermesV1Enabled_returnsTrueByDefault() {
121+
assertThat(createProject().isHermesV1Enabled).isTrue()
122122
}
123123

124124
@Test

packages/react-native/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,7 @@ extension Target {
924924
.define("NDEBUG", .when(configuration: .release)),
925925
.define("USE_HERMES", to: "1"),
926926
.define("RCT_REMOVE_LEGACY_ARCH", to: "1"),
927+
.define("HERMES_V1_ENABLED", to: "1"),
927928
] + defines + cxxCommonHeaderPaths
928929

929930
return .target(

packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <jsi/decorator.h>
1414
#include <jsinspector-modern/InspectorFlags.h>
1515

16+
#include <thread>
17+
1618
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
1719

1820
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)

packages/react-native/scripts/ios-prebuild/hermes.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,13 @@ async function prepareHermesArtifactsAsync(
5454
// Only check if the artifacts folder exists if we are not using a local tarball
5555
if (!localPath) {
5656
// Resolve the version from the environment variable or use the default version
57-
let resolvedVersion = process.env.HERMES_VERSION ?? 'nightly';
57+
let resolvedVersion = process.env.HERMES_VERSION ?? 'latest-v1';
5858

59-
if (resolvedVersion === 'nightly') {
59+
if (resolvedVersion === 'latest-v1') {
60+
hermesLog('Using latest-v1 tarball');
61+
const hermesVersion = await getLatestV1VersionFromNPM();
62+
resolvedVersion = hermesVersion;
63+
} else if (resolvedVersion === 'nightly') {
6064
hermesLog('Using latest nightly tarball');
6165
const hermesVersion = await getNightlyVersionFromNPM();
6266
resolvedVersion = hermesVersion;
@@ -102,14 +106,31 @@ async function prepareHermesArtifactsAsync(
102106
return artifactsPath;
103107
}
104108

109+
async function getLatestV1VersionFromNPM() /*: Promise<string> */ {
110+
const npmResponse /*: Response */ = await fetch(
111+
'https://registry.npmjs.org/hermes-compiler/latest-v1',
112+
);
113+
114+
if (!npmResponse.ok) {
115+
throw new Error(
116+
`Couldn't get a response from NPM: ${npmResponse.status} ${npmResponse.statusText}`,
117+
);
118+
}
119+
120+
const json = await npmResponse.json();
121+
const latestV1 = json.version;
122+
hermesLog(`Using version ${latestV1}`);
123+
return latestV1;
124+
}
125+
105126
async function getNightlyVersionFromNPM() /*: Promise<string> */ {
106127
const npmResponse /*: Response */ = await fetch(
107128
'https://registry.npmjs.org/hermes-compiler/nightly',
108129
);
109130

110131
if (!npmResponse.ok) {
111132
throw new Error(
112-
`Couldn't get an answer from NPM: ${npmResponse.status} ${npmResponse.statusText}`,
133+
`Couldn't get a response from NPM: ${npmResponse.status} ${npmResponse.statusText}`,
113134
);
114135
}
115136

0 commit comments

Comments
 (0)