@codingame/monaco-vscode-view-common-service-override 17.2.0 → 18.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/index.js +2 -2
  2. package/package.json +43 -42
  3. package/service-override/vs/workbench/contrib/webview/browser/pre/service-worker.js +328 -444
  4. package/vscode/src/vs/workbench/api/browser/viewsExtensionPoint.js +59 -59
  5. package/vscode/src/vs/workbench/browser/actions/listCommands.js +3 -3
  6. package/vscode/src/vs/workbench/browser/actions/navigationActions.js +6 -6
  7. package/vscode/src/vs/workbench/browser/parts/editor/editor.contribution.js +170 -167
  8. package/vscode/src/vs/workbench/browser/parts/editor/editorConfiguration.js +10 -9
  9. package/vscode/src/vs/workbench/contrib/callHierarchy/browser/callHierarchy.contribution.js +12 -12
  10. package/vscode/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyPeek.js +5 -5
  11. package/vscode/src/vs/workbench/contrib/callHierarchy/browser/callHierarchyTree.js +3 -3
  12. package/vscode/src/vs/workbench/contrib/customEditor/browser/customEditor.contribution.js +1 -1
  13. package/vscode/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.d.ts +1 -1
  14. package/vscode/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.js +2 -2
  15. package/vscode/src/vs/workbench/contrib/customEditor/common/contributedCustomEditors.js +2 -2
  16. package/vscode/src/vs/workbench/contrib/customEditor/common/customEditor.js +1 -1
  17. package/vscode/src/vs/workbench/contrib/customEditor/common/extensionPoint.js +12 -12
  18. package/vscode/src/vs/workbench/contrib/languageStatus/browser/languageStatus.js +7 -7
  19. package/vscode/src/vs/workbench/contrib/limitIndicator/browser/limitIndicator.contribution.js +8 -8
  20. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/commands/commands.js +30 -30
  21. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/commands/devCommands.js +14 -14
  22. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/mergeEditor.contribution.js +4 -4
  23. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/mergeEditorAccessibilityHelp.js +5 -5
  24. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/colors.js +13 -13
  25. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editorGutter.d.ts +3 -3
  26. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editorGutter.js +8 -9
  27. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/baseCodeEditorView.js +5 -5
  28. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/codeEditorView.js +3 -3
  29. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView.d.ts +2 -2
  30. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/inputCodeEditorView.js +15 -14
  31. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/editors/resultCodeEditorView.js +10 -10
  32. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/lineAlignment.js +3 -3
  33. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.d.ts +1 -1
  34. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.js +5 -4
  35. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/scrollSynchronizer.js +3 -3
  36. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/viewModel.d.ts +5 -5
  37. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/viewModel.js +7 -9
  38. package/vscode/src/vs/workbench/contrib/mergeEditor/browser/view/viewZones.js +3 -3
  39. package/vscode/src/vs/workbench/contrib/preferences/browser/keyboardLayoutPicker.js +13 -13
  40. package/vscode/src/vs/workbench/contrib/sash/browser/sash.contribution.js +2 -2
  41. package/vscode/src/vs/workbench/contrib/typeHierarchy/browser/typeHierarchy.contribution.js +10 -10
  42. package/vscode/src/vs/workbench/contrib/typeHierarchy/browser/typeHierarchyPeek.js +5 -5
  43. package/vscode/src/vs/workbench/contrib/typeHierarchy/browser/typeHierarchyTree.js +3 -3
  44. package/vscode/src/vs/workbench/contrib/webview/browser/overlayWebview.d.ts +1 -1
  45. package/vscode/src/vs/workbench/contrib/webview/browser/overlayWebview.js +1 -1
  46. package/vscode/src/vs/workbench/contrib/webview/browser/themeing.d.ts +2 -2
  47. package/vscode/src/vs/workbench/contrib/webview/browser/themeing.js +1 -1
  48. package/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.d.ts +1 -1
  49. package/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.js +2 -2
  50. package/vscode/src/vs/workbench/contrib/webview/browser/webviewFindWidget.js +1 -1
  51. package/vscode/src/vs/workbench/contrib/webview/browser/webviewService.d.ts +1 -1
  52. package/vscode/src/vs/workbench/contrib/webviewPanel/browser/webviewCommands.js +7 -7
  53. package/vscode/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.d.ts +2 -2
  54. package/vscode/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.js +1 -1
  55. package/vscode/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.js +3 -3
  56. package/vscode/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.d.ts +1 -1
  57. package/vscode/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.js +5 -5
  58. package/vscode/src/vs/workbench/contrib/webviewView/browser/webviewViewService.d.ts +1 -1
  59. package/vscode/src/vs/workbench/services/editor/browser/editorPaneService.js +1 -1
  60. package/vscode/src/vs/workbench/services/editor/browser/editorResolverService.js +15 -11
  61. package/vscode/src/vs/workbench/services/history/browser/historyService.js +10 -10
  62. package/vscode/src/vs/workbench/services/progress/browser/progressService.js +11 -11
  63. package/vscode/src/vs/workbench/services/untitled/common/untitledTextEditorHandler.d.ts +2 -2
  64. package/vscode/src/vs/workbench/services/untitled/common/untitledTextEditorHandler.js +2 -2
  65. package/vscode/src/vs/workbench/services/views/browser/viewDescriptorService.js +9 -9
  66. package/vscode/src/vs/workbench/services/views/common/viewContainerModel.js +4 -4
