mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-20 02:08:47 +00:00
Introduces IWebWorkerService to allow the monaco editor to customize web worker handling via service injection
This commit is contained in:
committed by
Henning Dieterichs
parent
77a0f670d3
commit
32b7a94b60
@@ -3,8 +3,11 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
WebWorkerDescriptor.useBundlerLocationRef();
|
||||
registerSingleton(IWebWorkerService, StandaloneWebWorkerService, InstantiationType.Eager);
|
||||
|
||||
import { WebWorkerDescriptor } from '../../src/vs/base/browser/webWorkerFactory.js';
|
||||
import '../../src/vs/code/browser/workbench/workbench.ts';
|
||||
import { InstantiationType, registerSingleton } from '../../src/vs/platform/instantiation/common/extensions.ts';
|
||||
import { IWebWorkerService } from '../../src/vs/platform/webWorker/browser/webWorkerService.ts';
|
||||
// eslint-disable-next-line local/code-no-standalone-editor
|
||||
import { StandaloneWebWorkerService } from '../../src/vs/editor/standalone/browser/services/standaloneWebWorkerService.ts';
|
||||
|
||||
|
||||
@@ -206,7 +206,6 @@ export default tseslint.config(
|
||||
'src/vs/base/browser/dom.ts',
|
||||
'src/vs/base/browser/markdownRenderer.ts',
|
||||
'src/vs/base/browser/touch.ts',
|
||||
'src/vs/base/browser/webWorkerFactory.ts',
|
||||
'src/vs/base/common/async.ts',
|
||||
'src/vs/base/common/desktopEnvironmentInfo.ts',
|
||||
'src/vs/base/common/objects.ts',
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts"
|
||||
],
|
||||
"ban-worker-calls": [
|
||||
"vs/base/browser/webWorkerFactory.ts",
|
||||
"vs/platform/webWorker/browser/webWorkerServiceImpl.ts",
|
||||
"vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts"
|
||||
],
|
||||
"ban-worker-importscripts": [
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createTrustedTypesPolicy } from './trustedTypes.js';
|
||||
import { onUnexpectedError } from '../common/errors.js';
|
||||
import { COI } from '../common/network.js';
|
||||
import { URI } from '../common/uri.js';
|
||||
import { IWebWorker, IWebWorkerClient, Message, WebWorkerClient } from '../common/worker/webWorker.js';
|
||||
import { Disposable, toDisposable } from '../common/lifecycle.js';
|
||||
import { coalesce } from '../common/arrays.js';
|
||||
import { getNLSLanguage, getNLSMessages } from '../../nls.js';
|
||||
import { Emitter } from '../common/event.js';
|
||||
import { getMonacoEnvironment } from './browser.js';
|
||||
|
||||
type WorkerGlobalWithPolicy = typeof globalThis & {
|
||||
workerttPolicy?: ReturnType<typeof createTrustedTypesPolicy>;
|
||||
};
|
||||
|
||||
// Reuse the trusted types policy defined from worker bootstrap
|
||||
// when available.
|
||||
// Refs https://github.com/microsoft/vscode/issues/222193
|
||||
let ttPolicy: ReturnType<typeof createTrustedTypesPolicy>;
|
||||
const workerGlobalThis = globalThis as WorkerGlobalWithPolicy;
|
||||
if (typeof self === 'object' && self.constructor && self.constructor.name === 'DedicatedWorkerGlobalScope' && workerGlobalThis.workerttPolicy !== undefined) {
|
||||
ttPolicy = workerGlobalThis.workerttPolicy;
|
||||
} else {
|
||||
ttPolicy = createTrustedTypesPolicy('defaultWorkerFactory', { createScriptURL: value => value });
|
||||
}
|
||||
|
||||
export function createBlobWorker(blobUrl: string, options?: WorkerOptions): Worker {
|
||||
if (!blobUrl.startsWith('blob:')) {
|
||||
throw new URIError('Not a blob-url: ' + blobUrl);
|
||||
}
|
||||
return new Worker(ttPolicy ? ttPolicy.createScriptURL(blobUrl) as unknown as string : blobUrl, { ...options, type: 'module' });
|
||||
}
|
||||
|
||||
function getWorker(descriptor: WebWorkerDescriptor, id: number): Worker | Promise<Worker> {
|
||||
const label = descriptor.label || 'anonymous' + id;
|
||||
|
||||
// Option for hosts to overwrite the worker script (used in the standalone editor)
|
||||
const monacoEnvironment = getMonacoEnvironment();
|
||||
if (monacoEnvironment) {
|
||||
if (typeof monacoEnvironment.getWorker === 'function') {
|
||||
const w = monacoEnvironment.getWorker('workerMain.js', label);
|
||||
if (w !== undefined) {
|
||||
return w;
|
||||
}
|
||||
}
|
||||
if (typeof monacoEnvironment.getWorkerUrl === 'function') {
|
||||
const workerUrl = monacoEnvironment.getWorkerUrl('workerMain.js', label);
|
||||
if (workerUrl !== undefined) {
|
||||
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label, type: 'module' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const esmWorkerLocation = descriptor.getUrl();
|
||||
if (esmWorkerLocation) {
|
||||
const workerUrl = getWorkerBootstrapUrl(label, esmWorkerLocation);
|
||||
const worker = new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label, type: 'module' });
|
||||
return whenESMWorkerReady(worker);
|
||||
}
|
||||
|
||||
throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);
|
||||
}
|
||||
|
||||
function getWorkerBootstrapUrl(label: string, workerScriptUrl: string): string {
|
||||
if (/^((http:)|(https:)|(file:))/.test(workerScriptUrl) && workerScriptUrl.substring(0, globalThis.origin.length) !== globalThis.origin) {
|
||||
// this is the cross-origin case
|
||||
// i.e. the webpage is running at a different origin than where the scripts are loaded from
|
||||
} else {
|
||||
const start = workerScriptUrl.lastIndexOf('?');
|
||||
const end = workerScriptUrl.lastIndexOf('#', start);
|
||||
const params = start > 0
|
||||
? new URLSearchParams(workerScriptUrl.substring(start + 1, ~end ? end : undefined))
|
||||
: new URLSearchParams();
|
||||
|
||||
COI.addSearchParam(params, true, true);
|
||||
const search = params.toString();
|
||||
if (!search) {
|
||||
workerScriptUrl = `${workerScriptUrl}#${label}`;
|
||||
} else {
|
||||
workerScriptUrl = `${workerScriptUrl}?${params.toString()}#${label}`;
|
||||
}
|
||||
}
|
||||
|
||||
// In below blob code, we are using JSON.stringify to ensure the passed
|
||||
// in values are not breaking our script. The values may contain string
|
||||
// terminating characters (such as ' or ").
|
||||
const blob = new Blob([coalesce([
|
||||
`/*${label}*/`,
|
||||
`globalThis._VSCODE_NLS_MESSAGES = ${JSON.stringify(getNLSMessages())};`,
|
||||
`globalThis._VSCODE_NLS_LANGUAGE = ${JSON.stringify(getNLSLanguage())};`,
|
||||
`globalThis._VSCODE_FILE_ROOT = ${JSON.stringify(globalThis._VSCODE_FILE_ROOT)};`,
|
||||
`const ttPolicy = globalThis.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });`,
|
||||
`globalThis.workerttPolicy = ttPolicy;`,
|
||||
`await import(ttPolicy?.createScriptURL(${JSON.stringify(workerScriptUrl)}) ?? ${JSON.stringify(workerScriptUrl)});`,
|
||||
`globalThis.postMessage({ type: 'vscode-worker-ready' });`,
|
||||
`/*${label}*/`
|
||||
]).join('')], { type: 'application/javascript' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
function whenESMWorkerReady(worker: Worker): Promise<Worker> {
|
||||
return new Promise<Worker>((resolve, reject) => {
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data.type === 'vscode-worker-ready') {
|
||||
worker.onmessage = null;
|
||||
resolve(worker);
|
||||
}
|
||||
};
|
||||
worker.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function isPromiseLike<T>(obj: unknown): obj is PromiseLike<T> {
|
||||
return !!obj && typeof (obj as PromiseLike<T>).then === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* A worker that uses HTML5 web workers so that is has
|
||||
* its own global scope and its own thread.
|
||||
*/
|
||||
class WebWorker extends Disposable implements IWebWorker {
|
||||
|
||||
private static LAST_WORKER_ID = 0;
|
||||
|
||||
private readonly id: number;
|
||||
private worker: Promise<Worker> | null;
|
||||
|
||||
private readonly _onMessage = this._register(new Emitter<Message>());
|
||||
public readonly onMessage = this._onMessage.event;
|
||||
|
||||
private readonly _onError = this._register(new Emitter<MessageEvent | ErrorEvent>());
|
||||
public readonly onError = this._onError.event;
|
||||
|
||||
constructor(descriptorOrWorker: WebWorkerDescriptor | Worker | Promise<Worker>) {
|
||||
super();
|
||||
this.id = ++WebWorker.LAST_WORKER_ID;
|
||||
const workerOrPromise = (
|
||||
descriptorOrWorker instanceof Worker
|
||||
? descriptorOrWorker :
|
||||
'then' in descriptorOrWorker ? descriptorOrWorker
|
||||
: getWorker(descriptorOrWorker, this.id)
|
||||
);
|
||||
if (isPromiseLike(workerOrPromise)) {
|
||||
this.worker = workerOrPromise;
|
||||
} else {
|
||||
this.worker = Promise.resolve(workerOrPromise);
|
||||
}
|
||||
this.postMessage('-please-ignore-', []); // TODO: Eliminate this extra message
|
||||
const errorHandler = (ev: ErrorEvent) => {
|
||||
this._onError.fire(ev);
|
||||
};
|
||||
this.worker.then((w) => {
|
||||
w.onmessage = (ev) => {
|
||||
this._onMessage.fire(ev.data);
|
||||
};
|
||||
w.onmessageerror = (ev) => {
|
||||
this._onError.fire(ev);
|
||||
};
|
||||
if (typeof w.addEventListener === 'function') {
|
||||
w.addEventListener('error', errorHandler);
|
||||
}
|
||||
});
|
||||
this._register(toDisposable(() => {
|
||||
this.worker?.then(w => {
|
||||
w.onmessage = null;
|
||||
w.onmessageerror = null;
|
||||
w.removeEventListener('error', errorHandler);
|
||||
w.terminate();
|
||||
});
|
||||
this.worker = null;
|
||||
}));
|
||||
}
|
||||
|
||||
public getId(): number {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public postMessage(message: unknown, transfer: Transferable[]): void {
|
||||
this.worker?.then(w => {
|
||||
try {
|
||||
w.postMessage(message, transfer);
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
onUnexpectedError(new Error(`FAILED to post message to worker`, { cause: err }));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class WebWorkerDescriptor {
|
||||
private static _useBundlerLocationRef = false;
|
||||
|
||||
/** TODO @hediet: Use web worker service! */
|
||||
public static useBundlerLocationRef() {
|
||||
WebWorkerDescriptor._useBundlerLocationRef = true;
|
||||
}
|
||||
|
||||
public readonly esmModuleLocation: URI | (() => URI) | undefined;
|
||||
public readonly esmModuleLocationBundler: URL | (() => URL) | undefined;
|
||||
public readonly label: string | undefined;
|
||||
|
||||
constructor(args: {
|
||||
/** The location of the esm module after transpilation */
|
||||
esmModuleLocation?: URI | (() => URI);
|
||||
/** The location of the esm module when used in a bundler environment. Refer to the typescript file in the src folder and use `?worker`. */
|
||||
esmModuleLocationBundler?: URL | (() => URL);
|
||||
label?: string;
|
||||
}) {
|
||||
this.esmModuleLocation = args.esmModuleLocation;
|
||||
this.esmModuleLocationBundler = args.esmModuleLocationBundler;
|
||||
this.label = args.label;
|
||||
}
|
||||
|
||||
getUrl(): string | undefined {
|
||||
if (WebWorkerDescriptor._useBundlerLocationRef) {
|
||||
if (this.esmModuleLocationBundler) {
|
||||
const esmWorkerLocation = typeof this.esmModuleLocationBundler === 'function' ? this.esmModuleLocationBundler() : this.esmModuleLocationBundler;
|
||||
return esmWorkerLocation.toString();
|
||||
}
|
||||
} else if (this.esmModuleLocation) {
|
||||
const esmWorkerLocation = typeof this.esmModuleLocation === 'function' ? this.esmModuleLocation() : this.esmModuleLocation;
|
||||
return esmWorkerLocation.toString(true);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function createWebWorker<T extends object>(workerDescriptor: WebWorkerDescriptor | Worker | Promise<Worker>): IWebWorkerClient<T> {
|
||||
return new WebWorkerClient<T>(new WebWorker(workerDescriptor));
|
||||
}
|
||||
@@ -7,7 +7,8 @@ import { timeout } from '../../../base/common/async.js';
|
||||
import { Disposable, IDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { logOnceWebWorkerWarning, IWebWorkerClient, Proxied } from '../../../base/common/worker/webWorker.js';
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from '../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { Position } from '../../common/core/position.js';
|
||||
import { IRange, Range } from '../../common/core/range.js';
|
||||
import { ITextModel } from '../../common/model.js';
|
||||
@@ -67,6 +68,7 @@ export class EditorWorkerService extends Disposable implements IEditorWorkerServ
|
||||
@ILogService logService: ILogService,
|
||||
@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
|
||||
@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
|
||||
@IWebWorkerService private readonly _webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
this._modelService = modelService;
|
||||
@@ -77,7 +79,7 @@ export class EditorWorkerService extends Disposable implements IEditorWorkerServ
|
||||
label: 'editorWorkerService'
|
||||
});
|
||||
|
||||
this._workerManager = this._register(new WorkerManager(workerDescriptor, this._modelService));
|
||||
this._workerManager = this._register(new WorkerManager(workerDescriptor, this._modelService, this._webWorkerService));
|
||||
this._logService = logService;
|
||||
|
||||
// register default link-provider and default completions-provider
|
||||
@@ -333,15 +335,18 @@ class WordBasedCompletionItemProvider implements languages.CompletionItemProvide
|
||||
class WorkerManager extends Disposable {
|
||||
|
||||
private readonly _modelService: IModelService;
|
||||
private readonly _webWorkerService: IWebWorkerService;
|
||||
private _editorWorkerClient: EditorWorkerClient | null;
|
||||
private _lastWorkerUsedTime: number;
|
||||
|
||||
constructor(
|
||||
private readonly _workerDescriptor: WebWorkerDescriptor,
|
||||
@IModelService modelService: IModelService
|
||||
@IModelService modelService: IModelService,
|
||||
@IWebWorkerService webWorkerService: IWebWorkerService
|
||||
) {
|
||||
super();
|
||||
this._modelService = modelService;
|
||||
this._webWorkerService = webWorkerService;
|
||||
this._editorWorkerClient = null;
|
||||
this._lastWorkerUsedTime = (new Date()).getTime();
|
||||
|
||||
@@ -393,7 +398,7 @@ class WorkerManager extends Disposable {
|
||||
public withWorker(): Promise<EditorWorkerClient> {
|
||||
this._lastWorkerUsedTime = (new Date()).getTime();
|
||||
if (!this._editorWorkerClient) {
|
||||
this._editorWorkerClient = new EditorWorkerClient(this._workerDescriptor, false, this._modelService);
|
||||
this._editorWorkerClient = new EditorWorkerClient(this._workerDescriptor, false, this._modelService, this._webWorkerService);
|
||||
}
|
||||
return Promise.resolve(this._editorWorkerClient);
|
||||
}
|
||||
@@ -428,6 +433,7 @@ export interface IEditorWorkerClient {
|
||||
export class EditorWorkerClient extends Disposable implements IEditorWorkerClient {
|
||||
|
||||
private readonly _modelService: IModelService;
|
||||
private readonly _webWorkerService: IWebWorkerService;
|
||||
private readonly _keepIdleModels: boolean;
|
||||
private _worker: IWebWorkerClient<EditorWorker> | null;
|
||||
private _modelManager: WorkerTextModelSyncClient | null;
|
||||
@@ -437,9 +443,11 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
|
||||
private readonly _workerDescriptorOrWorker: WebWorkerDescriptor | Worker | Promise<Worker>,
|
||||
keepIdleModels: boolean,
|
||||
@IModelService modelService: IModelService,
|
||||
@IWebWorkerService webWorkerService: IWebWorkerService
|
||||
) {
|
||||
super();
|
||||
this._modelService = modelService;
|
||||
this._webWorkerService = webWorkerService;
|
||||
this._keepIdleModels = keepIdleModels;
|
||||
this._worker = null;
|
||||
this._modelManager = null;
|
||||
@@ -453,7 +461,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
|
||||
private _getOrCreateWorker(): IWebWorkerClient<EditorWorker> {
|
||||
if (!this._worker) {
|
||||
try {
|
||||
this._worker = this._register(createWebWorker<EditorWorker>(this._workerDescriptorOrWorker));
|
||||
this._worker = this._register(this._webWorkerService.createWorkerClient<EditorWorker>(this._workerDescriptorOrWorker));
|
||||
EditorWorkerHost.setChannel(this._worker, this._createEditorWorkerHost());
|
||||
} catch (err) {
|
||||
logOnceWebWorkerWarning(err);
|
||||
|
||||
@@ -9,9 +9,6 @@ import { createMonacoEditorAPI } from './standalone/browser/standaloneEditor.js'
|
||||
import { createMonacoLanguagesAPI } from './standalone/browser/standaloneLanguages.js';
|
||||
import { FormattingConflicts } from './contrib/format/browser/format.js';
|
||||
import { getMonacoEnvironment } from '../base/browser/browser.js';
|
||||
import { WebWorkerDescriptor } from '../base/browser/webWorkerFactory.js';
|
||||
|
||||
WebWorkerDescriptor.useBundlerLocationRef();
|
||||
|
||||
// Set defaults for standalone editor
|
||||
EditorOptions.wrappingIndent.defaultValue = WrappingIndent.None;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getMonacoEnvironment } from '../../../../base/browser/browser.js';
|
||||
import { WebWorkerDescriptor } from '../../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { WebWorkerService } from '../../../../platform/webWorker/browser/webWorkerServiceImpl.js';
|
||||
|
||||
export class StandaloneWebWorkerService extends WebWorkerService {
|
||||
protected override _createWorker(descriptor: WebWorkerDescriptor): Promise<Worker> {
|
||||
const monacoEnvironment = getMonacoEnvironment();
|
||||
if (monacoEnvironment) {
|
||||
if (typeof monacoEnvironment.getWorker === 'function') {
|
||||
const worker = monacoEnvironment.getWorker('workerMain.js', descriptor.label);
|
||||
if (worker !== undefined) {
|
||||
return Promise.resolve(worker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super._createWorker(descriptor);
|
||||
}
|
||||
|
||||
protected override _getUrl(descriptor: WebWorkerDescriptor): string {
|
||||
const monacoEnvironment = getMonacoEnvironment();
|
||||
if (monacoEnvironment) {
|
||||
if (typeof monacoEnvironment.getWorkerUrl === 'function') {
|
||||
const workerUrl = monacoEnvironment.getWorkerUrl('workerMain.js', descriptor.label);
|
||||
if (workerUrl !== undefined) {
|
||||
return workerUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!descriptor.esmModuleLocationBundler) {
|
||||
throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);
|
||||
}
|
||||
|
||||
const url = typeof descriptor.esmModuleLocationBundler === 'function' ? descriptor.esmModuleLocationBundler() : descriptor.esmModuleLocationBundler;
|
||||
const urlStr = url.toString();
|
||||
return urlStr;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import { IKeybindingService } from '../../../platform/keybinding/common/keybindi
|
||||
import { IMarker, IMarkerData, IMarkerService } from '../../../platform/markers/common/markers.js';
|
||||
import { IOpenerService } from '../../../platform/opener/common/opener.js';
|
||||
import { MultiDiffEditorWidget } from '../../browser/widget/multiDiffEditor/multiDiffEditorWidget.js';
|
||||
import { IWebWorkerService } from '../../../platform/webWorker/browser/webWorkerService.js';
|
||||
|
||||
/**
|
||||
* Create a new editor under `domElement`.
|
||||
@@ -332,7 +333,7 @@ export function onDidChangeModelLanguage(listener: (e: { readonly model: ITextMo
|
||||
* Specify an AMD module to load that will `create` an object that will be proxied.
|
||||
*/
|
||||
export function createWebWorker<T extends object>(opts: IInternalWebWorkerOptions): MonacoWebWorker<T> {
|
||||
return actualCreateWebWorker<T>(StandaloneServices.get(IModelService), opts);
|
||||
return actualCreateWebWorker<T>(StandaloneServices.get(IModelService), StandaloneServices.get(IWebWorkerService), opts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -96,6 +96,8 @@ import { ResourceMap } from '../../../base/common/map.js';
|
||||
import { ITreeSitterLibraryService } from '../../common/services/treeSitter/treeSitterLibraryService.js';
|
||||
import { StandaloneTreeSitterLibraryService } from './standaloneTreeSitterLibraryService.js';
|
||||
import { IDataChannelService, NullDataChannelService } from '../../../platform/dataChannel/common/dataChannel.js';
|
||||
import { IWebWorkerService } from '../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { StandaloneWebWorkerService } from './services/standaloneWebWorkerService.js';
|
||||
|
||||
class SimpleModel implements IResolvedTextEditorModel {
|
||||
|
||||
@@ -1110,6 +1112,7 @@ export interface IEditorOverrideServices {
|
||||
}
|
||||
|
||||
|
||||
registerSingleton(IWebWorkerService, StandaloneWebWorkerService, InstantiationType.Eager);
|
||||
registerSingleton(ILogService, StandaloneLogService, InstantiationType.Eager);
|
||||
registerSingleton(IConfigurationService, StandaloneConfigurationService, InstantiationType.Eager);
|
||||
registerSingleton(ITextResourceConfigurationService, StandaloneResourceConfigurationService, InstantiationType.Eager);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { IWebWorkerService } from '../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { EditorWorkerClient } from '../../browser/services/editorWorkerService.js';
|
||||
import { IModelService } from '../../common/services/model.js';
|
||||
|
||||
@@ -11,8 +12,8 @@ import { IModelService } from '../../common/services/model.js';
|
||||
* Create a new web worker that has model syncing capabilities built in.
|
||||
* Specify an AMD module to load that will `create` an object that will be proxied.
|
||||
*/
|
||||
export function createWebWorker<T extends object>(modelService: IModelService, opts: IInternalWebWorkerOptions): MonacoWebWorker<T> {
|
||||
return new MonacoWebWorkerImpl<T>(modelService, opts);
|
||||
export function createWebWorker<T extends object>(modelService: IModelService, webWorkerService: IWebWorkerService, opts: IInternalWebWorkerOptions): MonacoWebWorker<T> {
|
||||
return new MonacoWebWorkerImpl<T>(modelService, webWorkerService, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,8 +56,8 @@ class MonacoWebWorkerImpl<T extends object> extends EditorWorkerClient implement
|
||||
private readonly _foreignModuleHost: { [method: string]: Function } | null;
|
||||
private _foreignProxy: Promise<T>;
|
||||
|
||||
constructor(modelService: IModelService, opts: IInternalWebWorkerOptions) {
|
||||
super(opts.worker, opts.keepIdleModels || false, modelService);
|
||||
constructor(modelService: IModelService, webWorkerService: IWebWorkerService, opts: IInternalWebWorkerOptions) {
|
||||
super(opts.worker, opts.keepIdleModels || false, modelService, webWorkerService);
|
||||
this._foreignModuleHost = opts.host || null;
|
||||
this._foreignProxy = this._getProxy().then(proxy => {
|
||||
return new Proxy({}, {
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../webWorker/browser/webWorkerDescriptor.js';
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
import { Proxied } from '../../../base/common/worker/webWorker.js';
|
||||
import { InstantiationType, registerSingleton } from '../../instantiation/common/extensions.js';
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { IWebWorkerService } from '../../webWorker/browser/webWorkerService.js';
|
||||
import { ILogService } from '../../log/common/log.js';
|
||||
import { IV8Profile } from '../common/profiling.js';
|
||||
import { BottomUpSample } from '../common/profilingModel.js';
|
||||
@@ -44,11 +45,12 @@ class ProfileAnalysisWorkerService implements IProfileAnalysisWorkerService {
|
||||
constructor(
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IWebWorkerService private readonly _webWorkerService: IWebWorkerService,
|
||||
) { }
|
||||
|
||||
private async _withWorker<R>(callback: (worker: Proxied<IProfileAnalysisWorker>) => Promise<R>): Promise<R> {
|
||||
|
||||
const worker = createWebWorker<IProfileAnalysisWorker>(
|
||||
const worker = this._webWorkerService.createWorkerClient<IProfileAnalysisWorker>(
|
||||
new WebWorkerDescriptor({
|
||||
esmModuleLocation: FileAccess.asBrowserUri('vs/platform/profiling/electron-browser/profileAnalysisWorkerMain.js'),
|
||||
label: 'CpuProfileAnalysisWorker'
|
||||
|
||||
24
src/vs/platform/webWorker/browser/webWorkerDescriptor.ts
Normal file
24
src/vs/platform/webWorker/browser/webWorkerDescriptor.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from '../../../base/common/uri.js';
|
||||
|
||||
export class WebWorkerDescriptor {
|
||||
public readonly esmModuleLocation: URI | (() => URI) | undefined;
|
||||
public readonly esmModuleLocationBundler: URL | (() => URL) | undefined;
|
||||
public readonly label: string;
|
||||
|
||||
constructor(args: {
|
||||
/** The location of the esm module after transpilation */
|
||||
esmModuleLocation?: URI | (() => URI);
|
||||
/** The location of the esm module when used in a bundler environment. Refer to the typescript file in the src folder and use `?worker`. */
|
||||
esmModuleLocationBundler?: URL | (() => URL);
|
||||
label: string;
|
||||
}) {
|
||||
this.esmModuleLocation = args.esmModuleLocation;
|
||||
this.esmModuleLocationBundler = args.esmModuleLocationBundler;
|
||||
this.label = args.label;
|
||||
}
|
||||
}
|
||||
16
src/vs/platform/webWorker/browser/webWorkerService.ts
Normal file
16
src/vs/platform/webWorker/browser/webWorkerService.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||
import { IWebWorkerClient } from '../../../base/common/worker/webWorker.js';
|
||||
import { WebWorkerDescriptor } from './webWorkerDescriptor.js';
|
||||
|
||||
export const IWebWorkerService = createDecorator<IWebWorkerService>('IWebWorkerService');
|
||||
|
||||
export interface IWebWorkerService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
createWorkerClient<T extends object>(workerDescriptor: WebWorkerDescriptor | Worker | Promise<Worker>): IWebWorkerClient<T>;
|
||||
}
|
||||
181
src/vs/platform/webWorker/browser/webWorkerServiceImpl.ts
Normal file
181
src/vs/platform/webWorker/browser/webWorkerServiceImpl.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createTrustedTypesPolicy } from '../../../base/browser/trustedTypes.js';
|
||||
import { coalesce } from '../../../base/common/arrays.js';
|
||||
import { onUnexpectedError } from '../../../base/common/errors.js';
|
||||
import { Emitter } from '../../../base/common/event.js';
|
||||
import { Disposable, toDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { COI } from '../../../base/common/network.js';
|
||||
import { IWebWorker, IWebWorkerClient, Message, WebWorkerClient } from '../../../base/common/worker/webWorker.js';
|
||||
import { getNLSLanguage, getNLSMessages } from '../../../nls.js';
|
||||
import { WebWorkerDescriptor } from './webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from './webWorkerService.js';
|
||||
|
||||
export class WebWorkerService implements IWebWorkerService {
|
||||
private static _workerIdPool: number = 0;
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
createWorkerClient<T extends object>(workerDescriptor: WebWorkerDescriptor | Worker | Promise<Worker>): IWebWorkerClient<T> {
|
||||
let worker: Worker | Promise<Worker>;
|
||||
const id = ++WebWorkerService._workerIdPool;
|
||||
if (workerDescriptor instanceof Worker || isPromiseLike<Worker>(workerDescriptor)) {
|
||||
worker = Promise.resolve(workerDescriptor);
|
||||
} else {
|
||||
worker = this._createWorker(workerDescriptor);
|
||||
}
|
||||
|
||||
return new WebWorkerClient<T>(new WebWorker(worker, id));
|
||||
}
|
||||
|
||||
protected _createWorker(descriptor: WebWorkerDescriptor): Promise<Worker> {
|
||||
const workerRunnerUrl = this._getUrl(descriptor);
|
||||
|
||||
const workerUrl = getWorkerBootstrapUrl(descriptor.label, workerRunnerUrl);
|
||||
const worker = new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: descriptor.label, type: 'module' });
|
||||
return whenESMWorkerReady(worker);
|
||||
}
|
||||
|
||||
protected _getUrl(descriptor: WebWorkerDescriptor): string {
|
||||
if (!descriptor.esmModuleLocation) {
|
||||
throw new Error('Missing esmModuleLocation in WebWorkerDescriptor');
|
||||
}
|
||||
const uri = typeof descriptor.esmModuleLocation === 'function' ? descriptor.esmModuleLocation() : descriptor.esmModuleLocation;
|
||||
const urlStr = uri.toString(true);
|
||||
return urlStr;
|
||||
}
|
||||
}
|
||||
|
||||
const ttPolicy = ((): ReturnType<typeof createTrustedTypesPolicy> => {
|
||||
type WorkerGlobalWithPolicy = typeof globalThis & {
|
||||
workerttPolicy?: ReturnType<typeof createTrustedTypesPolicy>;
|
||||
};
|
||||
|
||||
// Reuse the trusted types policy defined from worker bootstrap
|
||||
// when available.
|
||||
// Refs https://github.com/microsoft/vscode/issues/222193
|
||||
const workerGlobalThis = globalThis as WorkerGlobalWithPolicy;
|
||||
if (typeof self === 'object' && self.constructor && self.constructor.name === 'DedicatedWorkerGlobalScope' && workerGlobalThis.workerttPolicy !== undefined) {
|
||||
return workerGlobalThis.workerttPolicy;
|
||||
} else {
|
||||
return createTrustedTypesPolicy('defaultWorkerFactory', { createScriptURL: value => value });
|
||||
}
|
||||
})();
|
||||
|
||||
export function createBlobWorker(blobUrl: string, options?: WorkerOptions): Worker {
|
||||
if (!blobUrl.startsWith('blob:')) {
|
||||
throw new URIError('Not a blob-url: ' + blobUrl);
|
||||
}
|
||||
return new Worker(ttPolicy ? ttPolicy.createScriptURL(blobUrl) as unknown as string : blobUrl, { ...options, type: 'module' });
|
||||
}
|
||||
|
||||
function getWorkerBootstrapUrl(label: string, workerScriptUrl: string): string {
|
||||
if (/^((http:)|(https:)|(file:))/.test(workerScriptUrl) && workerScriptUrl.substring(0, globalThis.origin.length) !== globalThis.origin) {
|
||||
// this is the cross-origin case
|
||||
// i.e. the webpage is running at a different origin than where the scripts are loaded from
|
||||
} else {
|
||||
const start = workerScriptUrl.lastIndexOf('?');
|
||||
const end = workerScriptUrl.lastIndexOf('#', start);
|
||||
const params = start > 0
|
||||
? new URLSearchParams(workerScriptUrl.substring(start + 1, ~end ? end : undefined))
|
||||
: new URLSearchParams();
|
||||
|
||||
COI.addSearchParam(params, true, true);
|
||||
const search = params.toString();
|
||||
if (!search) {
|
||||
workerScriptUrl = `${workerScriptUrl}#${label}`;
|
||||
} else {
|
||||
workerScriptUrl = `${workerScriptUrl}?${params.toString()}#${label}`;
|
||||
}
|
||||
}
|
||||
|
||||
// In below blob code, we are using JSON.stringify to ensure the passed
|
||||
// in values are not breaking our script. The values may contain string
|
||||
// terminating characters (such as ' or ").
|
||||
const blob = new Blob([coalesce([
|
||||
`/*${label}*/`,
|
||||
`globalThis._VSCODE_NLS_MESSAGES = ${JSON.stringify(getNLSMessages())};`,
|
||||
`globalThis._VSCODE_NLS_LANGUAGE = ${JSON.stringify(getNLSLanguage())};`,
|
||||
`globalThis._VSCODE_FILE_ROOT = ${JSON.stringify(globalThis._VSCODE_FILE_ROOT)};`,
|
||||
`const ttPolicy = globalThis.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });`,
|
||||
`globalThis.workerttPolicy = ttPolicy;`,
|
||||
`await import(ttPolicy?.createScriptURL(${JSON.stringify(workerScriptUrl)}) ?? ${JSON.stringify(workerScriptUrl)});`,
|
||||
`globalThis.postMessage({ type: 'vscode-worker-ready' });`,
|
||||
`/*${label}*/`
|
||||
]).join('')], { type: 'application/javascript' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
function whenESMWorkerReady(worker: Worker): Promise<Worker> {
|
||||
return new Promise<Worker>((resolve, reject) => {
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data.type === 'vscode-worker-ready') {
|
||||
worker.onmessage = null;
|
||||
resolve(worker);
|
||||
}
|
||||
};
|
||||
worker.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function isPromiseLike<T>(obj: unknown): obj is PromiseLike<T> {
|
||||
return !!obj && typeof (obj as PromiseLike<T>).then === 'function';
|
||||
}
|
||||
|
||||
export class WebWorker extends Disposable implements IWebWorker {
|
||||
private readonly id: number;
|
||||
private worker: Promise<Worker> | null;
|
||||
|
||||
private readonly _onMessage = this._register(new Emitter<Message>());
|
||||
public readonly onMessage = this._onMessage.event;
|
||||
|
||||
private readonly _onError = this._register(new Emitter<MessageEvent | ErrorEvent>());
|
||||
public readonly onError = this._onError.event;
|
||||
|
||||
constructor(worker: Promise<Worker>, id: number) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.worker = worker;
|
||||
this.postMessage('-please-ignore-', []); // TODO: Eliminate this extra message
|
||||
const errorHandler = (ev: ErrorEvent) => {
|
||||
this._onError.fire(ev);
|
||||
};
|
||||
this.worker.then((w) => {
|
||||
w.onmessage = (ev) => {
|
||||
this._onMessage.fire(ev.data);
|
||||
};
|
||||
w.onmessageerror = (ev) => {
|
||||
this._onError.fire(ev);
|
||||
};
|
||||
if (typeof w.addEventListener === 'function') {
|
||||
w.addEventListener('error', errorHandler);
|
||||
}
|
||||
});
|
||||
this._register(toDisposable(() => {
|
||||
this.worker?.then(w => {
|
||||
w.onmessage = null;
|
||||
w.onmessageerror = null;
|
||||
w.removeEventListener('error', errorHandler);
|
||||
w.terminate();
|
||||
});
|
||||
this.worker = null;
|
||||
}));
|
||||
}
|
||||
|
||||
public getId(): number {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public postMessage(message: unknown, transfer: Transferable[]): void {
|
||||
this.worker?.then(w => {
|
||||
try {
|
||||
w.postMessage(message, transfer);
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
onUnexpectedError(new Error(`FAILED to post message to worker`, { cause: err }));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,8 @@
|
||||
import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from '../../../../../base/common/lifecycle.js';
|
||||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { IWebWorkerClient, Proxied } from '../../../../../base/common/worker/webWorker.js';
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from '../../../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { NotebookCellTextModel } from '../../common/model/notebookCellTextModel.js';
|
||||
import { CellUri, IMainCellDto, INotebookDiffResult, NotebookCellsChangeType, NotebookRawContentEventDto } from '../../common/notebookCommon.js';
|
||||
import { INotebookService } from '../../common/notebookService.js';
|
||||
@@ -26,10 +27,11 @@ export class NotebookEditorWorkerServiceImpl extends Disposable implements INote
|
||||
constructor(
|
||||
@INotebookService notebookService: INotebookService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IWebWorkerService webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
|
||||
this._workerManager = this._register(new WorkerManager(notebookService, modelService));
|
||||
this._workerManager = this._register(new WorkerManager(notebookService, modelService, webWorkerService));
|
||||
}
|
||||
canComputeDiff(original: URI, modified: URI): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
@@ -55,6 +57,7 @@ class WorkerManager extends Disposable {
|
||||
constructor(
|
||||
private readonly _notebookService: INotebookService,
|
||||
private readonly _modelService: IModelService,
|
||||
private readonly _webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
this._editorWorkerClient = null;
|
||||
@@ -64,7 +67,7 @@ class WorkerManager extends Disposable {
|
||||
withWorker(): Promise<NotebookWorkerClient> {
|
||||
// this._lastWorkerUsedTime = (new Date()).getTime();
|
||||
if (!this._editorWorkerClient) {
|
||||
this._editorWorkerClient = new NotebookWorkerClient(this._notebookService, this._modelService);
|
||||
this._editorWorkerClient = new NotebookWorkerClient(this._notebookService, this._modelService, this._webWorkerService);
|
||||
this._register(this._editorWorkerClient);
|
||||
}
|
||||
return Promise.resolve(this._editorWorkerClient);
|
||||
@@ -240,7 +243,11 @@ class NotebookWorkerClient extends Disposable {
|
||||
private _modelManager: NotebookEditorModelManager | null;
|
||||
|
||||
|
||||
constructor(private readonly _notebookService: INotebookService, private readonly _modelService: IModelService) {
|
||||
constructor(
|
||||
private readonly _notebookService: INotebookService,
|
||||
private readonly _modelService: IModelService,
|
||||
private readonly _webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
this._worker = null;
|
||||
this._modelManager = null;
|
||||
@@ -273,7 +280,7 @@ class NotebookWorkerClient extends Disposable {
|
||||
private _getOrCreateWorker(): IWebWorkerClient<NotebookWorker> {
|
||||
if (!this._worker) {
|
||||
try {
|
||||
this._worker = this._register(createWebWorker<NotebookWorker>(
|
||||
this._worker = this._register(this._webWorkerService.createWorkerClient<NotebookWorker>(
|
||||
new WebWorkerDescriptor({
|
||||
esmModuleLocation: FileAccess.asBrowserUri('vs/workbench/contrib/notebook/common/services/notebookWebWorkerMain.js'),
|
||||
label: 'NotebookEditorWorker'
|
||||
|
||||
@@ -12,7 +12,8 @@ import { OUTPUT_MODE_ID, LOG_MODE_ID } from '../../../services/output/common/out
|
||||
import { OutputLinkComputer } from '../common/outputLinkComputer.js';
|
||||
import { IDisposable, dispose, Disposable } from '../../../../base/common/lifecycle.js';
|
||||
import { ILanguageFeaturesService } from '../../../../editor/common/services/languageFeatures.js';
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from '../../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { IWebWorkerClient } from '../../../../base/common/worker/webWorker.js';
|
||||
import { WorkerTextModelSyncClient } from '../../../../editor/common/services/textModelSync/textModelSync.impl.js';
|
||||
import { FileAccess } from '../../../../base/common/network.js';
|
||||
@@ -29,6 +30,7 @@ export class OutputLinkProvider extends Disposable {
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@ILanguageFeaturesService private readonly languageFeaturesService: ILanguageFeaturesService,
|
||||
@IWebWorkerService private readonly webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -70,7 +72,7 @@ export class OutputLinkProvider extends Disposable {
|
||||
this.disposeWorkerScheduler.schedule();
|
||||
|
||||
if (!this.worker) {
|
||||
this.worker = new OutputLinkWorkerClient(this.contextService, this.modelService);
|
||||
this.worker = new OutputLinkWorkerClient(this.contextService, this.modelService, this.webWorkerService);
|
||||
}
|
||||
|
||||
return this.worker;
|
||||
@@ -96,9 +98,10 @@ class OutputLinkWorkerClient extends Disposable {
|
||||
constructor(
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IWebWorkerService webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
this._workerClient = this._register(createWebWorker<OutputLinkComputer>(
|
||||
this._workerClient = this._register(webWorkerService.createWorkerClient<OutputLinkComputer>(
|
||||
new WebWorkerDescriptor({
|
||||
esmModuleLocation: FileAccess.asBrowserUri('vs/workbench/contrib/output/common/outputLinkComputerMain.js'),
|
||||
label: 'OutputLinkDetectionWorker'
|
||||
|
||||
@@ -22,7 +22,8 @@ import { IStorageService, StorageScope, StorageTarget } from '../../../../platfo
|
||||
import { LRUCache } from '../../../../base/common/map.js';
|
||||
import { ILogService } from '../../../../platform/log/common/log.js';
|
||||
import { canASAR } from '../../../../amdX.js';
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from '../../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { WorkerTextModelSyncClient } from '../../../../editor/common/services/textModelSync/textModelSync.impl.js';
|
||||
import { ILanguageDetectionWorker, LanguageDetectionWorkerHost } from './languageDetectionWorker.protocol.js';
|
||||
|
||||
@@ -62,7 +63,8 @@ export class LanguageDetectionService extends Disposable implements ILanguageDet
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ILogService private readonly _logService: ILogService
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IWebWorkerService webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -71,6 +73,7 @@ export class LanguageDetectionService extends Disposable implements ILanguageDet
|
||||
modelService,
|
||||
languageService,
|
||||
telemetryService,
|
||||
webWorkerService,
|
||||
// TODO See if it's possible to bundle vscode-languagedetection
|
||||
useAsar
|
||||
? FileAccess.asBrowserUri(`${moduleLocationAsar}/dist/lib/index.js`).toString(true)
|
||||
@@ -187,6 +190,7 @@ export class LanguageDetectionWorkerClient extends Disposable {
|
||||
private readonly _modelService: IModelService,
|
||||
private readonly _languageService: ILanguageService,
|
||||
private readonly _telemetryService: ITelemetryService,
|
||||
private readonly _webWorkerService: IWebWorkerService,
|
||||
private readonly _indexJsUri: string,
|
||||
private readonly _modelJsonUri: string,
|
||||
private readonly _weightsUri: string,
|
||||
@@ -200,7 +204,7 @@ export class LanguageDetectionWorkerClient extends Disposable {
|
||||
workerTextModelSyncClient: WorkerTextModelSyncClient;
|
||||
} {
|
||||
if (!this.worker) {
|
||||
const workerClient = this._register(createWebWorker<ILanguageDetectionWorker>(
|
||||
const workerClient = this._register(this._webWorkerService.createWorkerClient<ILanguageDetectionWorker>(
|
||||
new WebWorkerDescriptor({
|
||||
esmModuleLocation: FileAccess.asBrowserUri('vs/workbench/services/languageDetection/browser/languageDetectionWebWorkerMain.js'),
|
||||
label: 'LanguageDetectionWorker'
|
||||
|
||||
@@ -16,7 +16,8 @@ import { SearchService } from '../common/searchService.js';
|
||||
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
|
||||
import { IWebWorkerClient, logOnceWebWorkerWarning } from '../../../../base/common/worker/webWorker.js';
|
||||
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from '../../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
|
||||
import { ILocalFileSearchWorker, LocalFileSearchWorkerHost } from '../common/localFileSearchWorkerTypes.js';
|
||||
import { memoize } from '../../../../base/common/decorators.js';
|
||||
@@ -60,6 +61,7 @@ export class LocalFileSearchWorkerClient extends Disposable implements ISearchRe
|
||||
constructor(
|
||||
@IFileService private fileService: IFileService,
|
||||
@IUriIdentityService private uriIdentityService: IUriIdentityService,
|
||||
@IWebWorkerService private webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
super();
|
||||
this._worker = null;
|
||||
@@ -187,7 +189,7 @@ export class LocalFileSearchWorkerClient extends Disposable implements ISearchRe
|
||||
private _getOrCreateWorker(): IWebWorkerClient<ILocalFileSearchWorker> {
|
||||
if (!this._worker) {
|
||||
try {
|
||||
this._worker = this._register(createWebWorker<ILocalFileSearchWorker>(
|
||||
this._worker = this._register(this.webWorkerService.createWorkerClient<ILocalFileSearchWorker>(
|
||||
new WebWorkerDescriptor({
|
||||
esmModuleLocation: FileAccess.asBrowserUri('vs/workbench/services/search/worker/localFileSearchMain.js'),
|
||||
label: 'LocalFileSearchWorker'
|
||||
|
||||
@@ -22,7 +22,8 @@ import { TextMateWorkerHost } from './worker/textMateWorkerHost.js';
|
||||
import { TextMateWorkerTokenizerController } from './textMateWorkerTokenizerController.js';
|
||||
import { IValidGrammarDefinition } from '../../common/TMScopeRegistry.js';
|
||||
import type { IRawTheme } from 'vscode-textmate';
|
||||
import { createWebWorker, WebWorkerDescriptor } from '../../../../../base/browser/webWorkerFactory.js';
|
||||
import { WebWorkerDescriptor } from '../../../../../platform/webWorker/browser/webWorkerDescriptor.js';
|
||||
import { IWebWorkerService } from '../../../../../platform/webWorker/browser/webWorkerService.js';
|
||||
import { IWebWorkerClient, Proxied } from '../../../../../base/common/worker/webWorker.js';
|
||||
|
||||
export class ThreadedBackgroundTokenizerFactory implements IDisposable {
|
||||
@@ -46,6 +47,7 @@ export class ThreadedBackgroundTokenizerFactory implements IDisposable {
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@IWebWorkerService private readonly _webWorkerService: IWebWorkerService,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -137,7 +139,7 @@ export class ThreadedBackgroundTokenizerFactory implements IDisposable {
|
||||
grammarDefinitions: this._grammarDefinitions,
|
||||
onigurumaWASMUri: FileAccess.asBrowserUri(onigurumaWASM).toString(true),
|
||||
};
|
||||
const worker = this._worker = createWebWorker<TextMateTokenizationWorker>(
|
||||
const worker = this._worker = this._webWorkerService.createWorkerClient<TextMateTokenizationWorker>(
|
||||
new WebWorkerDescriptor({
|
||||
esmModuleLocation: FileAccess.asBrowserUri('vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.workerMain.js'),
|
||||
label: 'TextMateWorker'
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IPaneCompositePartService } from '../../panecomposite/browser/panecompo
|
||||
import { ViewContainerLocation } from '../../../common/views.js';
|
||||
import { TelemetryTrustedValue } from '../../../../platform/telemetry/common/telemetryUtils.js';
|
||||
import { isWeb } from '../../../../base/common/platform.js';
|
||||
import { createBlobWorker } from '../../../../base/browser/webWorkerFactory.js';
|
||||
import { createBlobWorker } from '../../../../platform/webWorker/browser/webWorkerServiceImpl.js';
|
||||
import { Registry } from '../../../../platform/registry/common/platform.js';
|
||||
import { ITerminalBackendRegistry, TerminalExtensions } from '../../../../platform/terminal/common/terminal.js';
|
||||
|
||||
|
||||
@@ -159,6 +159,8 @@ import { AllowedExtensionsService } from '../platform/extensionManagement/common
|
||||
import { IAllowedMcpServersService, IMcpGalleryService } from '../platform/mcp/common/mcpManagement.js';
|
||||
import { McpGalleryService } from '../platform/mcp/common/mcpGalleryService.js';
|
||||
import { AllowedMcpServersService } from '../platform/mcp/common/allowedMcpServersService.js';
|
||||
import { IWebWorkerService } from '../platform/webWorker/browser/webWorkerService.js';
|
||||
import { WebWorkerService } from '../platform/webWorker/browser/webWorkerServiceImpl.js';
|
||||
|
||||
registerSingleton(IUserDataSyncLogService, UserDataSyncLogService, InstantiationType.Delayed);
|
||||
registerSingleton(IAllowedExtensionsService, AllowedExtensionsService, InstantiationType.Delayed);
|
||||
@@ -173,6 +175,7 @@ registerSingleton(IContextKeyService, ContextKeyService, InstantiationType.Delay
|
||||
registerSingleton(ITextResourceConfigurationService, TextResourceConfigurationService, InstantiationType.Delayed);
|
||||
registerSingleton(IDownloadService, DownloadService, InstantiationType.Delayed);
|
||||
registerSingleton(IOpenerService, OpenerService, InstantiationType.Delayed);
|
||||
registerSingleton(IWebWorkerService, WebWorkerService, InstantiationType.Delayed);
|
||||
registerSingleton(IMcpGalleryService, McpGalleryService, InstantiationType.Delayed);
|
||||
registerSingleton(IAllowedMcpServersService, AllowedMcpServersService, InstantiationType.Delayed);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user