Skip to content

Commit

Permalink
start service worker when loading code, #75061
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Jul 11, 2019
1 parent 38aadec commit 7008b20
Showing 1 changed file with 60 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/

import { IFileService } from 'vs/platform/files/common/files';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions } from 'vs/workbench/common/contributions';
Expand All @@ -13,58 +12,78 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { isEqualOrParent } from 'vs/base/common/resources';
import { ILogService } from 'vs/platform/log/common/log';

class ResourceServiceWorker {
// load and start service worker as soon as this file
// is being loaded and later, when services are ready,
// claim this service worker so that messages can be
// replied to
const _serviceWorker = new class ServiceWorkerStarter {

private static _url = require.toUrl('./resourceServiceWorkerMain.js');

private _beforeReadyEvents: ExtendableMessageEvent[] = [];
private _messageHandler?: (event: ExtendableMessageEvent) => void;

constructor() {
navigator.serviceWorker.register(ServiceWorkerStarter._url, { scope: '/' }).then(reg => {
// console.debug('SW#reg', reg);
return navigator.serviceWorker.ready;
}).then(() => {
// console.debug('SW#init');
}).catch(err => {
console.error('SW#init', err);
});

const handleMessage = (event: ExtendableMessageEvent) => {
if (!this._messageHandler) {
this._beforeReadyEvents.push(event);
console.debug('SW#buffered', event.data);
} else {
this._messageHandler(event);
}
};

navigator.serviceWorker.addEventListener('message', e => handleMessage(e as ExtendableMessageEvent));
}

dispose(): void {
// when to dispose?
}

private readonly _disposables = new DisposableStore();
claim(handler: (event: ExtendableMessageEvent) => void): void {
this._messageHandler = handler;
this._beforeReadyEvents.forEach(this._messageHandler);
}
};

class ResourceServiceWorker {

constructor(
@IFileService private readonly _fileService: IFileService,
@IExtensionService private readonly _extensionService: IExtensionService,
@ILogService private readonly _logService: ILogService,
) {
this._initServiceWorker();
this._initFetchHandler();
_serviceWorker.claim(e => this._handleMessage(e));
}

dispose(): void {
this._disposables.dispose();
}
private _handleMessage(event: ExtendableMessageEvent): void {
this._logService.trace('SW#fetch', event.data.uri);

private _initServiceWorker(): void {
const url = require.toUrl('./resourceServiceWorkerMain.js');
navigator.serviceWorker.register(url, { scope: '/' }).then(reg => {
return navigator.serviceWorker.ready;
}).then(() => {
this._logService.trace('SW#init', navigator.serviceWorker.controller);
}).catch(err => {
this._logService.error('SW#init', err);
const uri = URI.revive(event.data.uri);
Promise.all([
this._fileService.readFile(uri),
this._isExtensionResource(uri)
]).then(([file, isExtensionResource]) => {
if (!event.source) {
return;
}
event.source.postMessage({
token: event.data.token,
data: file.value.buffer.buffer,
isExtensionResource
}, [file.value.buffer.buffer]);
});
}

private _initFetchHandler(): void {

const fetchListener: (this: ServiceWorkerContainer, ev: ExtendableMessageEvent) => void = event => {
this._logService.trace('SW#fetch', event.data.uri);

const uri = URI.revive(event.data.uri);
Promise.all([
this._fileService.readFile(uri),
this._isExtensionResource(uri)
]).then(([file, isExtensionResource]) => {
if (!event.source) {
return;
}
event.source.postMessage({
token: event.data.token,
data: file.value.buffer.buffer,
isExtensionResource
}, [file.value.buffer.buffer]);
});
};
navigator.serviceWorker.addEventListener('message', fetchListener);
this._disposables.add(toDisposable(() => navigator.serviceWorker.removeEventListener('message', fetchListener)));
}

private async _isExtensionResource(uri: URI): Promise<boolean> {
for (const ext of await this._extensionService.getExtensions()) {
if (isEqualOrParent(uri, ext.extensionLocation)) {
Expand All @@ -77,7 +96,7 @@ class ResourceServiceWorker {

Registry.as<IWorkbenchContributionsRegistry>(Extensions.Workbench).registerWorkbenchContribution(
ResourceServiceWorker,
LifecyclePhase.Starting
LifecyclePhase.Ready
);


0 comments on commit 7008b20

Please sign in to comment.