src/vs/platform/sharedProcess/electron-browser/sharedProcessWorkerService.ts/SharedProcessWorkerService/createWorker
class SharedProcessWorkerService:	async createWorker(configuration: ISharedProcessWorkerConfiguration): Promise<IOnDidTerminateSharedProcessWorkerProcess> {
		const workerLogId = `window: ${configuration.reply.windowId}, moduleId: ${configuration.process.moduleId}`;
		this.logService.trace(`SharedProcess: createWorker (${workerLogId})`);

		// Ensure to dispose any existing process for config
		const configurationHash = hash(configuration);
		if (this.processeDisposables.has(configurationHash)) {
			this.logService.warn(`SharedProcess: createWorker found an existing worker that will be terminated (${workerLogId})`);

			this.doDisposeWorker(configuration);
		}

		const cts = new CancellationTokenSource();

		let worker: SharedProcessWebWorker | undefined = undefined;
		let windowPort: MessagePort | undefined = undefined;
		let workerPort: MessagePort | undefined = undefined;

		// Store as process for termination support
		this.processeDisposables.set(configurationHash, (reason?: ISharedProcessWorkerProcessExit) => {

			// Signal to token
			cts.dispose(true);

			// Terminate process
			worker?.terminate(configuration, CancellationToken.None /* we want to deliver this message */);

			// Close ports
			windowPort?.close();
			workerPort?.close();

			// Remove from processes
			this.processeDisposables.delete(configurationHash);

			// Release process resolvers if any
			const processResolver = this.processResolvers.get(configurationHash);
			if (processResolver) {
				this.processResolvers.delete(configurationHash);
				processResolver({ reason });
			}
		});

		// Acquire a worker for the configuration
		worker = await this.getOrCreateWebWorker(configuration);

		// Keep a promise that will resolve in the future when the
		// underlying process terminates.
		const onDidTerminate = new Promise<IOnDidTerminateSharedProcessWorkerProcess>(resolve => {
			this.processResolvers.set(configurationHash, resolve);
		});

		if (cts.token.isCancellationRequested) {
			return onDidTerminate;
		}

		// Create a `MessageChannel` with 2 ports:
		// `windowPort`: send back to the requesting window
		// `workerPort`: send into a new worker to use
		const { port1, port2 } = new MessageChannel();
		windowPort = port1;
		workerPort = port2;

		// Spawn in worker and pass over port
		await worker.spawn(configuration, workerPort, cts.token);

		if (cts.token.isCancellationRequested) {
			return onDidTerminate;
		}

		// We cannot just send the `MessagePort` through our protocol back
		// because the port can only be sent via `postMessage`. So we need
		// to send it through the main process back to the window.
		this.logService.trace(`SharedProcess: createWorker sending message port back to window (${workerLogId})`);
		ipcRenderer.postMessage('vscode:relaySharedProcessWorkerMessageChannel', configuration, [windowPort]);

		return onDidTerminate;
	}