OSSCA Chromium

기여 목록 / 8505797

CacheStorage: Detach pending resolvers after synchronous errors

BlinkfixMerged

Cache API가 작업을 시작하다 동기 예외를 만나면 사용하지 않게 된 내부 Promise resolver를 분리하도록 수정했습니다. addAll()에서 앞서 시작한 fetch를 먼저 중단하고, 이후 도착한 응답도 해당 resolver를 처리하지 않게 합니다.

문제 설명

Cache::addAll()은 fetch를 시작하기 전에 내부 resolver를 만듭니다. fetch가 ExceptionState를 설정하면 Web IDL 바인딩은 별도의 거절된 Promise를 반환하지만, 기존 내부 resolver는 pending 상태로 남아 GC 중 ScriptPromiseResolverBase::Dispose 검사를 실패시킬 수 있습니다.

해결 내용

  1. 응답을 모으는 barrier에 Detach()를 추가합니다. 기존 Stop()을 먼저 호출해 AbortController가 있으면 진행 중인 fetch를 중단하고, Blob 목록을 비우며 이후 응답 처리를 멈춥니다. 그 뒤 resolver를 분리합니다.
  2. AddAllImpl()에서 fetch 호출 직후 동기 예외를 확인합니다. 예외가 있으면 barrier를 분리하고 EmptyPromise()를 반환하며, 정상일 때만 .Then()을 연결합니다.
  3. Cache::put()이 응답 본문 로딩을 시작하다 내부 예외를 만나는 경로에도 같은 정리를 적용합니다.

테스트 방법

  • ScopedFetcherForTests가 동기 TypeError를 던지도록 설정하는 기능과 fetch에 전달된 AbortSignal을 기록하는 기능을 추가합니다.
  • AddAllDetachesResolverWhenFetchThrows는 예외와 빈 내부 Promise 반환을 확인한 뒤 강제로 GC를 실행해 resolver 정리 경로를 검증합니다.
  • AddAllAbortsEarlierFetchesWhenLaterFetchThrows는 세 번째 fetch에서 동기 예외를 발생시킵니다. 먼저 시작한 두 fetch의 AbortSignal이 중단 상태인지 확인하고, microtask 처리 후에도 캐시 백엔드 호출 없이 GC가 수행되는지 검증합니다.
  • 두 회귀 테스트는 addAll()의 fetch 예외를 직접 재현합니다. put()의 내부 예외에는 같은 정리 처리가 적용되지만 별도의 새 테스트가 추가된 것은 아닙니다.

Gerrit 기록상 Patch Set 3은 2026년 10월 7일 UTC에 CQ dry run을 통과했습니다. 최종 Patch Set 4는 같은 날 15:51:45 UTC에 Chromium main에 반영됐습니다(refs/heads/main@{#1713483}). 보고서 작성 과정에서 Chromium 테스트를 별도로 실행하지는 않았습니다.

관련 이슈와 외부 PR

배운 점

  • Web IDL 바인딩이 JavaScript에 반환하는 Promise와 C++ 내부 resolver가 관리하는 Promise는 예외 경로에서 서로 달라질 수 있습니다.
  • 조기 반환할 때 resolver의 수명과 나중에 도착할 비동기 응답까지 정리해야 GC 시점의 오류를 막을 수 있습니다. 여러 fetch 중 뒤의 요청에서 예외가 나면 앞선 요청의 중단 여부도 확인해야 합니다.

참고 자료