Skip to content

Stop rewriting files that only ever had a BOM - #60

Merged
Seungpyo1007 merged 1 commit into
developfrom
fix/bom-preserved
Aug 5, 2026
Merged

Stop rewriting files that only ever had a BOM#60
Seungpyo1007 merged 1 commit into
developfrom
fix/bom-preserved

Conversation

@Seungpyo1007

Copy link
Copy Markdown
Member

A UTF-8 BOM is not text — it is a mark on the file, and Monaco treats it that way, keeping it outside the model so getValue() returns the content without it. The string read from disk does contain it, and that string was being used as the saved baseline. The two never match, so:

  • a file with a BOM is "unsaved" the moment you open it, and
  • Save All rewrites a file nobody touched, dropping the BOM on the way out.

The result is a whole-file diff, and a broken build anywhere the BOM is required.

Everything inside now works BOM-free: it is removed on read, the fact that it was there is remembered, and it is put back only when writing to disk. Comparisons and offset arithmetic all run on the same BOM-free string, so nothing shifts by one. Renaming a file carries the mark with it.

There are four places that write: pane save (Ctrl+S), Save All, the extension API's document.save(), and accepting a proposal. The proposal path is the awkward one — its base text comes from the model (no BOM) when the buffer is dirty and from disk (BOM) when it is not — so it strips once and re-attaches based only on whether that file ever had one.

Verification

A round-trip over five files — open, type a character, delete it, save — comparing bytes before and after: 5 of 5, covering CRLF, LF, BOM, BOM+CRLF, and no trailing newline. Line endings and the missing final newline were already preserved; the BOM was not.

Separately, opening a BOM file and pressing Save All without editing it: the file is now byte-identical, where before it came back without its BOM.

And with the re-attach removed, both BOM cases fail again exactly as before.

954 tests, npm run typecheck clean.

UTF-8 BOM 은 본문이 아니라 파일의 표식이다. Monaco 도 그렇게 보고 따로 들고 있어서
getValue() 는 BOM 을 빼고 준다. 그런데 디스크에서 읽은 문자열에는 BOM 이 들어 있고,
그걸 그대로 기준선으로 삼았다. 두 값이 영원히 다르니 —

  · BOM 파일은 **열자마자 "저장 안 함"** 이 되고,
  · "모두 저장" 이 손도 안 댄 파일을 고쳐 쓰면서 BOM 을 떼어 버린다.

파일 전체가 바뀐 diff 가 되고, BOM 을 요구하는 도구에서는 빌드가 깨진다.

안쪽은 전부 BOM 없이 다룬다. 읽을 때 떼고, 있었다는 사실만 기억했다가, 디스크에 쓸
때만 도로 붙인다. 비교·오프셋 계산이 전부 BOM 없는 문자열로 도니 한 글자씩 밀리는
일도 없다. 이름을 바꿔도 표식은 그 파일을 따라간다.

쓰는 자리는 넷이다 — 페인 저장(Ctrl+S), 모두 저장, 확장의 document.save(),
제안 수락. 제안 수락은 기준 텍스트가 모델에서 올 때(BOM 없음)와 디스크에서 올 때
(BOM 있음)가 섞이므로, 한 번 떼고 그 파일이 원래 갖고 있었는지로만 다시 붙인다.

같이 확인한 것: 줄 끝(CRLF/LF)과 마지막 줄바꿈 없음은 원래 그대로 보존되고 있었다.
@Seungpyo1007 Seungpyo1007 added this to the v0.3 (2026-09-30) milestone Aug 5, 2026
@Seungpyo1007 Seungpyo1007 added the bug Something isn't working label Aug 5, 2026
@Seungpyo1007 Seungpyo1007 self-assigned this Aug 5, 2026
@Seungpyo1007
Seungpyo1007 merged commit 470a803 into develop Aug 5, 2026
1 check passed
@Seungpyo1007
Seungpyo1007 deleted the fix/bom-preserved branch August 5, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant