-
Notifications
You must be signed in to change notification settings - Fork 2
fix: disable bg-pty-host factory via native chunk source rewrite #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e548271
7ee98ac
da607b0
25ef6fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -627,6 +627,13 @@ function rewriteNativeChunkSource(source) { | |
| 'npmInstallDeprecated flag', | ||
| _npmInstallDeprecatedExpected, | ||
| ); | ||
| patched = replaceRequired( | ||
| patched, | ||
| /function ([A-Za-z_$][\w$]*)\(\)\{(return\([A-Za-z_$][\w$]*,[A-Za-z_$][\w$]*,[A-Za-z_$][\w$]*\)=>\{let\{cmd:([A-Za-z_$][\w$]*),prefixArgs:([A-Za-z_$][\w$]*)\}=[A-Za-z_$][\w$]*\(\{pinToCurrentBinary:!0\}\),[A-Za-z_$][\w$]*=\[\3,\.\.\.\4,"--bg-pty-host")/g, | ||
| 'function $1(){return undefined;$2', | ||
| 'bg-pty-host factory disable', | ||
| 1, | ||
| ); | ||
| return patched; | ||
| } | ||
|
|
||
|
|
@@ -795,9 +802,47 @@ async function main() { | |
| gte: (a, b) => _cmp(a, b) >= 0, | ||
| lt: (a, b) => _cmp(a, b) < 0, | ||
| lte: (a, b) => _cmp(a, b) <= 0, | ||
| }; | ||
| }; | ||
| })(), | ||
| YAML: globalThis.__claudeYaml, | ||
| spawn: (cmd, options) => { | ||
| const opts = options || {}; | ||
| const stdioArrayRaw = opts.stdio; | ||
| const cmdArray = Array.isArray(cmd) ? cmd : [cmd]; | ||
| const normalizeStdio = (v) => { | ||
| if (typeof v === 'number' && Number.isInteger(v) && v >= 0) return v; | ||
| return (v === 'ignore' || v === 'pipe' || v === 'inherit') ? v : 'pipe'; | ||
| }; | ||
| const stdioMapped = Array.isArray(stdioArrayRaw) | ||
| ? stdioArrayRaw.map(normalizeStdio) | ||
| : [normalizeStdio(opts.stdin), normalizeStdio(opts.stdout), normalizeStdio(opts.stderr)]; | ||
| const child = _realChild.spawn(cmdArray[0], cmdArray.slice(1), { | ||
| stdio: stdioMapped, | ||
| cwd: opts.cwd, | ||
| env: opts.env, | ||
| detached: !!opts.detached, | ||
| argv0: opts.argv0, | ||
| }); | ||
| const stdoutChunks = []; | ||
| if (child.stdout) child.stdout.on('data', d => stdoutChunks.push(d)); | ||
| let resolveExited; | ||
| const exited = new Promise(resolve => { resolveExited = resolve; }); | ||
| child.on('exit', (code, signal) => resolveExited(code !== null ? code : (signal ? 128 : 0))); | ||
| child.on('error', () => resolveExited(1)); | ||
|
Comment on lines
+830
to
+831
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a spawned command writes stdout that can still be draining after the process exits, resolving Useful? React with 👍 / 👎. |
||
| return { | ||
| pid: child.pid, | ||
| exited, | ||
| stdout: { text: async () => { await exited; return Buffer.concat(stdoutChunks).toString('utf8'); } }, | ||
| unref: () => { try { child.unref(); } catch {} }, | ||
| kill: (signal) => { try { child.kill(signal); } catch {} }, | ||
| }; | ||
| }, | ||
| file: (path) => { | ||
| const err = new Error(`ENOENT: Bun.file(${String(path)}) is not supported by the Termux compatibility shim`); | ||
| err.code = 'ENOENT'; | ||
| err.errno = -2; | ||
| throw err; | ||
| }, | ||
| }; | ||
| Object.assign(globalThis.__claudeBunShim, globalThis.Bun); | ||
| if (typeof globalThis.__claudeBunShim.gc !== 'function') { | ||
|
|
@@ -1447,6 +1492,13 @@ function rewriteNativeChunkSource(source) { | |
| 'npmInstallDeprecated flag', | ||
| _npmInstallDeprecatedExpected, | ||
| ); | ||
| patched = replaceRequired( | ||
| patched, | ||
| /function ([A-Za-z_$][\w$]*)\(\)\{(return\([A-Za-z_$][\w$]*,[A-Za-z_$][\w$]*,[A-Za-z_$][\w$]*\)=>\{let\{cmd:([A-Za-z_$][\w$]*),prefixArgs:([A-Za-z_$][\w$]*)\}=[A-Za-z_$][\w$]*\(\{pinToCurrentBinary:!0\}\),[A-Za-z_$][\w$]*=\[\3,\.\.\.\4,"--bg-pty-host")/g, | ||
| 'function $1(){return undefined;$2', | ||
| 'bg-pty-host factory disable', | ||
| 1, | ||
| ); | ||
| return patched; | ||
| } | ||
|
|
||
|
|
@@ -1619,6 +1671,44 @@ async function main() { | |
| }; | ||
| })(), | ||
| YAML: globalThis.__claudeYaml, | ||
| spawn: (cmd, options) => { | ||
| const opts = options || {}; | ||
| const stdioArrayRaw = opts.stdio; | ||
| const cmdArray = Array.isArray(cmd) ? cmd : [cmd]; | ||
| const normalizeStdio = (v) => { | ||
| if (typeof v === 'number' && Number.isInteger(v) && v >= 0) return v; | ||
| return (v === 'ignore' || v === 'pipe' || v === 'inherit') ? v : 'pipe'; | ||
| }; | ||
| const stdioMapped = Array.isArray(stdioArrayRaw) | ||
| ? stdioArrayRaw.map(normalizeStdio) | ||
| : [normalizeStdio(opts.stdin), normalizeStdio(opts.stdout), normalizeStdio(opts.stderr)]; | ||
| const child = _realChild.spawn(cmdArray[0], cmdArray.slice(1), { | ||
| stdio: stdioMapped, | ||
| cwd: opts.cwd, | ||
| env: opts.env, | ||
| detached: !!opts.detached, | ||
| argv0: opts.argv0, | ||
| }); | ||
| const stdoutChunks = []; | ||
| if (child.stdout) child.stdout.on('data', d => stdoutChunks.push(d)); | ||
| let resolveExited; | ||
| const exited = new Promise(resolve => { resolveExited = resolve; }); | ||
| child.on('exit', (code, signal) => resolveExited(code !== null ? code : (signal ? 128 : 0))); | ||
| child.on('error', () => resolveExited(1)); | ||
| return { | ||
| pid: child.pid, | ||
| exited, | ||
| stdout: { text: async () => { await exited; return Buffer.concat(stdoutChunks).toString('utf8'); } }, | ||
| unref: () => { try { child.unref(); } catch {} }, | ||
| kill: (signal) => { try { child.kill(signal); } catch {} }, | ||
| }; | ||
| }, | ||
| file: (path) => { | ||
| const err = new Error(`ENOENT: Bun.file(${String(path)}) is not supported by the Termux compatibility shim`); | ||
| err.code = 'ENOENT'; | ||
| err.errno = -2; | ||
| throw err; | ||
| }, | ||
| }; | ||
| Object.assign(globalThis.__claudeBunShim, globalThis.Bun); | ||
| if (typeof globalThis.__claudeBunShim.gc !== 'function') { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the upstream bundle uses the new
Bun.spawnshim to launch an npm/pnpm/yarn/npx update path, this delegates straight to the realchild_process.spawninstead of the guarded child-process wrapper that blocks official self-updates. That creates a second process-spawning API which bypassesnative-update-guard.js, so the same command blocked throughrequire('child_process')can run if reached throughBun.spawn; build the shim on the guarded child process object instead.Useful? React with 👍 / 👎.