118 lines
5.0 KiB
JavaScript
118 lines
5.0 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.buildHermesBundleAsync = buildHermesBundleAsync;
|
|
const metro_source_map_1 = require("@expo/metro/metro-source-map");
|
|
const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
|
|
const chalk_1 = __importDefault(require("chalk"));
|
|
const fs_1 = __importDefault(require("fs"));
|
|
const os_1 = __importDefault(require("os"));
|
|
const path_1 = __importDefault(require("path"));
|
|
const process_1 = __importDefault(require("process"));
|
|
const resolve_from_1 = __importDefault(require("resolve-from"));
|
|
const debug = require('debug')('expo:metro:hermes');
|
|
function importHermesCommandFromProject(projectRoot) {
|
|
const platformExecutable = getHermesCommandPlatform();
|
|
const reactNativeRoot = path_1.default.dirname((0, resolve_from_1.default)(projectRoot, 'react-native/package.json'));
|
|
const hermesCompilerRoot = path_1.default.dirname((0, resolve_from_1.default)(reactNativeRoot, 'hermes-compiler/package.json'));
|
|
const hermescPaths = [
|
|
// Override hermesc dir by environment variables
|
|
process_1.default.env['REACT_NATIVE_OVERRIDE_HERMES_DIR']
|
|
? `${process_1.default.env['REACT_NATIVE_OVERRIDE_HERMES_DIR']}/build/bin/hermesc`
|
|
: '',
|
|
// Building hermes from source
|
|
`${reactNativeRoot}/ReactAndroid/hermes-engine/build/hermes/bin/hermesc`,
|
|
// react-native 0.83+ moved hermesc to a separate package
|
|
`${hermesCompilerRoot}/hermesc/${platformExecutable}`,
|
|
// Prebuilt hermesc in official react-native 0.69+
|
|
`${reactNativeRoot}/sdks/hermesc/${platformExecutable}`,
|
|
];
|
|
for (const hermescPath of hermescPaths) {
|
|
try {
|
|
if (fs_1.default.existsSync(hermescPath)) {
|
|
return hermescPath;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
throw new Error('Cannot find the hermesc executable.');
|
|
}
|
|
function getHermesCommandPlatform() {
|
|
switch (os_1.default.platform()) {
|
|
case 'darwin':
|
|
return 'osx-bin/hermesc';
|
|
case 'linux':
|
|
return 'linux64-bin/hermesc';
|
|
case 'win32':
|
|
return 'win64-bin/hermesc.exe';
|
|
default:
|
|
throw new Error(`Unsupported host platform for Hermes compiler: ${os_1.default.platform()}`);
|
|
}
|
|
}
|
|
// Only one hermes build at a time is supported.
|
|
let currentHermesBuild = null;
|
|
async function buildHermesBundleAsync(options) {
|
|
if (currentHermesBuild) {
|
|
debug(`Waiting for existing Hermes builds to finish`);
|
|
await currentHermesBuild;
|
|
}
|
|
currentHermesBuild = directlyBuildHermesBundleAsync(options);
|
|
return await currentHermesBuild;
|
|
}
|
|
async function directlyBuildHermesBundleAsync({ projectRoot, code, map, minify = false, filename, }) {
|
|
const tempDir = path_1.default.join(os_1.default.tmpdir(), `expo-bundler-${Math.random()}-${Date.now()}`);
|
|
await fs_1.default.promises.mkdir(tempDir, { recursive: true });
|
|
try {
|
|
const tempBundleFile = path_1.default.join(tempDir, 'index.js');
|
|
await fs_1.default.promises.writeFile(tempBundleFile, code, 'utf8');
|
|
if (map) {
|
|
const tempSourcemapFile = path_1.default.join(tempDir, 'index.js.map');
|
|
await fs_1.default.promises.writeFile(tempSourcemapFile, map, 'utf8');
|
|
}
|
|
const tempHbcFile = path_1.default.join(tempDir, 'index.hbc');
|
|
const hermesCommand = importHermesCommandFromProject(projectRoot);
|
|
const args = ['-emit-binary', '-out', tempHbcFile, tempBundleFile];
|
|
if (minify) {
|
|
args.push('-O');
|
|
}
|
|
if (map) {
|
|
args.push('-output-source-map');
|
|
}
|
|
debug(`Running hermesc: ${hermesCommand} ${args.join(' ')}`);
|
|
await (0, spawn_async_1.default)(hermesCommand, args);
|
|
let hbc;
|
|
let sourcemap = null;
|
|
if (!map) {
|
|
hbc = await fs_1.default.promises.readFile(tempHbcFile);
|
|
}
|
|
else {
|
|
[hbc, sourcemap] = await Promise.all([
|
|
fs_1.default.promises.readFile(tempHbcFile),
|
|
createHermesSourcemapAsync(map, `${tempHbcFile}.map`),
|
|
]);
|
|
}
|
|
return {
|
|
hbc,
|
|
sourcemap,
|
|
};
|
|
}
|
|
catch (error) {
|
|
console.error(chalk_1.default.red(`\nFailed to generate Hermes bytecode for: ${filename}`));
|
|
if ('status' in error) {
|
|
console.error(error.output.join('\n'));
|
|
}
|
|
throw error;
|
|
}
|
|
finally {
|
|
await fs_1.default.promises.rm(tempDir, { force: true, recursive: true });
|
|
}
|
|
}
|
|
async function createHermesSourcemapAsync(sourcemap, hermesMapFile) {
|
|
const bundlerSourcemap = JSON.parse(sourcemap);
|
|
const hermesSourcemapContent = await fs_1.default.promises.readFile(hermesMapFile, 'utf8');
|
|
const hermesSourcemap = JSON.parse(hermesSourcemapContent);
|
|
return JSON.stringify((0, metro_source_map_1.composeSourceMaps)([bundlerSourcemap, hermesSourcemap]));
|
|
}
|
|
//# sourceMappingURL=exportHermes.js.map
|