Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions apps/test-app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ msbuild.binlog

# Ignoring the Podfile.lock as the `react-native-node-api-modules` hash updates too frequently
Podfile.lock

hermes/
3 changes: 2 additions & 1 deletion packages/react-native-node-api-modules/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"!android/build",
"ios",
"include",
"babel-plugin.js",
"scripts/patch-hermes.rb",
"weak-node-api/**",
"!weak-node-api/build/",
Expand Down Expand Up @@ -89,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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
65 changes: 46 additions & 19 deletions packages/react-native-node-api-modules/src/node/cli/hermes.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
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 {
if (force) {
fs.rmSync(HERMES_PATH, { recursive: true, force: true });
const appPackageRoot = packageDirectorySync({ cwd: from });
assert(appPackageRoot, "Failed to find package root");
const hermesPath = path.join(HOST_PACKAGE_ROOT, "hermes");
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(HERMES_PATH)) {
if (!fs.existsSync(hermesPath)) {
await oraPromise(
spawn(
"git",
Expand All @@ -37,27 +50,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",
Expand All @@ -67,7 +94,7 @@ export const command = new Command("vendor-hermes")
}
);
}
console.log(HERMES_PATH);
console.log(hermesPath);
} catch (error) {
if (error instanceof SpawnFailure) {
error.flushOutput("both");
Expand Down