9
9
10
10
const sw = /** @type {ServiceWorkerGlobalScope } */ ( /** @type {any } */ ( self ) ) ;
11
11
12
- const VERSION = 2 ;
12
+ const VERSION = 3 ;
13
13
14
14
const resourceCacheName = `vscode-resource-cache-${ VERSION } ` ;
15
15
16
16
const rootPath = sw . location . pathname . replace ( / \/ s e r v i c e - w o r k e r .j s $ / , '' ) ;
17
17
18
-
19
18
const searchParams = new URL ( location . toString ( ) ) . searchParams ;
20
19
21
20
/**
@@ -98,11 +97,16 @@ class RequestStore {
98
97
}
99
98
}
100
99
100
+ /**
101
+ * @typedef {{ readonly status: 200; id: number; path: string; mime: string; data: Uint8Array; etag: string | undefined; mtime: number | undefined; }
102
+ * | { readonly status: 304; id: number; path: string; mime: string; mtime: number | undefined }
103
+ * | { readonly status: 401; id: number; path: string }
104
+ * | { readonly status: 404; id: number; path: string }} ResourceResponse
105
+ */
106
+
101
107
/**
102
108
* Map of requested paths to responses.
103
- * @typedef {{ type: 'response', body: Uint8Array, mime: string, etag: string | undefined, mtime: number | undefined } |
104
- * { type: 'not-modified', mime: string, mtime: number | undefined } |
105
- * undefined} ResourceResponse
109
+ *
106
110
* @type {RequestStore<ResourceResponse> }
107
111
*/
108
112
const resourceRequestStore = new RequestStore ( ) ;
@@ -120,48 +124,41 @@ const notFound = () =>
120
124
const methodNotAllowed = ( ) =>
121
125
new Response ( 'Method Not Allowed' , { status : 405 , } ) ;
122
126
123
- sw . addEventListener ( 'message' , async ( event ) => {
127
+ const vscodeMessageChannel = new MessageChannel ( ) ;
128
+
129
+ sw . addEventListener ( 'message' , event => {
124
130
switch ( event . data . channel ) {
125
- case 'version ' :
131
+ case 'init ' :
126
132
{
127
133
const source = /** @type {Client } */ ( event . source ) ;
128
134
sw . clients . get ( source . id ) . then ( client => {
129
- if ( client ) {
130
- client . postMessage ( {
131
- channel : 'version' ,
132
- version : VERSION
133
- } ) ;
134
- }
135
+ client ?. postMessage ( {
136
+ channel : 'init' ,
137
+ version : VERSION
138
+ } , [ vscodeMessageChannel . port2 ] ) ;
135
139
} ) ;
136
140
return ;
137
141
}
142
+ }
143
+
144
+ console . log ( 'Unknown message' ) ;
145
+ } ) ;
146
+
147
+ vscodeMessageChannel . port1 . onmessage = ( event ) => {
148
+ switch ( event . data . channel ) {
138
149
case 'did-load-resource' :
139
150
{
140
- /** @type {ResourceResponse } */
141
- let response = undefined ;
142
-
143
- const data = event . data . data ;
144
- switch ( data . status ) {
145
- case 200 :
146
- {
147
- response = { type : 'response' , body : data . data , mime : data . mime , etag : data . etag , mtime : data . mtime } ;
148
- break ;
149
- }
150
- case 304 :
151
- {
152
- response = { type : 'not-modified' , mime : data . mime , mtime : data . mtime } ;
153
- break ;
154
- }
155
- }
156
151
157
- if ( ! resourceRequestStore . resolve ( data . id , response ) ) {
158
- console . log ( 'Could not resolve unknown resource' , data . path ) ;
152
+ /** @type {ResourceResponse } */
153
+ const response = event . data ;
154
+ if ( ! resourceRequestStore . resolve ( response . id , response ) ) {
155
+ console . log ( 'Could not resolve unknown resource' , response . path ) ;
159
156
}
160
157
return ;
161
158
}
162
159
case 'did-load-localhost' :
163
160
{
164
- const data = event . data . data ;
161
+ const data = event . data ;
165
162
if ( ! localhostRequestStore . resolve ( data . id , data . location ) ) {
166
163
console . log ( 'Could not resolve unknown localhost' , data . origin ) ;
167
164
}
@@ -170,7 +167,7 @@ sw.addEventListener('message', async (event) => {
170
167
}
171
168
172
169
console . log ( 'Unknown message' ) ;
173
- } ) ;
170
+ } ;
174
171
175
172
sw . addEventListener ( 'fetch' , ( event ) => {
176
173
const requestUrl = new URL ( event . request . url ) ;
@@ -192,7 +189,7 @@ sw.addEventListener('fetch', (event) => {
192
189
} ) ;
193
190
194
191
sw . addEventListener ( 'install' , ( event ) => {
195
- event . waitUntil ( sw . skipWaiting ( ) ) ; // Activate worker immediately
192
+ event . waitUntil ( sw . skipWaiting ( ) ) ;
196
193
} ) ;
197
194
198
195
sw . addEventListener ( 'activate' , ( event ) => {
@@ -210,35 +207,29 @@ async function processResourceRequest(event, requestUrl) {
210
207
return notFound ( ) ;
211
208
}
212
209
213
- const webviewId = getWebviewIdForClient ( client ) ;
214
- if ( ! webviewId ) {
215
- console . error ( 'Could not resolve webview id' ) ;
216
- return notFound ( ) ;
217
- }
218
-
219
210
const shouldTryCaching = ( event . request . method === 'GET' ) ;
220
211
221
212
/**
222
213
* @param {ResourceResponse } entry
223
214
* @param {Response | undefined } cachedResponse
224
215
*/
225
216
async function resolveResourceEntry ( entry , cachedResponse ) {
226
- if ( ! entry ) {
227
- return notFound ( ) ;
228
- }
229
-
230
- if ( entry . type === 'not-modified' ) {
217
+ if ( entry . status === 304 ) { // Not modified
231
218
if ( cachedResponse ) {
232
219
return cachedResponse . clone ( ) ;
233
220
} else {
234
221
throw new Error ( 'No cache found' ) ;
235
222
}
236
223
}
237
224
225
+ if ( entry . status !== 200 ) {
226
+ return notFound ( ) ;
227
+ }
228
+
238
229
/** @type {Record<string, string> } */
239
230
const headers = {
240
231
'Content-Type' : entry . mime ,
241
- 'Content-Length' : entry . body . byteLength . toString ( ) ,
232
+ 'Content-Length' : entry . data . byteLength . toString ( ) ,
242
233
'Access-Control-Allow-Origin' : '*' ,
243
234
} ;
244
235
if ( entry . etag ) {
@@ -248,7 +239,7 @@ async function processResourceRequest(event, requestUrl) {
248
239
if ( entry . mtime ) {
249
240
headers [ 'Last-Modified' ] = new Date ( entry . mtime ) . toUTCString ( ) ;
250
241
}
251
- const response = new Response ( entry . body , {
242
+ const response = new Response ( entry . data , {
252
243
status : 200 ,
253
244
headers
254
245
} ) ;
@@ -261,12 +252,6 @@ async function processResourceRequest(event, requestUrl) {
261
252
return response . clone ( ) ;
262
253
}
263
254
264
- const parentClients = await getOuterIframeClient ( webviewId ) ;
265
- if ( ! parentClients . length ) {
266
- console . log ( 'Could not find parent client for request' ) ;
267
- return notFound ( ) ;
268
- }
269
-
270
255
/** @type {Response | undefined } */
271
256
let cached ;
272
257
if ( shouldTryCaching ) {
@@ -280,17 +265,15 @@ async function processResourceRequest(event, requestUrl) {
280
265
const scheme = firstHostSegment . split ( '+' , 1 ) [ 0 ] ;
281
266
const authority = firstHostSegment . slice ( scheme . length + 1 ) ; // may be empty
282
267
283
- for ( const parentClient of parentClients ) {
284
- parentClient . postMessage ( {
285
- channel : 'load-resource' ,
286
- id : requestId ,
287
- path : requestUrl . pathname ,
288
- scheme,
289
- authority,
290
- query : requestUrl . search . replace ( / ^ \? / , '' ) ,
291
- ifNoneMatch : cached ?. headers . get ( 'ETag' ) ,
292
- } ) ;
293
- }
268
+ vscodeMessageChannel . port1 . postMessage ( {
269
+ channel : 'load-resource' ,
270
+ id : requestId ,
271
+ path : requestUrl . pathname ,
272
+ scheme,
273
+ authority,
274
+ query : requestUrl . search . replace ( / ^ \? / , '' ) ,
275
+ ifNoneMatch : cached ?. headers . get ( 'ETag' ) ,
276
+ } ) ;
294
277
295
278
return promise . then ( entry => resolveResourceEntry ( entry , cached ) ) ;
296
279
}
@@ -307,11 +290,6 @@ async function processLocalhostRequest(event, requestUrl) {
307
290
// that are not spawned by vs code
308
291
return fetch ( event . request ) ;
309
292
}
310
- const webviewId = getWebviewIdForClient ( client ) ;
311
- if ( ! webviewId ) {
312
- console . error ( 'Could not resolve webview id' ) ;
313
- return fetch ( event . request ) ;
314
- }
315
293
316
294
const origin = requestUrl . origin ;
317
295
@@ -332,42 +310,13 @@ async function processLocalhostRequest(event, requestUrl) {
332
310
} ) ;
333
311
} ;
334
312
335
- const parentClients = await getOuterIframeClient ( webviewId ) ;
336
- if ( ! parentClients . length ) {
337
- console . log ( 'Could not find parent client for request' ) ;
338
- return notFound ( ) ;
339
- }
340
-
341
313
const { requestId, promise } = localhostRequestStore . create ( ) ;
342
- for ( const parentClient of parentClients ) {
343
- parentClient . postMessage ( {
344
- channel : 'load-localhost' ,
345
- origin : origin ,
346
- id : requestId ,
347
- } ) ;
348
- }
349
-
350
- return promise . then ( resolveRedirect ) ;
351
- }
352
-
353
- /**
354
- * @param {Client } client
355
- * @returns {string | null }
356
- */
357
- function getWebviewIdForClient ( client ) {
358
- const requesterClientUrl = new URL ( client . url ) ;
359
- return requesterClientUrl . searchParams . get ( 'id' ) ;
360
- }
361
314
362
- /**
363
- * @param {string } webviewId
364
- * @returns {Promise<Client[]> }
365
- */
366
- async function getOuterIframeClient ( webviewId ) {
367
- const allClients = await sw . clients . matchAll ( { includeUncontrolled : true } ) ;
368
- return allClients . filter ( client => {
369
- const clientUrl = new URL ( client . url ) ;
370
- const hasExpectedPathName = ( clientUrl . pathname === `${ rootPath } /` || clientUrl . pathname === `${ rootPath } /index.html` ) ;
371
- return hasExpectedPathName && clientUrl . searchParams . get ( 'id' ) === webviewId ;
315
+ vscodeMessageChannel . port1 . postMessage ( {
316
+ channel : 'load-localhost' ,
317
+ origin : origin ,
318
+ id : requestId ,
372
319
} ) ;
320
+
321
+ return promise . then ( resolveRedirect ) ;
373
322
}
0 commit comments