From 7b63d81d6483d50ee0db74de0182309f5eb2548c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 15 May 2025 12:08:05 +0200 Subject: [PATCH 1/5] Make the reactNativeDir resolve from the app package root --- apps/test-app/.gitignore | 2 + .../scripts/patch-hermes.rb | 2 +- .../src/node/cli/hermes.ts | 54 ++++++++++++------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/apps/test-app/.gitignore b/apps/test-app/.gitignore index b0dd8f88..4550bc8f 100644 --- a/apps/test-app/.gitignore +++ b/apps/test-app/.gitignore @@ -13,3 +13,5 @@ msbuild.binlog # Ignoring the Podfile.lock as the `react-native-node-api-modules` hash updates too frequently Podfile.lock + +hermes/ diff --git a/packages/react-native-node-api-modules/scripts/patch-hermes.rb b/packages/react-native-node-api-modules/scripts/patch-hermes.rb index 93737ffc..6e200250 100644 --- a/packages/react-native-node-api-modules/scripts/patch-hermes.rb +++ b/packages/react-native-node-api-modules/scripts/patch-hermes.rb @@ -1,6 +1,6 @@ Pod::UI.warn "!!! PATCHING HERMES WITH NODE-API SUPPORT !!!" -VENDORED_HERMES_DIR ||= `npx react-native-node-api-modules vendor-hermes --silent`.strip +VENDORED_HERMES_DIR ||= `npx react-native-node-api-modules vendor-hermes --silent '#{Pod::Config.instance.installation_root}'`.strip if Dir.exist?(VENDORED_HERMES_DIR) Pod::UI.info "Hermes vendored into #{VENDORED_HERMES_DIR.inspect}" else diff --git a/packages/react-native-node-api-modules/src/node/cli/hermes.ts b/packages/react-native-node-api-modules/src/node/cli/hermes.ts index 50e184a1..df717f14 100644 --- a/packages/react-native-node-api-modules/src/node/cli/hermes.ts +++ b/packages/react-native-node-api-modules/src/node/cli/hermes.ts @@ -1,31 +1,35 @@ +import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; import { Command } from "@commander-js/extra-typings"; import { spawn, SpawnFailure } from "bufout"; import { oraPromise } from "ora"; -import { prettyPath } from "../path-utils"; +import { packageDirectorySync } from "pkg-dir"; -const HERMES_PATH = path.resolve(__dirname, "../../../hermes"); +import { getLatestMtime, prettyPath } from "../path-utils"; + +const HOST_PACKAGE_ROOT = path.resolve(__dirname, "../../.."); const HERMES_GIT_URL = "https://github.com/kraenhansen/hermes.git"; const HERMES_GIT_TAG = "node-api-for-react-native-0.79.0"; -const REACT_NATIVE_DIR = path.dirname( - require.resolve("react-native/package.json") -); export const command = new Command("vendor-hermes") + .argument("[from]", "Path to a file inside the app package", process.cwd()) .option("--silent", "Don't print anything except the final path", false) .option( "--force", "Don't check timestamps of input files to skip unnecessary rebuilds", false ) - .action(async ({ force, silent }) => { + .action(async (from, { force, silent }) => { try { + const appPackageRoot = packageDirectorySync({ cwd: from }); + assert(appPackageRoot, "Failed to find package root"); + const hermesPath = path.join(HOST_PACKAGE_ROOT, "hermes"); if (force) { - fs.rmSync(HERMES_PATH, { recursive: true, force: true }); + fs.rmSync(hermesPath, { recursive: true, force: true }); } - if (!fs.existsSync(HERMES_PATH)) { + if (!fs.existsSync(hermesPath)) { await oraPromise( spawn( "git", @@ -37,27 +41,41 @@ export const command = new Command("vendor-hermes") "--branch", HERMES_GIT_TAG, HERMES_GIT_URL, - HERMES_PATH, + hermesPath, ], { outputMode: "buffered", } ), { - text: `Cloning custom Hermes into ${prettyPath(HERMES_PATH)}`, + text: `Cloning custom Hermes into ${prettyPath(hermesPath)}`, successText: "Cloned custom Hermes", failText: (err) => `Failed to clone custom Hermes: ${err.message}`, isEnabled: !silent, } ); + } + const hermesJsiPath = path.join(hermesPath, "API/jsi/jsi"); + const reactNativePath = path.dirname( + require.resolve("react-native/package.json", { + // Ensures we'll be patching the React Native package actually used by the app + paths: [appPackageRoot], + }) + ); + const reactNativeJsiPath = path.join( + reactNativePath, + "ReactCommon/jsi/jsi/" + ); + + if ( + fs.existsSync(reactNativeJsiPath) && + (force || + getLatestMtime(hermesJsiPath) > getLatestMtime(reactNativeJsiPath)) + ) { await oraPromise( - fs.promises.cp( - path.join(HERMES_PATH, "API/jsi/jsi"), - path.join(REACT_NATIVE_DIR, "ReactCommon/jsi/jsi/"), - { - recursive: true, - } - ), + fs.promises.cp(hermesJsiPath, reactNativeJsiPath, { + recursive: true, + }), { text: `Copying JSI from Hermes to React Native`, successText: "Copied JSI from Hermes to React Native", @@ -67,7 +85,7 @@ export const command = new Command("vendor-hermes") } ); } - console.log(HERMES_PATH); + console.log(hermesPath); } catch (error) { if (error instanceof SpawnFailure) { error.flushOutput("both"); From e78ed70dd2cf6f08087892c0445e63383418ec66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Sat, 17 May 2025 13:35:46 +0200 Subject: [PATCH 2/5] Clean hermes using async fs --- .../src/node/cli/hermes.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/react-native-node-api-modules/src/node/cli/hermes.ts b/packages/react-native-node-api-modules/src/node/cli/hermes.ts index df717f14..a6338e5f 100644 --- a/packages/react-native-node-api-modules/src/node/cli/hermes.ts +++ b/packages/react-native-node-api-modules/src/node/cli/hermes.ts @@ -26,8 +26,17 @@ export const command = new Command("vendor-hermes") const appPackageRoot = packageDirectorySync({ cwd: from }); assert(appPackageRoot, "Failed to find package root"); const hermesPath = path.join(HOST_PACKAGE_ROOT, "hermes"); - if (force) { - fs.rmSync(hermesPath, { recursive: true, force: true }); + if (force && fs.existsSync(hermesPath)) { + await oraPromise( + fs.promises.rm(hermesPath, { recursive: true, force: true }), + { + text: "Removing existing Hermes clone", + successText: "Removed existing Hermes clone", + failText: (error) => + `Failed to remove existing Hermes clone: ${error.message}`, + isEnabled: !silent, + } + ); } if (!fs.existsSync(hermesPath)) { await oraPromise( From d675b81ab40a3773cf7318c51a8df3dea1b10e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Sat, 17 May 2025 14:02:55 +0200 Subject: [PATCH 3/5] Add babel entry-point fallback to "files" --- packages/react-native-node-api-modules/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-node-api-modules/package.json b/packages/react-native-node-api-modules/package.json index 425ec03c..e0eac737 100644 --- a/packages/react-native-node-api-modules/package.json +++ b/packages/react-native-node-api-modules/package.json @@ -31,6 +31,7 @@ "!android/build", "ios", "include", + "babel-plugin.js", "scripts/patch-hermes.rb", "weak-node-api/**", "!weak-node-api/build/", From 4c9d21efb2aa8912a581aa56e4e71708a11a61fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Sat, 17 May 2025 14:03:10 +0200 Subject: [PATCH 4/5] Add React Native 0.79.2 to supported versions --- packages/react-native-node-api-modules/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-node-api-modules/package.json b/packages/react-native-node-api-modules/package.json index e0eac737..c7f07a71 100644 --- a/packages/react-native-node-api-modules/package.json +++ b/packages/react-native-node-api-modules/package.json @@ -90,7 +90,7 @@ }, "peerDependencies": { "@babel/core": "^7.26.10", - "react-native": "0.79.1" + "react-native": "0.79.1 || 0.79.2" }, "codegenConfig": { "name": "NodeApiHostSpec", From 93c3c64d403d781f8e3d3c0283cd71ed747b41b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 22 May 2025 07:57:49 +0200 Subject: [PATCH 5/5] Update packages/react-native-node-api-modules/src/node/cli/hermes.ts Co-authored-by: Matt Hargett --- packages/react-native-node-api-modules/src/node/cli/hermes.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-node-api-modules/src/node/cli/hermes.ts b/packages/react-native-node-api-modules/src/node/cli/hermes.ts index a6338e5f..40128e9b 100644 --- a/packages/react-native-node-api-modules/src/node/cli/hermes.ts +++ b/packages/react-native-node-api-modules/src/node/cli/hermes.ts @@ -10,6 +10,7 @@ import { packageDirectorySync } from "pkg-dir"; import { getLatestMtime, prettyPath } from "../path-utils"; const HOST_PACKAGE_ROOT = path.resolve(__dirname, "../../.."); +// FIXME: make this configurable with reasonable fallback before public release const HERMES_GIT_URL = "https://github.com/kraenhansen/hermes.git"; const HERMES_GIT_TAG = "node-api-for-react-native-0.79.0";