@@ -1,487 +1,371 @@
1
+ "use strict";
1
2
  /*---------------------------------------------------------------------------------------------
2
3
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
4
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
5
  *--------------------------------------------------------------------------------------------*/
5
- // @ts-check
6
-
7
6
  /// <reference lib="webworker" />
8
-
9
- const sw = /** @type {ServiceWorkerGlobalScope} */ (/** @type {any} */ (self));
10
-
7
+ const sw = self;
11
8
  const VERSION = 4;
12
-
13
9
  const resourceCacheName = `vscode-resource-cache-${VERSION}`;
14
-
15
10
  const rootPath = sw.location.pathname.replace(/\/service-worker.js$/, '');
16
-
17
11
  const searchParams = new URL(location.toString()).searchParams;
18
-
19
12
  const remoteAuthority = searchParams.get('remoteAuthority');
20
-
21
- const ID = searchParams.get('id');
22
-
13
+ let outerIframeMessagePort;
23
14
  /**
24
15
  * Origin used for resources
25
16
  */
26
17
  const resourceBaseAuthority = searchParams.get('vscode-resource-base-authority');
27
-
28
18
  const resolveTimeout = 30_000;
29
-
30
- /**
31
- * @template T
32
- * @typedef {{ status: 'ok'; value: T } | { status: 'timeout' }} RequestStoreResult
33
- */
34
-
35
- /**
36
- * @template T
37
- * @typedef {{
38
- * resolve: (x: RequestStoreResult<T>) => void,
39
- * promise: Promise<RequestStoreResult<T>>
40
- * }} RequestStoreEntry
41
- */
42
-
43
- /**
44
- * Caches
45
- * @template T
46
- */
47
19
  class RequestStore {
48
- constructor() {
49
- /** @type {Map<number, RequestStoreEntry<T>>} */
50
- this.map = new Map();
51
-
52
- this.requestPool = 0;
53
- }
54
-
55
- /**
56
- * @returns {{ requestId: number, promise: Promise<RequestStoreResult<T>> }}
57
- */
58
- create() {
59
- const requestId = ++this.requestPool;
60
-
61
- /** @type {undefined | ((x: RequestStoreResult<T>) => void)} */
62
- let resolve;
63
-
64
- /** @type {Promise<RequestStoreResult<T>>} */
65
- const promise = new Promise(r => resolve = r);
66
-
67
- /** @type {RequestStoreEntry<T>} */
68
- const entry = { resolve: /** @type {(x: RequestStoreResult<T>) => void} */ (resolve), promise };
69
-
70
- this.map.set(requestId, entry);
71
-
72
- const dispose = () => {
73
- clearTimeout(timeout);
74
- const existingEntry = this.map.get(requestId);
75
- if (existingEntry === entry) {
76
- existingEntry.resolve({ status: 'timeout' });
77
- this.map.delete(requestId);
78
- return;
79
- }
80
- };
81
- const timeout = setTimeout(dispose, resolveTimeout);
82
- return { requestId, promise };
83
- }
84
-
85
- /**
86
- * @param {number} requestId
87
- * @param {T} result
88
- * @return {boolean}
89
- */
90
- resolve(requestId, result) {
91
- const entry = this.map.get(requestId);
92
- if (!entry) {
93
- return false;
94
- }
95
- entry.resolve({ status: 'ok', value: result });
96
- this.map.delete(requestId);
97
- return true;
98
- }
20
+ constructor() {
21
+ this.map = new Map();
22
+ this.requestPool = 0;
23
+ }
24
+ create() {
25
+ const requestId = ++this.requestPool;
26
+ let resolve;
27
+ const promise = new Promise(r => resolve = r);
28
+ const entry = { resolve: resolve, promise };
29
+ this.map.set(requestId, entry);
30
+ const dispose = () => {
31
+ clearTimeout(timeout);
32
+ const existingEntry = this.map.get(requestId);
33
+ if (existingEntry === entry) {
34
+ existingEntry.resolve({ status: 'timeout' });
35
+ this.map.delete(requestId);
36
+ }
37
+ };
38
+ const timeout = setTimeout(dispose, resolveTimeout);
39
+ return { requestId, promise };
40
+ }
41
+ resolve(requestId, result) {
42
+ const entry = this.map.get(requestId);
43
+ if (!entry) {
44
+ return false;
45
+ }
46
+ entry.resolve({ status: 'ok', value: result });
47
+ this.map.delete(requestId);
48
+ return true;
49
+ }
99
50
  }
