revenge-bundle-next/scripts/plugins/hermesc.ts

89 lines
2.9 KiB
TypeScript
Raw Permalink Normal View History

import { spawnSync } from 'child_process'
import { existsSync, readFileSync } from 'fs'
import type { OutputChunk, RolldownPlugin } from 'rolldown'
export default function hermesCPlugin({
after,
before,
flags,
}: {
flags?: string[]
before?: (v: string) => void
after?: (v: string) => void
} = {}): RolldownPlugin {
const paths = {
win32: 'win64-bin/hermesc.exe',
darwin: 'osx-bin/hermesc',
linux: 'linux64-bin/hermesc',
}
if (!(process.platform in paths))
throw new Error(`Unsupported platform: ${process.platform}`)
const sdksDir = './node_modules/hermes-compiler/hermesc'
const binPath = `${sdksDir}/${paths[process.platform as keyof typeof paths]}`
if (!existsSync(binPath))
throw new Error(
`Hermes compiler not found at ${binPath}. Please ensure you have react-native installed.`,
)
const ver = JSON.parse(
readFileSync(`${sdksDir}/../package.json`).toString(),
).version
return {
name: 'hermesc',
generateBundle(_, bundle) {
if (before) before(ver)
const file = bundle['revenge.js'] as OutputChunk
if (!file) throw new Error('No code to compile')
const argList = ['-emit-binary', ...(flags ?? [])]
const cmd =
// TODO: Move away from Bun: https://github.com/oven-sh/bun/issues/25498
typeof Bun !== 'undefined'
? (() => {
const cmd = Bun.spawnSync([binPath, ...argList], {
// @ts-expect-error: Works but types are incorrect
stdio: [new Blob([file.code]), 'pipe'],
})
return {
status: cmd.exitCode,
stdout: cmd.stdout,
stderr: cmd.stderr,
}
})()
: spawnSync(binPath, argList, {
stdio: ['pipe', 'pipe'],
input: file.code,
})
if (cmd.status !== 0) {
if (cmd.stderr.length)
throw new Error(
`Got error from hermesc: ${cmd.stderr.toString()}`,
)
else throw new Error(`hermesc exited with code: ${cmd.status}`)
}
const buf = cmd.stdout
if (!buf.length)
throw new Error(
`No output from hermesc. Probably a compilation error.\nTry running the command manually: ${binPath} ${argList.join(' ')}`,
)
this.emitFile({
type: 'asset',
fileName: `${file.fileName.split('.')[0]!}.bundle`,
source: buf,
})
if (after) after(ver)
},
}
}