2
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
4
*--------------------------------------------------------------------------------------------*/
5
+ //@ts -check
5
6
/// <reference lib="webworker" />
6
7
7
- const sw : ServiceWorkerGlobalScope = self as any as ServiceWorkerGlobalScope ;
8
+ /** @type {ServiceWorkerGlobalScope } */
9
+ const sw = /** @type {any } */ ( self ) ;
8
10
9
11
const VERSION = 4 ;
10
12
@@ -16,38 +18,54 @@ const searchParams = new URL(location.toString()).searchParams;
16
18
17
19
const remoteAuthority = searchParams . get ( 'remoteAuthority' ) ;
18
20
19
- let outerIframeMessagePort : MessagePort | undefined ;
21
+ /** @type {MessagePort|undefined } */
22
+ let outerIframeMessagePort ;
20
23
21
24
/**
22
25
* Origin used for resources
23
26
*/
24
27
const resourceBaseAuthority = searchParams . get ( 'vscode-resource-base-authority' ) ;
25
28
29
+
30
+ /** @type {number } */
26
31
const resolveTimeout = 30_000 ;
27
32
28
- type RequestStoreResult < T > = {
29
- status : 'ok' ;
30
- value : T ;
31
- } | {
32
- status : 'timeout' ;
33
- } ;
34
33
35
- interface RequestStoreEntry < T > {
36
- resolve : ( x : RequestStoreResult < T > ) => void ;
37
- promise : Promise < RequestStoreResult < T > > ;
38
- }
34
+ /**
35
+ * @template T
36
+ * @typedef {{ status: 'ok', value: T } | { status: 'timeout' } } RequestStoreResult
37
+ */
38
+
39
+
40
+ /**
41
+ * @template T
42
+ * @typedef {{ resolve: (x: RequestStoreResult<T>) => void, promise: Promise<RequestStoreResult<T>> } } RequestStoreEntry
43
+ */
39
44
40
- class RequestStore < T > {
41
- private map : Map < number , RequestStoreEntry < T > > = new Map ( ) ;
42
- private requestPool : number = 0 ;
43
45
44
- create ( ) : { requestId : number ; promise : Promise < RequestStoreResult < T > > } {
46
+ /**
47
+ * @template T
48
+ */
49
+ class RequestStore {
50
+ constructor ( ) {
51
+ /** @type {Map<number, RequestStoreEntry<T>> } */
52
+ this . map = new Map ( ) ;
53
+ /** @type {number } */
54
+ this . requestPool = 0 ;
55
+ }
56
+
57
+ /**
58
+ * @returns {{ requestId: number, promise: Promise<RequestStoreResult<T>> } }
59
+ */
60
+ create ( ) {
45
61
const requestId = ++ this . requestPool ;
46
62
47
- let resolve : ( x : RequestStoreResult < T > ) => void ;
48
- const promise = new Promise < RequestStoreResult < T > > ( r => resolve = r ) ;
63
+ /** @type {(x: RequestStoreResult<T>) => void } */
64
+ let resolve ;
65
+ const promise = new Promise ( r => resolve = r ) ;
49
66
50
- const entry : RequestStoreEntry < T > = { resolve : resolve ! , promise } ;
67
+ /** @type {RequestStoreEntry<T> } */
68
+ const entry = { resolve, promise } ;
51
69
this . map . set ( requestId , entry ) ;
52
70
53
71
const dispose = ( ) => {
@@ -62,7 +80,12 @@ class RequestStore<T> {
62
80
return { requestId, promise } ;
63
81
}
64
82
65
- resolve ( requestId : number , result : T ) : boolean {
83
+ /**
84
+ * @param {number } requestId
85
+ * @param {T } result
86
+ * @returns {boolean }
87
+ */
88
+ resolve ( requestId , result ) {
66
89
const entry = this . map . get ( requestId ) ;
67
90
if ( ! entry ) {
68
91
return false ;
@@ -76,12 +99,14 @@ class RequestStore<T> {
76
99
/**
77
100
* Map of requested paths to responses.
78
101
*/
79
- const resourceRequestStore = new RequestStore < ResourceResponse > ( ) ;
102
+ /** @type {RequestStore<ResourceResponse> } */
103
+ const resourceRequestStore = new RequestStore ( ) ;
80
104
81
105
/**
82
106
* Map of requested localhost origins to optional redirects.
83
107
*/
84
- const localhostRequestStore = new RequestStore < string | undefined > ( ) ;
108
+ /** @type {RequestStore<string|undefined> } */
109
+ const localhostRequestStore = new RequestStore ( ) ;
85
110
86
111
const unauthorized = ( ) =>
87
112
new Response ( 'Unauthorized' , { status : 401 , } ) ;
@@ -95,12 +120,13 @@ const methodNotAllowed = () =>
95
120
const requestTimeout = ( ) =>
96
121
new Response ( 'Request Timeout' , { status : 408 , } ) ;
97
122
98
- sw . addEventListener ( 'message' , async ( event : ExtendableMessageEvent ) => {
123
+ sw . addEventListener ( 'message' , async ( event ) => {
99
124
if ( ! event . source ) {
100
125
return ;
101
126
}
102
127
103
- const source = event . source as Client ;
128
+ /** @type {Client } */
129
+ const source = event . source ;
104
130
switch ( event . data . channel ) {
105
131
case 'version' : {
106
132
outerIframeMessagePort = event . ports [ 0 ] ;
@@ -115,7 +141,8 @@ sw.addEventListener('message', async (event: ExtendableMessageEvent) => {
115
141
return ;
116
142
}
117
143
case 'did-load-resource' : {
118
- const response = event . data . data as ResourceResponse ;
144
+ /** @type {ResourceResponse } */
145
+ const response = event . data . data ;
119
146
if ( ! resourceRequestStore . resolve ( response . id , response ) ) {
120
147
console . log ( 'Could not resolve unknown resource' , response . path ) ;
121
148
}
@@ -135,7 +162,7 @@ sw.addEventListener('message', async (event: ExtendableMessageEvent) => {
135
162
}
136
163
} ) ;
137
164
138
- sw . addEventListener ( 'fetch' , ( event : FetchEvent ) => {
165
+ sw . addEventListener ( 'fetch' , ( event ) => {
139
166
const requestUrl = new URL ( event . request . url ) ;
140
167
if ( typeof resourceBaseAuthority === 'string' && requestUrl . protocol === 'https:' && requestUrl . hostname . endsWith ( '.' + resourceBaseAuthority ) ) {
141
168
switch ( event . request . method ) {
@@ -184,25 +211,32 @@ sw.addEventListener('fetch', (event: FetchEvent) => {
184
211
}
185
212
} ) ;
186
213
187
- sw . addEventListener ( 'install' , ( event : ExtendableEvent ) => {
214
+ sw . addEventListener ( 'install' , ( event ) => {
188
215
event . waitUntil ( sw . skipWaiting ( ) ) ; // Activate worker immediately
189
216
} ) ;
190
217
191
- sw . addEventListener ( 'activate' , ( event : ExtendableEvent ) => {
218
+ sw . addEventListener ( 'activate' , ( event ) => {
192
219
event . waitUntil ( sw . clients . claim ( ) ) ; // Become available to all pages
193
220
} ) ;
194
221
195
- interface ResourceRequestUrlComponents {
196
- scheme : string ;
197
- authority : string ;
198
- path : string ;
199
- query : string ;
200
- }
201
222
223
+ /**
224
+ * @typedef {Object } ResourceRequestUrlComponents
225
+ * @property {string } scheme
226
+ * @property {string } authority
227
+ * @property {string } path
228
+ * @property {string } query
229
+ */
230
+
231
+ /**
232
+ * @param {FetchEvent } event
233
+ * @param {ResourceRequestUrlComponents } requestUrlComponents
234
+ * @returns {Promise<Response> }
235
+ */
202
236
async function processResourceRequest (
203
- event : FetchEvent ,
204
- requestUrlComponents : ResourceRequestUrlComponents
205
- ) : Promise < Response > {
237
+ event ,
238
+ requestUrlComponents
239
+ ) {
206
240
let client = await sw . clients . get ( event . clientId ) ;
207
241
if ( ! client ) {
208
242
client = await getWorkerClientForId ( event . clientId ) ;
@@ -227,10 +261,12 @@ async function processResourceRequest(
227
261
228
262
const shouldTryCaching = ( event . request . method === 'GET' ) ;
229
263
230
- const resolveResourceEntry = (
231
- result : RequestStoreResult < ResourceResponse > ,
232
- cachedResponse : Response | undefined
233
- ) : Response => {
264
+ /**
265
+ * @param {RequestStoreResult<ResourceResponse> } result
266
+ * @param {Response|undefined } cachedResponse
267
+ * @returns {Response }
268
+ */
269
+ const resolveResourceEntry = ( result , cachedResponse ) => {
234
270
if ( result . status === 'timeout' ) {
235
271
return requestTimeout ( ) ;
236
272
}
@@ -252,7 +288,8 @@ async function processResourceRequest(
252
288
return notFound ( ) ;
253
289
}
254
290
255
- const commonHeaders : Record < string , string > = {
291
+ /** @type {Record<string, string> } */
292
+ const commonHeaders = {
256
293
'Access-Control-Allow-Origin' : '*' ,
257
294
} ;
258
295
@@ -287,7 +324,8 @@ async function processResourceRequest(
287
324
}
288
325
}
289
326
290
- const headers : Record < string , string > = {
327
+ /** @type {Record<string, string> } */
328
+ const headers = {
291
329
...commonHeaders ,
292
330
'Content-Type' : entry . mime ,
293
331
'Content-Length' : byteLength . toString ( ) ,
@@ -312,7 +350,7 @@ async function processResourceRequest(
312
350
headers [ 'Cross-Origin-Opener-Policy' ] = 'same-origin' ;
313
351
}
314
352
315
- const response = new Response ( entry . data as Uint8Array < ArrayBuffer > , {
353
+ const response = new Response ( entry . data , {
316
354
status : 200 ,
317
355
headers
318
356
} ) ;
@@ -325,7 +363,8 @@ async function processResourceRequest(
325
363
return response . clone ( ) ;
326
364
} ;
327
365
328
- let cached : Response | undefined ;
366
+ /** @type {Response|undefined } */
367
+ let cached ;
329
368
if ( shouldTryCaching ) {
330
369
const cache = await caches . open ( resourceCacheName ) ;
331
370
cached = await cache . match ( event . request ) ;
@@ -366,10 +405,15 @@ async function processResourceRequest(
366
405
return promise . then ( entry => resolveResourceEntry ( entry , cached ) ) ;
367
406
}
368
407
408
+ /**
409
+ * @param {FetchEvent } event
410
+ * @param {URL } requestUrl
411
+ * @returns {Promise<Response> }
412
+ */
369
413
async function processLocalhostRequest (
370
- event : FetchEvent ,
371
- requestUrl : URL
372
- ) : Promise < Response > {
414
+ event ,
415
+ requestUrl
416
+ ) {
373
417
const client = await sw . clients . get ( event . clientId ) ;
374
418
if ( ! client ) {
375
419
// This is expected when requesting resources on other localhost ports
@@ -390,9 +434,11 @@ async function processLocalhostRequest(
390
434
391
435
const origin = requestUrl . origin ;
392
436
393
- const resolveRedirect = async (
394
- result : RequestStoreResult < string | undefined >
395
- ) : Promise < Response > => {
437
+ /**
438
+ * @param {RequestStoreResult<string|undefined> } result
439
+ * @returns {Promise<Response> }
440
+ */
441
+ const resolveRedirect = async function ( result ) {
396
442
if ( result . status !== 'ok' || ! result . value ) {
397
443
return fetch ( event . request ) ;
398
444
}
@@ -432,12 +478,20 @@ async function processLocalhostRequest(
432
478
return promise . then ( resolveRedirect ) ;
433
479
}
434
480
435
- function getWebviewIdForClient ( client : Client ) : string | null {
481
+ /**
482
+ * @param {Client } client
483
+ * @returns {string|null }
484
+ */
485
+ function getWebviewIdForClient ( client ) {
436
486
const requesterClientUrl = new URL ( client . url ) ;
437
487
return requesterClientUrl . searchParams . get ( 'id' ) ;
438
488
}
439
489
440
- async function getOuterIframeClient ( webviewId : string ) : Promise < Client [ ] > {
490
+ /**
491
+ * @param {string } webviewId
492
+ * @returns {Promise<Client[]> }
493
+ */
494
+ async function getOuterIframeClient ( webviewId ) {
441
495
const allClients = await sw . clients . matchAll ( { includeUncontrolled : true } ) ;
442
496
return allClients . filter ( client => {
443
497
const clientUrl = new URL ( client . url ) ;
@@ -446,7 +500,11 @@ async function getOuterIframeClient(webviewId: string): Promise<Client[]> {
446
500
} ) ;
447
501
}
448
502
449
- async function getWorkerClientForId ( clientId : string ) : Promise < Client | undefined > {
503
+ /**
504
+ * @param {string } clientId
505
+ * @returns {Promise<Client|undefined> }
506
+ */
507
+ async function getWorkerClientForId ( clientId ) {
450
508
const allDedicatedWorkerClients = await sw . clients . matchAll ( { type : 'worker' } ) ;
451
509
const allSharedWorkerClients = await sw . clients . matchAll ( { type : 'sharedworker' } ) ;
452
510
const allWorkerClients = [ ...allDedicatedWorkerClients , ...allSharedWorkerClients ] ;
@@ -455,9 +513,12 @@ async function getWorkerClientForId(clientId: string): Promise<Client | undefine
455
513
} ) ;
456
514
}
457
515
458
- type ResourceResponse =
459
- | { readonly status : 200 ; id : number ; path : string ; mime : string ; data : Uint8Array ; etag : string | undefined ; mtime : number | undefined }
460
- | { readonly status : 304 ; id : number ; path : string ; mime : string ; mtime : number | undefined }
461
- | { readonly status : 401 ; id : number ; path : string }
462
- | { readonly status : 404 ; id : number ; path : string }
463
- ;
516
+
517
+ /**
518
+ * @typedef {(
519
+ * | { readonly status: 200, id: number, path: string, mime: string, data: Uint8Array, etag: string|undefined, mtime: number|undefined }
520
+ * | { readonly status: 304, id: number, path: string, mime: string, mtime: number|undefined }
521
+ * | { readonly status: 401, id: number, path: string }
522
+ * | { readonly status: 404, id: number, path: string }
523
+ * )} ResourceResponse
524
+ */
0 commit comments