@bash0816/claude-code 2.1.222 → 2.1.223
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -616,6 +616,24 @@
|
|
|
616
616
|
"entry_end_offset": 279849039,
|
|
617
617
|
"tarball_integrity": "sha512-EXSediF1ujcqQeElbXdCEe+uW3NUQAOjn1xHHAgvwzY08nzJeePjagn9+YS6bmhHxBgDKwlGu7pL8Kv7EpiFtg==",
|
|
618
618
|
"tarball_sha256": "1bb3c8364d652dd08a15856ee27c6600ecd1e45360243154fa846f240ce7a1df",
|
|
619
|
+
"status": "termux_verified"
|
|
620
|
+
},
|
|
621
|
+
"2.1.222-1": {
|
|
622
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.222",
|
|
623
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.222",
|
|
624
|
+
"entry_js_offset": 256895476,
|
|
625
|
+
"entry_end_offset": 279849039,
|
|
626
|
+
"tarball_integrity": "sha512-EXSediF1ujcqQeElbXdCEe+uW3NUQAOjn1xHHAgvwzY08nzJeePjagn9+YS6bmhHxBgDKwlGu7pL8Kv7EpiFtg==",
|
|
627
|
+
"tarball_sha256": "1bb3c8364d652dd08a15856ee27c6600ecd1e45360243154fa846f240ce7a1df",
|
|
628
|
+
"status": "offset_discovered"
|
|
629
|
+
},
|
|
630
|
+
"2.1.223": {
|
|
631
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.223",
|
|
632
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.223",
|
|
633
|
+
"entry_js_offset": 257987828,
|
|
634
|
+
"entry_end_offset": 281109040,
|
|
635
|
+
"tarball_integrity": "sha512-gh0n3fvUgzsrjeTqZraOhDKOzS7afB9U/qFvRY0FBpccogbJCk8otTYavPfdhAA2xESAoA0BaoVdzO4k4VkphA==",
|
|
636
|
+
"tarball_sha256": "29c49ec62bfbe995e5b1354a4c32d17101065d2c7722d5d0285cfa6a08d8c441",
|
|
619
637
|
"status": "offset_discovered"
|
|
620
638
|
}
|
|
621
639
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"package_name": "@bash0816/claude-code",
|
|
4
|
-
"latest_audited_version": "2.1.
|
|
5
|
-
"latest_candidate_version": "2.1.
|
|
6
|
-
"previous_stable_version": "2.1.220",
|
|
4
|
+
"latest_audited_version": "2.1.222",
|
|
5
|
+
"latest_candidate_version": "2.1.223",
|
|
6
|
+
"previous_stable_version": "2.1.220-2",
|
|
7
7
|
"stable_pinned_version": "2.1.193",
|
|
8
8
|
"manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
|
|
9
9
|
}
|
|
@@ -599,6 +599,7 @@ function rewriteNativeChunkSource(source) {
|
|
|
599
599
|
const _bunPropertyAccessExpected = (() => {
|
|
600
600
|
const _ver = String(process.env.CURRENT_CLAUDE_VERSION || '');
|
|
601
601
|
const _m = _ver.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
602
|
+
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 223)) return 43;
|
|
602
603
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 219)) return 42;
|
|
603
604
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 216)) return 40;
|
|
604
605
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 214)) return 39;
|
|
@@ -627,6 +628,13 @@ function rewriteNativeChunkSource(source) {
|
|
|
627
628
|
'npmInstallDeprecated flag',
|
|
628
629
|
_npmInstallDeprecatedExpected,
|
|
629
630
|
);
|
|
631
|
+
patched = replaceRequired(
|
|
632
|
+
patched,
|
|
633
|
+
/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,
|
|
634
|
+
'function $1(){return undefined;$2',
|
|
635
|
+
'bg-pty-host factory disable',
|
|
636
|
+
1,
|
|
637
|
+
);
|
|
630
638
|
return patched;
|
|
631
639
|
}
|
|
632
640
|
|
|
@@ -795,9 +803,47 @@ async function main() {
|
|
|
795
803
|
gte: (a, b) => _cmp(a, b) >= 0,
|
|
796
804
|
lt: (a, b) => _cmp(a, b) < 0,
|
|
797
805
|
lte: (a, b) => _cmp(a, b) <= 0,
|
|
798
|
-
|
|
806
|
+
};
|
|
799
807
|
})(),
|
|
800
808
|
YAML: globalThis.__claudeYaml,
|
|
809
|
+
spawn: (cmd, options) => {
|
|
810
|
+
const opts = options || {};
|
|
811
|
+
const stdioArrayRaw = opts.stdio;
|
|
812
|
+
const cmdArray = Array.isArray(cmd) ? cmd : [cmd];
|
|
813
|
+
const normalizeStdio = (v) => {
|
|
814
|
+
if (typeof v === 'number' && Number.isInteger(v) && v >= 0) return v;
|
|
815
|
+
return (v === 'ignore' || v === 'pipe' || v === 'inherit') ? v : 'pipe';
|
|
816
|
+
};
|
|
817
|
+
const stdioMapped = Array.isArray(stdioArrayRaw)
|
|
818
|
+
? stdioArrayRaw.map(normalizeStdio)
|
|
819
|
+
: [normalizeStdio(opts.stdin), normalizeStdio(opts.stdout), normalizeStdio(opts.stderr)];
|
|
820
|
+
const child = _realChild.spawn(cmdArray[0], cmdArray.slice(1), {
|
|
821
|
+
stdio: stdioMapped,
|
|
822
|
+
cwd: opts.cwd,
|
|
823
|
+
env: opts.env,
|
|
824
|
+
detached: !!opts.detached,
|
|
825
|
+
argv0: opts.argv0,
|
|
826
|
+
});
|
|
827
|
+
const stdoutChunks = [];
|
|
828
|
+
if (child.stdout) child.stdout.on('data', d => stdoutChunks.push(d));
|
|
829
|
+
let resolveExited;
|
|
830
|
+
const exited = new Promise(resolve => { resolveExited = resolve; });
|
|
831
|
+
child.on('exit', (code, signal) => resolveExited(code !== null ? code : (signal ? 128 : 0)));
|
|
832
|
+
child.on('error', () => resolveExited(1));
|
|
833
|
+
return {
|
|
834
|
+
pid: child.pid,
|
|
835
|
+
exited,
|
|
836
|
+
stdout: { text: async () => { await exited; return Buffer.concat(stdoutChunks).toString('utf8'); } },
|
|
837
|
+
unref: () => { try { child.unref(); } catch {} },
|
|
838
|
+
kill: (signal) => { try { child.kill(signal); } catch {} },
|
|
839
|
+
};
|
|
840
|
+
},
|
|
841
|
+
file: (path) => {
|
|
842
|
+
const err = new Error(`ENOENT: Bun.file(${String(path)}) is not supported by the Termux compatibility shim`);
|
|
843
|
+
err.code = 'ENOENT';
|
|
844
|
+
err.errno = -2;
|
|
845
|
+
throw err;
|
|
846
|
+
},
|
|
801
847
|
};
|
|
802
848
|
Object.assign(globalThis.__claudeBunShim, globalThis.Bun);
|
|
803
849
|
if (typeof globalThis.__claudeBunShim.gc !== 'function') {
|
|
@@ -1419,6 +1465,7 @@ function rewriteNativeChunkSource(source) {
|
|
|
1419
1465
|
const _bunPropertyAccessExpected = (() => {
|
|
1420
1466
|
const _ver = String(process.env.CURRENT_CLAUDE_VERSION || '');
|
|
1421
1467
|
const _m = _ver.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
1468
|
+
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 223)) return 43;
|
|
1422
1469
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 219)) return 42;
|
|
1423
1470
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 216)) return 40;
|
|
1424
1471
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 214)) return 39;
|
|
@@ -1447,6 +1494,13 @@ function rewriteNativeChunkSource(source) {
|
|
|
1447
1494
|
'npmInstallDeprecated flag',
|
|
1448
1495
|
_npmInstallDeprecatedExpected,
|
|
1449
1496
|
);
|
|
1497
|
+
patched = replaceRequired(
|
|
1498
|
+
patched,
|
|
1499
|
+
/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,
|
|
1500
|
+
'function $1(){return undefined;$2',
|
|
1501
|
+
'bg-pty-host factory disable',
|
|
1502
|
+
1,
|
|
1503
|
+
);
|
|
1450
1504
|
return patched;
|
|
1451
1505
|
}
|
|
1452
1506
|
|
|
@@ -1619,6 +1673,44 @@ async function main() {
|
|
|
1619
1673
|
};
|
|
1620
1674
|
})(),
|
|
1621
1675
|
YAML: globalThis.__claudeYaml,
|
|
1676
|
+
spawn: (cmd, options) => {
|
|
1677
|
+
const opts = options || {};
|
|
1678
|
+
const stdioArrayRaw = opts.stdio;
|
|
1679
|
+
const cmdArray = Array.isArray(cmd) ? cmd : [cmd];
|
|
1680
|
+
const normalizeStdio = (v) => {
|
|
1681
|
+
if (typeof v === 'number' && Number.isInteger(v) && v >= 0) return v;
|
|
1682
|
+
return (v === 'ignore' || v === 'pipe' || v === 'inherit') ? v : 'pipe';
|
|
1683
|
+
};
|
|
1684
|
+
const stdioMapped = Array.isArray(stdioArrayRaw)
|
|
1685
|
+
? stdioArrayRaw.map(normalizeStdio)
|
|
1686
|
+
: [normalizeStdio(opts.stdin), normalizeStdio(opts.stdout), normalizeStdio(opts.stderr)];
|
|
1687
|
+
const child = _realChild.spawn(cmdArray[0], cmdArray.slice(1), {
|
|
1688
|
+
stdio: stdioMapped,
|
|
1689
|
+
cwd: opts.cwd,
|
|
1690
|
+
env: opts.env,
|
|
1691
|
+
detached: !!opts.detached,
|
|
1692
|
+
argv0: opts.argv0,
|
|
1693
|
+
});
|
|
1694
|
+
const stdoutChunks = [];
|
|
1695
|
+
if (child.stdout) child.stdout.on('data', d => stdoutChunks.push(d));
|
|
1696
|
+
let resolveExited;
|
|
1697
|
+
const exited = new Promise(resolve => { resolveExited = resolve; });
|
|
1698
|
+
child.on('exit', (code, signal) => resolveExited(code !== null ? code : (signal ? 128 : 0)));
|
|
1699
|
+
child.on('error', () => resolveExited(1));
|
|
1700
|
+
return {
|
|
1701
|
+
pid: child.pid,
|
|
1702
|
+
exited,
|
|
1703
|
+
stdout: { text: async () => { await exited; return Buffer.concat(stdoutChunks).toString('utf8'); } },
|
|
1704
|
+
unref: () => { try { child.unref(); } catch {} },
|
|
1705
|
+
kill: (signal) => { try { child.kill(signal); } catch {} },
|
|
1706
|
+
};
|
|
1707
|
+
},
|
|
1708
|
+
file: (path) => {
|
|
1709
|
+
const err = new Error(`ENOENT: Bun.file(${String(path)}) is not supported by the Termux compatibility shim`);
|
|
1710
|
+
err.code = 'ENOENT';
|
|
1711
|
+
err.errno = -2;
|
|
1712
|
+
throw err;
|
|
1713
|
+
},
|
|
1622
1714
|
};
|
|
1623
1715
|
Object.assign(globalThis.__claudeBunShim, globalThis.Bun);
|
|
1624
1716
|
if (typeof globalThis.__claudeBunShim.gc !== 'function') {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const test = require('node:test');
|
|
4
|
+
const { mock } = require('node:test');
|
|
4
5
|
const assert = require('node:assert/strict');
|
|
5
6
|
const crypto = require('crypto');
|
|
6
7
|
const child_process = require('child_process');
|
|
@@ -300,9 +301,36 @@ test('cleanupStaleEntryFiles removes only stale extracted files for the same off
|
|
|
300
301
|
function buildSyntheticBundleSource() {
|
|
301
302
|
const typeofBun = Array.from({ length: 6 }, () => 'typeof Bun').join('; ');
|
|
302
303
|
const bunProps = Array.from({ length: 37 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
303
|
-
return `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0 }`;
|
|
304
|
+
return `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
304
305
|
}
|
|
305
306
|
|
|
307
|
+
test('rewriteNativeChunkSource disables the bg-pty-host factory', () => {
|
|
308
|
+
process.env.CURRENT_CLAUDE_VERSION = '2.1.198';
|
|
309
|
+
try {
|
|
310
|
+
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
311
|
+
const patched = rewriteNativeChunkSource(buildSyntheticBundleSource());
|
|
312
|
+
const start = patched.indexOf('function dYs(){');
|
|
313
|
+
assert.notEqual(start, -1);
|
|
314
|
+
let depth = 0;
|
|
315
|
+
let end = -1;
|
|
316
|
+
for (let index = start; index < patched.length; index += 1) {
|
|
317
|
+
if (patched[index] === '{') depth += 1;
|
|
318
|
+
if (patched[index] === '}') {
|
|
319
|
+
depth -= 1;
|
|
320
|
+
if (depth === 0) {
|
|
321
|
+
end = index + 1;
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
assert.notEqual(end, -1);
|
|
327
|
+
const rewrittenFactory = eval('(' + patched.slice(start, end) + ')');
|
|
328
|
+
assert.equal(rewrittenFactory(), undefined);
|
|
329
|
+
} finally {
|
|
330
|
+
delete process.env.CURRENT_CLAUDE_VERSION;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
306
334
|
test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.198)', () => {
|
|
307
335
|
process.env.CURRENT_CLAUDE_VERSION = '2.1.198';
|
|
308
336
|
try {
|
|
@@ -328,7 +356,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
328
356
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
329
357
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
330
358
|
const bunProps = Array.from({ length: 40 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
331
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0 }`;
|
|
359
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
332
360
|
const patched = rewriteNativeChunkSource(source);
|
|
333
361
|
|
|
334
362
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -349,7 +377,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
349
377
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
350
378
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
351
379
|
const bunProps = Array.from({ length: 41 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
352
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0 }`;
|
|
380
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
353
381
|
const patched = rewriteNativeChunkSource(source);
|
|
354
382
|
|
|
355
383
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -370,7 +398,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
370
398
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
371
399
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
372
400
|
const bunProps = Array.from({ length: 41 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
373
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
401
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
374
402
|
const patched = rewriteNativeChunkSource(source);
|
|
375
403
|
|
|
376
404
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -391,7 +419,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
391
419
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
392
420
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
393
421
|
const bunProps = Array.from({ length: 38 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
394
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
422
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
395
423
|
const patched = rewriteNativeChunkSource(source);
|
|
396
424
|
|
|
397
425
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -412,7 +440,7 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
|
|
|
412
440
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
413
441
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
414
442
|
const bunProps = Array.from({ length: 41 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
415
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
443
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
416
444
|
|
|
417
445
|
assert.throws(
|
|
418
446
|
() => rewriteNativeChunkSource(source),
|
|
@@ -429,7 +457,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
429
457
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
430
458
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
431
459
|
const bunProps = Array.from({ length: 39 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
432
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
460
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
433
461
|
const patched = rewriteNativeChunkSource(source);
|
|
434
462
|
|
|
435
463
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -450,7 +478,7 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
|
|
|
450
478
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
451
479
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
452
480
|
const bunProps = Array.from({ length: 38 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
453
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
481
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
454
482
|
|
|
455
483
|
assert.throws(
|
|
456
484
|
() => rewriteNativeChunkSource(source),
|
|
@@ -467,7 +495,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
467
495
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
468
496
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
469
497
|
const bunProps = Array.from({ length: 40 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
470
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
498
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
471
499
|
const patched = rewriteNativeChunkSource(source);
|
|
472
500
|
|
|
473
501
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -487,7 +515,7 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
|
|
|
487
515
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
488
516
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
489
517
|
const bunProps = Array.from({ length: 39 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
490
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
518
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
491
519
|
|
|
492
520
|
assert.throws(
|
|
493
521
|
() => rewriteNativeChunkSource(source),
|
|
@@ -504,7 +532,7 @@ test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.
|
|
|
504
532
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
505
533
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
506
534
|
const bunProps = Array.from({ length: 42 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
507
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
535
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
508
536
|
const patched = rewriteNativeChunkSource(source);
|
|
509
537
|
|
|
510
538
|
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
@@ -524,7 +552,7 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
|
|
|
524
552
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
525
553
|
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
526
554
|
const bunProps = Array.from({ length: 41 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
527
|
-
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0 }`;
|
|
555
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
528
556
|
|
|
529
557
|
assert.throws(
|
|
530
558
|
() => rewriteNativeChunkSource(source),
|
|
@@ -535,6 +563,43 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
|
|
|
535
563
|
}
|
|
536
564
|
});
|
|
537
565
|
|
|
566
|
+
test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.223)', () => {
|
|
567
|
+
process.env.CURRENT_CLAUDE_VERSION = '2.1.223';
|
|
568
|
+
try {
|
|
569
|
+
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
570
|
+
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
571
|
+
const bunProps = Array.from({ length: 43 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
572
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
573
|
+
const patched = rewriteNativeChunkSource(source);
|
|
574
|
+
|
|
575
|
+
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
576
|
+
assert.match(patched, /typeof __claudeBun/);
|
|
577
|
+
assert.match(patched, /typeof globalThis\.__claudeBun/);
|
|
578
|
+
assert.match(patched, /globalThis\.__claudeBun/);
|
|
579
|
+
assert.match(patched, /__claudeBun\./);
|
|
580
|
+
assert.equal((patched.match(/__claudeBun\./g) || []).length, 43);
|
|
581
|
+
} finally {
|
|
582
|
+
delete process.env.CURRENT_CLAUDE_VERSION;
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
test('rewriteNativeChunkSource rejects stale Bun property access count for version 2.1.223', () => {
|
|
587
|
+
process.env.CURRENT_CLAUDE_VERSION = '2.1.223';
|
|
588
|
+
try {
|
|
589
|
+
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
590
|
+
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
591
|
+
const bunProps = Array.from({ length: 42 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
592
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
593
|
+
|
|
594
|
+
assert.throws(
|
|
595
|
+
() => rewriteNativeChunkSource(source),
|
|
596
|
+
/unexpected Bun property access count 42/,
|
|
597
|
+
);
|
|
598
|
+
} finally {
|
|
599
|
+
delete process.env.CURRENT_CLAUDE_VERSION;
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
|
|
538
603
|
test('rewriteNativeChunkSource rejects unexpected replacement counts', () => {
|
|
539
604
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
540
605
|
const source = buildSyntheticBundleSource().replace('Bun.p30;', '');
|
|
@@ -571,6 +636,7 @@ function buildScenarioFixtureSource() {
|
|
|
571
636
|
return `function(exports, require, module, __filename, __dirname) {
|
|
572
637
|
${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps};
|
|
573
638
|
npmInstallDeprecated:!0; npmInstallDeprecated:!0;
|
|
639
|
+
function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}}
|
|
574
640
|
const scenario = process.env.TEST_SCENARIO;
|
|
575
641
|
if (scenario === 'sync-exit') { process.stdout.write('ok'); process.exit(0); return; }
|
|
576
642
|
if (scenario === 'async-exit') {
|
|
@@ -1338,3 +1404,145 @@ test('installStreamJsonTerminalWatcher waits for write callback before completin
|
|
|
1338
1404
|
|
|
1339
1405
|
watcher.restore();
|
|
1340
1406
|
});
|
|
1407
|
+
|
|
1408
|
+
function extractShimSource(block) {
|
|
1409
|
+
const startMarker = 'const _realChild = require(\'child_process\');';
|
|
1410
|
+
const endMarker = 'Object.assign(globalThis.__claudeBunShim, globalThis.Bun);';
|
|
1411
|
+
const start = block.indexOf(startMarker);
|
|
1412
|
+
assert.notEqual(start, -1, 'missing Bun shim start');
|
|
1413
|
+
const end = block.indexOf(endMarker, start);
|
|
1414
|
+
assert.notEqual(end, -1, 'missing Bun shim end');
|
|
1415
|
+
return block.slice(start, end + endMarker.length);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
function loadBunShim(source) {
|
|
1419
|
+
const context = vm.createContext({
|
|
1420
|
+
stringWidth: () => 0,
|
|
1421
|
+
wrapAnsi: value => value,
|
|
1422
|
+
stripANSI: value => value,
|
|
1423
|
+
stableHash: () => 0,
|
|
1424
|
+
__claudeYaml: {},
|
|
1425
|
+
Buffer,
|
|
1426
|
+
require,
|
|
1427
|
+
});
|
|
1428
|
+
context.__claudeBunShim = {};
|
|
1429
|
+
context.__claudeYaml = {};
|
|
1430
|
+
context.Bun = {};
|
|
1431
|
+
context.module = { exports: {} };
|
|
1432
|
+
vm.runInContext(`${source}\nmodule.exports = globalThis.__claudeBunShim;`, context);
|
|
1433
|
+
return context.module.exports;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
test('helper and bootstrap Bun shim source is identical', () => {
|
|
1437
|
+
const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1438
|
+
const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1439
|
+
assert.equal(extractShimSource(helperBlock), extractShimSource(bootstrapBlock));
|
|
1440
|
+
});
|
|
1441
|
+
|
|
1442
|
+
test('Bun.file always throws ENOENT', () => {
|
|
1443
|
+
for (const blockMarker of ['cat <<\'NODE\' > "$_helper"', 'cat <<\'NODE\' > "$_bootstrap"']) {
|
|
1444
|
+
const block = extractBlock(blockMarker, '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1445
|
+
const Bun = loadBunShim(extractShimSource(block));
|
|
1446
|
+
assert.throws(() => Bun.file('/some/path'), error =>
|
|
1447
|
+
error.code === 'ENOENT' && error.errno === -2);
|
|
1448
|
+
}
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
test('Bun.spawn supports top-level and array stdio forms', async () => {
|
|
1452
|
+
const block = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1453
|
+
const Bun = loadBunShim(extractShimSource(block));
|
|
1454
|
+
const topLevel = Bun.spawn(['echo', 'hello'], { stdout: 'pipe', stderr: 'ignore' });
|
|
1455
|
+
assert.equal(await topLevel.stdout.text(), 'hello\n');
|
|
1456
|
+
assert.equal(await topLevel.exited, 0);
|
|
1457
|
+
const arrayForm = Bun.spawn(['echo', 'hello'], { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
1458
|
+
assert.equal(await arrayForm.stdout.text(), 'hello\n');
|
|
1459
|
+
assert.equal(await arrayForm.exited, 0);
|
|
1460
|
+
});
|
|
1461
|
+
|
|
1462
|
+
test('Bun.spawn forwards options, preserves numeric fds, and delegates child controls', () => {
|
|
1463
|
+
const block = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1464
|
+
const calls = [];
|
|
1465
|
+
const handlers = {};
|
|
1466
|
+
const child = {
|
|
1467
|
+
pid: 123,
|
|
1468
|
+
stdout: null,
|
|
1469
|
+
on(event, handler) { handlers[event] = handler; return this; },
|
|
1470
|
+
unref() { calls.push(['unref']); },
|
|
1471
|
+
kill(signal) { calls.push(['kill', signal]); },
|
|
1472
|
+
};
|
|
1473
|
+
mock.method(child_process, 'spawn', (...args) => {
|
|
1474
|
+
calls.push(args);
|
|
1475
|
+
return child;
|
|
1476
|
+
});
|
|
1477
|
+
try {
|
|
1478
|
+
const Bun = loadBunShim(extractShimSource(block));
|
|
1479
|
+
const result = Bun.spawn(['cmd', 'arg'], {
|
|
1480
|
+
detached: true,
|
|
1481
|
+
argv0: 'argv0-value',
|
|
1482
|
+
cwd: '/tmp/work',
|
|
1483
|
+
env: { TEST: 'yes' },
|
|
1484
|
+
stdio: [0, 1, 2],
|
|
1485
|
+
});
|
|
1486
|
+
assert.deepEqual(JSON.parse(JSON.stringify(calls[0])), [
|
|
1487
|
+
'cmd',
|
|
1488
|
+
['arg'],
|
|
1489
|
+
{
|
|
1490
|
+
stdio: [0, 1, 2],
|
|
1491
|
+
cwd: '/tmp/work',
|
|
1492
|
+
env: { TEST: 'yes' },
|
|
1493
|
+
detached: true,
|
|
1494
|
+
argv0: 'argv0-value',
|
|
1495
|
+
},
|
|
1496
|
+
]);
|
|
1497
|
+
result.unref();
|
|
1498
|
+
result.kill('SIGTERM');
|
|
1499
|
+
assert.deepEqual(JSON.parse(JSON.stringify(calls.slice(1))), [['unref'], ['kill', 'SIGTERM']]);
|
|
1500
|
+
} finally {
|
|
1501
|
+
mock.restoreAll();
|
|
1502
|
+
}
|
|
1503
|
+
});
|
|
1504
|
+
|
|
1505
|
+
test('Bun.spawn prefers stdio array over top-level stdio options', () => {
|
|
1506
|
+
for (const blockMarker of ['cat <<\'NODE\' > "$_helper"', 'cat <<\'NODE\' > "$_bootstrap"']) {
|
|
1507
|
+
const block = extractBlock(blockMarker, '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1508
|
+
const calls = [];
|
|
1509
|
+
mock.method(child_process, 'spawn', (...args) => {
|
|
1510
|
+
calls.push(args);
|
|
1511
|
+
return { pid: 123, stdout: null, on() { return this; } };
|
|
1512
|
+
});
|
|
1513
|
+
try {
|
|
1514
|
+
const Bun = loadBunShim(extractShimSource(block));
|
|
1515
|
+
Bun.spawn(['cmd'], {
|
|
1516
|
+
stdio: [0, 1, 2],
|
|
1517
|
+
stdin: 'pipe',
|
|
1518
|
+
stdout: 'pipe',
|
|
1519
|
+
stderr: 'pipe',
|
|
1520
|
+
});
|
|
1521
|
+
assert.deepEqual(JSON.parse(JSON.stringify(calls[0][2])), {
|
|
1522
|
+
stdio: [0, 1, 2],
|
|
1523
|
+
detached: false,
|
|
1524
|
+
});
|
|
1525
|
+
} finally {
|
|
1526
|
+
mock.restoreAll();
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
});
|
|
1530
|
+
|
|
1531
|
+
test('Bun.spawn forwards top-level stdin in the first stdio position', () => {
|
|
1532
|
+
for (const blockMarker of ['cat <<\'NODE\' > "$_helper"', 'cat <<\'NODE\' > "$_bootstrap"']) {
|
|
1533
|
+
const block = extractBlock(blockMarker, '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1534
|
+
const calls = [];
|
|
1535
|
+
mock.method(child_process, 'spawn', (...args) => {
|
|
1536
|
+
calls.push(args);
|
|
1537
|
+
return { pid: 123, stdout: null, on() { return this; } };
|
|
1538
|
+
});
|
|
1539
|
+
try {
|
|
1540
|
+
const Bun = loadBunShim(extractShimSource(block));
|
|
1541
|
+
Bun.spawn(['cmd'], { stdin: 'inherit', stdout: 'pipe', stderr: 'ignore' });
|
|
1542
|
+
assert.equal(calls[0][2].stdio[0], 'inherit');
|
|
1543
|
+
assert.deepEqual(JSON.parse(JSON.stringify(calls[0][2].stdio)), ['inherit', 'pipe', 'ignore']);
|
|
1544
|
+
} finally {
|
|
1545
|
+
mock.restoreAll();
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
});
|