src/vs/workbench/services/lifecycle/browser/lifecycleService.ts/BrowserLifecycleService/doShutdown
class BrowserLifecycleService:	private doShutdown(vetoShutdown?: () => void): void {
		const logService = this.logService;

		// Optimistically trigger a UI state flush
		// without waiting for it. The browser does
		// not guarantee that this is being executed
		// but if a dialog opens, we have a chance
		// to succeed.
		this.storageService.flush(WillSaveStateReason.SHUTDOWN);

		let veto = false;

		function handleVeto(vetoResult: boolean | Promise<boolean>, id: string) {
			if (typeof vetoShutdown !== 'function') {
				return; // veto handling disabled
			}

			if (vetoResult instanceof Promise) {
				logService.error(`[lifecycle] Long running operations before shutdown are unsupported in the web (id: ${id})`);

				veto = true; // implicitly vetos since we cannot handle promises in web
			}

			if (vetoResult === true) {
				logService.info(`[lifecycle]: Unload was prevented (id: ${id})`);

				veto = true;
			}
		}

		// Before Shutdown
		this._onBeforeShutdown.fire({
			reason: ShutdownReason.QUIT,
			veto(value, id) {
				handleVeto(value, id);
			},
			finalVeto(valueFn, id) {
				handleVeto(valueFn(), id); // in browser, trigger instantly because we do not support async anyway
			}
		});

		// Veto: handle if provided
		if (veto && typeof vetoShutdown === 'function') {
			return vetoShutdown();
		}

		// No veto, continue to shutdown
		return this.onUnload();
	}