fix(desktop): find spawn-helper in universal macOS builds (#1630)

The universal build ships app-arm64.asar and app-x64.asar instead of
app.asar, so node-pty's helper path rewrite never pointed at the
unpacked copy and every local terminal failed with posix_spawnp failed.
This commit is contained in:
ZacharyZcR authored and GitHub committed 2026-10-14 08:59:46 +08:00
1 parent 4c9ee5923e
commit 1396b3a70c
4 files changed
+129 -36

No files matched your search

@@ -11,7 +11,48 @@ import { tmpdir } from "node:os";
import { describe, expect, it } from "vitest";
const require = createRequire(import.meta.url);
const { chmodSpawnHelpers } = require("../../../../scripts/patch-node-pty.cjs");
const {
chmodSpawnHelpers,
patchUnixTerminalHelperRewrite,
} = require("../../../../scripts/patch-node-pty.cjs");
const upstreamRewrite = [
"helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');",
"helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');",
].join("\n");
const previouslyPatchedRewrite = [
"if (!helperPath.includes('app.asar.unpacked')) {",
" helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');",
"}",
"if (!helperPath.includes('node_modules.asar.unpacked')) {",
" helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');",
"}",
].join("\n");
const resources = "/Applications/Termix.app/Contents/Resources";
const helperPaths = [
["app.asar", "app.asar.unpacked"],
["app-arm64.asar", "app-arm64.asar.unpacked"],
["app-x64.asar", "app-x64.asar.unpacked"],
["app.asar.unpacked", "app.asar.unpacked"],
["app-arm64.asar.unpacked", "app-arm64.asar.unpacked"],
].map(([from, to]) => [
`${resources}/${from}/node_modules/node-pty/build/Release/spawn-helper`,
`${resources}/${to}/node_modules/node-pty/build/Release/spawn-helper`,
]);
function writeUnixTerminal(rewrite: string) {
const file = join(
tmpdir(),
`termix-unix-terminal-${Date.now()}-${Math.random()}.cjs`,
);
writeFileSync(
file,
`module.exports = function (helperPath) {\n${rewrite}\nreturn helperPath;\n};\n`,
);
return file;
}
// chmod's execute bit is a POSIX concept; Windows/NTFS has no equivalent mode bit.
const itPosix = process.platform === "win32" ? it.skip : it;
@@ -30,4 +71,22 @@ describe("patch-node-pty", () => {
expect(chmodSpawnHelpers(root)).toBe(0);
expect(existsSync(helper)).toBe(true);
});
it.each([
["upstream", upstreamRewrite],
["previously patched", previouslyPatchedRewrite],
])(
"points the %s helper path at the unpacked copy of any app asar",
(_, rewrite) => {
const file = writeUnixTerminal(rewrite);
expect(patchUnixTerminalHelperRewrite(file)).toBe(true);
expect(patchUnixTerminalHelperRewrite(file)).toBe(false);
const rewriteHelperPath = require(file);
for (const [from, to] of helperPaths) {
expect(rewriteHelperPath(from)).toBe(to);
}
},
);
});