UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

297 lines (294 loc) 15.5 kB
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js'; import { addDisposableListener } from 'vscode/vscode/vs/base/browser/dom'; import { parentOriginHash } from 'vscode/vscode/vs/base/browser/iframe'; import { mainWindow } from 'vscode/vscode/vs/base/browser/window'; import { Barrier } from 'vscode/vscode/vs/base/common/async'; import { VSBuffer } from 'vscode/vscode/vs/base/common/buffer'; import { onUnexpectedError, canceled } from 'vscode/vscode/vs/base/common/errors'; import { Emitter, Event } from 'vscode/vscode/vs/base/common/event'; import { Disposable, toDisposable } from 'vscode/vscode/vs/base/common/lifecycle'; import { COI, FileAccess } from 'vscode/vscode/vs/base/common/network'; import { isWeb, Language, language } from 'vscode/vscode/vs/base/common/platform'; import { joinPath } from 'vscode/vscode/vs/base/common/resources'; import { URI } from 'vscode/vscode/vs/base/common/uri'; import { generateUuid } from 'vscode/vscode/vs/base/common/uuid'; import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label.service'; import { ILayoutService } from 'vscode/vscode/vs/platform/layout/browser/layoutService.service'; import { ILogService, ILoggerService } from 'vscode/vscode/vs/platform/log/common/log.service'; import { IProductService } from 'vscode/vscode/vs/platform/product/common/productService.service'; import { StorageScope, StorageTarget } from 'vscode/vscode/vs/platform/storage/common/storage'; import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage.service'; import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry.service'; import { isLoggingOnly } from 'vscode/vscode/vs/platform/telemetry/common/telemetryUtils'; import { IUserDataProfilesService } from 'vscode/vscode/vs/platform/userDataProfile/common/userDataProfile.service'; import { WorkbenchState } from 'vscode/vscode/vs/platform/workspace/common/workspace'; import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace.service'; import { IBrowserWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/browser/environmentService.service'; import { ExtensionHostExitCode, isMessageOfType, MessageType, createMessageOfType, UIKind } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionHostProtocol'; import { ExtensionHostStartup } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions'; let WebWorkerExtensionHost = class WebWorkerExtensionHost extends Disposable { constructor(runningLocation, startup, _initDataProvider, _telemetryService, _contextService, _labelService, _logService, _loggerService, _environmentService, _userDataProfilesService, _productService, _layoutService, _storageService) { super(); this.runningLocation = runningLocation; this.startup = startup; this._initDataProvider = _initDataProvider; this._telemetryService = _telemetryService; this._contextService = _contextService; this._labelService = _labelService; this._logService = _logService; this._loggerService = _loggerService; this._environmentService = _environmentService; this._userDataProfilesService = _userDataProfilesService; this._productService = _productService; this._layoutService = _layoutService; this._storageService = _storageService; this.pid = null; this.remoteAuthority = null; this.extensions = null; this._onDidExit = this._register(( new Emitter())); this.onExit = this._onDidExit.event; this._isTerminating = false; this._protocolPromise = null; this._protocol = null; this._extensionHostLogsLocation = joinPath(this._environmentService.extHostLogsPath, 'webWorker'); } async _getWebWorkerExtensionHostIframeSrc() { const suffixSearchParams = ( new URLSearchParams()); if (this._environmentService.debugExtensionHost && this._environmentService.debugRenderer) { suffixSearchParams.set('debugged', '1'); } COI.addSearchParam(suffixSearchParams, true, true); const suffix = `?${( suffixSearchParams.toString())}`; const iframeModulePath = 'vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html'; if (isWeb) { const webEndpointUrlTemplate = this._productService.webEndpointUrlTemplate; const commit = this._productService.commit; const quality = this._productService.quality; if (webEndpointUrlTemplate && commit && quality) { const key = 'webWorkerExtensionHostIframeStableOriginUUID'; let stableOriginUUID = this._storageService.get(key, StorageScope.WORKSPACE); if (typeof stableOriginUUID === 'undefined') { stableOriginUUID = generateUuid(); this._storageService.store(key, stableOriginUUID, StorageScope.WORKSPACE, StorageTarget.MACHINE); } const hash = await parentOriginHash(mainWindow.origin, stableOriginUUID); const baseUrl = (webEndpointUrlTemplate .replace('{{uuid}}', `v--${hash}`) .replace('{{commit}}', commit) .replace('{{quality}}', quality)); const res = ( new URL(`${baseUrl}/out/${iframeModulePath}${suffix}`)); res.searchParams.set('parentOrigin', mainWindow.origin); res.searchParams.set('salt', stableOriginUUID); return ( res.toString()); } } const relativeExtensionHostIframeSrc = ( FileAccess.asBrowserUri(iframeModulePath)); return `${( relativeExtensionHostIframeSrc.toString(true))}${suffix}`; } async start() { if (!this._protocolPromise) { this._protocolPromise = this._startInsideIframe(); this._protocolPromise.then(protocol => this._protocol = protocol); } return this._protocolPromise; } async _startInsideIframe() { const webWorkerExtensionHostIframeSrc = await this._getWebWorkerExtensionHostIframeSrc(); const emitter = this._register(( new Emitter())); const iframe = document.createElement('iframe'); iframe.setAttribute('class', 'web-worker-ext-host-iframe'); iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin'); iframe.setAttribute('allow', 'usb; serial; hid; cross-origin-isolated;'); iframe.setAttribute('aria-hidden', 'true'); iframe.style.display = 'none'; const vscodeWebWorkerExtHostId = generateUuid(); iframe.setAttribute('src', `${webWorkerExtensionHostIframeSrc}&vscodeWebWorkerExtHostId=${vscodeWebWorkerExtHostId}`); const barrier = ( new Barrier()); let port; let barrierError = null; let barrierHasError = false; let startTimeout = null; const rejectBarrier = (exitCode, error) => { barrierError = error; barrierHasError = true; onUnexpectedError(barrierError); clearTimeout(startTimeout); this._onDidExit.fire([ExtensionHostExitCode.UnexpectedError, barrierError.message]); barrier.open(); }; const resolveBarrier = (messagePort) => { port = messagePort; clearTimeout(startTimeout); barrier.open(); }; startTimeout = setTimeout(() => { console.warn(`The Web Worker Extension Host did not start in 60s, that might be a problem.`); }, 60000); this._register(addDisposableListener(mainWindow, 'message', (event) => { if (event.source !== iframe.contentWindow) { return; } if (event.data.vscodeWebWorkerExtHostId !== vscodeWebWorkerExtHostId) { return; } if (event.data.error) { const { name, message, stack } = event.data.error; const err = ( new Error()); err.message = message; err.name = name; err.stack = stack; return rejectBarrier(ExtensionHostExitCode.UnexpectedError, err); } if (event.data.type === 'vscode.bootstrap.nls') { const factoryModuleId = 'vs/base/worker/workerMain.js'; const baseUrl = require.toUrl(factoryModuleId).slice(0, -factoryModuleId.length); iframe.contentWindow.postMessage({ type: event.data.type, data: { baseUrl, workerUrl: require.toUrl(factoryModuleId), nls: { messages: globalThis._VSCODE_NLS_MESSAGES, language: globalThis._VSCODE_NLS_LANGUAGE } } }, '*'); return; } const { data } = event.data; if (barrier.isOpen() || !(data instanceof MessagePort)) { console.warn('UNEXPECTED message', event); const err = ( new Error('UNEXPECTED message')); return rejectBarrier(ExtensionHostExitCode.UnexpectedError, err); } resolveBarrier(data); })); this._layoutService.mainContainer.appendChild(iframe); this._register(toDisposable(() => iframe.remove())); await barrier.wait(); if (barrierHasError) { throw barrierError; } const messagePorts = this._environmentService.options?.messagePorts ?? ( new Map()); iframe.contentWindow.postMessage({ type: 'vscode.init', data: messagePorts }, '*', [...( messagePorts.values())]); port.onmessage = (event) => { const { data } = event; if (!(data instanceof ArrayBuffer)) { console.warn('UNKNOWN data received', data); this._onDidExit.fire([77, 'UNKNOWN data received']); return; } emitter.fire(VSBuffer.wrap(( new Uint8Array(data, 0, data.byteLength)))); }; const protocol = { onMessage: emitter.event, send: vsbuf => { const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteOffset + vsbuf.buffer.byteLength); port.postMessage(data, [data]); } }; return this._performHandshake(protocol); } async _performHandshake(protocol) { await Event.toPromise(Event.filter(protocol.onMessage, msg => isMessageOfType(msg, MessageType.Ready))); if (this._isTerminating) { throw canceled(); } protocol.send(VSBuffer.fromString(JSON.stringify(await this._createExtHostInitData()))); if (this._isTerminating) { throw canceled(); } await Event.toPromise(Event.filter(protocol.onMessage, msg => isMessageOfType(msg, MessageType.Initialized))); if (this._isTerminating) { throw canceled(); } return protocol; } dispose() { if (this._isTerminating) { return; } this._isTerminating = true; this._protocol?.send(createMessageOfType(MessageType.Terminate)); super.dispose(); } getInspectPort() { return undefined; } enableInspectPort() { return Promise.resolve(false); } async _createExtHostInitData() { const initData = await this._initDataProvider.getInitData(); this.extensions = initData.extensions; const workspace = this._contextService.getWorkspace(); const nlsBaseUrl = this._productService.extensionsGallery?.nlsBaseUrl; let nlsUrlWithDetails = undefined; if (nlsBaseUrl && this._productService.commit && !Language.isDefaultVariant()) { nlsUrlWithDetails = URI.joinPath(( URI.parse(nlsBaseUrl)), this._productService.commit, this._productService.version, Language.value()); } return { commit: this._productService.commit, version: this._productService.version, quality: this._productService.quality, parentPid: 0, environment: { isExtensionDevelopmentDebug: this._environmentService.debugRenderer, appName: this._productService.nameLong, appHost: this._productService.embedderIdentifier ?? (isWeb ? 'web' : 'desktop'), appUriScheme: this._productService.urlProtocol, appLanguage: language, extensionTelemetryLogResource: this._environmentService.extHostTelemetryLogFile, isExtensionTelemetryLoggingOnly: isLoggingOnly(this._productService, this._environmentService), extensionDevelopmentLocationURI: this._environmentService.extensionDevelopmentLocationURI, extensionTestsLocationURI: this._environmentService.extensionTestsLocationURI, globalStorageHome: this._userDataProfilesService.defaultProfile.globalStorageHome, workspaceStorageHome: this._environmentService.workspaceStorageHome, extensionLogLevel: this._environmentService.extensionLogLevel }, workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? undefined : { configuration: workspace.configuration || undefined, id: workspace.id, name: this._labelService.getWorkspaceLabel(workspace), transient: workspace.transient }, consoleForward: { includeStack: false, logNative: this._environmentService.debugRenderer }, extensions: this.extensions.toSnapshot(), nlsBaseUrl: nlsUrlWithDetails, telemetryInfo: { sessionId: this._telemetryService.sessionId, machineId: this._telemetryService.machineId, sqmId: this._telemetryService.sqmId, devDeviceId: this._telemetryService.devDeviceId, firstSessionDate: this._telemetryService.firstSessionDate, msftInternal: this._telemetryService.msftInternal }, logLevel: this._logService.getLevel(), loggers: [...this._loggerService.getRegisteredLoggers()], logsLocation: this._extensionHostLogsLocation, autoStart: (this.startup === ExtensionHostStartup.EagerAutoStart), remote: { authority: this._environmentService.remoteAuthority, connectionData: null, isRemote: false }, uiKind: isWeb ? UIKind.Web : UIKind.Desktop }; } }; WebWorkerExtensionHost = ( __decorate([ ( __param(3, ITelemetryService)), ( __param(4, IWorkspaceContextService)), ( __param(5, ILabelService)), ( __param(6, ILogService)), ( __param(7, ILoggerService)), ( __param(8, IBrowserWorkbenchEnvironmentService)), ( __param(9, IUserDataProfilesService)), ( __param(10, IProductService)), ( __param(11, ILayoutService)), ( __param(12, IStorageService)) ], WebWorkerExtensionHost)); export { WebWorkerExtensionHost };