diff --git a/.changeset/cuddly-months-think.md b/.changeset/cuddly-months-think.md new file mode 100644 index 000000000..6f79b23d7 --- /dev/null +++ b/.changeset/cuddly-months-think.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Fix hermes-compiler path for RN 0.82+ in the hermes bytecode plugin diff --git a/packages/repack/src/plugins/HermesBytecodePlugin/utils/getHermesCLIPath.ts b/packages/repack/src/plugins/HermesBytecodePlugin/utils/getHermesCLIPath.ts index c5cad5b33..61b031414 100644 --- a/packages/repack/src/plugins/HermesBytecodePlugin/utils/getHermesCLIPath.ts +++ b/packages/repack/src/plugins/HermesBytecodePlugin/utils/getHermesCLIPath.ts @@ -1,3 +1,4 @@ +import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; @@ -20,7 +21,7 @@ const getHermesOSBin = (): string | null => { /** * Determines the path to the Hermes compiler binary. * - * Defaults to './node_modules/react-native/sdks/hermesc/{os-bin}/hermesc' + * Defaults to './node_modules/hermes-compiler/hermesc/{os-bin}/hermesc' */ export const getHermesCLIPath = (reactNativePath: string): string => { const osBin = getHermesOSBin(); @@ -32,5 +33,19 @@ export const getHermesCLIPath = (reactNativePath: string): string => { ); } + const hermesCompilerPath = path.join( + reactNativePath, + '..', + 'hermes-compiler', + 'hermesc', + osBin, + 'hermesc' + ); + + if (fs.existsSync(hermesCompilerPath)) { + return hermesCompilerPath; + } + + // Fallback to the previous hermesc path in older react native versions, <0.82. return path.join(reactNativePath, 'sdks', 'hermesc', osBin, 'hermesc'); }; diff --git a/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts b/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts index 10568640b..f93c32447 100644 --- a/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts +++ b/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts @@ -1,11 +1,14 @@ import fs from 'node:fs'; +import os from 'node:os'; import { type Compiler, ModuleFilenameHelpers } from '@rspack/core'; import execa from 'execa'; import { HermesBytecodePlugin } from '../HermesBytecodePlugin/index.js'; +import { getHermesCLIPath } from '../HermesBytecodePlugin/utils/getHermesCLIPath.js'; jest.mock('node:fs', () => ({ __esModule: true, default: { + existsSync: jest.fn(), promises: { access: jest.fn(), rename: jest.fn(), @@ -142,4 +145,30 @@ describe('HermesBytecodePlugin', () => { expect(execaMock.mock.calls[0][0]).toEqual('path/to/hermesc'); }); }); + + describe('getHermesCLIPath', () => { + const reactNativePath = 'path/to/react-native'; + + it('returns new hermes-compiler path when it exists', () => { + jest.spyOn(os, 'platform').mockReturnValue('darwin'); + jest.mocked(fs.existsSync).mockReturnValue(true); + + const hermesPath = getHermesCLIPath(reactNativePath); + + expect(hermesPath).toBe( + 'path/to/hermes-compiler/hermesc/osx-bin/hermesc' + ); + }); + + it('falls back to legacy hermesc path when hermes-compiler does not exist', () => { + jest.spyOn(os, 'platform').mockReturnValue('darwin'); + jest.mocked(fs.existsSync).mockReturnValue(false); + + const hermesPath = getHermesCLIPath(reactNativePath); + + expect(hermesPath).toBe( + 'path/to/react-native/sdks/hermesc/osx-bin/hermesc' + ); + }); + }); });