bun#43660 の再現

bun#43660 と同じコマンドを、開いた直後の cp932 の窓で bun 1.4.2 と canary 版で流した結果

📅 作成: 2026-10-04 / 更新: 2026-10-04

条件

項目値
窓conhost.exe で新しく開いた cmd(開始時 932)。chcp 932 は実行しない
bun1.4.2+744846f84 / 1.4.3-canary.1+bb35d1b81
OSWindows 11 Home 10.0.26300
スクリプトtests/manual/issue-43660-repro.cmd <bun> <ログ>

スクリプトは次の 2 本を順に流す。2 本の窓(安定版・canary 版)は同時に開いた。

bun -e "console.log('bun 2 bun   日本語')" | bun -e "process.stdin.pipe(process.stdout)"
bun -e "console.log('bun 2 bun   日本語')" | bun -e "process.stdin.pipe(process.stdout)" > ログ.bytes

1・2 回目は chcp の値をログにだけ書いた。3 回目は画面とログの両方に書き、見出しを ASCII にした。

この 3 回の後、スクリプトの文字列を abc 東京大阪 xyz に変えた(化けても壊れたバイトが残らず、改行も消えないため。計画の T5 を参照)。この資料の結果は、変える前の bun 2 bun 日本語 で取ったもの。

結果

結果は回の順に並べる(1 回目・2 回目・3 回目)。✅ 期待どおり / ❌ 期待と違う / ⚠️ 入力側だけ 932 に戻った(chcp の数字は 932 だがメッセージが英語) / ⬜ 未確認(2 回目の画面は見ていない)。

確かめたこと1.4.21.4.3-canary.1
画面の表示❌⬜❌❌⬜✅
画面に出したあとのコードページ❌❌✅⚠️❌✅
ファイルに出したあとのコードページ❌❌✅❌❌❌
ファイルに届いたバイト列❌❌✅❌❌✅

3 回目の画面(1.4.2)

1.4.2+744846f84
[1] before
現在のコード ページ: 932
--- bun to bun, output to console ---
bun 2 bun   譌・譛ャ隱・[2] after console run
現在のコード ページ: 932
--- bun to bun, output to file ---
[3] after file run
現在のコード ページ: 932
--- end ---
続行するには何かキーを押してください . . .

3 回目の画面(1.4.3-canary.1)

1.4.3-canary.1+bb35d1b81
[1] before
現在のコード ページ: 932
--- bun to bun, output to console ---
bun 2 bun   日本語
[2] after console run
現在のコード ページ: 932
--- bun to bun, output to file ---
[3] after file run
Active code page: 65001
--- end ---
Press any key to continue . . .

ファイルに届いたバイト列

回日本語の部分
1・2 回目(両版)ef bf bd ef bf bd ef bf bd 7b ef bf bd ef bf bd(U+FFFD と {)
3 回目(両版)e6 97 a5 e6 9c ac e8 aa 9e(正しい UTF-8)

読み違えていたこと

1・2 回目でファイルに届いたバイト列が壊れていたのを、当初は「bun のパイプを流れるデータが壊れる」と読んだ。これは誤りだった。

  1. 1 本目のパイプのあと、窓に 65001 が残った
  2. cmd はバッチファイルを 1 行ずつ読み直すため、2 本目の行を 65001 で読んだ。SJIS で書かれた 日本語 は UTF-8 として読めず、bun には U+FFFD が渡った
  3. 3 回目は 2 本目の前に 932 に戻っていたため、正しいバイト列が届いた

壊れたバイト列は、bun が残したコードページで 同じ窓の cmd がスクリプトを読み違えた ことの証拠である。1・2 回目に日本語の見出しが化けた理由も同じ。

仮説

未検証。各 bun が「起動時に今の値を控えて 65001 にし、終了時に控えた値へ戻す」と仮定すると、観測をすべて説明できる。

  1. 送り手 A が起動し、932 を控えて 65001 にする
  2. 受け手 B が起動し、65001 を「元の値」として控える
  3. A が先に終わり 932 に戻すと、その後に B が書いた UTF-8 は化ける(1.4.2 の 3 回目: コードページは 932 のままなのに化けた)
  4. B が終わると控えた 65001 に戻し、窓に 65001 が残る(canary 版の 3 回目のファイル出力)

1.4.2 の 3 回目の 譌・譛ャ隱・ は、UTF-8 の e6 97 a5 e6 9c ac e8 aa 9e を CP932 として読んだ形である。最後の 9e が 2 バイト文字の先頭と見なされ、続く改行を巻き込んで ・ になったため、改行も消えた。受け手の bun は画面に UTF-8 のバイト列をそのまま書いている(WriteConsoleW を使っていない)と考えられる。

分かったことと次の確認