100
-
101
- /**
102
- * @typedef {{ readonly status: 200; id: number; path: string; mime: string; data: Uint8Array; etag: string | undefined; mtime: number | undefined; }
103
- * | { readonly status: 304; id: number; path: string; mime: string; mtime: number | undefined }
104
- * | { readonly status: 401; id: number; path: string }
105
- * | { readonly status: 404; id: number; path: string }} ResourceResponse
106
- */
107
-
108
51
  /**
109
52
  * Map of requested paths to responses.
110
- *
111
- * @type {RequestStore<ResourceResponse>}
112
53
  */
113
54
  const resourceRequestStore = new RequestStore();
114
-
115
55
  /**
116
56
  * Map of requested localhost origins to optional redirects.
117
- *
118
- * @type {RequestStore<string | undefined>}
119
57
  */
120
58
  const localhostRequestStore = new RequestStore();
121
-
122
- const unauthorized = () =>
123
- new Response('Unauthorized', { status: 401, });
124
-
125
- const notFound = () =>
126
- new Response('Not Found', { status: 404, });
127
-
128
- const methodNotAllowed = () =>
129
- new Response('Method Not Allowed', { status: 405, });
130
-
131
- const requestTimeout = () =>
132
- new Response('Request Timeout', { status: 408, });
133
-
59
+ const unauthorized = () => new Response('Unauthorized', { status: 401, });
60
+ const notFound = () => new Response('Not Found', { status: 404, });
61
+ const methodNotAllowed = () => new Response('Method Not Allowed', { status: 405, });
62
+ const requestTimeout = () => new Response('Request Timeout', { status: 408, });
134
63
  sw.addEventListener('message', async (event) => {
135
- switch (event.data.channel) {
136
- case 'version': {
137
- const source = /** @type {Client} */ (event.source);
138
- sw.clients.get(source.id).then(client => {
139
- if (client) {
140
- client.postMessage({
141
- channel: 'version',
142
- version: VERSION
143
- });
144
- }
145
- });
146
- return;
147
- }
148
- case 'did-load-resource': {
149
- /** @type {ResourceResponse} */
150
- const response = event.data.data;
151
- if (!resourceRequestStore.resolve(response.id, response)) {
152
- console.log('Could not resolve unknown resource', response.path);
153
- }
154
- return;
155
- }
156
- case 'did-load-localhost': {
157
- const data = event.data.data;
158
- if (!localhostRequestStore.resolve(data.id, data.location)) {
159
- console.log('Could not resolve unknown localhost', data.origin);
160
- }
161
- return;
162
- }
163
- default: {
164
- console.log('Unknown message');
165
- return;
166
- }
167
- }
64
+ if (!event.source) {
65
+ return;
66
+ }
67
+ const source = event.source;
68
+ switch (event.data.channel) {
69
+ case 'version': {
70
+ outerIframeMessagePort = event.ports[0];
71
+ sw.clients.get(source.id).then(client => {
72
+ if (client) {
73
+ client.postMessage({
74
+ channel: 'version',
75
+ version: VERSION
76
+ });
77
+ }
78
+ });
79
+ return;
80
+ }
81
+ case 'did-load-resource': {
82
+ const response = event.data.data;
83
+ if (!resourceRequestStore.resolve(response.id, response)) {
84
+ console.log('Could not resolve unknown resource', response.path);
85
+ }
86
+ return;
87
+ }
88
+ case 'did-load-localhost': {
89
+ const data = event.data.data;
90
+ if (!localhostRequestStore.resolve(data.id, data.location)) {
91
+ console.log('Could not resolve unknown localhost', data.origin);
92
+ }
93
+ return;
94
+ }
95
+ default: {
96
+ console.log('Unknown message');
97
+ return;
98
+ }
99
+ }
168
100
  });
