This commit is contained in:
Clay 2026-04-21 04:31:49 +00:00 committed by GitHub
commit b9859af565
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 25 additions and 1 deletions

View file

@ -25,6 +25,7 @@ import {
import { NoopSandboxManager } from './sandboxManager.js';
import { ExecutionLifecycleService } from './executionLifecycleService.js';
import type { AnsiOutput, AnsiToken } from '../utils/terminalSerializer.js';
import { getCachedEncodingForBuffer } from '../utils/systemEncoding.js';
// Hoisted Mocks
const mockPtySpawn = vi.hoisted(() => vi.fn());
@ -338,6 +339,23 @@ describe('ShellExecutionService', () => {
expect(result.output.trim()).toBe('你好');
});
it('should decode PTY output as UTF-8 regardless of system encoding', async () => {
// Simulate a Japanese Windows system where chcp returns code page 932 (Shift-JIS).
// The PTY decoder should be pre-initialized to UTF-8, so this mock override
// should have no effect on PTY output decoding. Regression test for #12468.
vi.mocked(getCachedEncodingForBuffer).mockReturnValue('shift_jis');
const { result } = await simulateExecution('echo "こんにちは"', (pty) => {
pty.onData.mock.calls[0][0]('こんにちは\r\n');
pty.onExit.mock.calls[0][0]({ exitCode: 0, signal: null });
});
expect(result.output).toContain('こんにちは');
// Restore default mock for subsequent tests
vi.mocked(getCachedEncodingForBuffer).mockReturnValue('utf-8');
});
it('should handle commands with no output', async () => {
mockSerializeTerminalToObject.mockReturnValue(
createMockSerializeTerminalToObjectReturnValue(''),

View file

@ -984,7 +984,13 @@ export class ShellExecutionService {
}).result;
let processingChain = Promise.resolve();
let decoder: TextDecoder | null = null;
// node-pty delivers data as JavaScript strings via onData().
// Buffer.from(data, 'utf-8') in the onData handler always produces
// UTF-8 bytes, regardless of the system code page. Pre-initializing
// the decoder to UTF-8 prevents getCachedEncodingForBuffer() from
// using the system code page (e.g. Shift-JIS on Japanese Windows)
// to decode what is already UTF-8 data. Fixes #12468.
let decoder: TextDecoder | null = new TextDecoder('utf-8');
let output: string | AnsiOutput | null = null;
const sniffChunks: Buffer[] = [];
let binaryBytesReceived = 0;