-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathhermes.ts
More file actions
131 lines (123 loc) · 4.2 KB
/
hermes.ts
File metadata and controls
131 lines (123 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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 { packageDirectorySync } from "pkg-dir";
import { 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";
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 (from, { force, silent }) => {
try {
const appPackageRoot = packageDirectorySync({ cwd: from });
assert(appPackageRoot, "Failed to find package root");
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 hermesVersionPath = path.join(
reactNativePath,
"sdks",
".hermesversion"
);
const hermesVersion = fs.readFileSync(hermesVersionPath, "utf8").trim();
if (!silent) {
console.log(`Using Hermes version: ${hermesVersion}`);
}
const reactNativeJsiPath = path.join(
reactNativePath,
"ReactCommon/jsi/jsi/"
);
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}`,
isSilent: silent,
}
);
}
if (!fs.existsSync(hermesPath)) {
const patchedTag = `node-api-${hermesVersion}`;
try {
await oraPromise(
spawn(
"git",
[
"clone",
"--recursive",
"--depth",
"1",
"--branch",
patchedTag,
HERMES_GIT_URL,
hermesPath,
],
{
outputMode: "buffered",
}
),
{
text: `Cloning custom Hermes into ${prettyPath(hermesPath)}`,
successText: "Cloned custom Hermes",
failText: (err) =>
`Failed to clone custom Hermes: ${err.message}`,
isSilent: silent,
}
);
} catch (error) {
if (error instanceof SpawnFailure) {
error.flushOutput("both");
console.error(
`\n🛑 React Native uses the ${hermesVersion} tag and cloning our fork failed.`,
`Please see the Node-API package's peer dependency on "react-native" for supported versions.`
);
process.exitCode = 1;
return;
} else {
throw error;
}
}
}
const hermesJsiPath = path.join(hermesPath, "API/jsi/jsi");
assert(
fs.existsSync(hermesJsiPath),
`Hermes JSI path does not exist: ${hermesJsiPath}`
);
await oraPromise(
fs.promises.cp(hermesJsiPath, reactNativeJsiPath, {
recursive: true,
}),
{
text: `Copying JSI from patched Hermes to React Native`,
successText: "Copied JSI from patched Hermes to React Native",
failText: (err) =>
`Failed to copy JSI from Hermes to React Native: ${err.message}`,
isSilent: silent,
}
);
console.log(hermesPath);
} catch (error) {
process.exitCode = 1;
if (error instanceof SpawnFailure) {
error.flushOutput("both");
}
throw error;
}
});