169
-
170
101
  sw.addEventListener('fetch', (event) => {
171
- const requestUrl = new URL(event.request.url);
172
- if (typeof resourceBaseAuthority === 'string' && requestUrl.protocol === 'https:' && requestUrl.hostname.endsWith('.' + resourceBaseAuthority)) {
173
- switch (event.request.method) {
174
- case 'GET':
175
- case 'HEAD': {
176
- const firstHostSegment = requestUrl.hostname.slice(0, requestUrl.hostname.length - (resourceBaseAuthority.length + 1));
177
- const scheme = firstHostSegment.split('+', 1)[0];
178
- const authority = firstHostSegment.slice(scheme.length + 1); // may be empty
179
- return event.respondWith(processResourceRequest(event, {
180
- scheme,
181
- authority,
182
- path: requestUrl.pathname,
183
- query: requestUrl.search.replace(/^\?/, ''),
184
- }));
185
- }
186
- default: {
187
- return event.respondWith(methodNotAllowed());
188
- }
189
- }
190
- }
191
-
192
- // If we're making a request against the remote authority, we want to go
193
- // through VS Code itself so that we are authenticated properly. If the
194
- // service worker is hosted on the same origin we will have cookies and
195
- // authentication will not be an issue.
196
- if (requestUrl.origin !== sw.origin && requestUrl.host === remoteAuthority) {
197
- switch (event.request.method) {
198
- case 'GET':
199
- case 'HEAD': {
200
- return event.respondWith(processResourceRequest(event, {
201
- path: requestUrl.pathname,
202
- scheme: requestUrl.protocol.slice(0, requestUrl.protocol.length - 1),
203
- authority: requestUrl.host,
204
- query: requestUrl.search.replace(/^\?/, ''),
205
- }));
206
- }
207
- default: {
208
- return event.respondWith(methodNotAllowed());
209
- }
210
- }
211
- }
212
-
213
- // See if it's a localhost request
214
- if (requestUrl.origin !== sw.origin && requestUrl.host.match(/^(localhost|127.0.0.1|0.0.0.0):(\d+)$/)) {
215
- return event.respondWith(processLocalhostRequest(event, requestUrl));
216
- }
102
+ const requestUrl = new URL(event.request.url);
103
+ if (typeof resourceBaseAuthority === 'string' && requestUrl.protocol === 'https:' && requestUrl.hostname.endsWith('.' + resourceBaseAuthority)) {
104
+ switch (event.request.method) {
105
+ case 'GET':
106
+ case 'HEAD': {
107
+ const firstHostSegment = requestUrl.hostname.slice(0, requestUrl.hostname.length - (resourceBaseAuthority.length + 1));
108
+ const scheme = firstHostSegment.split('+', 1)[0];
109
+ const authority = firstHostSegment.slice(scheme.length + 1); // may be empty
110
+ return event.respondWith(processResourceRequest(event, {
111
+ scheme,
112
+ authority,
113
+ path: requestUrl.pathname,
114
+ query: requestUrl.search.replace(/^\?/, ''),
115
+ }));
116
+ }
117
+ default: {
118
+ return event.respondWith(methodNotAllowed());
119
+ }
120
+ }
121
+ }
122
+ // If we're making a request against the remote authority, we want to go
123
+ // through VS Code itself so that we are authenticated properly. If the
124
+ // service worker is hosted on the same origin we will have cookies and
125
+ // authentication will not be an issue.
126
+ if (requestUrl.origin !== sw.origin && requestUrl.host === remoteAuthority) {
127
+ switch (event.request.method) {
128
+ case 'GET':
129
+ case 'HEAD': {
130
+ return event.respondWith(processResourceRequest(event, {
131
+ path: requestUrl.pathname,
132
+ scheme: requestUrl.protocol.slice(0, requestUrl.protocol.length - 1),
133
+ authority: requestUrl.host,
134
+ query: requestUrl.search.replace(/^\?/, ''),
135
+ }));
136
+ }
137
+ default: {
138
+ return event.respondWith(methodNotAllowed());
139
+ }
140
+ }
141
+ }
142
+ // See if it's a localhost request
143
+ if (requestUrl.origin !== sw.origin && requestUrl.host.match(/^(localhost|127.0.0.1|0.0.0.0):(\d+)$/)) {
144
+ return event.respondWith(processLocalhostRequest(event, requestUrl));
145
+ }
217
146
  });
