Repository navigation
Description
Goal Anchor
- Outcome: 지원하는 Web Cut에서 clipboard 표현 확보가 실패하면 브라우저의 후속 삭제로 넘어가지 않고 문서·선택·History를 보존한다.
- Done: 표현 인코딩/쓰기 실패를 회귀 테스트로 고정하고, 실제 Rich Text Usage의 native Cut 단축키에서 실패 후 문서·DOM 선택·Undo/Redo 보존과 정상 재시도를 확인한다. 공통 Web owner 문서와 이슈 댓글에 이벤트 책임·명세 근거·검증 한계를 남긴다.
- Don't: Core·Profile·공개 API 형태를 늘리지 않는다. Copy/Paste 및 Cut 미지원·clipboardData 부재·payload 부재의 기존 위임 정책을 바꾸지 않는다. Host나 Rich Text에 별도 우회 구현을 만들지 않는다. OS clipboard와 문서의 원자성이나 이미 쓴 표현의 롤백을 보장하지 않는다.
이어받은 계약
사용자의 “계속해줘 다음 작업”, “merge하고” 요청에 따라 #728을 머지한 뒤 기존 EG-CUT의 실패 시 원본 보존 계약을 이어서 검증한다. #726 설계 초안에도 ‘제거 callback 미호출 외에 event 취소·후속 beforeinput/input·document·History 관찰’이 미검증 질문으로 남아 있다. 이번 이슈는 그 실행 경로의 결함 수정이며 #725의 설계 범위를 변경하지 않는다.
재현된 현재 동작
기준 main: aae30a66159e4ec0649fa94806d55805341cb965.
실제 /editing/rich-text Usage에서 text-editable의 offset 2–4를 선택하고, 테스트에서 DataTransfer.setData의 첫 structured MIME 쓰기를 예외로 실패시킨 뒤 실제 ControlOrMeta+x를 입력했다.
- Chrome 152.0.7977.83, Firefox 150.0.2, WebKit 26.4 모두 같은 결과.
cut은isTrusted: true,defaultPrevented: false.- 이어
beforeinput(deleteByCut)이 발생하고 Rich Text editor가 선택 영역을 제거한다. 여기를 선택하고 직접 입력해 보세요.→여기선택하고 직접 입력해 보세요.로 canonical document가 바뀌고 Undo가 활성화된다.- 직접 호출한 clipboard binding에서는
clipboard.unavailable, 제거 callback 0회지만preventDefault도 0회다. 기존 단위 검증만으로는 브라우저의 후속 삭제를 발견하지 못했다.
실패는 테스트에서 주입했으며 실제 OS 권한 거절을 재현했다고 주장하지 않는다. 합성 ClipboardEvent로 후속 삭제를 흉내 내지 않았다.
책임 경계
정본은 packages/json-document-web/src/clipboard.ts의 createWebClipboardBinding이다. 지원하는 Cut callback, 사용 가능한 event clipboardData, 확보한 payload가 있는 경우 표현 인코딩/쓰기 전에 native Cut 책임을 확보해야 한다. 쓰기가 끝난 뒤에만 정본 제거 callback을 호출하는 순서는 유지한다. 실패 결과와 이벤트 소유권은 서로 다른 사실이다.
기존 createWebClipboardSurface, Rich Text Web binding 및 사이트 Usage는 이 정본을 소비한다. 기존 공개 export·API reference·Usage·source 등록을 유지하고 실제 경로를 검증한다.
완료 증거
- 기본 codec와 명시적 representations의 인코딩/쓰기 실패에서 native 이벤트가 취소되고 제거·문서 발행·History 변경이 없다.
- Cut 미지원, clipboardData/payload 부재, Copy 실패, Paste의 기존 위임/거절 경계가 유지된다.
- 실제 브라우저에서 실패한 Cut의 후속 삭제가 없고 문서·방향 있는 선택·Undo/Redo가 보존된다. 정상 재시도와 Undo도 동작한다.
- owning package 문서가 취소 시점과 clipboard 부분 쓰기의 한계를 설명하고 기존 Usage/source 연결을 확인한다.
- 관련 테스트·typecheck·build·문서 검사와 전체 diff 검토 후 하나의 PR로 제공한다.
읽을 거리
- W3C Clipboard API — Cut event: 취소하지 않은 editable Cut에는 브라우저의 기본 복사·삭제가 남는다.
- W3C Clipboard API — Cut action: 이벤트 취소 여부에 따라 기본 삭제 경로가 갈린다. 2026-06-24 Working Draft이며, OS clipboard transaction 보장으로 해석하지 않는다.
- W3C Input Events Level 2:
deleteByCut의 의미와 beforeinput 취소 가능성을 확인할 수 있다. 이번 이벤트 순서의 실행 증거는 위의 세 엔진 재현이다.
Activity
developer-1px commentedon Sep 8, 2026
작업 계획과 학습 포인트
Goal Anchor는 본문의 원본·선택·History 보존 계약으로 고정한다. Copy/Paste와 미지원/빈 Cut 위임, 공개 API 형태, OS clipboard 비원자성은 유지한다.
return { ok: false }는 library 호출자에게만 의미가 있다. 브라우저는 그 반환값을 읽지 않으므로preventDefault()가 별도로 필요하다. ‘실패했으니 다른 owner에게 맡긴다’는 정책은 이미 맡은 파괴적 작업에서는 원본 보존과 충돌한다. W3C Cut action의 취소 분기와 실제 세 엔진 trace를 함께 보면 이 차이를 확인할 수 있다.진행 순서:
이벤트 취소가 OS 쓰기 성공을 인증하지는 않는다. 이미 쓴 일부 표현은 남을 수 있고, 브라우저 내부의 예외 없는 실패나 시스템 clipboard rollback까지 이 테스트가 보장하지 않는다. 현재 미해결 항목은 구현과 회귀 검증이며 범위 변경은 없다.
developer-1px commentedon Sep 8, 2026
구현 검증: 실패 결과와 native 이벤트는 별도 계약이다
수정 전 회귀 테스트는 Web에서 8개 모두
preventDefault0회로 실패했다. 실제 Chrome Cut 회귀 테스트도 canonical document의여기를 선택하고 직접 입력해 보세요.가여기선택하고 직접 입력해 보세요.로 바뀌어 실패했다.수정은
createWebClipboardBinding내부에서 supported Cut의 취소를 표현 인코딩/쓰기 앞으로 옮기는 것이다. 공개 함수·옵션·결과 형태는 그대로다. Rich Text나 Host의beforeinput에 우회 상태를 추가하지 않았다.브라우저 사례는 각자 실제 편집 → Undo로 실행 가능한 Redo를 먼저 만든다. 그런 다음 역방향 선택에서 쓰기 실패를 주입하고 실제
ControlOrMeta+x를 입력한다. 실패 후 문서·DOM 텍스트·canonical/DOM 선택이 그대로이고 Undo/Redo 상태가 유지됨을 확인한다. 기록된 이벤트는 취소된 trustedcut하나이며 후속beforeinput(deleteByCut)은 없다. Redo를 실제 실행해 미래 기록도 보존됐음을 확인한다. 실패 주입을 복구한 뒤 정상 Cut → Undo가 원문과 역방향 선택을 복원한다.관련 네 패키지 테스트는 20 files / 138 tests 통과했다. 남은 검증은 문서·타입·사이트 검사, 기존 Usage/source 연결 및 전체 diff 검토다.
공부할 점
단위 테스트가 callback을 관찰하는 것과 브라우저가 문서를 보존하는 것은 같은 증거가 아니다. 예전 검증에는 다음 화살표가 빠져 있었다.
Clipboard Cut event는 합성 Cut이 실제 삭제를 수행하지 않는다는 점도 설명한다. 그래서 이 회귀 테스트는 쓰기만 실패 주입하고 Cut 자체는 실제 단축키로 발생시킨다. 명세는 이벤트 모델을 설명하고, 실행 테스트는 현재 세 엔진과 이 Usage에서 그 계약을 확인한다. 이를 모든 OS clipboard 장애의 원자성 보장으로 확대하지 않는다.
developer-1px commentedon Sep 8, 2026
PR 제공 및 완료 증거
PR: #730 · commit
ba1f0ee520e2f7ffa6ff43e19afb3f2bc8bd5def· branchissue-729-cut-failure-ownership.createWebClipboardSurface를 소비하며, 등록된clipboard.ts소스와 Web API Reference로 연결됨을 기존 workbench 브라우저 검사에서 확인했다. Rich Text는 같은 binding을 소비하고 Host 우회 구현은 추가하지 않았다.검증 결과:
사이트 단위 테스트의 최초 실행에서는 브라우저 검증과 병행 중 기존 문서/화면 로딩 3개가 대기 시간 제한에 걸렸다. 브라우저 종료 후
--maxWorkers=1로 전체 재실행해 통과했다. 테스트나 timeout 설정을 바꾸지 않았다.현재 상태는
pr-open이다. CI의 Plan·External kit는 통과했고 Package·Site는 실행 중이다. 이번 PR의 merge는 아직 진행하지 않았다. 완료된 계약은 위의 동기 Web 이벤트 실패 경로이며, OS 권한 실패의 모든 형태나 clipboard rollback을 보장하지 않는 한계는 그대로다. 승인된 범위 변경은 없다.developer-1px commentedon Sep 10, 2026
승인된 contract delta: Cut의 입력 소유권과 실행 준비를 분리하는 정본 경계를 구현합니다. Web의 기존 editing-host target 판정을 Clipboard 라우팅에 연결하고, 다른 편집영역은 payload를 읽거나 취소하지 않고 위임합니다. 앱 소유 Cut은 먼저 취소하고 빈 선택·clipboard 없음·쓰기 실패는 소유한 실패로 종료합니다. 모든 표현을 쓴 뒤 동일 캡처 대상을 삭제하며 부모의 중복 처리를 막습니다. 공개 API·소유 문서·Usage·Source와 중첩 입력/실패/중복 처리 검증을 연결합니다. 기존 빈 입력 위임 정책을 보존한다는 이전 항목은 이 승인된 소유권 계약으로 대체합니다.