diff --git a/packages/client/src/vscode/services.ts b/packages/client/src/vscode/services.ts index 51e05b81e..77d962150 100644 --- a/packages/client/src/vscode/services.ts +++ b/packages/client/src/vscode/services.ts @@ -18,6 +18,7 @@ import type { EnvironmentOverride } from '@codingame/monaco-vscode-api/workbench import type { Logger } from 'monaco-languageclient/tools'; import { FakeWorker as Worker } from './fakeWorker.js'; import { setUnexpectedErrorHandler } from '@codingame/monaco-vscode-api/monaco'; +import { useWorkerFactory } from '../workerFactory.js'; export interface MonacoEnvironmentEnhanced extends monaco.Environment { vscodeInitialising?: boolean; @@ -50,11 +51,12 @@ export interface InitServicesInstructions { caller?: string; performServiceConsistencyChecks?: () => boolean; logger?: Logger; + monacoWorkerFactory?: (logger?: Logger) => void; } -export const initEnhancedMonacoEnvironment = () => { +export const getEnhancedMonacoEnvironment = (): MonacoEnvironmentEnhanced => { const monWin = (self as Window); - if (!monWin.MonacoEnvironment) { + if (monWin.MonacoEnvironment === undefined) { monWin.MonacoEnvironment = {}; } const envEnhanced = monWin.MonacoEnvironment as MonacoEnvironmentEnhanced; @@ -97,8 +99,15 @@ export const mergeServices = (overrideServices: monaco.editor.IEditorOverrideSer }; export const initServices = async (vscodeApiConfig: VscodeApiConfig, instructions?: InitServicesInstructions) => { - const envEnhanced = initEnhancedMonacoEnvironment(); + const envEnhanced = getEnhancedMonacoEnvironment(); + if (typeof instructions?.monacoWorkerFactory === 'function') { + instructions.monacoWorkerFactory(instructions.logger); + } else { + useWorkerFactory({ + logger: instructions?.logger + }); + } if (!(envEnhanced.vscodeInitialising ?? false)) { if (envEnhanced.vscodeApiInitialised ?? false) { diff --git a/packages/client/src/workerFactory.ts b/packages/client/src/workerFactory.ts index 47f2b2498..c94093a1c 100644 --- a/packages/client/src/workerFactory.ts +++ b/packages/client/src/workerFactory.ts @@ -3,24 +3,24 @@ * Licensed under the MIT License. See LICENSE in the package root for license information. * ------------------------------------------------------------------------------------------ */ -import { initEnhancedMonacoEnvironment } from 'monaco-languageclient/vscode/services'; +import { getEnhancedMonacoEnvironment } from 'monaco-languageclient/vscode/services'; import type { Logger } from 'monaco-languageclient/tools'; export type WorkerLoader = (() => Worker) | undefined; export interface WorkerFactoryConfig { - workerLoaders: Record; + workerLoaders?: Record; logger?: Logger; getWorkerOverride?: (moduleId: string, label: string) => Worker; } export const useWorkerFactory = (config: WorkerFactoryConfig) => { - const envEnhanced = initEnhancedMonacoEnvironment(); + const envEnhanced = getEnhancedMonacoEnvironment(); const getWorker = (moduleId: string, label: string) => { config.logger?.info(`getWorker: moduleId: ${moduleId} label: ${label}`); - const workerFunc = config.workerLoaders[label]; + const workerFunc = config.workerLoaders?.[label] ?? undefined; if (workerFunc === undefined) { throw new Error(`Unimplemented worker ${label} (${moduleId})`); } diff --git a/packages/client/test/vscode/services.test.ts b/packages/client/test/vscode/services.test.ts index 6160702db..5cf0b9159 100644 --- a/packages/client/test/vscode/services.test.ts +++ b/packages/client/test/vscode/services.test.ts @@ -6,7 +6,7 @@ import { describe, expect, test } from 'vitest'; import { initServices, type MonacoEnvironmentEnhanced } from 'monaco-languageclient/vscode/services'; -describe('VSCde services Tests', () => { +describe('VSCode services Tests', () => { test('initServices', async () => { const vscodeApiConfig = { diff --git a/packages/client/test/workerFactory.test.ts b/packages/client/test/workerFactory.test.ts new file mode 100644 index 000000000..3e55f8437 --- /dev/null +++ b/packages/client/test/workerFactory.test.ts @@ -0,0 +1,42 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) 2024 TypeFox and others. + * Licensed under the MIT License. See LICENSE in the package root for license information. + * ------------------------------------------------------------------------------------------ */ + +import { describe, expect, test } from 'vitest'; +import { LogLevel } from '@codingame/monaco-vscode-api'; +import { ConsoleLogger } from 'monaco-languageclient/tools'; +import { useWorkerFactory } from 'monaco-languageclient/workerFactory'; + +describe('WorkerFactory Tests', () => { + + test('useWorkerFactory: Nothing', () => { + + useWorkerFactory({}); + + const monWin = (self as Window); + const getWorker = () => monWin.MonacoEnvironment?.getWorker?.('test', 'TextEditorWorker'); + expect(getWorker).toThrowError('Unimplemented worker TextEditorWorker (test)'); + }); + + test('useWorkerFactory: TextEditorWorker', async () => { + const logger = new ConsoleLogger(LogLevel.Info); + + useWorkerFactory({ + workerLoaders: { + TextEditorWorker: () => new Worker( + new URL('@codingame/monaco-vscode-editor-api/esm/vs/editor/editor.worker.js', import.meta.url), + { type: 'module' } + ) + }, + logger + }); + + const monWin = (self as Window); + const getWorker = () => monWin.MonacoEnvironment?.getWorker?.('test', 'TextEditorWorker'); + const workerFunc = getWorker(); + expect(workerFunc).toBeDefined(); + expect(workerFunc).toBeInstanceOf(Worker); + }); + +}); diff --git a/packages/wrapper/src/wrapper.ts b/packages/wrapper/src/wrapper.ts index 58d9acb90..a30cf0319 100644 --- a/packages/wrapper/src/wrapper.ts +++ b/packages/wrapper/src/wrapper.ts @@ -100,11 +100,7 @@ export class MonacoEditorLanguageClientWrapper { this.markInitializing(); this.id = wrapperConfig.id ?? Math.floor(Math.random() * 1000001).toString(); - this.logger.setLevel(wrapperConfig.logLevel ?? LogLevel.Off); - if (typeof wrapperConfig.editorAppConfig?.monacoWorkerFactory === 'function') { - wrapperConfig.editorAppConfig.monacoWorkerFactory(this.logger); - } if (!(wrapperConfig.vscodeApiConfig?.vscodeApiInitPerformExternally === true)) { wrapperConfig.vscodeApiConfig = await augmentVscodeApiConfig(wrapperConfig.$type, { @@ -114,6 +110,7 @@ export class MonacoEditorLanguageClientWrapper { semanticHighlighting: wrapperConfig.editorAppConfig?.editorOptions?.['semanticHighlighting.enabled'] === true }); await initServices(wrapperConfig.vscodeApiConfig, { + monacoWorkerFactory: wrapperConfig.editorAppConfig?.monacoWorkerFactory, htmlContainer: wrapperConfig.htmlContainer, caller: `monaco-editor (${this.id})`, performServiceConsistencyChecks: checkServiceConsistency, diff --git a/packages/wrapper/test/wrapper.test.ts b/packages/wrapper/test/wrapper.test.ts index 004fbff82..5884a96aa 100644 --- a/packages/wrapper/test/wrapper.test.ts +++ b/packages/wrapper/test/wrapper.test.ts @@ -307,4 +307,18 @@ describe('Test MonacoEditorLanguageClientWrapper', () => { expect(error).toBe(false); }); + test('monacoWorkerFactory: Nothing', async () => { + const wrapperConfig = createWrapperConfigExtendedApp({}); + wrapperConfig.editorAppConfig!.monacoWorkerFactory = undefined; + + const wrapper = new MonacoEditorLanguageClientWrapper(); + await expect(await wrapper.init(wrapperConfig)).toBeUndefined(); + + const monWin = (self as Window); + const getWorker = () => monWin.MonacoEnvironment?.getWorker?.('test', 'TextEditorWorker'); + expect(getWorker).toThrowError('Unimplemented worker TextEditorWorker (test)'); + + await expect(await wrapper.start()).toBeUndefined(); + }); + }); diff --git a/vitest.config.ts b/vitest.config.ts index b7335fc85..7217b10e9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -29,6 +29,7 @@ export const vitestConfig = { }, // keep an explicit list of tests to run, so they can be commented in case of problems include: [ + '**/client/test/workerFactory.test.ts', '**/client/test/fs/endpoints/emptyEndpoint.test.ts', '**/client/test/tools/index.test.ts', '**/client/test/tools/utils.test.ts',