218
-
219
147
  sw.addEventListener('install', (event) => {
220
- event.waitUntil(sw.skipWaiting()); // Activate worker immediately
148
+ event.waitUntil(sw.skipWaiting()); // Activate worker immediately
221
149
  });
222
-
223
150
  sw.addEventListener('activate', (event) => {
224
- event.waitUntil(sw.clients.claim()); // Become available to all pages
151
+ event.waitUntil(sw.clients.claim()); // Become available to all pages
225
152
  });
226
-
227
- /**
228
- * @param {FetchEvent} event
229
- * @param {{
230
- * scheme: string;
231
- * authority: string;
232
- * path: string;
233
- * query: string;
234
- * }} requestUrlComponents
235
- */
236
153
  async function processResourceRequest(event, requestUrlComponents) {
237
- const client = await sw.clients.get(event.clientId);
238
- let webviewId;
239
- if (!client) {
240
- const workerClient = await getWorkerClientForId(event.clientId);
241
- if (!workerClient) {
242
- console.error('Could not find inner client for request');
243
- return notFound();
244
- } else {
245
- webviewId = getWebviewIdForClient(workerClient);
246
- }
247
- } else {
248
- webviewId = getWebviewIdForClient(client);
249
- }
250
-
251
- if (!webviewId) {
252
- console.error('Could not resolve webview id');
253
- return notFound();
254
- }
255
-
256
- const shouldTryCaching = (event.request.method === 'GET');
257
-
258
- /**
259
- * @param {RequestStoreResult<ResourceResponse>} result
260
- * @param {Response | undefined} cachedResponse
261
- */
262
- const resolveResourceEntry = (result, cachedResponse) => {
263
- if (result.status === 'timeout') {
264
- return requestTimeout();
265
- }
266
-
267
- const entry = result.value;
268
- if (entry.status === 304) { // Not modified
269
- if (cachedResponse) {
270
- return cachedResponse.clone();
271
- } else {
272
- throw new Error('No cache found');
273
- }
274
- }
275
-
276
- if (entry.status === 401) {
277
- return unauthorized();
278
- }
279
-
280
- if (entry.status !== 200) {
281
- return notFound();
282
- }
283
-
284
- /** @type {Record<string, string>} */
285
- const commonHeaders = {
286
- 'Access-Control-Allow-Origin': '*',
287
- };
288
-
289
- const byteLength = entry.data.byteLength;
290
-
291
- const range = event.request.headers.get('range');
292
- if (range) {
293
- // To support seeking for videos, we need to handle range requests
294
- const bytes = range.match(/^bytes\=(\d+)\-(\d+)?$/g);
295
- if (bytes) {
296
- // TODO: Right now we are always reading the full file content. This is a bad idea
297
- // for large video files :)
298
-
299
- const start = Number(bytes[1]);
300
- const end = Number(bytes[2]) || byteLength - 1;
301
- return new Response(entry.data.slice(start, end + 1), {
302
- status: 206,
303
- headers: {
304
- ...commonHeaders,
305
- 'Content-range': `bytes 0-${end}/${byteLength}`,
306
- }
307
- });
308
- } else {
309
- // We don't understand the requested bytes
310
- return new Response(null, {
311
- status: 416,
312
- headers: {
313
- ...commonHeaders,
314
- 'Content-range': `*/${byteLength}`
315
- }
316
- });
317
- }
318
- }
319
-
320
- /** @type {Record<string, string>} */
321
- const headers = {
322
- ...commonHeaders,
323
- 'Content-Type': entry.mime,
324
- 'Content-Length': byteLength.toString(),
325
- };
326
-
327
- if (entry.etag) {
328
- headers['ETag'] = entry.etag;
329
- headers['Cache-Control'] = 'no-cache';
330
- }
331
- if (entry.mtime) {
332
- headers['Last-Modified'] = new Date(entry.mtime).toUTCString();
333
- }
334
-
335
- // support COI requests, see network.ts#COI.getHeadersFromQuery(...)
336
- const coiRequest = new URL(event.request.url).searchParams.get('vscode-coi');
337
- if (coiRequest === '3') {
338
- headers['Cross-Origin-Opener-Policy'] = 'same-origin';
339
- headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
340
- } else if (coiRequest === '2') {
341
- headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
342
- } else if (coiRequest === '1') {
343
- headers['Cross-Origin-Opener-Policy'] = 'same-origin';
344
- }
345
-
346
- const response = new Response(entry.data, {
347
- status: 200,
348
- headers
349
- });
350
-
351
- if (shouldTryCaching && entry.etag) {
352
- caches.open(resourceCacheName).then(cache => {
353
- return cache.put(event.request, response);
354
- });
355
- }
356
- return response.clone();
357
- };
358
-
359
- const parentClients = await getOuterIframeClient(webviewId);
360
- if (!parentClients.length) {
361
- console.log('Could not find parent client for request');
362
- return notFound();
363
- }
364
-
365
- /** @type {Response | undefined} */
366
- let cached;
367
- if (shouldTryCaching) {
368
- const cache = await caches.open(resourceCacheName);
369
- cached = await cache.match(event.request);
370
- }
371
-
372
- const { requestId, promise } = resourceRequestStore.create();
373
-
374
- for (const parentClient of parentClients) {
375
- parentClient.postMessage({
376
- channel: 'load-resource',
377
- id: requestId,
378
- scheme: requestUrlComponents.scheme,
379
- authority: requestUrlComponents.authority,
380
- path: requestUrlComponents.path,
381
- query: requestUrlComponents.query,
382
- ifNoneMatch: cached?.headers.get('ETag'),
383
- });
384
- }
385
-
386
- return promise.then(entry => resolveResourceEntry(entry, cached));
154
+ let client = await sw.clients.get(event.clientId);
155
+ if (!client) {
156
+ client = await getWorkerClientForId(event.clientId);
157
+ if (!client) {
158
+ console.error('Could not find inner client for request');
159
+ return notFound();
160
+ }
161
+ }
162
+ const webviewId = getWebviewIdForClient(client);
163
+ // Refs https://github.com/microsoft/vscode/issues/244143
164
+ // With PlzDedicatedWorker, worker subresources and blob wokers
165
+ // will use clients different from the window client.
166
+ // Since we cannot different a worker main resource from a worker subresource
167
+ // we will use message channel to the outer iframe provided at the time
168
+ // of service worker controller version initialization.
169
+ if (!webviewId && client.type !== 'worker' && client.type !== 'sharedworker') {
170
+ console.error('Could not resolve webview id');
171
+ return notFound();
172
+ }
173
+ const shouldTryCaching = (event.request.method === 'GET');
174
+ const resolveResourceEntry = (result, cachedResponse) => {
175
+ if (result.status === 'timeout') {
176
+ return requestTimeout();
177
+ }
178
+ const entry = result.value;
179
+ if (entry.status === 304) { // Not modified
180
+ if (cachedResponse) {
181
+ return cachedResponse.clone();
182
+ }
183
+ else {
184
+ throw new Error('No cache found');
185
+ }
186
+ }
187
+ if (entry.status === 401) {
188
+ return unauthorized();
189
+ }
190
+ if (entry.status !== 200) {
191
+ return notFound();
192
+ }
193
+ const commonHeaders = {
194
+ 'Access-Control-Allow-Origin': '*',
195
+ };
196
+ const byteLength = entry.data.byteLength;
197
+ const range = event.request.headers.get('range');
198
+ if (range) {
199
+ // To support seeking for videos, we need to handle range requests
200
+ const bytes = range.match(/^bytes\=(\d+)\-(\d+)?$/g);
201
+ if (bytes) {
202
+ // TODO: Right now we are always reading the full file content. This is a bad idea
203
+ // for large video files :)
204
+ const start = Number(bytes[1]);
205
+ const end = Number(bytes[2]) || byteLength - 1;
206
+ return new Response(entry.data.slice(start, end + 1), {
207
+ status: 206,
208
+ headers: {
209
+ ...commonHeaders,
210
+ 'Content-range': `bytes 0-${end}/${byteLength}`,
211
+ }
212
+ });
213
+ }
214
+ else {
215
+ // We don't understand the requested bytes
216
+ return new Response(null, {
217
+ status: 416,
218
+ headers: {
219
+ ...commonHeaders,
220
+ 'Content-range': `*/${byteLength}`
221
+ }
222
+ });
223
+ }
224
+ }
225
+ const headers = {
226
+ ...commonHeaders,
227
+ 'Content-Type': entry.mime,
228
+ 'Content-Length': byteLength.toString(),
229
+ };
230
+ if (entry.etag) {
231
+ headers['ETag'] = entry.etag;
232
+ headers['Cache-Control'] = 'no-cache';
233
+ }
234
+ if (entry.mtime) {
235
+ headers['Last-Modified'] = new Date(entry.mtime).toUTCString();
236
+ }
237
+ // support COI requests, see network.ts#COI.getHeadersFromQuery(...)
238
+ const coiRequest = new URL(event.request.url).searchParams.get('vscode-coi');
239
+ if (coiRequest === '3') {
240
+ headers['Cross-Origin-Opener-Policy'] = 'same-origin';
241
+ headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
242
+ }
243
+ else if (coiRequest === '2') {
244
+ headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
245
+ }
246
+ else if (coiRequest === '1') {
247
+ headers['Cross-Origin-Opener-Policy'] = 'same-origin';
248
+ }
249
+ const response = new Response(entry.data, {
250
+ status: 200,
251
+ headers
252
+ });
253
+ if (shouldTryCaching && entry.etag) {
254
+ caches.open(resourceCacheName).then(cache => {
255
+ return cache.put(event.request, response);
256
+ });
257
+ }
258
+ return response.clone();
259
+ };
260
+ let cached;
261
+ if (shouldTryCaching) {
262
+ const cache = await caches.open(resourceCacheName);
263
+ cached = await cache.match(event.request);
264
+ }
265
+ const { requestId, promise } = resourceRequestStore.create();
266
+ if (webviewId) {
267
+ const parentClients = await getOuterIframeClient(webviewId);
268
+ if (!parentClients.length) {
269
+ console.log('Could not find parent client for request');
270
+ return notFound();
271
+ }
272
+ for (const parentClient of parentClients) {
273
+ parentClient.postMessage({
274
+ channel: 'load-resource',
275
+ id: requestId,
276
+ scheme: requestUrlComponents.scheme,
277
+ authority: requestUrlComponents.authority,
278
+ path: requestUrlComponents.path,
279
+ query: requestUrlComponents.query,
280
+ ifNoneMatch: cached?.headers.get('ETag'),
281
+ });
282
+ }
283
+ }
284
+ else if (client.type === 'worker' || client.type === 'sharedworker') {
285
+ outerIframeMessagePort?.postMessage({
286
+ channel: 'load-resource',
287
+ id: requestId,
288
+ scheme: requestUrlComponents.scheme,
289
+ authority: requestUrlComponents.authority,
290
+ path: requestUrlComponents.path,
291
+ query: requestUrlComponents.query,
292
+ ifNoneMatch: cached?.headers.get('ETag'),
293
+ });
294
+ }
295
+ return promise.then(entry => resolveResourceEntry(entry, cached));
387
296
  }
