"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