1+ import assert from "node:assert/strict" ;
12import fs from "node:fs" ;
23import path from "node:path" ;
34
45import { Command } from "@commander-js/extra-typings" ;
56import { spawn , SpawnFailure } from "bufout" ;
67import { oraPromise } from "ora" ;
7- import { prettyPath } from "../path-utils " ;
8+ import { packageDirectorySync } from "pkg-dir " ;
89
9- const HERMES_PATH = path . resolve ( __dirname , "../../../hermes" ) ;
10+ import { getLatestMtime , prettyPath } from "../path-utils" ;
11+
12+ const HOST_PACKAGE_ROOT = path . resolve ( __dirname , "../../.." ) ;
1013const HERMES_GIT_URL = "https://github.com/kraenhansen/hermes.git" ;
1114const HERMES_GIT_TAG = "node-api-for-react-native-0.79.0" ;
12- const REACT_NATIVE_DIR = path . dirname (
13- require . resolve ( "react-native/package.json" )
14- ) ;
1515
1616export const command = new Command ( "vendor-hermes" )
17+ . argument ( "[from]" , "Path to a file inside the app package" , process . cwd ( ) )
1718 . option ( "--silent" , "Don't print anything except the final path" , false )
1819 . option (
1920 "--force" ,
2021 "Don't check timestamps of input files to skip unnecessary rebuilds" ,
2122 false
2223 )
23- . action ( async ( { force, silent } ) => {
24+ . action ( async ( from , { force, silent } ) => {
2425 try {
26+ const appPackageRoot = packageDirectorySync ( { cwd : from } ) ;
27+ assert ( appPackageRoot , "Failed to find package root" ) ;
28+ const hermesPath = path . join ( HOST_PACKAGE_ROOT , "hermes" ) ;
2529 if ( force ) {
26- fs . rmSync ( HERMES_PATH , { recursive : true , force : true } ) ;
30+ fs . rmSync ( hermesPath , { recursive : true , force : true } ) ;
2731 }
28- if ( ! fs . existsSync ( HERMES_PATH ) ) {
32+ if ( ! fs . existsSync ( hermesPath ) ) {
2933 await oraPromise (
3034 spawn (
3135 "git" ,
@@ -37,27 +41,41 @@ export const command = new Command("vendor-hermes")
3741 "--branch" ,
3842 HERMES_GIT_TAG ,
3943 HERMES_GIT_URL ,
40- HERMES_PATH ,
44+ hermesPath ,
4145 ] ,
4246 {
4347 outputMode : "buffered" ,
4448 }
4549 ) ,
4650 {
47- text : `Cloning custom Hermes into ${ prettyPath ( HERMES_PATH ) } ` ,
51+ text : `Cloning custom Hermes into ${ prettyPath ( hermesPath ) } ` ,
4852 successText : "Cloned custom Hermes" ,
4953 failText : ( err ) => `Failed to clone custom Hermes: ${ err . message } ` ,
5054 isEnabled : ! silent ,
5155 }
5256 ) ;
57+ }
58+ const hermesJsiPath = path . join ( hermesPath , "API/jsi/jsi" ) ;
59+ const reactNativePath = path . dirname (
60+ require . resolve ( "react-native/package.json" , {
61+ // Ensures we'll be patching the React Native package actually used by the app
62+ paths : [ appPackageRoot ] ,
63+ } )
64+ ) ;
65+ const reactNativeJsiPath = path . join (
66+ reactNativePath ,
67+ "ReactCommon/jsi/jsi/"
68+ ) ;
69+
70+ if (
71+ fs . existsSync ( reactNativeJsiPath ) &&
72+ ( force ||
73+ getLatestMtime ( hermesJsiPath ) > getLatestMtime ( reactNativeJsiPath ) )
74+ ) {
5375 await oraPromise (
54- fs . promises . cp (
55- path . join ( HERMES_PATH , "API/jsi/jsi" ) ,
56- path . join ( REACT_NATIVE_DIR , "ReactCommon/jsi/jsi/" ) ,
57- {
58- recursive : true ,
59- }
60- ) ,
76+ fs . promises . cp ( hermesJsiPath , reactNativeJsiPath , {
77+ recursive : true ,
78+ } ) ,
6179 {
6280 text : `Copying JSI from Hermes to React Native` ,
6381 successText : "Copied JSI from Hermes to React Native" ,
@@ -67,7 +85,7 @@ export const command = new Command("vendor-hermes")
6785 }
6886 ) ;
6987 }
70- console . log ( HERMES_PATH ) ;
88+ console . log ( hermesPath ) ;
7189 } catch ( error ) {
7290 if ( error instanceof SpawnFailure ) {
7391 error . flushOutput ( "both" ) ;
0 commit comments