388
-
389
- /**
390
- * @param {FetchEvent} event
391
- * @param {URL} requestUrl
392
- * @return {Promise<Response>}
393
- */
394
297
  async function processLocalhostRequest(event, requestUrl) {
395
- const client = await sw.clients.get(event.clientId);
396
- if (!client) {
397
- // This is expected when requesting resources on other localhost ports
398
- // that are not spawned by vs code
399
- return fetch(event.request);
400
- }
401
- const webviewId = getWebviewIdForClient(client);
402
- if (!webviewId) {
403
- console.error('Could not resolve webview id');
404
- return fetch(event.request);
405
- }
406
-
407
- const origin = requestUrl.origin;
408
-
409
- /**
410
- * @param {RequestStoreResult<string | undefined>} result
411
- * @return {Promise<Response>}
412
- */
413
- const resolveRedirect = async (result) => {
414
- if (result.status !== 'ok' || !result.value) {
415
- return fetch(event.request);
416
- }
417
-
418
- const redirectOrigin = result.value;
419
- const location = event.request.url.replace(new RegExp(`^${requestUrl.origin}(/|$)`), `${redirectOrigin}$1`);
420
- return new Response(null, {
421
- status: 302,
422
- headers: {
423
- Location: location
424
- }
425
- });
426
- };
427
-
428
- const parentClients = await getOuterIframeClient(webviewId);
429
- if (!parentClients.length) {
430
- console.log('Could not find parent client for request');
431
- return notFound();
432
- }
433
-
434
- const { requestId, promise } = localhostRequestStore.create();
435
- for (const parentClient of parentClients) {
436
- parentClient.postMessage({
437
- channel: 'load-localhost',
438
- origin: origin,
439
- id: requestId,
440
- });
441
- }
442
-
443
- return promise.then(resolveRedirect);
298
+ const client = await sw.clients.get(event.clientId);
299
+ if (!client) {
300
+ // This is expected when requesting resources on other localhost ports
301
+ // that are not spawned by vs code
302
+ return fetch(event.request);
303
+ }
304
+ const webviewId = getWebviewIdForClient(client);
305
+ // Refs https://github.com/microsoft/vscode/issues/244143
306
+ // With PlzDedicatedWorker, worker subresources and blob wokers
307
+ // will use clients different from the window client.
308
+ // Since we cannot different a worker main resource from a worker subresource
309
+ // we will use message channel to the outer iframe provided at the time
310
+ // of service worker controller version initialization.
311
+ if (!webviewId && client.type !== 'worker' && client.type !== 'sharedworker') {
312
+ console.error('Could not resolve webview id');
313
+ return fetch(event.request);
314
+ }
315
+ const origin = requestUrl.origin;
316
+ const resolveRedirect = async (result) => {
317
+ if (result.status !== 'ok' || !result.value) {
318
+ return fetch(event.request);
319
+ }
320
+ const redirectOrigin = result.value;
321
+ const location = event.request.url.replace(new RegExp(`^${requestUrl.origin}(/|$)`), `${redirectOrigin}$1`);
322
+ return new Response(null, {
323
+ status: 302,
324
+ headers: {
325
+ Location: location
326
+ }
327
+ });
328
+ };
329
+ const { requestId, promise } = localhostRequestStore.create();
330
+ if (webviewId) {
331
+ const parentClients = await getOuterIframeClient(webviewId);
332
+ if (!parentClients.length) {
333
+ console.log('Could not find parent client for request');
334
+ return notFound();
335
+ }
336
+ for (const parentClient of parentClients) {
337
+ parentClient.postMessage({
338
+ channel: 'load-localhost',
339
+ origin: origin,
340
+ id: requestId,
341
+ });
342
+ }
343
+ }
344
+ else if (client.type === 'worker' || client.type === 'sharedworker') {
345
+ outerIframeMessagePort?.postMessage({
346
+ channel: 'load-localhost',
347
+ origin: origin,
348
+ id: requestId,
349
+ });
350
+ }
351
+ return promise.then(resolveRedirect);
444
352
  }
