1. 동기
이 섹션은 비규범적입니다.
웹 애플리케이션은 전통적으로 네트워크에 접근할 수 있다는 가정을 합니다. 이 가정은 플랫폼 전반에 퍼져 있습니다. HTML 문서는 HTTP를 통해 로드되고, 전통적으로 모든 하위 리소스를 이후의 HTTP 요청을 통해 가져옵니다. 이는 웹 콘텐츠가 다른 기술 스택에 비해 불리하게 만듭니다.
서비스 워커는 내비게이션이 발생하려고 할 때 런타임이 시작할 수 있는 웹 워커 컨텍스트를 제공함으로써 이러한 불균형을 해소하기 위해 설계되었습니다. 이 이벤트 기반 워커는 출처와 경로(또는 패턴)에 대해 등록되므로, 해당 위치로 내비게이션이 발생할 때 참조될 수 있습니다. 네트워크 요청에 해당하는 이벤트가 워커로 전달되고, 워커가 생성한 응답은 기본 네트워크 스택 동작을 대체할 수 있습니다. 서비스 워커는 개념적으로 네트워크와 문서 렌더러 사이에 위치하므로, 서비스 워커가 오프라인 상태에서도 문서에 콘텐츠를 제공할 수 있게 합니다.
오프라인 문제를 해결하기 위한 이전의 시도에 익숙한 웹 개발자들은 그러한 솔루션의 유연성이 부족하다고 보고했습니다. 그 결과 서비스 워커는 개발자에게 추가적인 복잡성을 요구하는 대신 최대한의 유연성을 제공하기 위해 매우 절차적으로 설계되었습니다. 이러한 복잡성의 일부는 서비스 워커가 단일 스레드 실행 모델에서도 응답성을 유지해야 한다는 필요성에서 비롯됩니다. 그 결과, 서비스 워커에서 노출되는 API는 거의 전부 비동기적으로 설계되어, 다른 자바스크립트 환경에서 익숙한 패턴이지만 문서와 리소스 로딩의 블로킹을 피해야 한다는 점에서 더욱 강조되었습니다.
HTML5 애플리케이션 캐시를 사용한 개발자들은 디자인의 여러 속성이 복구 불가능한 오류에 기여한다고 보고했습니다. 서비스 워커의 핵심 설계 원칙은 오류가 항상 복구 가능해야 한다는 것입니다. 서비스 워커의 업데이트 과정의 많은 세부 사항은 이러한 위험을 방지하도록 설계되었습니다.
서비스 워커는 문서가 아니라 이벤트와의 관계에 의해 시작되고 유지됩니다. 이 설계는 공유 워커와 Chrome 백그라운드 페이지에 대한 개발자 및 벤더의 경험에서 많은 부분을 차용했습니다. 이러한 시스템에서 얻은 주요 교훈은 백그라운드 처리 컨텍스트의 실행을 시간 제한해야 한다는 필요성입니다. 이는 자원을 절약하고, 백그라운드 컨텍스트의 손실 및 재시작이 개발자의 주요 고려 대상이 되도록 하기 위함입니다. 그 결과, 서비스 워커는 Chrome 이벤트 페이지(Background Pages의 후속작)와 매우 유사합니다. 서비스 워커는 사용자 에이전트가 문서를 첨부하지 않고도 시작할 수 있으며, 사용자 에이전트가 거의 언제든지 종료할 수 있습니다. 개념적으로, 서비스 워커는 문서에서 메시지를 처리하지 않고도 시작, 이벤트 처리, 종료가 가능한 공유 워커로 생각할 수 있습니다. 개발자들은 서비스 워커가 초당 여러 번 시작되고 종료될 수 있다는 점을 항상 염두에 두어야 합니다.
서비스 워커는 출처에서 실행되는 범용, 이벤트 기반, 시간 제한된 스크립트 컨텍스트입니다. 이러한 특성 덕분에 푸시 알림 처리, 백그라운드 데이터 동기화, 다른 출처의 리소스 요청 응답, 계산 비용이 큰 데이터(예: 위치정보나 자이로센서) 중앙 업데이트 등 특정 문서의 컨텍스트보다 오래 지속될 수 있는 다양한 런타임 서비스의 자연스러운 엔드포인트가 됩니다.
2. 모델
2.1. 서비스 워커
서비스 워커는 웹 워커의 한 종류입니다. 서비스 워커는 등록한 서비스 워커 클라이언트의 출처에서 실행됩니다.
서비스 워커는
"parsed
", "installing
", "installed
",
"activating
", "activated
", "redundant
" 중 하나의 상태를 가집니다. 초기 값은 "parsed
"입니다.
서비스 워커는
"classic
" 또는 "module
" 중 하나의 타입을 가집니다. 별도
명시가 없는 경우 "classic
"입니다.
서비스 워커는 등록된 서비스 워커 레지스트레이션(서비스 워커 레지스트레이션)을 가집니다. 이는 자기 자신을 포함합니다.
서비스 워커는 글로벌 객체(ServiceWorkerGlobalScope
객체 또는 null)을 가집니다.
서비스 워커는 스크립트 리소스(스크립트)를 가집니다. 이는 해당 워커의 스크립트 리소스를 나타냅니다. 초기 값은 null입니다.
스크립트 리소스는 평가된 적 있음 플래그를 가집니다. 초기에는 설정되지 않습니다.
스크립트 리소스는 정책 컨테이너(policy container)를 가집니다. 초기에는 새로운 정책 컨테이너입니다.
서비스 워커는 스크립트 리소스 맵을 가집니다. 이는 순서 있는 맵으로, 키는 URL이고, 값은 응답입니다.
서비스 워커는 사용된 스크립트 집합(집합)을 가집니다. 각 항목은 URL입니다. 초기에는 새로운 집합입니다.
참고: 사용된 스크립트 집합은 설치 후 새 워커의 맵에서 사용하지 않는 리소스를 제거하기 위해 사용됩니다. 이는 업데이트 검사 과정에서 이전 워커의 맵을 기반으로 채워집니다.
서비스 워커는 skip waiting 플래그를 가집니다. 별도 명시가 없는 한 설정되지 않습니다.
서비스 워커는 클래식 스크립트 import됨 플래그를 가집니다. 초기에는 설정되지 않습니다.
서비스 워커는 처리할 이벤트 타입 집합(집합)을 가집니다. 각 항목은 이벤트 리스너의 이벤트 타입입니다. 초기에는 새로운 집합입니다.
서비스 워커는 확장 이벤트 집합(집합)을 가집니다. 각 항목은 ExtendableEvent
입니다.
초기에는 새로운 집합입니다.
서비스 워커는 시작 상태를 가집니다. 이는 null 또는 Completion일 수 있으며, 초기에는 null입니다.
서비스 워커는 fetch 리스너가 모두 비어 있음 플래그를 가집니다. 초기에는 설정되지 않습니다.
서비스 워커는 라우터 규칙 목록(리스트의 RouterRule
들)입니다.
초기에는 빈 리스트입니다.
서비스 워커는 실행 중이라고 합니다. 이는 이벤트 루프가 실행 중일 때를 의미합니다.
서비스 워커는 [[service worker queue]](병렬 큐)를 가집니다.
2.1.1. 수명
서비스 워커의
수명은 이벤트의 실행 수명에 연결되며, 서비스 워커 클라이언트가 ServiceWorker
객체에 보유한 참조와는 관련이 없습니다.
사용자 에이전트는 다음과 같은 상황에서 언제든지 서비스 워커를 종료할 수 있습니다:
-
처리할 이벤트가 없을 때.
-
이벤트를 처리하는 중에 무한 루프, 시간 제한 초과 등의 비정상 동작을 감지한 경우.
2.1.2. 이벤트
서비스 워커 명세에서는 서비스 워커 이벤트(각각은 이벤트)를 정의합니다. 여기에는 아래와 같은 것들이 포함됩니다(목록 참조):
2.2. 서비스 워커 타이밍
서비스 워커는 navigation timing API를 통해 후에 노출되는 특정 시점을 표시합니다.
서비스 워커 타이밍 정보는 구조체입니다. 다음과 같은 항목을 가집니다:
- 시작 시간
-
DOMHighResTimeStamp
타입, 초기값은 0입니다. - fetch 이벤트 디스패치 시간
-
DOMHighResTimeStamp
타입, 초기값은 0입니다.
2.3. 서비스 워커 등록
서비스 워커 등록은 scope url, storage key, 서비스 워커 집합(서비스 워커), installing worker, waiting worker, active worker의 튜플입니다. 사용자 에이전트는 서비스 워커 등록을 단일 출처에 여러 개 활성화할 수 있습니다. 단 scope url이 서로 달라야 합니다. 동일한 scope url의 서비스 워커 등록이 이미 존재하는 경우, 기존 서비스 워커 등록이 대체됩니다.
서비스 워커 등록은 storage key(storage key)를 가집니다.
서비스 워커 등록은 scope url(URL)을 가집니다.
서비스 워커 등록은 installing worker(서비스 워커 또는 null)로, 상태가
"installing
"입니다. 초기값은 null입니다.
서비스 워커 등록은 waiting worker(서비스 워커 또는 null)로, 상태가 "installed
"입니다. 초기값은 null입니다.
서비스 워커 등록은 active worker(서비스 워커 또는 null)로, 상태가 "activating
" 또는
"activated
"입니다. 초기값은 null입니다.
서비스 워커 등록은 마지막 업데이트 검사 시간을 가집니다. 초기값은 null입니다.
서비스 워커 등록은 오래된(stale) 상태가 될 수 있습니다. 이 경우 등록의 마지막 업데이트 검사 시간이 null이 아니고, 현재 시간에서 마지막 업데이트 검사 시간을 뺀 초 단위의 차이가 86400보다 크면 해당됩니다.
서비스 워커 등록은 update via cache mode를 가집니다. 값은 "imports
",
"all
", "none
" 중 하나이며, 초기값은 "imports
"입니다.
서비스 워커 등록은 하나 이상의 작업 큐(task queue)를 가집니다. 이는 작업을 active worker의 이벤트 루프의 해당 작업 큐에서 백업합니다. (백업의 대상 작업 소스는 handle fetch task source와 handle functional event task source입니다.) 사용자 에이전트는 active worker의 작업을 서비스 워커 등록의 작업 큐에 덤프하며, 작업을 다시 큐로 active worker의 이벤트 루프의 해당 작업 큐에 재할당합니다. 작업 큐가 이벤트 루프에 의해 처리되는 것과 달리, 서비스 워커 등록의 작업 큐는 자체적으로 어떤 이벤트 루프에서도 처리되지 않습니다.
서비스 워커 등록은 NavigationPreloadManager
객체를 가집니다.
서비스 워커 등록은 navigation preload enabled 플래그를 가집니다. 초기에는 설정되지 않습니다.
서비스 워커 등록은 navigation preload header
값을 가집니다. 이는 바이트 시퀀스이며, 초기값은 `true
`입니다.
서비스 워커 등록은 등록 해제됨(unregistered) 상태가 될 수 있습니다. 이때 registration map[해당 서비스 워커 등록의 (storage key, 직렬화된 scope url)]이 해당 서비스 워커 등록이 아닐 경우입니다.
2.3.1. 수명
사용자 에이전트는 등록된 서비스 워커 등록 목록을 명시적으로 등록 해제하지 않는 한 지속적으로 유지해야
합니다. 사용자 에이전트는 registration map을 가지고 있습니다. 이는 서비스 워커 등록의 (storage key, 직렬화된 scope url) 튜플과 해당 서비스
워커 등록을 저장합니다. 서비스 워커 등록의 수명은 해당 서비스 워커 클라이언트의
수명 내에서 이를 나타내는 ServiceWorkerRegistration
객체의 수명보다 깁니다.
2.4. 서비스 워커 클라이언트
서비스 워커 클라이언트는 environment입니다.
서비스 워커 클라이언트는 discarded flag를 가집니다. 초기에는 설정되지 않습니다.
각 서비스 워커 클라이언트는 다음 environment discarding steps를 따릅니다:
-
client의 discarded flag를 설정합니다.
참고: discard된 flag가 설정된 클라이언트는 구현에 따라 폐기될 수 있습니다.
서비스 워커 클라이언트는 origin이라는 알고리즘을 가집니다. 이는 서비스 워커 클라이언트가 environment settings object일 경우 origin을 반환하고, 그렇지 않으면 creation URL의 origin을 반환합니다.
window client는 서비스 워커 클라이언트 중 global object가 Window
객체인 경우입니다.
dedicated worker client는 서비스 워커 클라이언트 중 global object가 DedicatedWorkerGlobalScope
객체인 경우입니다.
shared worker client는 서비스 워커 클라이언트 중 global object가 SharedWorkerGlobalScope
객체인 경우입니다.
worker client는 dedicated worker client 또는 shared worker client입니다.
2.5. 제어 및 사용
서비스 워커 클라이언트는 자신의 로딩과 하위 리소스 처리에 사용되는 active service worker를 가집니다. 서비스 워커 클라이언트가 null이 아닌 active service worker를 가지면, 해당 클라이언트는 그 active service worker에 의해 제어됨(controlled) 상태가 됩니다. 서비스 워커 클라이언트가 제어됨 상태일 때, 해당 클라이언트는 서비스 워커의 등록 정보를 사용함(used) 상태라 합니다. 서비스 워커 클라이언트의 active service worker는 아래 하위 섹션에서 설명한 대로 결정됩니다.
이 섹션의 나머지 부분은 비규범적입니다.
이 섹션의 동작은 아직 완전히 명세되지 않았으며, HTML 표준에서 명세될 예정입니다. 관련 작업은 이슈와 풀 리퀘스트에서 추적 중입니다.
2.5.1. 윈도우 클라이언트 케이스
window client는 생성될 때, 즉 browsing context가 생성될 때와 내비게이션이 발생할 때 생성됩니다.
window client가 생성되는 과정에서 browsing context가 생성된다면:
browsing context의 초기 active document의 origin이 opaque origin이면, window client의 active service worker는 null로 설정합니다. 그렇지 않으면, 생성자 document의 서비스 워커 클라이언트의 active service worker로 설정합니다.
window client가 생성되는 과정에서 browsing context의 내비게이션이 발생한다면:
fetch가 HTTP fetch를 통해 라우팅된다면, window client의 active service worker는 서비스 워커 등록 매칭의 결과로 설정합니다. 그렇지 않고 생성된 document의 origin이 opaque origin이거나 생성자 document의 origin과 동일하지 않다면, window client의 active service worker는 null로 설정합니다. 그렇지 않으면, 생성자 document의 서비스 워커 클라이언트의 active service worker로 설정합니다.
참고: 초기 대체 내비게이션의 경우, window client가 생성될 때 browsing context가 생성되지만, active service worker 결정 방식은 위와 동일하게 적용됩니다.
참고: 샌드박스된
iframe
에서 allow-same-origin
과 allow-scripts
샌드박싱 지시자가 없으면, 해당 active service worker 값이 null이
됩니다. 이는 origin이 opaque origin이기 때문입니다.
2.5.2. 워커 클라이언트 케이스
worker client는 사용자 에이전트가 워커 환경 설정 객체를 생성할 때, 즉 worker를 실행할 때 생성됩니다.
worker client가 생성될 때:
fetch가 HTTP fetch를 통해 라우팅된다면, worker client의 active service worker는 서비스 워커 등록 매칭의 결과로 설정합니다. 그렇지 않고 worker client의 origin이 opaque origin이거나, request의 URL이 blob URL이고 worker client의 origin이 동일하지 않다면, origin과 owner set의 마지막 worker client의 global object의 owner set과 동일하지 않다면, worker client의 active service worker는 null로 설정합니다. 그렇지 않으면, environment settings object의 마지막 owner set의 worker client의 global object의 owner set의 active service worker로 설정합니다.
참고: Window client와 worker client가 data: URL을 사용하면, 해당 active service worker 값은 null이 되며, 이는 origin이 opaque origin이기 때문입니다. Window client와 worker client가 blob URL을 사용하면, 생성자 document 또는 소유자의 active service worker를 상속받을 수 있습니다. 하지만 request의 origin이 생성자 document 또는 소유자의 origin과 동일하지 않으면, active service worker는 null로 설정됩니다.
2.6. 작업 소스
2.7. 사용자 에이전트 종료
사용자 에이전트는 저장된 서비스 워커 등록의 상태를 재시작 시에도 다음 규칙에 따라 반드시 유지해야 합니다:
-
설치 중인 워커는 지속되지 않고 버려집니다. 만약 설치 중인 워커가 해당 서비스 워커 등록의 유일한 서비스 워커였다면, 서비스 워커 등록도 버려집니다.
-
waiting worker는 active worker로 승격됩니다.
이를 위해 사용자 에이전트는 종료 시 Handle User Agent Shutdown을 반드시 호출해야 합니다.
3. 클라이언트 컨텍스트
// scope는 기본적으로 스크립트가 위치한 경로가 됩니다 // 이 예제에선 "/" navigator. serviceWorker. register( "/serviceworker.js" ). then( registration=> { console. log( "성공!" ); if ( registration. installing) { registration. installing. postMessage( "설치 중인 페이지에서 인사드립니다." ); } }, err=> { console. error( "워커 설치 실패!" , err); });
3.1.
ServiceWorker
[SecureContext ,Exposed =(Window ,Worker )]interface :
ServiceWorker EventTarget {readonly attribute USVString scriptURL ;readonly attribute ServiceWorkerState state ;undefined postMessage (any ,
message sequence <object >);
transfer undefined postMessage (any ,
message optional StructuredSerializeOptions = {}); // event
options attribute EventHandler onstatechange ; };ServiceWorker includes AbstractWorker ;enum {
ServiceWorkerState ,
"parsed" ,
"installing" ,
"installed" ,
"activating" ,
"activated" };
"redundant"
ServiceWorker
객체는 서비스 워커를
나타냅니다. 각 ServiceWorker
객체는 하나의 서비스
워커에 연결되어 있습니다. 여러 문서와 워커에서 ServiceWorker
인터페이스를 구현하는 별개의 객체들이 동시에 같은 서비스 워커에 연관될 수 있습니다.
ServiceWorker
객체는 ServiceWorkerState
객체를 가지고 있으며, 이는 서비스 워커의 상태와 연결되어 있습니다.
3.1.1. ServiceWorker
인스턴스 얻기
environment settings object는 service worker
object map을 가집니다. 이는 맵으로,
키는 서비스 워커이고, 값은 ServiceWorker
객체입니다.
-
objectMap을 environment의 service worker object map으로 한다.
-
objectMap[serviceWorker]이 존재하지 않으면 다음을 수행:
-
serviceWorkerObj를 environment의 Realm에서 생성된 새로운
ServiceWorker
객체로 하고, serviceWorker와 연관시킨다. -
objectMap[serviceWorker]에 serviceWorkerObj를 할당한다.
-
-
objectMap[serviceWorker]을 반환한다.
3.1.2.
scriptURL
3.1.3.
state
state
속성은 마지막으로 설정된 값을
(ServiceWorkerState
열거형에서) 반환해야 합니다.
3.1.4. postMessage(message, transfer)
postMessage(message, transfer)
메서드 단계:
-
options를 «[ "transfer" → transfer ]»로 한다.
-
postMessage(message, options)
를 message와 options로 호출한다.
3.1.5. postMessage(message, options)
postMessage(message, options)
메서드 단계:
-
incumbentSettings는 incumbent settings object로 한다.
-
incumbentGlobal은 incumbentSettings의 global object로 한다.
-
serializeWithTransferResult는 StructuredSerializeWithTransfer(message, options["
transfer
"])로 한다. 예외가 발생하면 다시 던진다. -
"message"와 serviceWorker로 Should Skip Event 알고리즘을 실행한 결과가 true라면 return 한다.
-
다음 하위 단계를 병렬로 실행:
-
Run Service Worker 알고리즘을 serviceWorker로 실행한 결과가 failure라면 return.
-
작업 큐에 추가를 DOM 조작 작업 소스에서 다음 단계로 실행:
-
source를 incumbentGlobal의 타입에 따라 결정:
ServiceWorkerGlobalScope
- incumbentGlobal의 service worker를 serviceWorker의 global object의 relevant settings object에서 service worker 객체 얻기로 반환.
Window
- incumbentGlobal의 relevant settings
object를 나타내는 새로운
WindowClient
객체. - 그 외
- incumbentGlobal의 연관된 워커를 나타내는 새로운
Client
객체.
-
origin을 incumbentSettings의 origin 직렬화 값으로 한다.
-
destination을 serviceWorker와 연관된
ServiceWorkerGlobalScope
객체로 한다. -
deserializeRecord를 StructuredDeserializeWithTransfer(serializeWithTransferResult, destination의 Realm)로 한다.
이 과정에서 예외가 발생하면, e를 이벤트 생성으로 하고, 이름은
messageerror
,ExtendableMessageEvent
사용,origin
속성은 origin,source
속성은 source로 초기화. -
그 외에는:
-
messageClone을 deserializeRecord.[[Deserialized]]로 한다.
-
newPorts를 frozen array로, deserializeRecord.[[TransferredValues]]에 포함된 모든
MessagePort
객체를 순서대로 포함. -
e를 이벤트 생성으로 하고, 이름은
message
,ExtendableMessageEvent
사용,origin
속성은 origin,source
속성은 source,data
속성은 messageClone,ports
속성은 newPorts로 초기화.
-
-
e를 destination에서 디스패치 한다.
-
서비스 워커 확장 이벤트 집합 업데이트를 serviceWorker와 e로 호출한다.
-
-
3.1.6. 이벤트 핸들러
아래는 이벤트 핸들러(및 해당 이벤트 핸들러 이벤트 타입)로, 이벤트 핸들러 IDL 속성으로 모든 ServiceWorker
인터페이스 객체가 반드시 지원해야 합니다:
이벤트 핸들러 | 이벤트 핸들러 이벤트 타입 |
---|---|
onstatechange
| statechange
|
3.2. ServiceWorkerRegistration
[SecureContext ,Exposed =(Window ,Worker )]interface :
ServiceWorkerRegistration EventTarget {readonly attribute ServiceWorker ?installing ;readonly attribute ServiceWorker ?waiting ;readonly attribute ServiceWorker ?active ; [SameObject ]readonly attribute NavigationPreloadManager navigationPreload ;readonly attribute USVString scope ;readonly attribute ServiceWorkerUpdateViaCache updateViaCache ; [NewObject ]Promise <undefined >update (); [NewObject ]Promise <boolean >unregister (); // eventattribute EventHandler onupdatefound ; };enum {
ServiceWorkerUpdateViaCache ,
"imports" ,
"all" };
"none"
ServiceWorkerRegistration
객체는 서비스 워커 등록(서비스 워커 등록)을 가집니다.
3.2.1. ServiceWorkerRegistration
인스턴스 얻기
environment settings object는 서비스 워커
등록 객체 맵을 가집니다. 이는 맵으로,
키는 서비스
워커 등록이고, 값은 ServiceWorkerRegistration
객체입니다.
-
objectMap을 environment의 서비스 워커 등록 객체 맵으로 한다.
-
objectMap[registration]이 존재하지 않으면 다음을 수행:
-
registrationObject를 environment의 Realm에서 생성된 새로운
ServiceWorkerRegistration
객체로 한다. -
registrationObject의 서비스 워커 등록을 registration으로 설정한다.
-
registrationObject의
installing
속성을 null로 설정한다. -
registrationObject의
waiting
속성을 null로 설정한다. -
registrationObject의
active
속성을 null로 설정한다. -
registration의 installing worker가 null이 아니면, registrationObject의
installing
속성을 registration의 installing worker를 environment에서 서비스 워커 객체 얻기로 반환한 값으로 설정한다. -
registration의 waiting worker가 null이 아니면, registrationObject의
waiting
속성을 registration의 waiting worker를 environment에서 서비스 워커 객체 얻기로 반환한 값으로 설정한다. -
registration의 active worker가 null이 아니면, registrationObject의
active
속성을 registration의 active worker를 environment에서 서비스 워커 객체 얻기로 반환한 값으로 설정한다. -
objectMap[registration]에 registrationObject를 할당한다.
-
-
objectMap[registration]을 반환한다.
3.2.2. installing
installing
속성은 마지막으로
설정된 값을 반환해야 합니다.
참고: Realm 내에서는, 연관된 서비스
워커마다 하나의 ServiceWorker
객체만 존재합니다.
3.2.3. waiting
waiting
속성은 마지막으로 설정된
값을 반환해야 합니다.
참고: Realm 내에서는, 연관된 서비스
워커마다 하나의 ServiceWorker
객체만 존재합니다.
3.2.4. active
active
속성은 마지막으로 설정된
값을 반환해야 합니다.
참고: Realm 내에서는, 연관된 서비스
워커마다 하나의 ServiceWorker
객체만 존재합니다.
3.2.5. navigationPreload
navigationPreload
getter 단계는 서비스 워커 등록의 NavigationPreloadManager
객체를 반환한다.
3.2.6. scope
scope
getter 단계는 서비스 워커 등록의 직렬화된 scope url을 반환한다.
registration.scope
의 값은
navigator.serviceWorker.ready.then(registration => console.log(registration.scope))
와 같이 얻을 때 "https://example.com/
"이 됩니다.
3.2.7. updateViaCache
updateViaCache
getter
단계는 서비스 워커 등록의 update
via cache mode를 반환한다.
3.2.8. update()
update()
메서드 단계:
-
registration을 서비스 워커 등록으로 한다.
-
newestWorker를 최신 워커 얻기 알고리즘을 registration을 인자로 실행한 결과로 한다.
-
newestWorker가 null이면, "
InvalidStateError
"DOMException
으로 거부된 프라미스를 반환하고 단계를 중단한다. -
this의 관련 글로벌 객체 globalObject가
ServiceWorkerGlobalScope
객체이고, globalObject에 연관된 서비스 워커의 상태가 "installing
"이면, "InvalidStateError
"DOMException
으로 거부된 프라미스를 반환하고 단계를 중단한다. -
promise를 프라미스로 한다.
-
job을 작업 생성 알고리즘을 update, registration의 storage key, registration의 scope url, newestWorker의 script url, promise, this의 관련 settings object를 인자로 실행한 결과로 한다.
-
job의 worker type을 newestWorker의 type으로 설정한다.
-
작업 예약을 job로 호출한다.
-
promise를 반환한다.
3.2.9. unregister()
참고: unregister()
메서드는 서비스 워커 등록을 등록 해제합니다. 현재 제어된 서비스 워커 클라이언트의 active service worker의 등록 정보는 해당 서비스 워커 등록을 사용하는 모든 서비스 워커 클라이언트 (자기 자신 포함)가 언로드될 때까지 유효합니다. 즉,
unregister()
메서드는 이후의 내비게이션에만 영향을 미칩니다.
unregister()
메서드 단계:
-
registration을 서비스 워커 등록으로 한다.
-
promise를 새 프라미스로 한다.
-
job을 작업 생성 알고리즘을 unregister, registration의 storage key, registration의 scope url, null, promise, this의 관련 settings object를 인자로 실행한 결과로 한다.
-
작업 예약을 job로 호출한다.
-
promise를 반환한다.
3.2.10. 이벤트 핸들러
아래는 이벤트 핸들러(및 해당 이벤트 핸들러 이벤트 타입)로, 이벤트 핸들러 IDL 속성으로 모든 ServiceWorkerRegistration
인터페이스 객체가 반드시 지원해야 합니다:
이벤트 핸들러 | 이벤트 핸들러 이벤트 타입 |
---|---|
onupdatefound
| updatefound
|
3.3.
navigator.serviceWorker
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute ServiceWorkerContainer serviceWorker ; };partial interface WorkerNavigator { [SecureContext ,SameObject ]readonly attribute ServiceWorkerContainer serviceWorker ; };
serviceWorker
getter 단계는
ServiceWorkerContainer
객체를 반환한다. 해당 객체는 this와 연관되어 있다.
3.4. ServiceWorkerContainer
[SecureContext ,Exposed =(Window ,Worker )]interface :
ServiceWorkerContainer EventTarget {readonly attribute ServiceWorker ?controller ;readonly attribute Promise <ServiceWorkerRegistration >ready ; [NewObject ]Promise <ServiceWorkerRegistration >register ((TrustedScriptURL or USVString ),
scriptURL optional RegistrationOptions = {}); [
options NewObject ]Promise <(ServiceWorkerRegistration or undefined )>getRegistration (optional USVString = ""); [
clientURL NewObject ]Promise <FrozenArray <ServiceWorkerRegistration >>getRegistrations ();undefined startMessages (); // eventsattribute EventHandler oncontrollerchange ;attribute EventHandler onmessage ; // event.source of message events is ServiceWorker objectattribute EventHandler onmessageerror ; };
dictionary {
RegistrationOptions USVString ;
scope WorkerType = "classic";
type ServiceWorkerUpdateViaCache = "imports"; };
updateViaCache
사용자 에이전트는 ServiceWorkerContainer
객체를 Navigator
객체 또는 WorkerNavigator
객체가 생성될 때 만들고 해당 객체와 연관시켜야 한다.
ServiceWorkerContainer
객체는 서비스 워커 등록을 등록, 해제, 업데이트하는 기능을 제공하며, 서비스 워커 등록 및 연관된 서비스 워커의 상태에 접근할 수 있다.
ServiceWorkerContainer
객체는 연관된 서비스 워커 클라이언트를 가진다. 이는 서비스 워커 클라이언트로, global object가 Navigator
객체 또는 WorkerNavigator
객체와 연관된 것이다.
ServiceWorkerContainer
객체는 연관된 ready promise
(promise 또는 null)을 가진다. 초기값은 null이다.
ServiceWorkerContainer
객체는 작업 소스인 클라이언트 메시지 큐를 가진다(초기값은 비어 있음). 클라이언트 메시지 큐는 활성/비활성화
상태가 될 수 있으며, 초기에는 비활성화 상태다. ServiceWorkerContainer
객체의 클라이언트 메시지 큐가 활성화되면, 이벤트 루프는 이를 작업 소스 중 하나로 사용해야 한다. ServiceWorkerContainer
객체의 관련 글로벌 객체가 Window
객체일 때, 클라이언트 메시지 큐에 대기 중인 모든 작업은 해당 settings object의 연관된 문서와 연관되어야 한다.
3.4.1. controller
controller
속성은 다음 단계를 반드시 실행해야 한다:
-
client를 this의 서비스 워커 클라이언트로 한다.
-
client의 active service worker 값이 null이면, null을 반환한다.
-
client의 active service worker를 서비스 워커 객체 얻기로 얻은 값을 this의 settings object에서 반환한다.
참고: navigator.serviceWorker.controller
는 요청이 강제 새로고침(shift+refresh)일 때 null
을 반환한다.
3.4.2. ready
ready
속성은 다음 단계를
반드시 실행해야 한다:
-
this의 ready promise가 null이면, this의 ready promise를 새 프라미스로 설정한다.
-
readyPromise를 this의 ready promise로 한다.
-
readyPromise가 pending이면, 다음 하위 단계를 병렬로 실행한다:
-
client를 this의 서비스 워커 클라이언트로 한다.
-
storage key를 obtain a storage key를 client에 대해 실행한 결과로 한다.
-
registration을 서비스 워커 등록 매칭을 storage key와 client의 creation URL을 인자로 실행한 결과로 한다.
-
registration이 null이 아니고, registration의 active worker가 null이 아니면, 작업 큐에 추가를 readyPromise의 settings object의 responsible event loop에서 DOM manipulation 작업 소스로 실행하여, readyPromise를 서비스 워커 등록 객체 얻기로 registration을 readyPromise의 settings object에서 반환한 값으로 resolve한다.
-
-
readyPromise를 반환한다.
참고: 반환된 ready promise는 절대 reject되지 않는다. 만약 이 알고리즘에서 resolve되지 않으면, 매칭되는 서비스 워커 등록이 등록되고 active worker가 설정될 때 결국 resolve된다. (Activate 알고리즘 단계 참고)
3.4.3. register(scriptURL, options)
참고: register(scriptURL, options)
메서드는 주어진 scope
url에 대해 서비스 워커 등록을 생성하거나 업데이트한다. 성공 시, 서비스 워커 등록은 제공된 scriptURL을 scope url에 연결하며,
이후 navigation
matching에 사용된다.
register(scriptURL, options)
메서드 단계:
-
p를 프라미스로 한다.
-
scriptURL을
TrustedScriptURL
, this의 관련 글로벌 객체, scriptURL, "ServiceWorkerContainer register", "script"로 Get Trusted Type compliant string을 실행한 결과로 한다. -
client를 this의 서비스 워커 클라이언트로 한다.
-
scriptURL을 파싱을 this의 settings object의 API base URL로 실행한 결과로 한다.
-
scopeURL을 null로 한다.
-
options["
scope
"] 값이 존재하면, scopeURL을 파싱을 options["scope
"] 와 this의 settings object의 API base URL로 실행한 결과로 한다. -
Start Register를 scopeURL, scriptURL, p, client, client의 creation URL, options["
type
"], options["updateViaCache
"]로 실행한다. -
p를 반환한다.
3.4.4. getRegistration(clientURL)
getRegistration(clientURL)
메서드 단계:
-
client를 this의 서비스 워커 클라이언트로 한다.
-
storage key를 obtain a storage key를 client에 대해 실행한 결과로 한다.
-
clientURL을 파싱을 clientURL과 this의 settings object의 API base URL로 실행한 결과로 한다.
-
clientURL이 실패면, promise를 TypeError로 reject해서 반환한다.
-
clientURL의 fragment를 null로 설정한다.
-
clientURL의 origin이 client의 origin과 다르면, promise를 "
SecurityError
"DOMException
으로 reject해서 반환한다. -
promise를 새 프라미스로 한다.
-
다음 단계를 병렬로 실행한다:
-
registration을 서비스 워커 등록 매칭을 storage key와 clientURL을 인자로 실행한 결과로 한다.
-
registration이 null이면, promise를 undefined로 resolve하고 단계를 중단한다.
-
promise를 서비스 워커 등록 객체 얻기로 registration을 promise의 settings object에서 반환한 값으로 resolve한다.
-
-
promise를 반환한다.
3.4.5. getRegistrations()
getRegistrations()
메서드 단계:
-
client를 this의 서비스 워커 클라이언트로 한다.
-
client storage key를 obtain a storage key를 client에 대해 실행한 결과로 한다.
-
promise를 새 프라미스로 한다.
-
다음 단계를 병렬로 실행한다:
-
registrations를 새 리스트로 한다.
-
각 (storage key, scope) → registration에 대해 registration map에서:
-
storage key가 client storage key와 같으면, registrations에 registration 추가.
-
-
작업 큐에 추가를 promise의 settings object의 responsible event loop에서 DOM manipulation 작업 소스로 다음 단계를 실행:
-
registrationObjects를 새 리스트로 한다.
-
각 registration에 대해 registrations에서:
-
registrationObj를 서비스 워커 등록 객체 얻기로 registration을 promise의 settings object에서 반환한 값으로 한다.
-
-
promise를 registrationObjects의 frozen array로 resolve한다. (promise의 Realm에서)
-
-
-
promise를 반환한다.
3.4.6. startMessages()
startMessages()
메서드 단계는 this의 클라이언트 메시지 큐가 비활성화 상태라면 활성화한다.
3.4.7. 이벤트 핸들러
아래는 이벤트 핸들러(및 해당 이벤트 핸들러 이벤트 타입)로, 이벤트 핸들러 IDL 속성으로 모든 ServiceWorkerContainer
인터페이스 객체가 반드시 지원해야 한다:
이벤트 핸들러 | 이벤트 핸들러 이벤트 타입 |
---|---|
oncontrollerchange
| controllerchange
|
onmessage
| message
|
onmessageerror
| messageerror
|
onmessage
setter가 처음 수행될 때, this의 클라이언트 메시지 큐를 활성화한다.
3.5. 이벤트
다음 이벤트는 ServiceWorker
객체에서 디스패치됩니다:
이벤트 이름 | 인터페이스 | 언제 디스패치되는가… |
---|---|---|
statechange
| Event
| state
속성이 ServiceWorker
객체에서 변경될 때.
|
다음 이벤트는 ServiceWorkerRegistration
객체에서 디스패치됩니다:
이벤트 이름 | 인터페이스 | 언제 디스패치되는가… |
---|---|---|
updatefound
| Event
| 서비스 워커 등록의 installing worker가 변경될 때. (설치 알고리즘의 8단계 참고) |
다음 이벤트들은 ServiceWorkerContainer
객체에서 디스패치됩니다:
이벤트 이름 | 인터페이스 | 언제 디스패치되는가… |
---|---|---|
controllerchange
| Event
| 서비스 워커 클라이언트의 active service worker
값이 변경될 때. (활성화 알고리즘의
9.2단계 참고. skip waiting 플래그가 설정된 서비스 워커는 서비스 워커 등록 활성화를 서비스 워커 클라이언트가 사용 중인 상황에서 발생시킬 수 있으며, navigator.serviceWorker.controller
값은 즉시 active worker를 서비스 워커로 반영하여 제어 중인 서비스 워커 클라이언트임을 나타냅니다.)
|
message
| Event
| 서비스 워커 클라이언트가 서비스 워커로부터 메시지를 받을 때. postMessage(message, options)
참고.
|
messageerror
| Event
| 서비스 워커 클라이언트가 서비스 워커로부터 역직렬화할 수 없는 메시지를 받을 때. postMessage(message, options)
참고.
|
3.6.
NavigationPreloadManager
[SecureContext ,Exposed =(Window ,Worker )]interface {
NavigationPreloadManager Promise <undefined >enable ();Promise <undefined >disable ();Promise <undefined >setHeaderValue (ByteString );
value Promise <NavigationPreloadState >getState (); };dictionary {
NavigationPreloadState boolean =
enabled false ;ByteString ; };
headerValue
3.6.1. enable()
enable()
메서드 단계는 다음과 같다:
-
promise를 새로운 프라미스로 설정한다.
-
다음 단계들을 병렬로 실행한다:
-
registration의 활성 워커가 null이면, "InvalidStateError"
DOMException
으로 promise를 거부하고, 이 단계들을 중단한다. -
registration의 navigation preload enabled flag를 설정한다.
-
promise를 undefined로 해결한다.
-
promise를 반환한다.
3.6.2. disable()
disable()
메서드 단계는 다음과
같다:
-
promise를 새로운 프라미스로 설정한다.
-
다음 단계들을 병렬로 실행한다:
-
registration의 활성 워커가 null이면, "InvalidStateError"
DOMException
으로 promise를 거부하고, 이 단계들을 중단한다. -
registration의 navigation preload enabled flag를 해제한다.
-
promise를 undefined로 해결한다.
-
promise를 반환한다.
3.6.3. setHeaderValue(value)
setHeaderValue(value)
메서드 단계는 다음과 같다:
-
promise를 새로운 프라미스로 설정한다.
-
다음 단계들을 병렬로 실행한다:
-
registration의 활성 워커가 null이면, "InvalidStateError"
DOMException
으로 promise를 거부하고, 이 단계들을 중단한다. -
registration의 navigation preload header value를 value로 설정한다.
-
promise를 undefined로 해결한다.
-
promise를 반환한다.
3.6.4. getState()
getState()
메서드 단계는 다음과
같다:
-
promise를 새로운 프라미스로 설정한다.
-
다음 단계들을 병렬로 실행한다:
-
state를 새로운
NavigationPreloadState
딕셔너리로 설정한다. -
registration의 navigation preload enabled flag가 설정되어 있으면, state["
enabled
"] 를 true로 설정한다. -
state["
headerValue
"] 를 registration의 navigation preload header value로 설정한다. -
promise를 state로 해결한다.
-
promise를 반환한다.
4. 실행 컨텍스트
// caching.js self. addEventListener( "install" , event=> { event. waitUntil( // 리소스 캐시를 연다. caches. open( "shell-v1" ). then( cache=> { // 리소스를 가져오는 과정을 시작한다. 모든 리소스가 저장되어야 성공한다. // 하나라도 실패하면 전체 작업이 실패한다. return cache. addAll([ "/app.html" , "/assets/v1/base.css" , "/assets/v1/app.js" , "/assets/v1/logo.png" , "/assets/v1/intro_video.webm" ]); }) ); }); self. addEventListener( "fetch" , event=> { // 서비스 워커가 성공적으로 설치되고 활성화되어야만 "fetch" 이벤트가 전달된다. // 캐시의 모든 작업은 비동기이므로, URL 매칭도 포함해 promise를 사용한다. e.respondWith()도 promise를 받을 수 있다: event. respondWith( caches. match( e. request). then( response=> { return response|| fetch( e. request); }). catch (() => { return caches. match( "/fallback.html" ); }) ); });
4.1. ServiceWorkerGlobalScope
[Global =(Worker ,ServiceWorker ),Exposed =ServiceWorker ,SecureContext ]interface :
ServiceWorkerGlobalScope WorkerGlobalScope { [SameObject ]readonly attribute Clients clients ; [SameObject ]readonly attribute ServiceWorkerRegistration registration ; [SameObject ]readonly attribute ServiceWorker serviceWorker ; [NewObject ]Promise <undefined >skipWaiting ();attribute EventHandler oninstall ;attribute EventHandler onactivate ;attribute EventHandler onfetch ;attribute EventHandler onmessage ;attribute EventHandler onmessageerror ; };
ServiceWorkerGlobalScope
객체는 서비스 워커의
글로벌 실행 컨텍스트를 나타낸다.
ServiceWorkerGlobalScope
객체는 서비스 워커(서비스 워커)와 연관된다.
ServiceWorkerGlobalScope
객체는 import
스크립트 캐시 무시 플래그를 가진다. 처음에는 해제되어 있다.
ServiceWorkerGlobalScope
객체는 race response map을 가진다. 이는
순서가 있는 map으로, key는 request이고 value는 race response이다.
race
response는 구조체로, "race-network-and-fetch-handler"
실행 시 네트워크 응답을 담는다. value는 response, "pending", 또는 null 이다.
참고: ServiceWorkerGlobalScope
객체는 오리진에서 실행되는 일반적인 이벤트 기반, 시간 제한 스크립트 실행 컨텍스트를 제공한다. 등록에 성공하면 서비스 워커는 이벤트와의 관계에 따라 시작·유지·종료된다. 서비스 워커 클라이언트와는 관련
없다. 서비스 워커
내부에서는 동기 요청을 시작하면 안 된다.
4.1.1. clients
4.1.2. registration
registration
getter 단계는 서비스 워커 registration 객체를 this의 서비스 워커의 containing service worker
registration을 this의 관련 설정 객체에서 반환한다.
4.1.3. serviceWorker
serviceWorker
getter 단계는
서비스 워커 객체를 this의 서비스 워커를 this의 관련 설정 객체에서 반환한다.
4.1.4. skipWaiting()
참고: skipWaiting()
메서드는 이 서비스
워커가 registration의 대기
위치에서 활성으로
진행하도록 한다. 서비스 워커 클라이언트가 사용 중이어도 registration이 진행된다.
skipWaiting()
메서드 단계는 다음과 같다:
-
promise를 새로운 프라미스로 설정한다.
-
다음 하위 단계들을 병렬로 실행한다:
-
서비스 워커의 skip waiting 플래그를 설정한다.
-
Try Activate를 서비스 워커의 containing service worker registration에 대해 호출한다.
-
promise를 undefined로 resolve 한다.
-
-
promise를 반환한다.
4.1.5. 이벤트 핸들러
다음은 이벤트 핸들러(그리고 대응되는 이벤트 핸들러 이벤트 타입)로서, 반드시 ServiceWorkerGlobalScope
인터페이스를 구현하는 모든 객체가 지원해야 한다:
이벤트 핸들러 | 이벤트 핸들러 이벤트 타입 |
---|---|
oninstall
| install
|
onactivate
| activate
|
onfetch
| fetch
|
onmessage
| message
|
onmessageerror
| messageerror
|
4.2. 클라이언트
[Exposed =ServiceWorker ]interface {
Client readonly attribute USVString url ;readonly attribute FrameType frameType ;readonly attribute DOMString id ;readonly attribute ClientType type ;undefined postMessage (any ,
message sequence <object >);
transfer undefined postMessage (any ,
message optional StructuredSerializeOptions = {}); }; [
options Exposed =ServiceWorker ]interface :
WindowClient Client {readonly attribute VisibilityState visibilityState ;readonly attribute boolean focused ; [SameObject ]readonly attribute FrozenArray <USVString >ancestorOrigins ; [NewObject ]Promise <WindowClient >focus (); [NewObject ]Promise <WindowClient ?>navigate (USVString ); };
url enum {
FrameType ,
"auxiliary" ,
"top-level" ,
"nested" };
"none"
Client
객체는 서비스 워커 클라이언트
(a 서비스 워커 클라이언트)와 연관되어 있다.
Client
객체는 프레임 타입과 연관되어 있는데, 이는
"auxiliary
", "top-level
", "nested
", "none
" 중
하나이다.
별도의 명시가 없으면 "none
"이다.
WindowClient
객체는 브라우징 컨텍스트와 연관되어 있는데,
이는 해당 서비스 워커 클라이언트의 글로벌 객체의 브라우징 컨텍스트이다.
WindowClient
객체는 가시성 상태와 연관되어 있는데, 이는 visibilityState
속성 값 중 하나이다.
WindowClient
객체는 포커스 상태와 연관되어 있는데, true 또는 false (초기값은 false)이다.
WindowClient
객체는 조상 출처 배열과 연관되어 있다.
4.2.1.
url
url
getter 단계는 this가 연관된 서비스 워커 클라이언트의 직렬화된 생성 URL을 반환한다.
4.2.2.
frameType
4.2.3.
id
id
getter 단계는 this가 연관된 서비스 워커 클라이언트의 id를 반환한다.
4.2.4.
type
type
getter 단계는 다음과 같다:
-
client를 this의 서비스 워커 클라이언트로 한다.
-
client가 환경 설정 객체라면:
-
client가 window client라면
"window"
를 반환한다. -
그 외에 client가 dedicated worker client라면
"worker"
를 반환한다. -
그 외에 client가 shared worker client라면
"sharedworker"
를 반환한다.
-
-
그 외의 경우:
-
"window"
를 반환한다.
-
4.2.5.
postMessage(message, transfer)
postMessage(message, transfer)
메서드 단계는 다음과 같다:
-
options를 «[ "transfer" → transfer ]»로 한다.
-
postMessage(message, options)
를 message와 options를 인수로 하여 호출한다.
4.2.6. postMessage(message, options)
postMessage(message, options)
메서드 단계는 다음과 같다:
-
contextObject를 this로 한다.
-
sourceSettings를 contextObject의 관련 설정 객체로 한다.
-
serializeWithTransferResult를 StructuredSerializeWithTransfer(message, options["
transfer
"])로 한다. 예외가 발생하면 다시 던진다. -
다음 단계들을 병렬로 실행한다:
-
targetClient를 null로 한다.
-
각 서비스 워커 클라이언트 client에 대해:
-
만약 client가 contextObject의 서비스 워커 클라이언트와 같다면, targetClient를 client로 지정하고 반복을 중단한다.
-
-
targetClient가 null이면 반환한다.
-
destination을 다음과 같이 한다:
ServiceWorkerContainer
객체이며, 연관된 서비스 워커 클라이언트가 targetClient인 것이다. -
destination의 클라이언트 메시지 큐에 다음 단계들을 실행하는 태스크를 추가한다:
-
origin을 설정 객체의 origin을 문자열로 변환한 값으로 한다.
-
source를 서비스 워커 객체를 얻는 것의 결과로 한다. contextObject의 관련 글로벌 객체의 서비스 워커를 targetClient에서 나타내는 것이다.
-
deserializeRecord를 StructuredDeserializeWithTransfer(serializeWithTransferResult, destination의 관련 Realm)로 한다.
이 과정에서 예외가 발생하면, 예외를 잡아 messageerror 이벤트를 발생시키고,
messageerror
이벤트를 destination에서MessageEvent
객체로 사용하여origin
속성은 origin으로,source
속성은 source로 초기화하고, 이 단계들을 중단한다. -
messageClone을 deserializeRecord.[[Deserialized]]로 한다.
-
newPorts를 frozen array로 새로 만들고, deserializeRecord.[[TransferredValues]]에 있는 모든
MessagePort
객체를 포함한다(있다면). -
message 이벤트를 dispatch한다.
message
이름으로 destination에서MessageEvent
객체를 사용하여,origin
속성은 origin,source
속성은 source,data
속성은 messageClone,ports
속성은 newPorts로 초기화한다.
-
-
4.2.7. visibilityState
4.2.8.
focused
4.2.9. ancestorOrigins
4.2.10.
focus()
focus()
메서드 단계는 다음과 같다:
-
이 출처(origin) 내에
Window
중 일시적 활성화가 없는 경우, "InvalidAccessError
"DOMException
으로 거부된 promise를 반환한다. -
promise를 새로운 promise로 한다.
-
태스크를 큐에 추가하여, this가 연관된 서비스 워커 클라이언트의 책임 이벤트 루프에서 사용자 상호작용 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
frameType을 Get Frame Type을 this의 브라우징 컨텍스트로 실행한 결과로 한다.
-
visibilityState를 this의 브라우징 컨텍스트의 active document의
visibilityState
속성 값으로 한다. -
focusState를 has focus 단계를 this의 브라우징 컨텍스트의 active document로 실행한 결과로 한다.
-
ancestorOriginsList를 this의 브라우징 컨텍스트의 active document의 관련 글로벌 객체의
Location
객체의 조상 출처 목록의 연관된 목록으로 한다. -
태스크를 큐에 추가하여, serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
windowClient를 Create Window Client를 this가 연관된 서비스 워커 클라이언트, frameType, visibilityState, focusState, ancestorOriginsList와 함께 실행한 결과로 한다.
-
windowClient의 포커스 상태가 true라면, promise를 windowClient로 resolve한다.
-
그 외에는 promise를
TypeError
로 reject한다.
-
-
promise를 반환한다.
4.2.11.
navigate(url)
navigate(url)
메서드 단계는 다음과 같다:
-
url을 파싱하여 얻은 값을 this의 관련 설정 객체의 API 기준 URL로 한다.
-
url이 실패라면
TypeError
로 거부된 promise를 반환한다. -
url이
about:blank
라면TypeError
로 거부된 promise를 반환한다. -
this가 연관된 서비스 워커 클라이언트의 활성 서비스 워커가 this의 관련 글로벌 객체의 서비스 워커가 아니라면,
TypeError
로 거부된 promise를 반환한다. -
promise를 새로운 promise로 한다.
-
태스크를 큐에 추가하여, this가 연관된 서비스 워커 클라이언트의 책임 이벤트 루프에서 사용자 상호작용 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
browsingContext의 연관된 문서가 완전히 활성화되어 있지 않다면, 태스크를 큐에 추가하여 promise를
TypeError
로 reject하고, serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하며, 이 단계들을 중단한다. -
HandleNavigate: 브라우징 컨텍스트를 url로 네비게이트한다. browsingContext의 연관된 문서를 사용하며, exceptionsEnabled는 true로 한다.
-
HandleNavigate 단계에서 예외가 발생하면, 태스크를 큐에 추가하여 promise를 해당 예외로 reject하고, serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하며, 이 단계들을 중단한다.
-
frameType을 Get Frame Type을 browsingContext로 실행한 결과로 한다.
-
visibilityState를 browsingContext의 active document의
visibilityState
속성 값으로 한다. -
focusState를 has focus 단계를 browsingContext의 active document로 실행한 결과로 한다.
-
ancestorOriginsList를 browsingContext의 active document의 관련 글로벌 객체의
Location
객체의 조상 출처 목록의 연관된 목록으로 한다. -
태스크를 큐에 추가하여, serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
browsingContext의
Window
객체의 환경 설정 객체의 생성 URL의 origin이 동일하지 않다면, 서비스 워커의 origin과 다르다면, promise를 null로 resolve하고 이 단계들을 중단한다. -
windowClient를 Create Window Client를 this가 연관된 서비스 워커 클라이언트, frameType, visibilityState, focusState, ancestorOriginsList와 함께 실행한 결과로 한다.
-
promise를 windowClient로 resolve한다.
-
-
promise를 반환한다.
4.3.
Clients
[Exposed =ServiceWorker ]interface { // 반환되는 객체는 항상 새로운 인스턴스이다 [
Clients NewObject ]Promise <(Client or undefined )>get (DOMString ); [
id NewObject ]Promise <FrozenArray <Client >>matchAll (optional ClientQueryOptions = {}); [
options NewObject ]Promise <WindowClient ?>openWindow (USVString ); [
url NewObject ]Promise <undefined >claim (); };
dictionary {
ClientQueryOptions boolean =
includeUncontrolled false ;ClientType = "window"; };
type
enum {
ClientType ,
"window" ,
"worker" ,
"sharedworker" };
"all"
사용자 에이전트는 Clients
객체를 ServiceWorkerGlobalScope
객체가 생성될 때 반드시 생성하고 해당 객체에 연관시켜야 한다.
4.3.1.
get(id)
get(id)
메서드 단계는 다음과 같다:
-
promise를 새로운 promise로 한다.
-
다음 하위 단계들을 병렬로 실행한다:
-
각 서비스 워커 클라이언트 client에 대해, 스토리지 키를 얻기를 client에 대해 실행한 결과가 연관된 서비스 워커의 등록 객체의 스토리지 키와 같은 경우:
-
promise를 undefined로 resolve한다.
-
-
promise를 반환한다.
4.3.2.
matchAll(options)
matchAll(options)
메서드 단계는 다음과 같다:
-
promise를 새로운 promise로 한다.
-
다음 단계들을 병렬로 실행한다:
-
targetClients를 새로운 리스트로 한다.
-
각 서비스 워커 클라이언트 client에 대해, 스토리지 키를 얻기를 client에 대해 실행한 결과가 연관된 서비스 워커의 등록 객체의 스토리지 키와 같은 경우:
-
matchedWindowData를 새로운 리스트로 한다.
-
matchedClients를 새로운 리스트로 한다.
-
targetClients에 있는 각 서비스 워커 클라이언트 client에 대해:
-
options["
type
"] 가"window"
또는"all"
이며, client가 환경 설정 객체가 아니거나 window client라면:-
windowData를 «[ "client" → client, "ancestorOriginsList" → 새로운 리스트 ]»로 한다.
-
browsingContext를 null로 한다.
-
isClientEnumerable를 true로 한다.
-
client가 환경 설정 객체라면, browsingContext를 client의 글로벌 객체의 브라우징 컨텍스트로 한다.
-
그 외의 경우 browsingContext를 client의 타겟 브라우징 컨텍스트로 한다.
-
태스크를 큐에 추가하여, browsingContext의 이벤트 루프에서 사용자 상호작용 태스크 소스를 사용하여 다음 하위 단계들을 실행한다:
-
browsingContext가 폐기(discarded)되었다면, isClientEnumerable를 false로 하고 이 단계들을 중단한다.
-
client가 window client이고 client의 연관된 문서가 browsingContext의 active document가 아니라면, isClientEnumerable를 false로 하고 이 단계들을 중단한다.
-
windowData["
frameType
"]에 Get Frame Type을 browsingContext로 실행한 결과를 할당한다. -
windowData["
visibilityState
"] 에 browsingContext의 active document의visibilityState
속성 값을 할당한다. -
windowData["
focusState
"]에 has focus 단계를 browsingContext의 active document로 실행한 결과를 할당한다. -
client가 window client라면, windowData["
ancestorOriginsList
"] 에 browsingContext의 active document의 글로벌 객체의Location
객체의 조상 출처 목록의 연관된 목록을 할당한다.
-
-
태스크가 실행될 때까지 대기한다.
참고: 대기는 블로킹 대기이지만, 구현체는 상태가 깨지지 않는 한 반복을 병렬로 실행할 수 있다.
-
isClientEnumerable가 true라면:
-
windowData를 matchedWindowData에 추가한다.
-
-
-
그 외에 options["
type
"] 가"worker"
또는"all"
이고 client가 dedicated worker client이거나, options["type
"] 가"sharedworker"
또는"all"
이고 client가 shared worker client라면, 다음을 실행한다:-
client를 matchedClients에 추가한다.
-
-
-
태스크를 큐에 추가하여, promise의 관련 설정 객체의 책임 이벤트 루프에서 DOM 조작 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
clientObjects를 새로운 리스트로 한다.
-
각 windowData에 대해 matchedWindowData에서:
-
windowClient를 Create Window Client 알고리즘을 windowData["
client
"], windowData["frameType
"], windowData["visibilityState
"], windowData["focusState
"], windowData["ancestorOriginsList
"]를 인수로 실행한 결과로 한다. -
windowClient를 clientObjects에 추가한다.
-
-
각 client에 대해 matchedClients에서:
-
clientObject를 Create Client 알고리즘을 client를 인수로 실행한 결과로 한다.
-
clientObject를 clientObjects에 추가한다.
-
-
clientObjects를 다음과 같이 정렬한다:
-
WindowClient
객체 중 브라우징 컨텍스트가 포커스됨인 것은 가장 먼저 놓고, 최근에 포커스된 순서대로 정렬한다. -
WindowClient
객체 중 브라우징 컨텍스트가 한 번도 포커스됨이 없는 것은 그 다음에 놓고, 서비스 워커 클라이언트의 생성 순서대로 정렬한다. -
Client
객체 중 연관된 서비스 워커 클라이언트가 worker client인 것은 그 다음에 놓고, 서비스 워커 클라이언트의 생성 순서대로 정렬한다.
참고: Window client가 항상 worker client보다 앞에 온다.
-
-
promise의 frozen array로 clientObjects를 resolve한다. relevant Realm에서 실행한다.
-
-
-
promise를 반환한다.
4.3.3.
openWindow(url)
openWindow(url)
메서드 단계는 다음과 같다:
-
url을 파싱하여 얻은 값을 this의 관련 설정 객체의 API 기준 URL로 한다.
-
url이 실패라면
TypeError
로 거부된 promise를 반환한다. -
url이
about:blank
라면TypeError
로 거부된 promise를 반환한다. -
이 출처 내에
Window
중 일시적 활성화가 없는 경우, "InvalidAccessError
"DOMException
으로 거부된 promise를 반환한다. -
promise를 새로운 promise로 한다.
-
다음 하위 단계들을 병렬로 실행한다:
-
newContext를 새로운 최상위 브라우징 컨텍스트로 한다.
-
태스크를 큐에 추가하여, newContext의
Window
객체의 환경 설정 객체의 책임 이벤트 루프에서 사용자 상호작용 태스크 소스를 사용하여 다음 단계들을 실행한다:-
HandleNavigate: newContext를 url로 네비게이트한다. exceptionsEnabled는 true, historyHandling "
replace
"로 한다. -
HandleNavigate 단계에서 예외가 발생하면, 태스크를 큐에 추가하여 promise를 해당 예외로 reject하고, serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하며, 이 단계들을 중단한다.
-
frameType을 Get Frame Type을 newContext로 실행한 결과로 한다.
-
visibilityState를 newContext의 active document의
visibilityState
속성 값으로 한다. -
focusState를 has focus 단계를 newContext의 active document를 인수로 실행한 결과로 한다.
-
ancestorOriginsList를 newContext의 active document의 글로벌 객체의
Location
객체의 조상 출처 목록의 연관된 목록으로 한다. -
태스크를 큐에 추가하여, serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
스토리지 키를 얻기를 newContext의
Window
객체의 환경 설정 객체로 실행한 결과가 동일하지 않으면, 서비스 워커의 등록 객체의 스토리지 키와 같지 않으면, promise를 null로 resolve하고 이 단계들을 중단한다. -
client를 Create Window Client를 newContext의
Window
객체의 환경 설정 객체, frameType, visibilityState, focusState, ancestorOriginsList를 인수로 실행한 결과로 한다. -
promise를 client로 resolve한다.
-
-
-
-
promise를 반환한다.
4.3.4.
claim()
claim()
메서드 단계는 다음과 같다:
-
서비스 워커가 활성 워커가 아니라면, "
InvalidStateError
"DOMException
으로 거부된 promise를 반환한다. -
promise를 새로운 promise로 한다.
-
다음 하위 단계들을 병렬로 실행한다:
-
각 서비스 워커 클라이언트 client에 대해, 스토리지 키를 얻기를 client에 대해 실행한 결과가 동일하면, 서비스 워커의 등록 객체의 스토리지 키와 같은 경우:
-
client의 실행 준비 플래그가 설정되어 있지 않거나 client의 폐기 플래그가 설정되어 있다면 다음 반복을 한다.
-
storage key를 스토리지 키를 얻기를 client에 대해 실행한 결과로 한다.
-
registration을 Match Service Worker Registration을 storage key와 client의 생성 URL을 인수로 실행한 결과로 한다.
-
client의 활성 서비스 워커가 서비스 워커가 아니라면 다음을 실행한다:
-
Handle Service Worker Client Unload를 client를 인수로 호출한다.
-
Notify Controller Change 알고리즘을 client를 인수로 실행한다.
-
-
-
promise를 undefined로 resolve한다.
-
-
promise를 반환한다.
4.4.
ExtendableEvent
[Exposed =ServiceWorker ]interface :
ExtendableEvent Event {(
constructor DOMString ,
type optional ExtendableEventInit = {});
eventInitDict undefined waitUntil (Promise <any >); };
f
dictionary :
ExtendableEventInit EventInit { // 파생 이벤트의 향후 호환성을 위해 정의됨 };
ExtendableEvent
객체는 수명 연장 프라미스(프라미스 배열)을 가지고 있다. 최초에는 빈 배열이다.
ExtendableEvent
객체는 대기 중 프라미스 수(수명 연장 프라미스 중 대기 중인 프라미스의 수)을 가지고 있다.
최초에는 0으로 설정된다.
ExtendableEvent
객체는 타임아웃 플래그를 가진다. 최초에는 설정되지 않으며, 대기 중 프라미스 수가 0보다 크면 사용자 에이전트가 부여한 선택적 지연
후에 설정된다.
ExtendableEvent
객체는 활성 상태라고 하는데, 이는 타임아웃 플래그가
설정되지 않았고, 대기 중 프라미스 수가 0보다 크거나 dispatch 플래그가 설정된 경우이다.
서비스 워커는 두 개의
라이프사이클
이벤트(install
및 activate
)를
갖는다.
서비스 워커는
ExtendableEvent
인터페이스를 activate
및 install
이벤트에 사용한다.
서비스 워커 확장에서 이벤트 핸들러를
정의하는 경우에는 ExtendableEvent
인터페이스를 사용할 수도 있고, 확장할 수도 있다.
4.4.1.
event.waitUntil(f)
참고: waitUntil()
메서드는 이벤트의 수명을 연장한다.
waitUntil(f)
메서드 단계는 수명 연장 프라미스 추가 f를 this에 추가하는 것이다.
ExtendableEvent
)에
추가하려면 다음 단계들을 실행한다:
-
event의
isTrusted
속성이 false이면, "InvalidStateError
"DOMException
을 throw한다. -
event가 활성 상태가 아니면, "
InvalidStateError
"DOMException
을 throw한다.참고: 이벤트 핸들러를 호출한 태스크에서 수명 연장 프라미스가 추가되지 않았다면, 이후 비동기 태스크에서
waitUntil()
을 호출하면 예외가 발생한다. -
promise를 event의 수명 연장 프라미스에 추가한다.
-
event의 대기 중 프라미스 수를 1 증가시킨다.
참고: 주어진 프라미스가 이미 settle된 경우에도 대기 중 프라미스 수는 증가한다. 해당 카운트 감소는 프라미스 반응의 미크로태스크에서 처리된다.
-
promise가 이행 또는 거부될 때, 미크로태스크를 큐에 추가하여 다음 하위 단계들을 실행한다:
-
event의 대기 중 프라미스 수를 1 감소시킨다.
-
event의 대기 중 프라미스 수가 0이면:
-
registration이 등록 해제됨이면, Try Clear Registration을 registration을 인수로 실행한다.
-
registration이 null이 아니면, Try Activate를 registration을 인수로 실행한다.
-
사용자 에이전트는 서비스 워커에 대기 중 이벤트 없음이 서비스 워커에 대해 false를 반환하면 해당 서비스 워커를 종료하지 않아야 한다.
서비스 워커 및 확장에서 이벤트 핸들러를 정의하는 경우, 자체 동작을 정의할 수 있으며, 수명 연장 프라미스가 작업 길이를 제안할 수 있고, 프라미스가 reject된 경우 작업 실패를 제안할 수 있다.
참고: 서비스 워커는 installing worker를
"installed
"로 처리하는 것을 install
이벤트의 수명 연장 프라미스가 모두 성공적으로 resolve될 때까지
지연한다. (Install 알고리즘 단계 참고.) 프라미스 중 하나라도 reject되면 설치가 실패한다. 이는 서비스
워커가 의존하는 핵심 캐시가 모두 채워질 때까지 "installed
"로 간주되지 않게 하는 데 주로 사용된다. 이와 마찬가지로, 서비스 워커는 active
worker를 "activated
"로 처리하는 것을 activate
이벤트의 수명 연장 프라미스가 모두 settle될 때까지 지연한다. (Activate 알고리즘 단계 참고.) 이는 서비스 워커가 데이터베이스 스키마를 업그레이드하고, 오래된 캐시
항목을 삭제할 때까지 기능성 이벤트가 active worker에 dispatch되지 않도록 하는 데 주로 사용된다.
4.5.
InstallEvent
[Exposed =ServiceWorker ]interface :
InstallEvent ExtendableEvent {(
constructor DOMString ,
type optional ExtendableEventInit = {});
eventInitDict Promise <undefined >addRoutes ((RouterRule or sequence <RouterRule >)); };
rules dictionary {
RouterRule required RouterCondition ;
condition required RouterSource ; };
source dictionary {
RouterCondition URLPatternCompatible ;
urlPattern ByteString ;
requestMethod RequestMode ;
requestMode RequestDestination ;
requestDestination RunningStatus ;
runningStatus sequence <RouterCondition >;
_or RouterCondition ; };
not typedef (RouterSourceDict or RouterSourceEnum );
RouterSource dictionary {
RouterSourceDict DOMString ; };
cacheName enum {
RunningStatus ,
"running" };
"not-running" enum {
RouterSourceEnum ,
"cache" ,
"fetch-event" ,
"network" };
"race-network-and-fetch-handler"
라우터 조건 결과 카운트는 구조체이며 다음으로 구성된다:
-
조건 카운트(숫자).
-
쿼터 초과(불리언).
4.5.1. event.addRoutes(rules)
참고: addRoutes(rules)
메서드는 이 서비스 워커를 위해 fetch 이벤트 핸들러가 일반적으로 하는 단순 작업을 오프로드할 규칙을 등록한다.
addRoutes(rules)
메서드 단계는 다음과 같다:
-
rules가
RouterRule
딕셔너리면, rules를 « rules »로 설정한다. -
rules의 각 rule에 대해:
-
라우터 조건 검증 알고리즘을 rule["
condition
"] 및 serviceWorker로 실행한 결과가 false라면, TypeError로 reject된 promise를 반환한다. -
rule["
source
"]가 "fetch-event
" 또는 "race-network-and-fetch-handler
" 중 하나이고, serviceWorker의 처리할 이벤트 타입 집합에 fetch 이벤트가 포함되지 않으면, TypeError로 reject된 promise를 반환한다.
-
-
lifetimePromise를 새로운 promise로 한다.
-
수명 연장 프라미스 추가 lifetimePromise를 this에 추가한다.
참고:
event.addRoutes(rules)
호출은event.waitUntil(promise)
와 같이 기본적으로 이벤트의 수명을 연장한다. -
promise를 새로운 promise로 한다.
-
promise가 이행되거나 거부될 때, lifetimePromise를 undefined로 resolve한다.
참고: 이 단계는 install 이벤트 실패를 방지하기 위해 lifetimePromise가 항상 이행되도록 한다.
-
다음 단계들을 [[service worker queue]]에 추가한다:
-
allRules를 serviceWorker의 라우터 규칙 목록의 복사본으로 한다.
-
rules의 각 rule에 대해:
-
rule을 allRules에 추가한다.
-
-
라우터 등록 제한 체크를 allRules로 실행한 결과가 false라면, promise를
TypeError
로 reject한다. -
serviceWorker의 라우터 규칙 목록을 allRules로 설정한다.
-
태스크를 큐에 추가하여 serviceWorkerEventLoop에서 DOM 조작 태스크 소스를 사용하여 다음 단계들을 실행한다:
-
promise를 undefined로 resolve한다.
-
-
-
promise를 반환한다.
4.6.
FetchEvent
[Exposed =ServiceWorker ]interface :
FetchEvent ExtendableEvent {(
constructor DOMString ,
type FetchEventInit ); [
eventInitDict SameObject ]readonly attribute Request request ;readonly attribute Promise <any >preloadResponse ;readonly attribute DOMString clientId ;readonly attribute DOMString resultingClientId ;readonly attribute DOMString replacesClientId ;readonly attribute Promise <undefined >handled ;undefined respondWith (Promise <Response >); };
r
dictionary :
FetchEventInit ExtendableEventInit {required Request ;
request Promise <any >;
preloadResponse DOMString = "";
clientId DOMString = "";
resultingClientId DOMString = "";
replacesClientId Promise <undefined >; };
handled
서비스 워커는 필수
기능성
이벤트 fetch
를
가진다.
fetch
이벤트에 대해, 서비스
워커는 FetchEvent
인터페이스를 사용하며, 이 인터페이스는 ExtendableEvent
인터페이스를 확장한다.
FetchEvent
인터페이스를 사용하는 각 이벤트는 잠재적 응답(response)을 갖고, 초깃값은 null이며 다음의 플래그들도 갖는다(초기값은 모두 unset):
-
응답 대기 플래그
-
respondWith 진입 플래그
-
respondWith 오류 플래그
4.6.1.
event.request
request
속성은 반드시 초기화된 값을 반환해야 한다.
4.6.2. event.preloadResponse
preloadResponse
속성은 반드시 초기화된 값을 반환해야
한다.
이벤트가 생성될 때 해당 속성은 반드시 undefined로 resolve된 promise로 초기화되어야 한다.
4.6.3.
event.clientId
clientId
속성은 반드시 초기화된 값을 반환해야 한다.
이벤트가 생성될 때 해당 속성은 반드시 빈 문자열로 초기화되어야 한다.
4.6.4. event.resultingClientId
resultingClientId
속성은 반드시 초기화된 값을
반환해야 한다.
이벤트가 생성될 때 해당 속성은 반드시 빈 문자열로 초기화되어야 한다.
4.6.5. event.replacesClientId
replacesClientId
속성은 반드시 초기화된 값을
반환해야 한다.
이벤트가 생성될 때 해당 속성은 반드시 빈 문자열로 초기화되어야 한다.
4.6.6.
event.handled
handled
속성은 반드시 초기화된 값을 반환해야 한다.
이벤트가 생성될 때 해당 속성은 반드시 pending 상태의 promise로 초기화되어야 한다.
4.6.7. event.respondWith(r)
참고: 개발자는 r 인수에 promise나 Response
객체를 직접 넣을 수 있다(Response 객체는 자동으로 promise로 캐스팅됨). 그렇지 않으면 네트워크 에러가 Fetch로
반환된다.
렌더러 측 보안 검사는 cross-origin 콘텐츠의 tainting과 관련이 있으며 filtered responses 타입에 따라 결정된다(Fetch 참고).
respondWith(r)
메서드 단계는 다음과 같다:
-
event를 this로 한다.
-
event의 dispatch 플래그가 unset이면, "
InvalidStateError
"DOMException
을 throw한다. -
event의 respondWith 진입 플래그가 설정되어 있으면, "
InvalidStateError
"DOMException
을 throw한다. -
수명 연장 프라미스 추가 r를 event에 추가한다.
참고:
event.respondWith(r)
호출은event.waitUntil(r)
과 같이 이벤트의 수명을 기본적으로 연장한다. -
event의 stop propagation 플래그와 stop immediate propagation 플래그를 설정한다.
-
event의 respondWith 진입 플래그를 설정한다.
-
event의 응답 대기 플래그를 설정한다.
-
targetRealm을 event의 relevant Realm으로 한다.
-
-
event의 respondWith 오류 플래그를 설정한다.
-
event의 응답 대기 플래그를 unset한다.
-
-
r가 이행될 때 response로:
-
response가
Response
객체가 아니면 respondWith 오류 플래그를 설정한다.참고: respondWith 오류 플래그가 설정되면, 네트워크 에러가 Fetch로 Handle Fetch 알고리즘을 통해 반환된다(21.1단계 참고). 그렇지 않으면 response 값이 Fetch로 Handle Fetch 알고리즘을 통해 반환된다(22.1단계 참고).
-
그 외에는:
-
bytes를 빈 바이트 시퀀스로 한다.
-
end-of-body를 false로 한다.
-
done을 false로 한다.
-
potentialResponse를 response의 연관 response의 복사본으로 하되, body는 제외한다.
-
response의 body가 null이 아니면, 다음 하위 단계를 실행한다:
-
pullAlgorithm을 다음 단계들을 실행하는 액션으로 한다:
-
readRequest를 새로운 read request로 하고, 다음 항목을 포함한다:
- chunk 단계, chunk가 주어졌을 때
-
-
단언: chunk는
Uint8Array
이다. -
chunk가 나타내는 바이트를 bytes에 추가한다.
-
potentialResponse의 body info의 encoded size를 bytes의 byte length만큼 증가시킨다.
-
potentialResponse의 body info의 decoded size를 bytes의 byte length만큼 증가시킨다.
-
! DetachArrayBuffer(chunk.[[ViewedArrayBuffer]])를 수행한다.
-
- close 단계
-
-
end-of-body를 true로 한다.
-
- error 단계
-
reader에서 chunk 읽기를 readRequest로 실행한다.
-
-
cancelAlgorithm을 reader cancel을 실행하는 액션으로 한다.
-
highWaterMark를 사용자 에이전트가 선택한 0 이상의 NaN이 아닌 값으로 한다.
-
sizeAlgorithm을 chunk 객체를 받아서 0 이상의 NaN/무한대가 아닌 값을 반환하는 알고리즘으로 한다(사용자 에이전트가 선택).
-
newStream을
ReadableStream
의 새 인스턴스로 만들고, set up에 pullAlgorithm pullAlgorithm, cancelAlgorithm cancelAlgorithm, highWaterMark highWaterMark, sizeAlgorithm sizeAlgorithm을 targetRealm에서 실행한다. -
potentialResponse의 body를, body의 새 인스턴스로 하고 그 stream을 newStream으로 한다.
-
done이 false인 동안 반복적으로 다음 하위 단계를 병렬로 실행한다:
-
newStream이 errored면 done을 true로 한다.
-
그 외에 bytes가 비어 있고 end-of-body가 true면, newStream 닫기를 하고 done을 true로 한다.
-
그 외에 bytes가 비어 있지 않으면 다음 하위 단계를 실행한다:
-
chunk를 bytes 처음부터의 부분 시퀀스로 한다.
-
chunk를 bytes에서 제거한다.
-
buffer를
ArrayBuffer
의 새 인스턴스로 만들고, targetRealm에서 chunk를 담는다. -
newStream에 enqueue한다.
Uint8Array
로 targetRealm에서 buffer를 감싼다.
-
-
참고: 이 단계들은 response의 body의 stream을 potentialResponse에 "파이프"하는 것과 동등한 observable 결과를 만든다.
참고: 서비스 워커가 chunk 단위로 쓴 데이터는 클라이언트가 동일 chunk 단위로 읽는다고 보장되지 않는다. 즉, 클라이언트는 동일 데이터를 읽지만 chunk 분할은 브라우저에 따라 다를 수 있다.
-
event의 잠재적 응답을 potentialResponse로 한다.
-
-
event의 응답 대기 플래그를 unset한다.
-
4.7. ExtendableMessageEvent
[Exposed =ServiceWorker ]interface :
ExtendableMessageEvent ExtendableEvent {(
constructor DOMString ,
type optional ExtendableMessageEventInit = {});
eventInitDict readonly attribute any data ;readonly attribute USVString origin ;readonly attribute DOMString lastEventId ; [SameObject ]readonly attribute (Client or ServiceWorker or MessagePort )?source ;readonly attribute FrozenArray <MessagePort >ports ; };
dictionary :
ExtendableMessageEventInit ExtendableEventInit {any =
data null ;USVString = "";
origin DOMString = ""; (
lastEventId Client or ServiceWorker or MessagePort )?=
source null ;sequence <MessagePort >= []; };
ports
서비스 워커는 extendable
message
이벤트를 정의하여 이벤트의 수명을 확장할 수 있도록 합니다. message
이벤트의 경우, 서비스
워커는 ExtendableMessageEvent
인터페이스를 사용하며, 이 인터페이스는 ExtendableEvent
인터페이스를 확장합니다.
4.7.1. event.data
data
속성은 초기화된 값을
반환해야 합니다. 객체가 생성될 때 이 속성은 null로 초기화되어야 합니다. 이 속성은 전송되는 메시지를 나타냅니다.
4.7.2. event.origin
origin
속성은 초기화된 값을
반환해야 합니다. 객체가 생성될 때 이 속성은 빈 문자열로 초기화되어야 합니다. 이 속성은 메시지를 보낸 origin을 나타내며, 서비스 워커 클라이언트의
origin입니다.
4.7.3. event.lastEventId
lastEventId
속성은
초기화된 값을 반환해야 합니다. 객체가 생성될 때 이 속성은 빈 문자열로 초기화되어야 합니다.
4.7.4. event.source
source
속성은 초기화된 값을
반환해야 합니다. 객체가 생성될 때 이 속성은 null로 초기화되어야 합니다. 이 속성은 메시지를 보낸 Client
객체를 나타냅니다.
4.7.5. event.ports
ports
속성은 초기화된 값을
반환해야 합니다. 객체가 생성될 때 이 속성은 빈 배열로 초기화되어야 합니다. 이 속성은 전송되는 MessagePort
배열을 나타냅니다.
4.8. 이벤트
다음 이벤트들은 서비스 워커 이벤트라고 하며, ServiceWorkerGlobalScope
객체에서 발생합니다:
이벤트 이름 | 인터페이스 | 카테고리 | 발생 조건 |
---|---|---|---|
install
| InstallEvent
| 라이프사이클 | 서비스 워커의 포함된 서비스 워커 등록의 설치 중인 워커가 변경될 때 발생합니다. (자세한 내용은 설치 알고리즘 11.2단계를 참고하세요.) |
activate
| ExtendableEvent
| 라이프사이클 | 서비스 워커의 포함된 서비스 워커 등록의 활성 워커가 변경될 때 발생합니다. (자세한 내용은 활성화 알고리즘 12.2단계를 참고하세요.) |
fetch
| FetchEvent
| 기능적 | HTTP fetch가 Handle Fetch를
request와 함께 호출할 때 발생합니다. Handle Fetch를 수행하면 서비스 워커가 응답을 HTTP fetch에 반환합니다. 응답은 Response
객체로 표현되며, Cache
객체에서 가져오거나 self.fetch(input, init)
메서드를 통해 네트워크에서 직접 가져올 수 있습니다. (사용자 정의 Response
객체도 가능합니다.)
|
push | PushEvent
| 기능적 | (자세한 내용은 푸시 이벤트 발생를 참고하세요.) |
notificationclick | NotificationEvent
| 기능적 | (자세한 내용은 알림 활성화를 참고하세요.) |
notificationclose | NotificationEvent
| 기능적 | (자세한 내용은 알림 닫기를 참고하세요.) |
sync | SyncEvent
| 기능적 | (자세한 내용은 Sync 이벤트 발생를 참고하세요.) |
canmakepayment | CanMakePaymentEvent | 기능적 | (자세한 내용은 CanMakePaymentEvent 처리를 참고하세요.) |
paymentrequest | PaymentRequestEvent | 기능적 | (자세한 내용은 PaymentRequestEvent 처리를 참고하세요.) |
message
| ExtendableMessageEvent
| 레거시 | 메시지를 수신할 때 발생합니다. |
messageerror
| MessageEvent
| 레거시 | 역직렬화할 수 없는 메시지를 수신할 때 발생합니다. |
5. 캐시
저자들이 오프라인 사용을 위해 콘텐츠 캐시를 완전히 관리할 수 있도록, Window
및 WorkerGlobalScope
는 비동기 캐싱 메서드를 제공하여 Cache
객체를 열고 조작할 수
있게 합니다. 하나의
origin은 여러 개의 이름이 있는 Cache
객체를 가질 수 있으며,
그 내용은 스크립트가 완전히 제어합니다. 캐시는 origin 간에 공유되지 않고, 브라우저의 HTTP 캐시와 완전히 분리되어 있습니다.
5.1. 구성요소
request response list는 리스트이며, 각각 튜플로 구성되어 있고, 요청(request)과 응답(response)을 포함합니다.
relevant request response list는 this가 나타내는 인스턴스입니다.
name to cache map은 순서가 있는 맵이며, 엔트리는 키 (즉, request response list의 이름을 나타내는 문자열)와 값(request response list)로 구성됩니다.
각 storage key는 연관된 name to cache map을 가집니다.
relevant name to cache map은 name to cache map이며, storage key를 얻은 this의 연관된 글로벌 객체의 환경 설정 객체에 연결되어 있습니다.
5.2. 캐시의 수명 이해하기
Cache
인스턴스는 브라우저의 HTTP 캐시의 일부가 아닙니다. Cache
객체는
저자가 직접 관리해야 하는 대상입니다. Cache
객체는 저자가
명시적으로 요청하지 않는 한 업데이트되지 않습니다. Cache
객체는 저자가
항목을 삭제하지 않는 한 만료되지 않습니다. Cache
객체는 서비스 워커
스크립트가 업데이트되어도 사라지지 않습니다. 즉, 캐시는 자동으로 업데이트되지 않으며, 수동으로 관리해야 합니다. 따라서 저자들은 캐시 이름에 버전을 부여하고, 해당 서비스 워커
버전에서만 캐시를 사용해야 합니다.
5.3. self.caches
partial interface mixin WindowOrWorkerGlobalScope { [SecureContext ,SameObject ]readonly attribute CacheStorage caches ; };
5.3.1.
caches
caches
getter 단계는 this의 연관된 CacheStorage
객체를 반환하는 것입니다.
5.4. Cache
[SecureContext ,Exposed =(Window ,Worker )]interface { [
Cache NewObject ]Promise <(Response or undefined )>match (RequestInfo ,
request optional CacheQueryOptions = {}); [
options NewObject ]Promise <FrozenArray <Response >>matchAll (optional RequestInfo ,
request optional CacheQueryOptions = {}); [
options NewObject ]Promise <undefined >add (RequestInfo ); [
request NewObject ]Promise <undefined >addAll (sequence <RequestInfo >); [
requests NewObject ]Promise <undefined >put (RequestInfo ,
request Response ); [
response NewObject ]Promise <boolean >delete (RequestInfo ,
request optional CacheQueryOptions = {}); [
options NewObject ]Promise <FrozenArray <Request >>keys (optional RequestInfo ,
request optional CacheQueryOptions = {}); };
options
dictionary {
CacheQueryOptions boolean =
ignoreSearch false ;boolean =
ignoreMethod false ;boolean =
ignoreVary false ; };
Cache
객체는 request response list를 나타냅니다. 문서와 워커에서 Cache
인터페이스를 구현하는 여러 개의 별도 객체가 동시에 동일한 request response list에 연결될 수 있습니다.
cache batch operation은 struct로 구성되며 다음을 포함합니다:
-
type ("
delete
" 또는 "put
") -
request (request)
-
response (response)
-
options (
CacheQueryOptions
)
5.4.1.
match(request, options)
match(request, options)
메서드
단계는 다음과 같습니다:
-
promise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
p를
matchAll(request, options)
메서드에 request와 options를 전달하여 실행한 결과로 둡니다. -
p가 완료될 때까지 대기합니다.
-
p가 예외와 함께 reject되면,
-
promise를 해당 예외로 reject합니다.
-
-
그렇지 않고 p가 배열 responses로 resolve되면,
-
responses가 빈 배열이면,
-
promise를 undefined로 resolve합니다.
-
-
그 외의 경우:
-
promise를 responses의 첫 번째 요소로 resolve합니다.
-
-
-
-
promise를 반환합니다.
5.4.2.
matchAll(request, options)
matchAll(request, options)
메서드 단계는 다음과 같습니다:
-
r을 null로 둡니다.
-
선택적 인자인 request가 생략되지 않았다면,
-
request가
Request
객체라면:-
r에 request의 request를 설정합니다.
-
r의 method가 `
GET
`이 아니고 options.ignoreMethod가 false인 경우, 빈 배열로 resolve된 promise를 반환합니다.
-
-
그렇지 않고 request가 문자열이라면:
-
r에
Request
생성자에 request를 인자로 주어 생성한 결과의 관련 request를 설정합니다. 만약 예외가 발생하면, 해당 예외로 reject된 promise를 반환합니다.
-
-
-
promise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
responses를 빈 리스트로 둡니다.
-
선택적 인자인 request가 생략된 경우,
-
각 requestResponse를 relevant request response list에서 반복하여:
-
requestResponse의 response의 복사본을 responses에 추가합니다.
-
-
-
그렇지 않은 경우:
-
requestResponses를 Query Cache에 r과 options를 전달하여 실행한 결과로 둡니다.
-
각 requestResponse를 requestResponses에서 반복하여:
-
requestResponse의 response의 복사본을 responses에 추가합니다.
-
-
-
각 response를 responses에서 반복하여:
-
response의 type이 "
opaque
"이고 cross-origin resource policy check에 promise의 relevant settings object의 origin, promise의 relevant settings object, "", response의 internal response가 blocked를 반환하면, promise를TypeError
로 reject하고 해당 단계를 중단합니다.
-
-
작업을 큐에 추가하여, promise의 relevant settings object의 responsible event loop에서 DOM manipulation task source로 다음 단계를 수행합니다:
-
-
promise를 반환합니다.
5.4.3.
add(request)
add(request)
메서드 단계는 다음과 같습니다:
-
requests를 request만을 포함하는 배열로 둡니다.
-
responseArrayPromise를
addAll(requests)
알고리즘에 requests를 인자로 전달하여 실행한 결과로 둡니다. -
responseArrayPromise가 fulfill될 때 undefined를 반환하는 fulfillment handler와 함께 reacting한 결과를 반환합니다.
5.4.4.
addAll(requests)
addAll(requests)
메서드 단계는 다음과 같습니다:
-
responsePromises를 빈 리스트로 둡니다.
-
requestList를 빈 리스트로 둡니다.
-
requests에서 타입이
Request
인 각 request에 대해:-
r을 request의 request로 둡니다.
-
r의 url의 scheme이 "
http
", "https
"가 아니거나, r의 method가 `GET
`이 아니면, TypeError로 reject된 promise를 반환합니다.
-
-
fetchControllers를 리스트로 두고, fetch controller를 포함합니다.
-
requests의 각 request에 대해:
-
r을
Request
생성자에 request를 인자로 하여 얻은 결과의 관련 request로 설정합니다. 만약 예외가 발생하면, 해당 예외로 reject된 promise를 반환합니다. -
r의 url의 scheme이 "
http
", "https
"가 아니면:-
TypeError로 reject된 promise를 반환합니다.
-
r의 client의 global object가
ServiceWorkerGlobalScope
객체라면, request의 service-workers mode를 "none
"으로 설정합니다. -
r의 initiator를 "
fetch
", destination을 "subresource
"로 설정합니다. -
r을 requestList에 추가합니다.
-
responsePromise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
processResponse에서 response에 대해 다음을 실행합니다:
-
response의 type이 "
error
"이거나, response의 status가 ok status가 아니거나206
이면, responsePromise를 TypeError로 reject합니다. -
그 외에 response의 header list에 header 이름이 `
Vary
`인 것이 있으면:-
fieldValues를 리스트로 두고, field-values에 해당하는 요소들을 포함합니다.
-
각 fieldValue를 fieldValues에서 반복하여:
-
-
-
processResponseEndOfBody에서 response에 대해 다음을 실행합니다:
-
response의 aborted flag가 설정되어 있으면, responsePromise를 "
AbortError
"DOMException
으로 reject하고 이 단계들을 중단합니다. -
responsePromise를 response로 resolve합니다.
참고: 응답의 body가 모두 수신되면 캐시 커밋이 허용됩니다.
-
-
responsePromise를 responsePromises에 추가합니다.
-
-
p를 모든 responsePromises를 기다리는 promise로 둡니다.
-
reacting을 통해 p가 fulfill될 때, responses를 인자로 받아 다음 하위 단계를 수행합니다:
-
operations를 빈 리스트로 둡니다.
-
index를 0으로 둡니다.
-
responses의 각 response에 대해:
-
operation을 캐시 배치 작업(cache batch operation)으로 둡니다.
-
operation의 type을 "
put
"으로 설정합니다. -
operation의 request를 requestList[index]로 설정합니다.
-
operation의 response를 response로 설정합니다.
-
Append를 통해 operation을 operations에 추가합니다.
-
index를 1 증가시킵니다.
-
-
cacheJobPromise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
errorData를 null로 둡니다.
-
Batch Cache Operations를 operations로 호출합니다. 이때 예외가 발생하면 errorData에 해당 예외를 설정합니다.
-
작업을 큐에 추가하여, cacheJobPromise의 relevant settings object의 responsible event loop에서 DOM manipulation task source로 다음 하위 단계를 수행합니다:
-
-
cacheJobPromise를 반환합니다.
-
5.4.5.
put(request, response)
put(request, response)
메서드 단계는
다음과 같습니다:
-
innerRequest를 null로 둡니다.
-
request가
Request
객체라면, innerRequest를 request의 request로 설정합니다. -
그 외의 경우:
-
requestObj를
Request
생성자에 request를 인자로 하여 실행한 결과로 설정합니다. 만약 예외가 발생하면, 해당 예외로 reject된 promise를 반환합니다. -
innerRequest를 requestObj의 request로 설정합니다.
-
-
innerRequest의 url의 scheme이 "
http
", "https
"가 아니거나, innerRequest의 method가 `GET
`이 아니면, TypeError로 reject된 promise를 반환합니다. -
innerResponse를 response의 response로 둡니다.
-
innerResponse의 status가
206
이면, TypeError로 reject된 promise를 반환합니다. -
innerResponse의 header list에 header 이름이 `
Vary
`인 것이 있으면:-
fieldValues를 리스트 중 item이 Vary 헤더의 field-values에 해당하는 것으로 둡니다.
-
각 fieldValue를 fieldValues에서 반복하여:
-
fieldValue가 "
*
"에 매칭되면, TypeError로 reject된 promise를 반환합니다.
-
-
-
innerResponse의 body가 disturbed 또는 locked 상태라면, TypeError로 reject된 promise를 반환합니다.
-
clonedResponse를 innerResponse의 복제본으로 둡니다.
-
bodyReadPromise를 undefined로 resolve된 promise로 둡니다.
-
innerResponse의 body가 null이 아니면, 다음 하위 단계를 실행합니다:
-
reader를 stream에 대한 reader 얻기 결과로 둡니다.
-
bodyReadPromise를 reader에서 모든 바이트 읽기 결과로 설정합니다.
참고: 이는 innerResponse의 body가 locked가 되고, clonedResponse에 body 버퍼 복사본이 생긴다는 것을 보장합니다. 구현은 메모리 대신 디스크로 스트리밍하여 최적화할 수 있습니다.
-
operations를 빈 리스트로 둡니다.
-
operation을 캐시 배치 작업(cache batch operation)으로 둡니다.
-
operation의 type을 "
put
"으로 설정합니다. -
operation의 request를 innerRequest로 설정합니다.
-
operation의 response를 clonedResponse로 설정합니다.
-
Append를 통해 operation을 operations에 추가합니다.
-
bodyReadPromise가 fulfill될 때의 결과로:
-
cacheJobPromise를 새로운 promise로 둡니다.
-
cacheJobPromise를 반환하고, 다음 단계들을 병렬로 수행합니다:
-
errorData를 null로 둡니다.
-
Batch Cache Operations를 operations에 대해 호출합니다. 만약 예외가 발생하면 errorData에 예외를 설정합니다.
-
작업을 큐에 추가하여, cacheJobPromise의 relevant settings object의 responsible event loop에서 DOM manipulation task source로 다음 단계들을 수행합니다:
-
-
5.4.6.
delete(request, options)
delete(request, options)
메서드 단계는 다음과 같습니다:
-
r을 null로 둡니다.
-
request가
Request
객체라면:-
r에 request의 request를 설정합니다.
-
r의 method가 `
GET
`이 아니고 options.ignoreMethod가 false인 경우, false로 resolve된 promise를 반환합니다.
-
-
그 외에 request가 문자열이라면:
-
r을
Request
생성자에 request를 인자로 하여 얻은 결과의 관련 request로 설정합니다. 만약 예외가 발생하면 해당 예외로 reject된 promise를 반환합니다.
-
-
operations를 빈 리스트로 둡니다.
-
operation을 캐시 배치 작업(cache batch operation)으로 둡니다.
-
operation의 type을 "
delete
"로 설정합니다. -
operation의 request를 r로 설정합니다.
-
operation의 options를 options로 설정합니다.
-
Append를 통해 operation을 operations에 추가합니다.
-
cacheJobPromise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
errorData를 null로 둡니다.
-
requestResponses를 Batch Cache Operations에 operations를 전달하여 실행한 결과로 둡니다. 이때 예외가 발생하면 errorData에 예외를 설정합니다.
-
작업을 큐에 추가하여, cacheJobPromise의 relevant settings object의 responsible event loop에서 DOM manipulation task source로 다음 하위 단계를 수행합니다:
-
-
cacheJobPromise를 반환합니다.
5.4.7.
keys(request, options)
keys(request, options)
메서드 단계는
다음과 같습니다:
-
r을 null로 둡니다.
-
선택적 인자인 request가 생략되지 않았다면:
-
request가
Request
객체라면:-
r을 request의 request로 설정합니다.
-
r의 method가 `
GET
`이 아니고 options.ignoreMethod가 false인 경우, 빈 배열로 resolve된 promise를 반환합니다.
-
-
그 외에 request가 문자열이라면:
-
r을
Request
생성자에 request를 인자로 하여 얻은 결과의 관련 request로 설정합니다. 만약 예외가 발생하면, 해당 예외로 reject된 promise를 반환합니다.
-
-
-
promise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
requests를 빈 리스트로 둡니다.
-
선택적 인자인 request가 생략된 경우,
-
각 requestResponse를 relevant request response list에서 반복하여:
-
requestResponse의 request를 requests에 추가합니다.
-
-
-
그 외의 경우:
-
requestResponses를 Query Cache에 r과 options를 전달하여 실행한 결과로 둡니다.
-
각 requestResponse를 requestResponses에서 반복하여:
-
requestResponse의 request를 requests에 추가합니다.
-
-
-
작업을 큐에 추가하여, promise의 relevant settings object의 responsible event loop에서 DOM manipulation task source로 다음 단계를 수행합니다:
-
-
promise를 반환합니다.
5.5.
CacheStorage
[SecureContext ,Exposed =(Window ,Worker )]interface { [
CacheStorage NewObject ]Promise <(Response or undefined )>match (RequestInfo ,
request optional MultiCacheQueryOptions = {}); [
options NewObject ]Promise <boolean >has (DOMString ); [
cacheName NewObject ]Promise <Cache >open (DOMString ); [
cacheName NewObject ]Promise <boolean >delete (DOMString ); [
cacheName NewObject ]Promise <sequence <DOMString >>keys (); };dictionary :
MultiCacheQueryOptions CacheQueryOptions {DOMString ; };
cacheName
참고: CacheStorage
인터페이스는 대부분 ECMAScript 6
Map 객체와 일치하도록 설계되어 있지만, 완전히 비동기이며 추가적인 편의 메서드를 제공합니다. clear
,
forEach
, entries
및 values
메서드는 TC39의 비동기 반복에 대한 지속적인 논의에 따라 첫
번째 버전에서는 일부러 제외되었습니다.
사용자 에이전트는 CacheStorage
객체를 Window
객체 또는 WorkerGlobalScope
객체가 생성될 때 생성하여 해당 글로벌 객체에 연결해야 합니다.
CacheStorage
객체는 자신과 연관된 name to cache map을 나타내며, 해당 글로벌 객체의 환경 설정 객체의 origin에 기반합니다. 여러 문서와 워커에서 CacheStorage
인터페이스를 구현하는 별도의 객체들이 동시에 같은 name to cache map에 연결될 수 있습니다.
5.5.1.
match(request, options)
match(request, options)
메서드 단계는 다음과 같습니다:
-
-
새로운 promise promise를 반환하고, 다음 하위 단계들을 병렬로 실행합니다:
-
각 cacheName → cache를 relevant name to cache map에서 반복하여:
-
options["
cacheName
"]가 cacheName과 일치하면:-
Cache
인터페이스의match(request, options)
메서드 알고리즘을 request와 options를 인자로 cache를 thisArgument로 하여 실행한 결과로 promise를 resolve합니다. -
이 단계들을 중단합니다.
-
-
-
promise를 undefined로 resolve합니다.
-
-
-
그 외의 경우:
-
promise를 undefined로 resolve된 promise로 둡니다.
-
각 cacheName → cache를 relevant name to cache map에서 반복하여:
-
promise를 자신에 reacting한 결과로 두고, fulfillment handler에서 response를 인자로 다음을 수행합니다:
-
response가 undefined가 아니면 response를 반환합니다.
-
Cache
인터페이스의match(request, options)
알고리즘을 request와 options를 인자로 cache를 thisArgument로 하여 실행한 결과를 반환합니다.
-
-
-
promise를 반환합니다.
-
5.5.2.
has(cacheName)
has(cacheName)
메서드 단계는 다음과 같습니다:
-
promise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
각 key → value를 relevant name to cache map에서 반복하여:
-
cacheName이 key와 일치하면, promise를 true로 resolve하고 이 단계들을 중단합니다.
-
-
promise를 false로 resolve합니다.
-
-
promise를 반환합니다.
5.5.3.
open(cacheName)
open(cacheName)
메서드 단계는 다음과 같습니다:
-
promise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
각 key → value를 relevant name to cache map에서 반복하여:
-
cacheName이 key와 일치하면:
-
value를 나타내는 새로운
Cache
객체로 promise를 resolve합니다. -
이 단계들을 중단합니다.
-
-
-
cache를 새로운 request response list로 둡니다.
-
Set을 통해 relevant name to cache map[cacheName]에 cache를 저장합니다. 만약 캐시 쓰기 작업이 할당된 quota 제한을 초과하여 실패하면, promise를 "
QuotaExceededError
"DOMException
으로 reject하고 이 단계들을 중단합니다. -
cache를 나타내는 새로운
Cache
객체로 promise를 resolve합니다.
-
-
promise를 반환합니다.
5.5.4.
delete(cacheName)
delete(cacheName)
메서드 단계는 다음과 같습니다:
-
promise를
has(cacheName)
알고리즘을 cacheName으로 실행한 결과로 둡니다. -
promise가 fulfill될 때, fulfillment handler에서 cacheExists를 인자로 다음을 수행합니다:
-
cacheExists가 false이면:
-
false를 반환합니다.
-
-
cacheJobPromise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
Remove를 통해 relevant name to cache map[cacheName]을 제거합니다.
-
cacheJobPromise를 true로 resolve합니다.
참고: 이 단계 이후에도 기존 DOM 객체(즉, 현재 참조된 Cache, Request, Response 객체)는 계속 동작해야 합니다.
-
-
cacheJobPromise를 반환합니다.
-
5.5.5.
keys()
keys()
메서드 단계는 다음과 같습니다:
-
promise를 새로운 promise로 둡니다.
-
다음 하위 단계를 병렬로 실행합니다:
-
cacheKeys를 relevant name to cache map의 키를 얻은 결과로 둡니다.
참고: 결과 ordered set에 있는 item들은 해당 엔트리가 name to cache map에 추가된 순서대로입니다.
-
promise를 cacheKeys로 resolve합니다.
-
-
promise를 반환합니다.
6. 보안 고려사항
6.1. 보안 컨텍스트
서비스 워커는 반드시 보안 컨텍스트에서 실행되어야 합니다. 서비스 워커 클라이언트 역시 반드시 보안 컨텍스트여야 하며, 서비스 워커 등록을 하거나, 서비스 워커 등록에 접근하거나, 서비스 워커를 얻거나, 서비스 워커와 메시지를 주고받거나, 서비스 워커에 의해 조작되려면 보안 컨텍스트여야 합니다.
참고: 이는 사실상 서비스 워커와 그 클라이언트가 HTTPS로 호스팅되어야 함을 의미합니다. 사용자 에이전트는 개발 목적에 한해
localhost
(관련 요구사항
참고), 127.0.0.0/8
, ::1/128
를 허용할 수 있습니다. 이러한 제한의 주요 목적은 비보안 컨텍스트에서 발생할 수 있는
위험으로부터 사용자를 보호하기 위함입니다.
6.2. 콘텐츠 보안 정책
사용자 에이전트가 서비스 워커 실행 알고리즘을 서비스 워커 serviceWorker에 대해 호출할 때:
-
serviceWorker의 스크립트 리소스가
Content-Security-Policy
HTTP 헤더와 policy 값을 포함하여 전달되었다면, 사용자 에이전트는 반드시 policy를 적용해야 합니다. -
serviceWorker의 스크립트 리소스가
Content-Security-Policy-Report-Only
HTTP 헤더와 policy 값을 포함하여 전달되었다면, 사용자 에이전트는 반드시 policy를 모니터링해야 합니다.
이러한 제한의 주요 목적은 교차 사이트 스크립팅(XSS)과 같은 다양한 컨텐츠 주입 취약점을 완화하기 위함입니다.
6.3. 오리진 상대성
6.3.1. 오리진 제한
이 절은 규범적이지 않습니다.
서비스 워커는 등록한 클라이언트의 오리진에서 실행됩니다. 주요 응용 프로그램에서 마주할 수 있는 고급 문제 중 하나는 CDN에서 서비스 워커를 호스팅할 수 있는지입니다. 정의상 CDN은 종종 다른 오리진에 위치합니다. 따라서 서비스 워커는 CDN에서 호스팅할 수 없습니다. 대신 importScripts()를 통해 리소스를 포함할 수 있습니다. 이러한 제한의 이유는 서비스 워커가 악의적인 공격자에게 심각한 보안 위협을 줄 수 있기 때문입니다.
6.3.2.
importScripts(urls)
importScripts(urls)
메서드가
ServiceWorkerGlobalScope
객체에서 호출되면, 사용자 에이전트는 반드시 해당 ServiceWorkerGlobalScope
객체와 urls를 사용해 워커 글로벌 스코프에 스크립트 가져오기를 수행해야 하며, 다음과
같은 페치 훅 단계를 request request에 대해 수행합니다:
-
map을 serviceWorker의 스크립트 리소스 맵으로 둡니다.
-
url을 request의 url로 둡니다.
-
serviceWorker의 상태가 "
parsed
" 또는 "installing
"이 아니면: -
map[url]이 존재하면:
-
Append를 통해 url을 serviceWorker의 사용된 스크립트 집합에 추가합니다.
-
map[url]을 반환합니다.
-
-
registration을 serviceWorker의 포함 서비스 워커 등록으로 둡니다.
-
request의 service-workers mode를 "
none
"으로 설정합니다. -
다음 중 하나라도 참이면 request의 cache mode를 "
no-cache
"로 설정합니다:-
registration의 update via cache mode가 "
none
"인 경우 -
현재 글로벌 객체의 importScripts 캐시 우회 플래그가 설정된 경우
-
registration이 stale인 경우
-
-
response를 request에 대해 fetch한 결과로 둡니다.
-
response의 cache state가 "
local
"이 아니면, registration의 마지막 업데이트 확인 시간을 현재 시간으로 설정합니다. -
response의 unsafe response가 잘못된 import 스크립트 응답이면 네트워크 오류를 반환합니다.
-
Set을 통해 map[url]에 response를 저장합니다.
-
Append를 통해 url을 serviceWorker의 사용된 스크립트 집합에 추가합니다.
-
serviceWorker의 클래식 스크립트 import 플래그를 설정합니다.
-
response를 반환합니다.
6.4. 교차 오리진 리소스 및 CORS
이 절은 규범적이지 않습니다.
애플리케이션은 CDN이나 다른 오리진에서 가져온 항목을 캐시하는 경우가 많습니다.
<script>
, <img>
, <video>
, <link>
요소를
통해 많은 리소스를 직접 요청할 수 있습니다. 이런 종류의 런타임 협업이 오프라인에서 깨진다면 상당한 제약이 될 것입니다. 마찬가지로 적절한 CORS 헤더가 설정된 경우 fetch를 통해 다양한 오프-오리진 리소스를 요청할 수 있습니다. 서비스 워커는 캐시
를 통해 오프-오리진
항목을 fetch 및 캐시할 수 있게 허용합니다. 단, 몇 가지 제한이 있습니다. 먼저, 동일 오리진 리소스는 Cache
에서 Response
객체로 관리되고, 해당 response는 기본 필터된 응답입니다. 반면, 오프-오리진에서 저장되는 객체는 Response
객체로, 해당 response가 CORS 필터된 응답 또는 불투명(opaque) 필터된 응답입니다. 이들은 event.respondWith(r)
메서드로 동일하게 전달할 수 있지만, 의미 있게 프로그래밍적으로 생성할 수는 없습니다. 이러한 제한은 플랫폼의 보안 불변성을 유지하기 위해 필요합니다. 캐시
가 이런 객체를 저장할
수 있게 하여 애플리케이션이 대부분의 경우 아키텍처를 변경하지 않아도 되도록 합니다.
6.5. 경로 제한
이 절은 규범적이지 않습니다.
오리진 제한 외에도, 서비스 워커는 서비스 워커 스크립트의 경로에 의해
제한됩니다. 예를 들어 https://www.example.com/~bob/sw.js
에 위치한 서비스 워커 스크립트는 scope url
https://www.example.com/~bob/
에는 등록할 수 있지만, https://www.example.com/
또는
https://www.example.com/~alice/
에는 등록할 수 없습니다. 이는 같은 오리진 내에서 여러 사용자 콘텐츠를 별도의 디렉터리에 분리해
호스팅하는 사이트에 어느 정도 보호를 제공합니다. 그러나 경로 제한은 오리진만큼 강력한 보안 경계로 간주되지 않습니다. 사이트에서는 적절할 경우 서로 다른 오리진을 사용해 사이트의
부분을 안전하게 격리할 것을 권장합니다.
서버는 서비스 워커 스크립트에 Service-Worker-Allowed 헤더를 설정함으로써 경로 제한을 제거할 수 있습니다.
6.6. 서비스 워커 스크립트 요청
이 절은 규범적이지 않습니다.
악의적인 서비스 워커의 등록을 방지하기 위해, 이 명세는 다음을 요구합니다:
-
서비스 워커 스크립트 요청에 Service-Worker 헤더가 포함되어야 하며,
-
서비스 워커 스크립트는 자바스크립트 MIME 타입으로 제공되어야 합니다.
6.7. 구현자 고려사항
이 절은 규범적이지 않습니다.
구현자들은 다음을 주의해야 합니다:
-
플러그인은 서비스 워커를 통해 로드되어서는 안 됩니다. 플러그인은 자체 URL에서 보안 오리진을 얻을 수 있으므로, 임베딩한 서비스 워커가 이를 처리할 수 없습니다. 이런 이유로 Handle Fetch 알고리즘은
<embed>
및<object>
요청을fetch
이벤트를 디스패치하지 않고 즉시 네트워크로 폴백합니다. -
레거시 네트워킹 스택 코드 중 일부는 서비스 워커와의 상호작용으로 인한 영향을 이해하기 위해 신중한 점검이 필요할 수 있습니다.
6.8. 프라이버시
서비스 워커는 등록 맵 (서비스 워커 등록 및 서비스 워커 등록과 서비스 워커), request response list, name to cache map (캐시용), 스크립트 리소스 맵 (스크립트 리소스용) 등 새로운 영구 저장소 기능을 도입합니다. 비인가 웹 추적 위협을 방지하기 위해, 이러한 영구 저장소는 사용자가 삭제를 원하는 경우 삭제되어야 하며, 모든 기존 사용자 제어 기능(예: 모든 영구 저장소 일괄 삭제)과 호환되어야 합니다.
7. 확장성
서비스 워커 명세는 다른 명세에서 확장할 수 있습니다.
7.1. Service Worker Registration에 바인딩된 API 정의
명세는 API를 서비스 워커 등록(service
worker registration)에 바인딩하도록 partial interface 정의를 ServiceWorkerRegistration
인터페이스에 작성할 수 있으며, 여기서 명세별 속성 및 메서드를 정의할 수 있습니다:
partial interface ServiceWorkerRegistration { // 예시: API 네임스페이스 정의readonly attribute APISpaceType APISpace ; // 예시: 메서드 정의Promise <T >methodName (/* 인자 목록 */); };
7.2. 기능적 이벤트 정의
명세는 기능적 이벤트(functional event)를 ExtendableEvent
인터페이스를 확장하여 정의할 수 있습니다:
// 예시: FunctionalEvent 인터페이스 정의interface FunctionalEvent :ExtendableEvent { // 기능적 이벤트의 속성 및 메서드 추가 };
7.3. 이벤트 핸들러 정의
명세는 기능적 이벤트(functional event)에 해당하는 이벤트 핸들러 속성을 partial interface 정의를 ServiceWorkerGlobalScope
인터페이스에 추가하여 정의할 수 있습니다:
partial interface ServiceWorkerGlobalScope {attribute EventHandler onfunctionalevent ; };
7.4. 기능적 이벤트 발생
기능적 이벤트를 활성 워커에 디스패치하도록 요청하려면, 명세는 반드시 Fire Functional Event를 호출해야 합니다.
부록 A: 알고리즘
다음 정의들은 명세 전반에서 사용되는 사용자 에이전트의 내부 데이터 구조입니다.
등록 맵은 (순서가 있는 맵)으로, 키는 (storage key, 직렬화된 scope url)이고 값은 서비스 워커 등록입니다.
job은 서비스 워커 등록에 대한 register, update, unregister 요청 중 하나의 추상화입니다.
job은 storage key(storage key)를 가집니다.
job은 worker type("classic" 또는 "module")을 가집니다.
job은 update via cache mode("imports", "all", "none") 중 하나입니다.
job은 client(서비스 워커 클라이언트)를 가지며, 초기값은 null입니다.
job은 referrer(URL 또는 null)을 가집니다.
job은 job promise(promise)를 가지며, 초기값은 null입니다.
job은 containing job queue(job queue 또는 null)을 가지며, 초기값은 null입니다.
job은 동등 job 리스트(job 리스트)이며, 초기값은 빈 리스트입니다.
job은 force bypass cache flag를 가지며, 초기값은 unset입니다.
두 job이 동등이려면 job type이 동일해야 하며, 다음 조건을 만족해야 합니다:
-
register와 update job의 경우, scope url, script url, worker type, update via cache mode가 모두 동일해야 합니다.
job queue는 동시 job 집합의 동기화를 위해 사용되는 thread-safe 큐입니다. job queue는 job을 item으로 포함하며, 초기값은 비어 있습니다.
scope to job queue map은 키가 scope url(직렬화됨)이고, 값이 job queue인 순서가 있는 맵입니다.
잘못된 import 스크립트 응답은 아래 조건 중 하나를 만족하는 response입니다:
-
response의 type이 "
error
"인 경우 -
response의 header list에서 MIME type 추출 결과가 자바스크립트 MIME 타입이 아닌 경우
참고: 이 정의는 클래식 워커-imported 스크립트 fetch와 동기화되어야 합니다.
작업 생성
작업 스케줄
- 입력
-
job, 작업
- 출력
-
없음
-
jobQueue를 null로 둔다.
-
scope to job queue map[jobScope]가 존재하지 않으면, scope to job queue map[jobScope]에 새 작업 큐를 설정한다.
-
jobQueue를 scope to job queue map[jobScope]로 설정한다.
-
jobQueue가 비어 있으면:
-
job의 containing job queue를 jobQueue로 설정하고, jobQueue에 job을 enqueue한다.
-
작업 실행을 jobQueue로 호출한다.
-
-
그 외의 경우:
-
lastJob을 jobQueue의 마지막 요소로 둔다.
-
job이 동등하고 lastJob의 작업 프라미스가 아직 settle되지 않았다면, job을 lastJob의 동등 작업 리스트에 추가한다.
-
그 외에는, job의 containing job queue를 jobQueue로 설정하고, jobQueue에 job을 enqueue한다.
-
작업 실행
- 입력
-
jobQueue, 작업 큐
- 출력
-
없음
작업 완료
- 입력
-
job, 작업
- 출력
-
없음
-
jobQueue를 job의 containing job queue로 둔다.
-
단언: jobQueue의 첫 번째 item이 job임을 보장한다.
작업 프라미스 해결
- 입력
-
job, 작업
value, 임의 값
- 출력
-
없음
작업 프라미스 거부
- 입력
-
job, 작업
errorData, 예외 생성에 필요한 정보
- 출력
-
없음
등록 시작
- 입력
-
scopeURL, URL 또는 실패 또는 null
scriptURL, URL 또는 실패
promise, 프라미스
client, 서비스 워커 클라이언트
referrer, URL
workerType, 워커 타입
updateViaCache, update via cache mode
- 출력
-
없음
-
scriptURL이 실패이면, promise를
TypeError
로 reject하고 이 단계를 중단한다. -
scriptURL의 fragment를 null로 설정한다.
참고: 사용자 에이전트는 스크립트 url의 fragment를 저장하지 않는다. 즉, fragment는 서비스 워커 식별에 영향을 주지 않는다.
-
scriptURL의 scheme이 "
http
", "https
"가 아니면, promise를TypeError
로 reject하고 이 단계를 중단한다. -
scriptURL의 path에 포함된 어떤 문자열이 ASCII 대소문자 구분 없이 "
%2f
", "%5c
"를 포함하면, promise를TypeError
로 reject하고 이 단계를 중단한다. -
scopeURL이 null이면, scopeURL을 "./" 문자열과 scriptURL로 파싱한 결과로 설정한다.
참고: 등록의 기본 scope url은 서비스 워커 스크립트 위치로 설정된다.
-
scopeURL이 실패이면, promise를
TypeError
로 reject하고 이 단계를 중단한다. -
scopeURL의 fragment를 null로 설정한다.
참고: 사용자 에이전트는 scope url의 fragment를 저장하지 않는다. 즉, fragment는 서비스 워커 등록 식별에 영향을 주지 않는다.
-
scopeURL의 scheme이 "
http
", "https
"가 아니면, promise를TypeError
로 reject하고 이 단계를 중단한다. -
scopeURL의 path에 포함된 어떤 문자열이 ASCII 대소문자 구분 없이 "
%2f
", "%5c
"를 포함하면, promise를TypeError
로 reject하고 이 단계를 중단한다. -
storage key를 클라이언트에서 스토리지 키 얻기 결과로 설정한다.
-
job을 작업 생성을 register, storage key, scopeURL, scriptURL, promise, client로 실행한 결과로 둔다.
-
job의 워커 타입을 workerType으로 설정한다.
-
job의 update via cache mode를 updateViaCache로 설정한다.
-
job의 referrer를 referrer로 설정한다.
-
작업 스케줄을 job로 호출한다.
등록
- 입력
-
job, 작업
- 출력
-
없음
-
잠재적으로 신뢰할 수 있는 오리진 알고리즘을 job의 script url의 오리진에 대해 실행한 결과가
Not Trusted
이면:-
작업 프라미스 거부를 job과 "
SecurityError
"DOMException
"로 호출한다. -
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
job의 script url의 오리진과 job의 referrer의 오리진이 동일 오리진이 아니면:
-
작업 프라미스 거부를 job과 "
SecurityError
"DOMException
"로 호출한다. -
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
job의 scope url의 오리진과 job의 referrer의 오리진이 동일 오리진이 아니면:
-
작업 프라미스 거부를 job과 "
SecurityError
"DOMException
"로 호출한다. -
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
registration을 등록 가져오기를 job의 스토리지 키와 job의 scope url로 실행한 결과로 둔다.
-
registration이 null이 아니면:
-
newestWorker를 최신 워커 가져오기를 registration에 대해 실행한 결과로 둔다.
-
newestWorker가 null이 아니고, job의 script url이 동등하고, job의 워커 타입이 newestWorker의 type과 같고, job의 update via cache mode 값이 registration의 update via cache mode와 같으면:
-
작업 프라미스 해결을 job과 registration으로 호출한다.
-
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
-
그 외에는:
-
등록 설정 알고리즘을 job의 스토리지 키, job의 scope url, job의 update via cache mode로 실행한다.
-
-
업데이트 알고리즘을 job로 실행한다.
업데이트
- 입력
-
job, 작업
- 출력
-
없음
-
registration을 등록 가져오기를 job의 스토리지 키와 job의 scope url로 실행한 결과로 둔다.
-
registration이 null이면:
-
작업 프라미스 거부를 job과
TypeError
로 호출한다. -
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
newestWorker를 최신 워커 가져오기 알고리즘을 registration에 대해 실행한 결과로 둔다.
-
job의 작업 타입이 update이고, newestWorker가 null이 아니면서 newestWorker의 script url이 동등하지 않으면 job의 script url과:
-
작업 프라미스 거부를 job과
TypeError
로 호출한다. -
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
hasUpdatedResources를 false로 둔다.
-
job의 워커 타입에 따라 다음 옵션으로 하위 단계를 실행한다:
- "
classic
" -
클래식 워커 스크립트 가져오기를 job의 직렬화된 script url, job의 클라이언트, "
serviceworker
", 그리고 이 서비스 워커의 환경 설정 객체로 실행한다. - "
module
" -
모듈 워커 스크립트 그래프 가져오기를 job의 직렬화된 script url, job의 클라이언트, "
serviceworker
", "omit
", 그리고 이 서비스 워커의 환경 설정 객체로 실행한다.
이 알고리즘에서는 실제 환경 설정 객체 대신 생성될 환경 설정 객체를 사용한다. 이는 서비스 워커의 고유한 처리 모델 때문이다.
HTML의 워커 스크립트 fetch 알고리즘은 job의 클라이언트를 인자로 받는다. job의 클라이언트는 Soft Update 알고리즘에서 전달받을 때 null이다.
fetch hook 수행에서 request에 대해 다음 단계를 실행한다:
-
request의 헤더 리스트에 `
Service-Worker
`/`script
`를 추가한다.참고: Service-Worker 헤더 정의는 Appendix B에 있다.
-
다음 중 하나라도 참이면, request의 캐시 모드를 "
no-cache
"로 설정한다:-
registration의 update via cache mode가 "
all
"이 아닌 경우 -
job의 force bypass cache flag 가 설정된 경우
-
newestWorker가 null이 아니고 registration이 stale인 경우
참고: 캐시 모드가 "
no-cache
"가 아니더라도, 사용자 에이전트는 네트워크 계층의 Cache-Control 헤더의 max-age 값을 따르며 브라우저 캐시 우회 여부를 결정한다. -
-
request의 service-workers mode를 "
none
"으로 설정한다. -
isTopLevel 플래그가 설정되지 않았다면, fetching request 결과를 반환한다.
-
request의 redirect mode를 "
error
"로 설정한다. -
fetch request를 실행하고, processResponse의 일부로 response response에 대해 나머지 단계를 비동기로 실행한다.
-
response의 헤더 리스트에서 MIME type 추출을 수행한다. 이 MIME 타입(파라미터 무시)이 자바스크립트 MIME 타입이 아니면:
-
작업 프라미스 거부를 job과 "
SecurityError
"DOMException
"로 호출한다. -
이 단계들을 비동기로 네트워크 에러로 완료한다.
-
-
serviceWorkerAllowed를 헤더 리스트 값 추출으로 `
Service-Worker-Allowed
`와 response의 헤더 리스트로 얻는다.참고: Service-Worker-Allowed 헤더 정의는 Appendix B에 있다.
-
policyContainer를 fetch 응답으로 정책 컨테이너 생성으로 response를 인자로 설정한다.
-
serviceWorkerAllowed가 실패이면:
-
이 단계들을 비동기로 네트워크 에러로 완료한다.
-
-
scopeURL을 registration의 scope url로 둔다.
-
maxScopeString을 null로 둔다.
-
serviceWorkerAllowed가 null이면:
-
resolvedScope를 "./" 문자열과 job의 script url로 파싱한 결과로 둔다.
-
maxScopeString을 "
/
" 다음에 resolvedScope의 path 문자열(빈 문자열 포함)을 "/
"로 구분하여 연결한 값으로 설정한다.참고: 마지막 resolvedScope의 path 요소는 항상 빈 문자열이므로, maxScopeString은 마지막에 "
/
"가 있음.
-
-
그 외에는:
-
maxScope를 serviceWorkerAllowed와 job의 script url을 인자로 파싱한 결과로 둔다.
-
maxScope의 오리진이 job의 script url의 오리진과 같으면:
-
maxScopeString을 "
/
" 다음에 maxScope의 path 문자열(빈 문자열 포함)을 "/
"로 구분하여 연결한 값으로 설정한다.
-
-
-
scopeString을 "
/
" 다음에 scopeURL의 path 문자열(빈 문자열 포함)을 "/
"로 구분하여 연결한 값으로 설정한다. -
maxScopeString이 null이거나 scopeString이 maxScopeString으로 시작하지 않으면:
-
작업 프라미스 거부를 job과 "
SecurityError
"DOMException
"로 호출한다. -
이 단계들을 비동기로 네트워크 에러로 완료한다.
-
-
url을 request의 url로 둔다.
-
updatedResourceMap[url] = response로 설정한다.
-
response의 cache state가 "
local
"이 아니면, registration의 마지막 업데이트 확인 시간을 현재 시간으로 설정한다. -
다음 중 하나라도 참이면 hasUpdatedResources를 true로 설정한다:
-
newestWorker가 null인 경우
-
newestWorker의 script url이 url과 다르거나 newestWorker의 type이 job의 worker type과 다른 경우
-
newestWorker의 script resource map[url]의 body가 response의 body와 바이트 단위로 동일하지 않은 경우
-
-
hasUpdatedResources가 false이고 newestWorker의 classic scripts imported flag가 설정되어 있다면:
참고: 아래는 import된 스크립트가 변경되었는지 확인하는 단계로, 메인 스크립트가 변경되지 않은 경우에만 검사한다.
-
각 importUrl → storedResponse를 newestWorker의 script resource map에서 반복한다:
-
importUrl이 url이면 다음 반복으로 간다.
-
importRequest를 새 request로, url은 importUrl, client는 job의 클라이언트, destination은 "
script
", parser metadata는 "not parser-inserted
", use-URL-credentials flag는 설정됨으로 생성한다. -
다음 중 하나라도 참이면, importRequest의 캐시 모드를 "
no-cache
"로 설정한다:-
registration의 update via cache mode가 "
none
"인 경우 -
job의 force bypass cache flag가 설정된 경우
-
registration이 stale인 경우
-
-
fetchedResponse를 fetching importRequest의 결과로 둔다.
-
updatedResourceMap[importRequest의 url] = fetchedResponse로 설정한다.
-
fetchedResponse를 fetchedResponse의 unsafe response로 설정한다.
-
fetchedResponse의 cache state가 "
local
"이 아니면, registration의 마지막 업데이트 확인 시간을 현재 시간으로 설정한다. -
fetchedResponse가 잘못된 import 스크립트 응답이면, 다음 반복으로 간다.
참고: importScripts()의 잘못된 응답은 바이트 비교에서 무시된다.
-
fetchedResponse의 body가 storedResponse의 unsafe response의 body와 바이트 단위로 동일하지 않으면, hasUpdatedResources를 true로 설정한다.
참고: 이 단계에서는 모든 import 스크립트의 캐시 채우기를 위해 반복을 멈추지 않는다.
-
-
-
이 단계들을 비동기로 response로 완료한다.
이 알고리즘이 비동기로 완료되면, 남은 단계들을 script를 비동기 완료 값으로 하여 계속한다.
- "
-
script가 null이거나 Is Async Module을 script의 record, script의 base URL, « »로 실행한 결과가 true이면:
-
작업 프라미스 거부를 job과
TypeError
로 호출한다.참고: 만약 이전 단계에서 작업 프라미스 거부가 "
SecurityError
"DOMException
"로 호출되었다면 아무 동작하지 않는다. -
newestWorker가 null이면, 등록 맵[(registration의 스토리지 키, 직렬화된 scopeURL)]을 제거한다.
-
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
hasUpdatedResources가 false이면:
-
registration의 update via cache mode를 job의 update via cache mode로 설정한다.
-
작업 프라미스 해결을 job과 registration으로 호출한다.
-
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
worker를 새로운 서비스 워커로 둔다.
-
worker의 script url을 job의 script url로, worker의 script resource를 script로, worker의 type을 job의 worker type으로, worker의 script resource map을 updatedResourceMap으로 설정한다.
-
url을 worker의 사용된 스크립트 집합에 추가한다.
-
worker의 script resource의 policy container를 policyContainer로 설정한다.
-
forceBypassCache를 job의 force bypass cache flag가 설정되어 있으면 true, 아니면 false로 둔다.
-
runResult를 서비스 워커 실행 알고리즘을 worker와 forceBypassCache로 실행한 결과로 둔다.
-
runResult가 실패 또는 abrupt completion이면:
-
작업 프라미스 거부를 job과
TypeError
로 호출한다. -
newestWorker가 null이면, 등록 맵[(registration의 스토리지 키, 직렬화된 scopeURL)]을 제거한다.
-
작업 완료를 job로 호출한다.
-
-
그 외에는 설치 알고리즘을 job, worker, registration을 인자로 실행한다.
소프트 업데이트
사용자 에이전트는 업데이트를 확인하기 위해 원하는 만큼 자주 이 알고리즘을 호출할 수 있습니다.
- 입력
-
registration, 서비스 워커 등록
forceBypassCache, 선택적 불리언, 기본값은 false
참고: 구현자는 forceBypassCache를 디버깅(예: 개발자 도구에서 호출)이나 서비스 워커를 확장하는 다른 명세에서 필요에 따라 사용할 수 있습니다.
- 출력
-
없음
-
newestWorker를 최신 워커 가져오기 알고리즘을 registration에 대해 실행한 결과로 둔다.
-
newestWorker가 null이면 이 단계를 중단한다.
-
job을 작업 생성을 update, registration의 스토리지 키, registration의 scope url, newestWorker의 script url, null, null로 실행한 결과로 둔다.
-
forceBypassCache가 true이면 job의 force bypass cache flag를 설정한다.
-
작업 스케줄을 job로 호출한다.
설치
-
installFailed를 false로 둔다.
-
newestWorker를 최신 워커 가져오기 알고리즘을 registration에 대해 실행한 결과로 둔다.
-
registration의 update via cache mode를 job의 update via cache mode로 설정한다.
-
등록 상태 업데이트 알고리즘을 registration, "
installing
", worker로 실행한다. -
워커 상태 업데이트 알고리즘을 registration의 설치 중인 워커, "
installing
"로 실행한다. -
단언: job의 작업 프라미스는 null이 아니다.
-
작업 프라미스 해결을 job과 registration으로 호출한다.
-
settingsObjects를 환경 설정 객체 중, 오리진이 registration의 scope url의 오리진과 같은 모든 객체로 둔다.
-
settingsObjects의 각 settingsObject에 대해, 작업을 큐에 추가하여 settingsObject의 책임 이벤트 루프에서 DOM 조작 태스크 소스로 다음 단계를 실행한다:
-
registrationObjects를 settingsObject의 realm에 있는 모든
ServiceWorkerRegistration
객체 중, service worker registration이 registration인 객체로 둔다. -
registrationObjects의 각 registrationObject에 대해, 이벤트 발행을 registrationObject에
updatefound
이름으로 실행한다.
-
-
installingWorker를 registration의 설치 중인 워커로 둔다.
-
이벤트 생략 여부 알고리즘을 installingWorker와 "install"로 실행한 결과가 false이면:
-
job의 force bypass cache flag가 설정되어 있으면 forceBypassCache를 true로, 아니면 false로 둔다.
-
서비스 워커 실행 알고리즘을 installingWorker와 forceBypassCache로 실행한 결과가 실패이면:
-
installFailed를 true로 설정한다.
-
-
그 외에는:
-
installingWorker의 이벤트 루프에서 DOM 조작 태스크 소스로 task 작업을 큐에 추가해 다음 단계들을 실행한다:
-
e를
InstallEvent
로 이벤트 생성한 결과로 둔다. -
WaitForAsynchronousExtensions: 다음 하위 단계들을 병렬로 실행한다:
-
e가 active가 아니게 될 때까지 기다린다.
-
e의 timed out flag가 설정되어 있으면 installFailed를 true로 설정한다.
-
p를 모든 promise를 기다림으로 e의 extend lifetime promises로 실행한 결과로 둔다.
-
p가 reject될 때 installFailed를 true로 설정한다.
-
task가 버려지면 installFailed를 true로 설정한다.
-
-
task가 실행되거나 버려질 때까지 기다린다.
-
WaitForAsynchronousExtensions 단계가 완료될 때까지 기다린다.
-
-
-
installFailed가 true이면:
-
워커 상태 업데이트 알고리즘을 registration의 설치 중인 워커, "
redundant
"로 실행한다. -
등록 상태 업데이트 알고리즘을 registration, "
installing
", null로 실행한다. -
newestWorker가 null이면, 등록 맵[(registration의 스토리지 키, 직렬화된 registration의 scope url)]을 제거한다.
-
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
map을 registration의 설치 중인 워커의 스크립트 리소스 맵으로 둔다.
-
usedSet을 registration의 설치 중인 워커의 사용된 스크립트 집합으로 둔다.
-
각 url을 map에서 반복하여:
-
usedSet에 url이 포함되지 않으면 map[url]을 제거한다.
-
-
registration의 대기 중인 워커가 null이 아니면:
-
워커 상태 업데이트 알고리즘을 registration의 대기 중인 워커, "
redundant
"로 실행한다.
-
등록 상태 업데이트 알고리즘을 registration, "
waiting
", registration의 설치 중인 워커로 실행한다. -
등록 상태 업데이트 알고리즘을 registration, "
installing
", null로 실행한다. -
워커 상태 업데이트 알고리즘을 registration의 대기 중인 워커, "
installed
"로 실행한다. -
작업 완료를 job로 호출한다.
-
활성화 시도 알고리즘을 registration으로 호출한다.
참고: 활성화 시도가 여기에서 활성화를 트리거하지 않으면, 활성화는 기존 활성 워커가 언로드되거나,
skipWaiting()
이 비동기로 호출되거나, 기존 extend lifetime promises가 settle될 때 다시 시도된다.
활성화
- 입력
-
registration, 서비스 워커 등록
- 출력
-
없음
-
registration의 대기 중인 워커가 null이면 이 단계를 중단한다.
-
registration의 활성 워커가 null이 아니면:
-
워커 상태 업데이트 알고리즘을 registration의 활성 워커, "
redundant
"로 실행한다.
-
등록 상태 업데이트 알고리즘을 registration, "
active
", registration의 대기 중인 워커로 실행한다. -
등록 상태 업데이트 알고리즘을 registration, "
waiting
", null로 실행한다. -
워커 상태 업데이트 알고리즘을 registration의 활성 워커, "
activating
"로 실행한다.참고: 활성 워커가 activating 상태가 되면 런타임 스크립트 오류나 강제 종료가 발생해도 활성 워커가 활성화되는 것을 막지 않는다.
참고: 활성화 핸들러는 필수적이지 않은 작업(예: 정리 작업)을 하도록 설계하는 것이 좋다. 브라우저가 활성화 중에 종료되는 등 모든 핸들러가 반드시 끝까지 실행되는 것은 아니기 때문이다. 활성화 핸들러가 모두 성공적으로 완료되지 않아도 서비스 워커가 정상적으로 동작해야 한다.
-
matchedClients를 리스트로 두고, 서비스 워커 클라이언트 중 creation URL이 registration의 스토리지 키와 registration의 scope url에 매칭되는 클라이언트로 둔다.
-
각 client를 matchedClients에서 반복하여, 작업을 큐에 추가하여 client의 책임 이벤트 루프에서 DOM 조작 태스크 소스로 다음 하위 단계들을 실행한다:
-
readyPromise를 client의 글로벌 객체의
ServiceWorkerContainer
객체의 ready promise로 둔다. -
readyPromise가 null이면 다음 반복으로 넘어간다.
-
readyPromise가 pending 상태이면, 서비스 워커 등록 객체 얻기를 registration과 readyPromise의 relevant settings object로 실행한 결과로 readyPromise를 resolve한다.
-
-
등록을 사용 중인 서비스 워커 클라이언트 client마다:
-
컨트롤러 변경 알림 알고리즘을 client에 대해 실행한다.
-
activeWorker를 registration의 활성 워커로 둔다.
-
이벤트 생략 여부 알고리즘을 activeWorker와 "activate"로 실행한 결과가 false이면:
-
서비스 워커 실행 알고리즘을 activeWorker로 실행한 결과가 실패가 아니면:
-
activeWorker의 이벤트 루프에 DOM 조작 태스크 소스로 task 작업을 큐에 추가해 다음 단계들을 실행한다:
-
task가 실행되거나 버려질 때까지 기다린다.
-
WaitForAsynchronousExtensions 단계가 완료될 때까지 기다린다.
-
-
-
워커 상태 업데이트 알고리즘을 registration의 활성 워커, "
activated
"로 실행한다.
활성화 시도
- 입력
-
registration, 서비스 워커 등록
- 출력
-
없음
-
registration의 대기 중인 워커가 null이면 반환한다.
-
registration의 활성 워커가 null이 아니면서, registration의 활성 워커의 state가 "
activating
"이면 반환한다.참고: 기존 활성 워커가 activating 상태라면, 대기 중인 워커의 활성화가 지연된다.
-
다음 중 하나라도 참이면 활성화를 registration로 호출한다:
-
registration의 활성 워커가 null인 경우
-
서비스 워커에 보류 중인 이벤트 없음 알고리즘을 registration의 활성 워커로 실행한 결과가 true이고, 서비스 워커 클라이언트가 registration을 사용하지 않거나, registration의 대기 중인 워커의 skip waiting flag가 설정된 경우.
-
ServiceWorkerGlobalScope 설정
- 입력
-
serviceWorker, 서비스 워커
- 출력
-
ServiceWorkerGlobalScope
객체 또는 null
참고: 이 알고리즘은 CSP 검사 등에 사용할 수 있는 ServiceWorkerGlobalScope
를
반환하거나 null을 반환한다. serviceWorker에 활성 ServiceWorkerGlobalScope
가
있으면 반환하고, 아니면 새로 생성한다.
명세에서는 이런 보안 검사가 ServiceWorkerGlobalScope
,
relevant settings object, realm, agent 생성을 요구하지만, 구현체에서는 더
적은 작업으로도 충분할 수 있다. 구현체는 이 알고리즘에서 덜 하고, 서비스 워커 실행에서 더 해도 된다. 단, 결과가 관찰 가능한 수준에서 동일해야 한다(특히 모든
보안 검사 결과가 동일할 것).
-
unsafeCreationTime을 unsafe shared current time으로 둔다.
-
serviceWorker의 상태가 "
redundant
"이면 null을 반환한다. -
serviceWorker의 글로벌 객체가 null이 아니면 serviceWorker의 글로벌 객체를 반환한다.
-
단언: serviceWorker의 start status가 null임을 보장한다.
-
setupFailed를 false로 둔다.
-
globalObject를 null로 둔다.
-
agent를 서비스 워커 agent 얻기로 설정하고, 그 context에서 다음 단계를 실행한다:
-
realmExecutionContext를 새 realm 생성 알고리즘을 agent와 다음 커스텀으로 실행한 결과로 둔다:
-
글로벌 객체로 새
ServiceWorkerGlobalScope
객체를 생성한다. workerGlobalScope를 생성된 객체로 둔다.
-
-
settingsObject를 새 환경 설정 객체로 두고, 알고리즘을 다음과 같이 정의한다:
- realm execution context
-
realmExecutionContext를 반환한다.
- module map
-
workerGlobalScope의 module map을 반환한다.
- API base URL
-
serviceWorker의 script url을 반환한다.
- 오리진
-
등록한 서비스 워커 클라이언트의 오리진을 반환한다.
- policy container
-
workerGlobalScope의 policy container를 반환한다.
- time origin
-
unsafeCreationTime을 coarsening한 결과로 workerGlobalScope의 cross-origin isolated capability를 인자로 한다.
-
settingsObject의 id를 새 고유 불투명 문자열로, creation URL을 serviceWorker의 script url로, top-level creation URL을 null로, top-level origin을 구현 정의 값으로, target browsing context를 null로, active service worker를 null로 설정한다.
-
workerGlobalScope의 url을 serviceWorker의 script url로 설정한다.
-
workerGlobalScope의 policy container를 serviceWorker의 script resource의 policy container로 설정한다.
-
새
WorkerLocation
객체를 생성하여 workerGlobalScope에 연결한다. -
글로벌 객체 CSP 초기화 알고리즘을 workerGlobalScope에 실행한 결과가 "
Blocked
"이면, setupFailed를 true로 설정하고 이 단계를 중단한다. -
globalObject를 workerGlobalScope로 설정한다.
-
-
globalObject가 null이 아니거나 setupFailed가 true가 될 때까지 기다린다.
-
setupFailed가 true면 null을 반환한다.
-
globalObject를 반환한다.
서비스 워커 실행
- 입력
-
serviceWorker, 서비스 워커
forceBypassCache, 선택적 불리언, 기본값은 false
- 출력
-
Completion 또는 실패
참고: 이 알고리즘은 서비스 워커가 실행 중이 되거나 시작에 실패할 때까지 블록됩니다.
-
serviceWorker가 실행 중이면, serviceWorker의 start status를 반환한다.
-
serviceWorker의 state가 "
redundant
"면 실패를 반환한다. -
단언: serviceWorker의 start status는 null이다.
-
script를 serviceWorker의 스크립트 리소스로 둔다.
-
단언: script는 null이 아니다.
-
startFailed를 false로 둔다.
-
workerGlobalScope를 serviceWorker의 글로벌 객체로 둔다.
-
workerGlobalScope가 null이면:
-
workerGlobalScope를 ServiceWorkerGlobalScope 설정 알고리즘을 serviceWorker로 실행한 결과로 둔다.
-
workerGlobalScope가 null이면 실패를 반환한다.
-
serviceWorker의 글로벌 객체를 workerGlobalScope로 설정한다.
-
-
workerGlobalScope의 realm execution context에 대한 agent를 얻고, 그 context에서 다음 단계들을 실행한다:
-
forceBypassCache가 true면 workerGlobalScope의 importScripts 캐시 우회 플래그를 설정한다.
-
serviceWorker가 활성 워커이고, serviceWorker의 등록 객체의 task queue에 대기 중인 작업이 있으면, 해당 작업들을 serviceWorker의 event loop의 task queue에 원래 순서대로 해당 task source와 함께 큐에 추가한다.
-
evaluationStatus를 null로 둔다.
-
script가 클래식 스크립트이면:
-
evaluationStatus를 클래식 스크립트 실행을 script로 실행한 결과로 둔다.
-
evaluationStatus.[[Value]]가 비어 있으면, 스크립트가 평가되지 않은 것임. startFailed를 true로 설정하고 이 단계를 중단한다.
-
-
그 외에 script가 모듈 스크립트라면:
-
evaluationPromise를 모듈 스크립트 실행을 script와 report errors=false로 실행한 결과로 둔다.
-
단언: evaluationPromise.[[PromiseState]]는 "pending"이 아니다.
-
evaluationPromise.[[PromiseState]]가 "rejected"이면:
-
evaluationStatus를 ThrowCompletion(evaluationPromise.[[PromiseResult]])로 설정한다.
-
-
그 외에는:
-
evaluationStatus를 NormalCompletion(undefined)로 설정한다.
-
-
-
스크립트가 서비스 워커 종료 알고리즘에 의해 중단되었다면, startFailed를 true로 설정하고 이 단계를 중단한다.
-
serviceWorker의 start status를 evaluationStatus로 설정한다.
-
script의 has ever been evaluated flag가 설정되지 않았다면:
-
settingsObject의 글로벌 객체에 연결된 이벤트 리스너의 event type마다:
-
Append eventType을 workerGlobalScope의 서비스 워커의 처리할 이벤트 타입 집합에 추가한다.
참고: 글로벌 객체의 이벤트 리스너가 현재 추가되어 있지 않으면, 서비스 워커의 처리할 이벤트 타입 집합은 빈 집합으로 남는다.
-
-
script의 has ever been evaluated flag를 설정한다.
-
serviceWorker의 모든 fetch 리스너 비어 있음 플래그를 해제한다.
-
만약 모든 fetch 리스너 비어 있음 알고리즘을 workerGlobalScope로 실행한 결과가 true이면, serviceWorker의 모든 fetch 리스너 비어 있음 플래그를 설정할 수 있다.
-
-
settingsObject가 지정한 책임 이벤트 루프를 파괴될 때까지 실행한다.
-
-
serviceWorker가 실행 중이 되거나 startFailed가 true가 될 때까지 기다린다.
-
startFailed가 true면 실패를 반환한다.
-
serviceWorker의 start status를 반환한다.
모든 fetch 리스너 비어 있음
- 입력
-
workerGlobalScope, 글로벌 객체
- 출력
-
불리언 값
-
workerGlobalScope의 처리할 이벤트 타입 집합이 fetch를 포함하지 않으면 true를 반환한다.
-
eventHandler를 workerGlobalScope의 event handler map["onfetch"] 값으로 둔다.
-
eventListenerCallbacks를 legacy-obtain service worker fetch event listener callbacks를 workerGlobalScope에 대해 실행한 결과로 둔다.
-
각 eventListenerCallback을 eventListenerCallbacks에서 반복하여:
-
callback을 null로 둔다.
-
eventHandler가 null이 아니고 eventListenerCallback이 eventHandler의 listener의 callback과 같으면, callback을 IDL을 ECMAScript 값으로 변환한 eventHandler의 value로 설정한다.
-
그 외에는 callback을 IDL을 ECMAScript 값으로 변환한 eventListenerCallback으로 설정한다.
-
IsCallable(callback)이 false이면 false를 반환한다.
참고: Callback 객체가
handleEvent(event)
를 사용하면 비어 있지 않은 것으로 간주한다. 이는handleEvent(event)
getter를 호출하는 것을 피하기 위함이다.
참고: 이는
() => {}
와 같은 빈 fetch 리스너를 탐지한다. 어떤 사이트들은 fetch 이벤트 리스너에 빈 본문을 추가하여 Chromium에서 PWA로 인식시키기도 한다. -
-
true를 반환한다.
참고: 사용자 에이전트는 불필요한 빈 "fetch
" 리스너가
있을 때 경고를 표시하고, 성능에 악영향을 줄 수 있음을 안내할 수 있다.
서비스 워커 종료
- 입력
-
serviceWorker, 서비스 워커
- 출력
-
없음
-
serviceWorker의 메인 루프와 병렬로 다음 단계를 실행한다:
-
serviceWorkerGlobalScope를 serviceWorker의 글로벌 객체로 둔다.
-
serviceWorkerGlobalScope의 closing 플래그를 true로 설정한다.
-
작업 중 task source가 handle fetch task source 또는 handle functional event task source인 작업이 serviceWorkerGlobalScope의 event loop의 task queue에 대기 중이면, 해당 작업들을 serviceWorker의 등록 객체의 해당 task queue에 원래 순서대로 task source와 함께 큐에 추가하고, serviceWorkerGlobalScope의 event loop의 task queue에서 모든 작업(메시지 이벤트 등 포함)을 처리하지 않고 버린다.
참고: 즉, fetch 이벤트와 다른 기능적 이벤트(push 등)는 등록 객체의 task queue로 백업되고, 메시지 등 나머지 작업은 버려진다.
-
serviceWorker의 start status를 null로 설정한다.
-
Fetch 처리
Fetch 처리 알고리즘은 fetch 처리를 서비스 워커 컨텍스트에 전달하는 진입점입니다.
- 입력
-
request, request
fetchController, fetch controller
useHighResPerformanceTimers, 불리언
- 출력
-
registration을 null로 둔다.
-
client를 request의 client로 둔다.
-
reservedClient를 request의 reserved client로 둔다.
-
preloadResponse를 새로운 promise로 둔다.
-
workerRealm을 null로 둔다.
-
timingInfo를 새로운 service worker timing info로 둔다.
-
단언: request의 destination은 "
serviceworker
"가 아님. -
request의 destination이 "
embed
" 또는 "object
"이면:-
null을 반환한다.
-
-
그 외에 request가 non-subresource request라면:
-
reservedClient가 null이 아니며 environment settings object라면:
-
reservedClient가 secure context가 아니면 null을 반환한다.
-
-
그 외에는:
-
request의 url이 잠재적으로 신뢰할 수 있는 URL이 아니면 null을 반환한다.
-
-
request가 navigation request이고, 이를 트리거한 navigation이 shift+reload 또는 동등한 동작으로 시작되었으면 null을 반환한다.
-
단언 reservedClient가 null이 아님을 보장한다.
-
storage key를 obtain a storage key를 reservedClient로 실행한 결과로 둔다.
-
registration을 Match Service Worker Registration을 storage key, request의 url로 실행한 결과로 둔다.
-
registration이 null이거나 registration의 활성 워커가 null이면 null을 반환한다.
-
request의 destination이
"report"
가 아니면, reservedClient의 active service worker를 registration의 활성 워커로 설정한다.
참고: 이 시점부터 서비스 워커 클라이언트는 use 상태가 되며 active service worker의 등록 객체를 사용한다.
-
-
그 외에 request가 subresource request라면:
-
client의 active service worker가 null이 아니면, registration을 client의 active service worker의 등록 객체로 설정한다.
-
그 외에는 null을 반환한다.
-
-
activeWorker를 registration의 활성 워커로 둔다.
-
다음 중 하나라도 참이면 shouldSoftUpdate를 true로, 아니면 false로 둔다:
-
request가 non-subresource request인 경우.
-
request가 subresource request이고, registration이 stale인 경우.
-
-
activeWorker의 라우터 규칙 목록이 비어 있지 않으면:
-
source를 Get Router Source 알고리즘을 registration의 활성 워커와 request로 실행한 결과로 둔다.
-
source가
"network"
인 경우: -
그 외에 source가
"cache"
또는 source["cacheName
"]가 존재하면:-
shouldSoftUpdate가 true이면 병렬로 소프트 업데이트 알고리즘을 registration으로 실행한다.
-
각 cacheName → cache를 registration의 스토리지 키의 name to cache map에서 반복한다.
-
source["
cacheName
"]가 존재하고 source["cacheName
"]가 cacheName이 아니면 다음 반복으로 간다. -
requestResponses를 Query Cache를 request, 새
CacheQueryOptions
, cache로 실행한 결과로 둔다. -
requestResponses가 빈 리스트이면 null을 반환한다.
-
그 외에는:
-
requestResponse를 requestResponses의 첫 번째 요소로 둔다.
-
response를 requestResponse의 response로 둔다.
-
globalObject를 activeWorker의 글로벌 객체로 둔다.
-
globalObject가 null이면:
-
globalObject를 ServiceWorkerGlobalScope 설정을 activeWorker로 실행한 결과로 둔다.
-
-
globalObject가 null이면 null을 반환한다.
참고: 이는 CORS 체크를 위해 ServiceWorkerGlobalScope를 생성하는 단계이지만, 실제 구현체에서 반드시 이 객체를 생성하라는 뜻은 아니다.
-
response의 type이 "
opaque
"이고, cross-origin resource policy check를 globalObject의 오리진, globalObject, "", response의 internal response로 실행한 결과가 blocked이면 null을 반환한다. -
response를 반환한다.
-
-
-
null을 반환한다.
-
-
그 외에 source가
"race-network-and-fetch-handler"
이고, request의 method가 `GET
`이면:-
shouldSoftUpdate가 true이면 병렬로 소프트 업데이트 알고리즘을 registration으로 실행한다.
-
queue를 빈 queue로 둔다.
-
raceFetchController를 null로 둔다.
-
raceResponse를 race response로, value는 "
pending
"으로 둔다. -
다음 하위 단계들을 병렬로 실행하되, abort when fetchController의 state가 "
terminated
" 또는 "aborted
"이면 중단한다:-
raceFetchController를 fetch를 request로 실행한 결과로 둔다. processResponse는 다음 단계로 처리한다:
-
-
If aborted이고 raceFetchController가 null이 아니면:
-
Abort raceFetchController.
-
raceResponse를 race response로, value는 null로 설정한다.
-
-
preloadResponse를 undefined로 resolve한다.
-
다음 하위 단계들을 병렬로 실행한다:
-
fetchHandlerResponse를 Fetch 이벤트 생성 및 디스패치를 request, registration, useHighResPerformanceTimers, timingInfo, workerRealm, reservedClient, preloadResponse, raceResponse로 실행한 결과로 둔다.
-
fetchHandlerResponse가 null이 아니고 network error가 아니며 raceFetchController가 null이 아니면, Abort raceFetchController.
-
Enqueue fetchHandlerResponse를 queue에 추가한다.
-
-
queue가 빈 상태가 아닐 때까지 기다린다.
-
dequeue queue의 결과를 반환한다.
-
-
단언: source는 "
fetch-event
"임.
-
-
request가 navigation request이고, registration의 navigation preload enabled flag가 설정되어 있고, request의 method가 `
GET
`이며, registration의 활성 워커의 처리할 이벤트 타입 집합이 fetch를 포함하고, registration의 활성 워커의 모든 fetch 리스너 비어 있음 플래그가 설정되지 않았다면:참고: 위 조건이 모두 참이나 registration의 활성 워커의 처리할 이벤트 타입 집합이 fetch를 포함하지 않으면, 사용자 에이전트는 개발자 콘솔에 경고를 표시할 수 있음.
-
preloadRequest를 cloning을 request로 실행한 결과로 둔다.
-
preloadRequestHeaders를 preloadRequest의 헤더 리스트로 둔다.
-
preloadResponseObject를 Response 객체로, Headers 객체와 연결된 상태로 생성하되 guard는 "
immutable
"로 한다. -
Append를 통해 preloadRequestHeaders에 헤더를 추가하되 name은 `
Service-Worker-Navigation-Preload
`, value는 registration의 navigation preload header value로 한다. -
preloadRequest의 service-workers mode를 "
none
"으로 설정한다. -
preloadFetchController를 null로 둔다.
-
다음 하위 단계들을 병렬로 실행하되, abort when fetchController의 state가 "
terminated
" 또는 "aborted
"이면 중단한다:-
preloadFetchController를 fetching preloadRequest의 결과로 둔다.
processResponse를 navigationPreloadResponse로 실행할 때 하위 단계:
-
navigationPreloadResponse의 type이 "
error
"이면, preloadResponse를TypeError
로 reject하고 하위 단계를 종료한다. -
preloadResponseObject를 navigationPreloadResponse와 연결한다.
-
preloadResponse를 preloadResponseObject로 resolve한다.
-
-
-
If aborted이면:
-
deserializedError를 deserialize a serialized abort reason를 null, workerRealm으로 실행한 결과로 둔다.
-
Abort preloadFetchController를 deserializedError로 실행한다.
-
-
-
그 외에는 preloadResponse를 undefined로 resolve한다.
-
Fetch 이벤트 생성 및 디스패치를 request, registration, useHighResPerformanceTimers, timingInfo, workerRealm, reservedClient, preloadResponse, null로 실행한 결과를 반환한다.
Fetch 이벤트 생성 및 디스패치
- 입력
-
request, request
registration, 서비스 워커 등록
useHighResPerformanceTimers, 불리언
timingInfo, service worker timing info
workerRealm, 글로벌 객체의 relevant realm
reservedClient, reserved client
preloadResponse, promise
raceResponse, race response 또는 null
- 출력
-
response를 null로 둔다.
-
eventCanceled를 false로 둔다.
-
client를 request의 client로 둔다.
-
activeWorker를 registration의 활성 워커로 둔다.
-
eventHandled를 null로 둔다.
-
handleFetchFailed를 false로 둔다.
-
respondWithEntered를 false로 둔다.
-
다음 중 하나라도 참이면 shouldSoftUpdate를 true로, 아니면 false로 둔다:
-
request가 non-subresource request인 경우.
-
request가 subresource request이고, registration이 stale인 경우.
-
-
이벤트 생략 여부 알고리즘을 "fetch", activeWorker로 실행한 결과가 true이면:
-
activeWorker의 모든 fetch 리스너 비어 있음 플래그가 설정되어 있으면:
-
useHighResPerformanceTimers가 true이면, useHighResPerformanceTimers를 activeWorker의 글로벌 객체의 cross-origin isolated capability로 설정한다.
-
timingInfo의 start time을 coarsened shared current time을 useHighResPerformanceTimers로 실행한 결과로 설정한다.
-
activeWorker의 상태가 "
activating
"이면, activeWorker의 상태가 "activated
"가 될 때까지 기다린다. -
서비스 워커 실행 알고리즘을 activeWorker로 실행한 결과가 실패이면 handleFetchFailed를 true로 설정한다.
-
그 외에는:
-
workerRealm를 activeWorker의 글로벌 객체의 relevant realm로 설정한다.
-
eventHandled를 새 promise로 workerRealm에 생성한다.
-
raceResponse가 null이 아니면, 설정 activeWorker의 글로벌 객체의 race response map[request]를 raceResponse로 설정한다.
-
작업을 큐에 추가하여 task에서 다음 하위 단계를 실행한다:
-
e를 이벤트 생성을
FetchEvent
로 실행한 결과로 둔다. -
abortController를 새
AbortController
객체로 workerRealm에 생성한다. -
requestObject를 Request 객체 생성을 request, 새
Headers
객체의 guard는 "immutable
", abortController의 signal, workerRealm로 실행한 결과로 둔다. -
e의
cancelable
속성을 true로 초기화한다. -
e의
request
속성을 requestObject로 초기화한다. -
e의
preloadResponse
속성을 preloadResponse로 초기화한다. -
request가 non-subresource request이고, request의 destination이
"report"
가 아니면, e의resultingClientId
속성을 reservedClient의 id로, 아니면 빈 문자열로 초기화한다. -
request가 navigation request이면, e의
replacesClientId
속성을 request의 replaces client id로, 아니면 빈 문자열로 초기화한다. -
e의
handled
속성을 eventHandled로 초기화한다. -
timingInfo의 fetch event dispatch time를 coarsened shared current time을 useHighResPerformanceTimers로 실행한 결과로 설정한다.
-
서비스 워커 확장 이벤트 집합 업데이트를 activeWorker, e로 실행한다.
-
e의 respond-with entered flag가 설정되어 있으면 respondWithEntered를 true로 설정한다.
-
e의 wait to respond flag가 설정되어 있으면:
-
e의 wait to respond flag가 해제될 때까지 기다린다.
-
e의 respond-with error flag가 설정되어 있으면 handleFetchFailed를 true로 설정한다.
-
그 외에는 response를 e의 potential response로 설정한다.
-
-
response가 null이고 request의 body가 null이 아니고, request의 body의 source가 null이면:
-
response가 null이 아니면 response의 service worker timing info를 timingInfo로 설정한다.
-
e의 canceled flag가 설정되어 있으면 eventCanceled를 true로 설정한다.
-
fetchController의 state가 "
terminated
" 또는 "aborted
"이면:-
deserializedError를 deserialize a serialized abort reason를 fetchController의 serialized abort reason, workerRealm으로 실행한 결과로 둔다.
-
작업을 큐에 추가하여 signal abort를 abortController, deserializedError로 실행한다.
-
task가 버려지면 handleFetchFailed를 true로 설정한다.
task는 반드시 activeWorker의 event loop와 fetch 처리 태스크 소스를 사용해야 한다.
-
-
-
task가 실행되거나 handleFetchFailed가 true가 될 때까지 기다린다.
-
shouldSoftUpdate가 true이면 병렬로 소프트 업데이트 알고리즘을 registration으로 실행한다.
-
activeWorker의 글로벌 객체의 race response map[request]이 존재하면, 제거 activeWorker의 글로벌 객체의 race response map[request]을 제거한다.
-
respondWithEntered가 false이면:
-
eventCanceled가 true이면:
-
eventHandled가 null이 아니면, reject eventHandled을 "
NetworkError
"DOMException
"과 함께 workerRealm에서 reject한다. -
network error를 반환한다.
-
-
eventHandled가 null이 아니면, resolve eventHandled을 실행한다.
-
raceResponse의 value가 null이 아니면:
-
null을 반환한다.
-
-
handleFetchFailed가 true이면:
-
eventHandled가 null이 아니면, reject eventHandled을 "
NetworkError
"DOMException
"과 함께 workerRealm에서 reject한다. -
network error를 반환한다.
-
-
eventHandled가 null이 아니면, resolve eventHandled을 실행한다.
-
response를 반환한다.
URL 패턴 파싱
- 입력
-
rawPattern,
URLPatternCompatible
serviceWorker, 서비스 워커
- 출력
-
baseURL을 serviceWorker의 스크립트 URL로 둔다.
-
rawPattern과 baseURL을 인자로 하여 Web IDL 값으로부터 URL 패턴 생성 알고리즘을 실행한 결과를 반환한다.
라우터 조건 검증
- 입력
-
condition,
RouterCondition
serviceWorker, 서비스 워커
- 출력
-
불리언 값
-
hasCondition을 false로 둔다.
-
condition["
urlPattern
"] 존재하면:-
rawPattern을 condition["
urlPattern
"]로 둔다. -
pattern을 URL 패턴 파싱 알고리즘을 rawPattern, serviceWorker로 실행한 결과로 둔다. 만약 예외가 발생하면 false를 반환한다.
-
pattern이 정규식 그룹을 포함하면 false를 반환한다.
참고: 사용자 정의 정규식을 실행하는 것은 보안상 문제이므로 금지된다.
-
hasCondition을 true로 설정한다.
-
-
condition["
requestMethod
"] 존재하면:-
method을 condition["
requestMethod
"]로 둔다. -
method가 method가 아니면 false를 반환한다.
-
method가 금지된 method이면 false를 반환한다.
-
hasCondition을 true로 설정한다.
-
-
condition["
requestMode
"] 존재하면 hasCondition을 true로 설정한다. -
condition["
requestDestination
"] 존재하면 hasCondition을 true로 설정한다. -
condition["
runningStatus
"] 존재하면 hasCondition을 true로 설정한다. -
hasCondition을 반환한다.
라우터 조건 매칭
- 입력
-
condition,
RouterCondition
serviceWorker, 서비스 워커
request, request
- 출력
-
불리언 값
참고: 여러 조건(e.g. urlPattern
,
runningStatus
, requestMethod
등이 설정된 경우), 모든 조건이 일치해야 true를 반환한다.
-
그 외에는:
참고: 라우터 조건 검증 알고리즘이
or
,not
과 다른 조건이 상호 배타적임을 보장한다.-
condition["
urlPattern
"] 존재하면:-
rawPattern을 condition["
urlPattern
"]로 둔다. -
pattern을 URL 패턴 파싱 알고리즘을 rawPattern, serviceWorker로 실행한 결과로 둔다.
-
match 알고리즘을 pattern, request의 URL로 실행한 결과가 null이면 false를 반환한다.
-
-
condition["
requestMethod
"] 존재하면:-
method을 condition["
requestMethod
"]로 둔다. -
method 정규화를 method로 실행한다.
-
request의 method가 method와 다르면 false를 반환한다.
-
-
condition["
requestMode
"] 존재하면:-
mode을 condition["
requestMode
"]로 둔다. -
request의 mode가 mode와 다르면 false를 반환한다.
-
-
condition["
requestDestination
"] 존재하면:-
destination을 condition["
requestDestination
"]로 둔다. -
request의 destination이 destination과 다르면 false를 반환한다.
-
-
condition["
runningStatus
"] 존재하면:-
runningStatus을 condition["
runningStatus
"]로 둔다. -
runningStatus가
"running"
이고, serviceWorker가 실행 중이 아니면 false를 반환한다. -
runningStatus가
"not-running"
이고, serviceWorker가 실행 중이면 false를 반환한다.
-
-
true를 반환한다.
-
라우터 등록 제한 검사
- 입력
-
routerRules, 라우터 규칙 리스트
- 출력
-
불리언 값
참고: 라우터 조건은 _or
와
not
을
사용하여 복잡하게 중첩될 수 있습니다.
과도한 처리를 방지하기 위해, 이 알고리즘은 두 가지 제한을 둡니다. 첫째, 중첩된 모든 조건을 합한 총 조건 수는 1024를 초과할 수 없습니다. 둘째, 중첩 깊이는 10단계로
제한하여 계산량이 지수적으로 증가하는 것을 막습니다.
-
result를 라우터 조건 카운트 결과로 둔다.
-
result의 condition count를 1024로 설정한다.
-
result의 quota exceeded를 false로 설정한다.
-
각 rule을 routerRules에서 반복하여:
-
result를 내부 라우터 조건 카운트 알고리즘을 rule["
condition
"], result, 10으로 실행한 결과로 둔다. -
result의 quota exceeded가 true면 false를 반환한다.
-
-
true를 반환한다.
내부 라우터 조건 카운트
- 입력
-
condition,
RouterCondition
result, 라우터 조건 카운트 결과
depth, 숫자
- 출력
-
result, 라우터 조건 카운트 결과
-
result의 condition count를 1 감소시킨다.
-
result의 condition count가 0이거나, depth가 0이면:
-
result의 quota exceeded를 true로 설정한다.
-
result를 반환한다.
-
-
-
depth를 1 감소시킨다.
-
condition["
_or
"]의 각 orCondition에 대해:-
result를 내부 라우터 조건 카운트 알고리즘을 orCondition, result, depth로 실행한 결과로 둔다.
-
result의 quota exceeded가 true면 result를 반환한다.
-
-
-
-
depth를 1 감소시킨다.
-
result를 내부 라우터 조건 카운트 알고리즘을 condition["
not
"], result, depth로 실행한 결과로 둔다. -
result의 quota exceeded가 true면 result를 반환한다.
-
-
result를 반환한다.
라우터 소스 확인
- 입력
-
serviceWorker, 서비스 워커
request, request
- 출력
-
RouterSource
또는 null
-
각 rule을 serviceWorker의 라우터 규칙 리스트에서 반복하여:
-
null을 반환한다.
이벤트 생략 여부
- 입력
-
eventName, 문자열
serviceWorker, 서비스 워커
- 출력
-
불리언 값
참고: 불필요한 지연을 피하기 위해, 이 표준은 서비스 워커의 글로벌에서 이벤트 리스너가 최초 스크립트 실행 시 결정적으로 추가되지 않은 경우 이벤트 디스패치를 생략할 수 있도록 허용합니다.
-
serviceWorker의 처리할 이벤트 타입 집합에 eventName이 포함되지 않으면, 사용자 에이전트는 true를 반환할 수 있습니다.
-
false를 반환한다.
기능성 이벤트 발행
- 입력
-
eventName, 문자열
eventConstructor,
ExtendableEvent
를 확장한 이벤트 생성자registration, 서비스 워커 등록
initialization, event을 eventConstructor로 생성할 때 사용할 속성 초기화 (옵션)
postDispatchSteps, 활성 워커의 이벤트 루프에서 eventConstructor의 인스턴스(dispatchedEvent)가 디스패치된 후 실행할 단계 (옵션)
- 출력
-
없음
-
단언: registration의 활성 워커는 null이 아니다.
-
activeWorker를 registration의 활성 워커로 둔다.
-
이벤트 생략 여부 알고리즘을 eventName, activeWorker로 실행한 결과가 true면:
-
activeWorker의 상태가 "
activating
"이면, activeWorker의 상태가 "activated
"가 될 때까지 기다린다. -
서비스 워커 실행 알고리즘을 activeWorker로 실행한 결과가 실패이면:
-
작업을 큐에 추가하여 task에서 다음 하위 단계를 실행한다:
-
event를 이벤트 생성을 eventConstructor와 activeWorker의 글로벌 객체의 relevant realm으로 실행한 결과로 둔다.
-
initialization이 null이 아니면, event를 initialization으로 초기화한다.
-
서비스 워커 확장 이벤트 집합 업데이트를 activeWorker, event로 실행한다.
-
postDispatchSteps가 null이 아니면, postDispatchSteps를 event를 dispatchedEvent로 전달하여 실행한다.
task는 반드시 activeWorker의 이벤트 루프와 기능성 이벤트 태스크 소스를 사용해야 한다.
-
-
task가 실행되거나 버려질 때까지 기다린다.
-
registration이 stale이면 병렬로 소프트 업데이트 알고리즘을 registration으로 실행한다.
amazingthing
" 이벤트(AmazingThingEvent
타입)를 특정 serviceWorkerRegistration에 발행하고, 이벤트 객체의 속성을 초기화하려면 다음과 같이 기술합니다:
-
기능성 이벤트 발행 "
amazingthing
"를AmazingThingEvent
로 serviceWorkerRegistration에 다음 속성으로 발행:- propertyName
-
value
- anotherPropertyName
-
anotherValue
그리고 dispatchedEvent로 다음 단계를 수행합니다:
-
서비스 워커의 이벤트 루프에서 dispatchedEvent로 필요한 작업을 수행합니다.
초기화 단계와 디스패치 후 단계는 옵션임을 참고하세요. 필요 없다면 다음과 같이 기술합니다:
-
기능성 이벤트 발행 "
whatever
"를ExtendableEvent
로 serviceWorkerRegistration에 발행.
서비스 워커 클라이언트 언로드 처리
사용자 에이전트는 서비스 워커 클라이언트가 문서 언로드 정리 단계 또는 종료에 의해 언로드될 때 반드시 다음 단계를 실행해야 합니다.
- 입력
-
client, 서비스 워커 클라이언트
- 출력
-
없음
사용자 에이전트 종료 처리
- 입력
-
없음
- 출력
-
없음
서비스 워커 확장 이벤트 집합 업데이트
등록 해제
- 입력
-
job, 작업
- 출력
-
없음
-
job의 origin과 job의 client의 origin이 다르면:
-
작업 프라미스 거부를 job, "
SecurityError
"DOMException
"로 호출한다. -
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
registration을 등록 가져오기를 job의 스토리지 키, job의 scope url로 실행한 결과로 둔다.
-
registration이 null이면:
-
작업 프라미스 해결을 job, false로 호출한다.
-
작업 완료를 job로 호출하고 이 단계를 중단한다.
-
-
작업 프라미스 해결을 job, true로 호출한다.
-
등록 정리 시도를 registration으로 호출한다.
참고: 등록 정리 시도가 여기에서 등록 정리를 트리거하지 않으면, 등록 정리는 등록을 사용 중인 마지막 클라이언트가 언로드되거나, 등록의 서비스 워커에 대한 extend lifetime promises가 settle될 때 다시 시도된다.
-
작업 완료를 job로 호출한다.
등록 설정
- 입력
-
storage key, 스토리지 키
scope, URL
updateViaCache, update via cache mode
- 출력
-
registration, 서비스 워커 등록
등록 정리
- 입력
-
registration, 서비스 워커 등록
- 출력
-
없음
-
다음 단계를 원자적으로 실행한다.
-
registration의 설치 중인 워커가 null이 아니면:
-
워커 상태 업데이트 알고리즘을 registration의 설치 중인 워커, "
redundant
"로 실행한다. -
등록 상태 업데이트 알고리즘을 registration, "
installing
", null로 실행한다.
-
registration의 대기 중인 워커가 null이 아니면:
-
워커 상태 업데이트 알고리즘을 registration의 대기 중인 워커, "
redundant
"로 실행한다. -
등록 상태 업데이트 알고리즘을 registration, "
waiting
", null로 실행한다.
-
registration의 활성 워커가 null이 아니면:
-
워커 상태 업데이트 알고리즘을 registration의 활성 워커, "
redundant
"로 실행한다. -
등록 상태 업데이트 알고리즘을 registration, "
active
", null로 실행한다.
등록 정리 시도
- 입력
-
registration, 서비스 워커 등록
- 출력
-
없음
-
다음 조건을 모두 만족하고 서비스 워커 클라이언트가 registration을 사용하지 않으면 등록 정리를 registration으로 호출한다:
-
registration의 설치 중인 워커가 null이거나, 서비스 워커에 보류 중인 이벤트 없음 알고리즘을 registration의 설치 중인 워커로 실행한 결과가 true.
-
registration의 대기 중인 워커가 null이거나, 서비스 워커에 보류 중인 이벤트 없음 알고리즘을 registration의 대기 중인 워커로 실행한 결과가 true.
-
registration의 활성 워커가 null이거나, 서비스 워커에 보류 중인 이벤트 없음 알고리즘을 registration의 활성 워커로 실행한 결과가 true.
-
등록 상태 업데이트
- 입력
-
registration, 서비스 워커 등록
target, 문자열 ("
installing
", "waiting
", "active
" 중 하나)source, 서비스 워커 또는 null
- 출력
-
없음
-
registrationObjects를 registration과 연결된 모든
ServiceWorkerRegistration
객체 배열로 둔다. -
target이 "
installing
"이면:-
registration의 설치 중인 워커를 source로 설정한다.
-
registrationObjects의 각 registrationObject에 대해:
-
작업을 큐에 추가하여 registrationObject의
installing
속성을 registration의 설치 중인 워커가 null이면 null로, 아니면 서비스 워커 객체 얻기 알고리즘을 registration의 설치 중인 워커와 registrationObject의 relevant settings object로 실행한 결과로 설정한다.
-
-
-
그 외에 target이 "
waiting
"이면:-
registration의 대기 중인 워커를 source로 설정한다.
-
registrationObjects의 각 registrationObject에 대해:
-
작업을 큐에 추가하여 registrationObject의
waiting
속성을 registration의 대기 중인 워커가 null이면 null로, 아니면 서비스 워커 객체 얻기 알고리즘을 registration의 대기 중인 워커와 registrationObject의 relevant settings object로 실행한 결과로 설정한다.
-
-
-
그 외에 target이 "
active
"이면:-
registration의 활성 워커를 source로 설정한다.
-
registrationObjects의 각 registrationObject에 대해:
-
작업을 큐에 추가하여 registrationObject의
active
속성을 registration의 활성 워커가 null이면 null로, 아니면 서비스 워커 객체 얻기 알고리즘을 registration의 활성 워커와 registrationObject의 relevant settings object로 실행한 결과로 설정한다.
-
작업은 registrationObject의 relevant settings object의 책임 이벤트 루프와 DOM 조작 태스크 소스를 사용해야 한다.
-
워커 상태 업데이트
-
단언: state는 "
parsed
"가 아니다.참고: "
parsed
"는 초기 상태이다. 서비스 워커는 이 상태로 업데이트되지 않는다. -
worker의 상태를 state로 설정한다.
-
settingsObjects를 환경 설정 객체 중 origin이 worker의 스크립트 URL의 origin인 것들의 집합으로 둔다.
-
settingsObjects의 각 settingsObject에 대해, 작업을 큐에 추가하여 settingsObject의 책임 이벤트 루프 및 DOM 조작 태스크 소스로 다음 단계 실행:
-
objectMap을 settingsObject의 서비스 워커 객체 맵으로 둔다.
-
objectMap[worker]가 존재하지 않으면 이 단계를 중단한다.
-
workerObj를 objectMap[worker]로 둔다.
-
workerObj의
state
속성을 state로 설정한다. -
"statechange" 이벤트 발행을 workerObj에 실행한다.
-
컨트롤러 변경 알림
- 입력
-
client, 서비스 워커 클라이언트
- 출력
-
없음
-
단언: client는 null이 아니다.
-
client가 환경 설정 객체라면, 작업을 큐에 추가하여
controllerchange
이벤트를 client가 연결된ServiceWorkerContainer
객체에 발행한다.
작업은 client의 책임 이벤트 루프와 DOM 조작 태스크 소스를 사용해야 한다.
서비스 워커 등록 매칭
-
다음 단계를 원자적으로 실행한다.
-
clientURLString을 직렬화된 clientURL로 둔다.
-
matchingScopeString을 빈 문자열로 둔다.
-
scopeStringSet을 빈 리스트로 둔다.
-
matchingScopeString을 scopeStringSet 중 clientURLString으로 시작하는 가장 긴 값으로 설정한다(존재하면).
참고: 이 단계의 URL 문자열 매칭은 접두사 기반으로 경로 구조와 무관하다. 예를 들어, 클라이언트 URL 문자열이 "https://example.com/prefix-of/resource.html"이면, "https://example.com/prefix" 범위에 등록된 경우 매칭된다. 동일 오리진 보안에 안전함을 보장하기 위해 HTTP(S) URL은 항상 오리진 부분 끝에 슬래시가 붙어 직렬화된다.
-
matchingScope를 null로 둔다.
-
matchingScopeString이 빈 문자열이 아니면:
-
등록 가져오기를 storage key, matchingScope로 실행한 결과를 반환한다.
등록 가져오기
최신 워커 가져오기
-
다음 단계를 원자적으로 실행한다.
-
newestWorker를 null로 둔다.
-
registration의 설치 중인 워커가 null이 아니면, newestWorker를 registration의 설치 중인 워커로 설정한다.
-
그 외에 registration의 대기 중인 워커가 null이 아니면, newestWorker를 registration의 대기 중인 워커로 설정한다.
-
그 외에 registration의 활성 워커가 null이 아니면, newestWorker를 registration의 활성 워커로 설정한다.
-
newestWorker를 반환한다.
서비스 워커에 보류 중인 이벤트 없음
- 입력
-
worker, 서비스 워커
- 출력
-
True 또는 false, 불리언
클라이언트 생성
- 입력
-
client, 서비스 워커 클라이언트
- 출력
-
clientObject,
Client
객체
-
clientObject를 새
Client
객체로 둔다. -
clientObject의 서비스 워커 클라이언트를 client로 설정한다.
-
clientObject를 반환한다.
윈도우 클라이언트 생성
- 입력
-
client, 서비스 워커 클라이언트
frameType, 문자열
visibilityState, 문자열
focusState, 불리언
ancestorOriginsList, 리스트
- 출력
-
windowClient,
WindowClient
객체
-
windowClient를 새
WindowClient
객체로 둔다. -
windowClient의 서비스 워커 클라이언트를 client로 설정한다.
-
windowClient의 프레임 타입을 frameType으로 설정한다.
-
windowClient의 가시성 상태를 visibilityState로 설정한다.
-
windowClient의 포커스 상태를 focusState로 설정한다.
-
windowClient의 ancestor origins array를 frozen array로 ancestorOriginsList로부터 생성하여 설정한다.
-
windowClient를 반환한다.
프레임 타입 가져오기
- 입력
-
navigable, navigable
- 출력
-
frameType, 문자열
-
navigable의 parent가 null이 아니면 "
nested
"를 반환한다. -
navigable의 active browsing context가 보조 브라우징 컨텍스트라면 "
auxiliary
"를 반환한다. -
"
top-level
"을 반환한다.
Get Client Promise 해석
- 입력
-
client, 서비스 워커 클라이언트
promise, 프라미스
- 출력
-
없음
-
client가 환경 설정 객체라면:
-
client가 보안 컨텍스트가 아니면, 작업을 큐에 추가하여 promise를 "
SecurityError
"DOMException
으로 거부하고, promise의 relevant settings object의 책임 이벤트 루프 및 DOM 조작 태스크 소스를 사용하고, 이 단계를 중단한다.
-
-
그 외의 경우:
-
client의 creation URL이 잠재적으로 신뢰할 수 있는 URL이 아니면, 작업을 큐에 추가하여 promise를 "
SecurityError
"DOMException
으로 거부하고, promise의 relevant settings object의 책임 이벤트 루프 및 DOM 조작 태스크 소스를 사용하고, 이 단계를 중단한다.
-
-
client가 환경 설정 객체이고 window client가 아니면:
-
clientObject를 클라이언트 생성 알고리즘을 client로 실행한 결과로 둔다.
-
작업을 큐에 추가하여 promise를 clientObject로 resolve하고, promise의 relevant settings object의 책임 이벤트 루프 및 DOM 조작 태스크 소스를 사용하고, 이 단계를 중단한다.
-
-
그 외의 경우:
-
browsingContext를 null로 둔다.
-
client가 환경 설정 객체이면, browsingContext를 client의 글로벌 객체의 browsing context로 둔다.
-
그 외에는 browsingContext를 client의 target browsing context로 둔다.
-
navigable을 navigable로 두고, active browsing context는 browsingContext로 둔다.
-
작업을 큐에 추가하여 browsingContext의 event loop에서 user interaction task source를 사용하여 다음 단계 실행:
-
frameType을 프레임 타입 가져오기 알고리즘을 navigable로 실행한 결과로 둔다.
-
visibilityState를 browsingContext의 active document의
visibilityState
값으로 둔다. -
focusState를 has focus steps 알고리즘을 browsingContext의 active document로 실행한 결과로 둔다.
-
ancestorOriginsList를 빈 리스트로 둔다.
-
client가 window client라면, ancestorOriginsList를 browsingContext의 active document의 relevant global object의
Location
객체의 ancestor origins list의 리스트로 둔다. -
작업을 큐에 추가하여 promise의 relevant settings object의 책임 이벤트 루프 및 DOM 조작 태스크 소스로 다음 단계 실행:
-
client의 discarded flag가 설정되어 있으면 promise를 undefined로 resolve하고 이 단계를 중단한다.
-
windowClient를 윈도우 클라이언트 생성 알고리즘을 client, frameType, visibilityState, focusState, ancestorOriginsList로 실행한 결과로 둔다.
-
promise를 windowClient로 resolve한다.
-
-
-
캐시 질의
- 입력
-
requestQuery, request
options,
CacheQueryOptions
객체, 옵션targetStorage, request response list, 옵션
- 출력
-
resultList, request response list
-
resultList를 빈 리스트로 둔다.
-
storage를 null로 둔다.
-
옵션 인자 targetStorage가 생략되었다면, storage를 relevant request response list로 설정한다.
-
그 외에는 storage를 targetStorage로 설정한다.
-
각 requestResponse를 storage에서 반복하여:
-
cachedRequest를 requestResponse의 request로 둔다.
-
cachedResponse를 requestResponse의 response로 둔다.
-
요청이 캐시 항목과 일치 알고리즘을 requestQuery, cachedRequest, cachedResponse, options로 실행한 결과가 true이면:
-
requestCopy를 cachedRequest의 복사본으로 둔다.
-
responseCopy를 cachedResponse의 복사본으로 둔다.
-
requestCopy/responseCopy를 resultList에 추가한다.
-
-
-
resultList를 반환한다.
요청이 캐시 항목과 일치
- 입력
-
requestQuery, request
request, request
response, response 또는 null, 선택적, 기본값은 null
options,
CacheQueryOptions
객체, 선택적 - 출력
-
불리언 값
-
options["
ignoreMethod
"]가 false이고 request의 method가 `GET
`이 아니면 false를 반환한다. -
queryURL을 requestQuery의 url로 둔다.
-
cachedURL을 request의 url로 둔다.
-
options["
ignoreSearch
"]가 true이면: -
queryURL이 cachedURL과 fragment 제외 플래그를 설정한 상태로 동일하지 않으면 false를 반환한다.
-
response가 null이거나, options["
ignoreVary
"]가 true이거나, response의 header list에 `Vary
`가 포함되지 않으면 true를 반환한다. -
fieldValues를 리스트로 두고, field-values 중 Vary 헤더의 값에 해당하는 요소들로 구성한다.
-
fieldValues의 각 fieldValue에 대해:
-
fieldValue가 "
*
"와 일치하거나, combined value를 fieldValue, request의 header list로 실행한 결과가 combined value를 fieldValue, requestQuery의 header list로 실행한 결과와 일치하지 않으면 false를 반환한다.
-
-
true를 반환한다.
캐시 일괄 작업
- 입력
- 출력
-
resultList, request response list
-
cache를 relevant request response list로 둔다.
-
backupCache를 cache의 복사본으로 새 request response list로 둔다.
-
addedItems를 빈 리스트로 둔다.
-
다음 하위 단계를 원자적으로 시도한다:
-
resultList를 빈 리스트로 둔다.
-
각 operation을 operations에서 반복하여:
-
operation의 type이 "
delete
"이고 operation의 response가 null이 아니면 TypeError를 throw한다. -
캐시 질의 알고리즘을 operation의 request, operation의 options, addedItems로 실행한 결과가 비어 있지 않으면 InvalidStateError
DOMException
을 throw한다. -
requestResponses를 빈 리스트로 둔다.
-
operation의 type이 "
delete
"이면: -
그 외에 operation의 type이 "
put
"이면:-
requestResponses를 캐시 질의 알고리즘을 operation의 request로 실행한 결과로 둔다.
-
각 requestResponse를 requestResponses에서 반복하여:
-
이전 두 단계에서 캐시 쓰기 작업이 할당된 quota 한도 초과로 실패하면, QuotaExceededError
DOMException
을 throw한다. -
Append operation의 request/operation의 response를 addedItems에 추가한다.
-
Append operation의 request/operation의 response를 resultList에 추가한다.
-
resultList를 반환한다.
-
-
그리고 만약 예외가 throw되었다면:
-
Remove 모든 item을 relevant request response list에서 제거한다.
-
각 requestResponse를 backupCache에서 반복하여:
-
Append requestResponse를 relevant request response list에 추가한다.
-
-
Throw 해당 예외를 throw한다.
참고: 예외가 throw되면, 구현체는 일괄 작업 중 캐시 저장소에 가한 변경 사항을 모두 undo(롤백)해야 한다.
-
비동기 모듈 여부 확인
경쟁 응답 조회
-
registration을 null로 둔다.
-
request가 non-subresource request이면:
-
request의 reserved client가 null이면 null을 반환한다.
-
storage key를 스토리지 키 획득을 request의 reserved client로 실행한 결과로 둔다.
-
registration을 서비스 워커 등록 매칭을 storage key, request의 url로 실행한 결과로 둔다.
-
-
그 외에 request가 subresource request이면:
-
client를 request의 client로 둔다.
-
client의 active service worker가 null이면 null을 반환한다.
-
registration을 client의 active service worker의 소속 서비스 워커 등록으로 둔다.
-
-
그 외의 경우 null을 반환한다.
-
activeWorker를 registration의 active worker로 둔다.
-
map을 activeWorker의 글로벌 객체의 race response map으로 둔다.
-
map[request]이 존재하면:
-
null을 반환한다.
부록 B: 확장된 HTTP 헤더
서비스 워커 스크립트 요청
서비스 워커 스크립트 응답
서비스 워커의 스크립트 리소스 요청에 대한 HTTP 응답에는 다음 헤더가 포함될 수 있습니다:
- `
Service-Worker-Allowed
` -
사용자 에이전트가 경로 제한(스크립트가 scope url을 제어할 수 있는 최대 경로)을 주어진 값으로 재정의함을 나타냅니다.
참고: 값은 URL입니다. 상대 URL이 주어지면, 스크립트의 URL을 기준으로 파싱됩니다.
// 최대 허용 범위는 기본적으로 스크립트가 위치한 경로로 설정됩니다 // 이 예시에서는 "/js/"입니다 navigator. serviceWorker. register( "/js/sw.js" ). then(() => { console. log( "기본 scope '/js/'로 설치 성공." ); });
// 스크립트 위치보다 상위 경로로 scope 설정 // 응답에 Service-Worker-Allowed 헤더 없음 navigator. serviceWorker. register( "/js/sw.js" , { scope: "/" }). catch (() => { console. error( "경로 제한 위반으로 설치 실패." ); });
문법
ABNF는 서비스 워커의 스크립트 리소스 요청 및 응답에서 사용되는 헤더 값에 대해 정의합니다:
Service-Worker = %x73.63.72.69.70.74 ; "script", 대소문자 구분
참고: Service-Worker-Allowed 헤더 값의 유효성 검사는 ABNF 대신 URL 파싱 알고리즘(갱신 알고리즘)으로 수행됩니다.
8. 감사의 글
Andrew Betts에게 동료들과 함께하는 작은 워크숍을 조직하고 진행해주신 데 깊이 감사드립니다. 참석자: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. 논의의 명확성과 그날 제시된 사용 사례들 덕분에 많은 것이 가능해졌습니다. 또한 오프라인 문제의 중요성을 일깨워준 Andrew에게 다시 한번 감사드립니다. 그가 EdgeConf를 조직하고 오프라인을 지속적인 주제로 삼은 덕분에 본 작업의 진전에 여러 기회와 연결이 생겼습니다.
Anne van Kesteren은 서비스 워커 개발 과정에서 웹 플랫폼의 심오한 지식과 표준화 경험을 아낌없이 공유해주셨습니다. URL, HTTP Fetch, Promises, DOM의 실제 동작을 기술한 그의 이전 작업 없이는 이 규격이 완성될 수 없었을 것입니다. Ian Hickson의 엄밀한 Web Worker 규격 역시 본 규격의 기반이 되었습니다. 그에게 깊은 감사를 전합니다.
순서는 없지만, 설계 방향과 논의에 깊이 감사드릴 분들: Jungkee Song, Alec Flett, David Barrett-Kahn, Aaron Boodman, Michael Nordman, Tom Ashworth, Kinuko Yasuda, Darin Fisher, Jonas Sicking, Jesús Leganés Combarro, Mark Christian, Dave Hermann, Yehuda Katz, François Remy, Ilya Grigorik, Will Chan, Domenic Denicola, Nikhil Marathe, Yves Lafon, Adam Barth, Greg Simon, Devdatta Akhawe, Dominic Cooney, Jeffrey Yasskin, Joshua Bell, Boris Zbarsky, Matt Falkenhagen, Tobie Langel, Gavin Peters, Ben Kelly, Hiroki Nakagawa, Jake Archibald, Josh Soref, Jinho Bang, Yutaka Hirano, Michael(tm) Smith, isonmad, Ali Alabbas, Philip Jägenstedt, Mike Pennisi, Eric Willigers.
Jason Weber, Chris Wilson, Paul Kinlan, Ehsan Akhgari, Daniel Austin은 요구사항과 표준화 과정에서 귀중한 피드백을 제공해주셨습니다.
저자들은 Dimitri Glazkov의 스크립트 및 포맷팅 도구에도 감사드립니다. 이 규격 제작에 필수적이었으며 많은 가르침도 받았습니다.
Vivian Cromwell, Greg Simon, Alex Komoroske, Wonsuk Lee, Seojin Kim에게도 전문적인 지원에 깊이 감사드립니다.