Files
nexe/src/steps/shim.ts
T
oxmc bc2c72d4e8 release: 5.0.0-beta
CI / infra:
  - Replace azure-pipelines with GitHub Actions (build-asset.yml)
  - Build and publish pre-built assets for windows-x64, mac-arm64,
    linux-x64, and linux-x64-musl on tag push
  - Remove EOL Node 18 and 20 from build matrix; default to lts/*, 22, 24

  Bug fixes:
  - fix: _assembleDeliverable deadlock — bundle.finalize() must be called
    before MultiStream starts consuming; calling it in the Transform's
    first-chunk callback deadlocked because archiver never emits without
    finalize, so the sentinel and trailers were never written
  - fix: ESM realpathSync ENOENT on Node 22.22+ / Node 24 — these versions
    removed the ENOENT catch in finalizeResolution; VFS paths don't exist
    on real FS so binding.lstat throws. Two-pronged fix:
    (1) boot-nexe.ts: install ENOENT-tolerant wrapper before _compile()
    (2) shim.ts: re-apply wrapper after shimFs() overwrites boot-nexe's
        patch, so the ESM resolver captures the tolerant version at first
        ESM load
  - fix: replace got (unmaintained) with axios in download step
  - fix: update default remote to oxmc/nexe releases

  Features:
  - macOS binary signing support (patchMachOExecutable)
  - bundleRules option for fine-grained VFS include/exclude per module
  - Improved SnapshotZipFS path handling and fallback behaviour
2026-05-19 01:16:37 -07:00

52 lines
1.7 KiB
TypeScript

import { NexeCompiler } from "../compiler";
import { wrap } from "../util";
export default async function (
compiler: NexeCompiler,
next: () => Promise<void>
) {
await next();
compiler.shims.push(
wrap(
[
"process.__nexe = {};",
"const fsPatcher = (function() {",
"const module = {exports: {}};",
"const exports = module.exports;",
'{{file("lib/fs/patch.bundle.js")}}',
"return module.exports;",
"})()",
"fsPatcher.shimFs(process.__nexe);",
// Re-apply ENOENT-tolerant realpathSync after shimFs overwrites boot-nexe's patch.
// Node 22.22+ / 24 no longer catches ENOENT in ESM finalizeResolution.
// ESM resolver captures fs.realpathSync by destructuring at first ESM load,
// which happens after the shim runs — so this wrapper is what it captures.
"(function(){var _fs=require('fs'),_o=_fs.realpathSync;_fs.realpathSync=function(p,o){try{return _o.call(this,p,o);}catch(e){if(e&&e.code==='ENOENT')return p;throw e;}};_fs.realpathSync.native=_o.native||_o;})()",
compiler.options.fs ? "" : "restoreFs();",
].join("\n")
//TODO support only restoring specific methods
)
);
compiler.shims.push(
wrap(`
if (process.argv[1] && process.env.NODE_UNIQUE_ID) {
const cluster = require('cluster')
cluster._setupWorker()
delete process.env.NODE_UNIQUE_ID
}
`)
);
compiler.shims.push(
wrap(`
if (!process.send) {
const path = require('path')
const entry = path.resolve(path.dirname(process.execPath),${JSON.stringify(
compiler.entrypoint
)})
process.argv.splice(1,0, entry)
}
`)
);
}