445
-
446
- /**
447
- * @param {Client} client
448
- * @returns {string | null}
449
- */
450
353
  function getWebviewIdForClient(client) {
451
- // Refs https://github.com/microsoft/vscode/issues/244143
452
- // With PlzDedicatedWorker, worker subresources and blob wokers
453
- // will use clients different from the window client.
454
- // Since we cannot different a worker main resource from a worker subresource
455
- // we will use the global webview ID passed in at the time of
456
- // service worker registration.
457
- if (client.type === 'worker' || client.type === 'sharedworker') {
458
- return ID;
459
- }
460
- const requesterClientUrl = new URL(client.url);
461
- return requesterClientUrl.searchParams.get('id');
354
+ const requesterClientUrl = new URL(client.url);
355
+ return requesterClientUrl.searchParams.get('id');
462
356
  }
463
-
464
- /**
465
- * @param {string} webviewId
466
- * @returns {Promise<Client[]>}
467
- */
468
357
  async function getOuterIframeClient(webviewId) {
469
- const allClients = await sw.clients.matchAll({ includeUncontrolled: true });
470
- return allClients.filter(client => {
471
- const clientUrl = new URL(client.url);
472
- return clientUrl.searchParams.get('id') === webviewId;
473
- });
358
+ const allClients = await sw.clients.matchAll({ includeUncontrolled: true });
359
+ return allClients.filter(client => {
360
+ const clientUrl = new URL(client.url);
361
+ return clientUrl.searchParams.get('id') === webviewId;
362
+ });
474
363
  }
475
-
476
- /**
477
- * @param {string} clientId
478
- * @returns {Promise<Client|undefined>}
479
- */
480
364
  async function getWorkerClientForId(clientId) {
481
- const allDedicatedWorkerClients = await sw.clients.matchAll({ type: 'worker' });
482
- const allSharedWorkerClients = await sw.clients.matchAll({ type: 'sharedworker' });
483
- const allWorkerClients = [...allDedicatedWorkerClients, ...allSharedWorkerClients];
484
- return allWorkerClients.find(client => {
485
- return client.id === clientId;
486
- });
365
+ const allDedicatedWorkerClients = await sw.clients.matchAll({ type: 'worker' });
366
+ const allSharedWorkerClients = await sw.clients.matchAll({ type: 'sharedworker' });
367
+ const allWorkerClients = [...allDedicatedWorkerClients, ...allSharedWorkerClients];
368
+ return allWorkerClients.find(client => {
369
+ return client.id === clientId;
370
+ });
487
371
  }