Change:
Steps to Reproduce: = workbench does not open From: Workaround:
I think depending on is logically correct. But, in web is depending on other workbench services like --and causing cycle. Not having consistent base services in desktop and web is causing confusion and debt and it might add up as we evolve. I think fixing in is just a patch. To unblock for now, I removed the dependency on and used . Assigning back to you for fixing this in .

Discussion:
import { IUserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; <del> import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; </del> <ins> import { IHostService } from 'vs/workbench/services/host/browser/host'; </ins> const SOURCE = 'IWorkbenchExtensionEnablementService';

@IUserDataSyncAccountService private readonly userDataSyncAccountService: IUserDataSyncAccountService, @ILifecycleService private readonly lifecycleService: ILifecycleService, @INotificationService private readonly notificationService: INotificationService, <del> @IInstantiationService instantiationService: IInstantiationService, </del> <ins> @IHostService hostService: IHostService, </ins> ) { super(); this.storageManger = this._register(new StorageManager(storageService));

this.lifecycleService.when(LifecyclePhase.Restored).then(() => { this.notificationService.prompt(Severity.Info, localize('extensionsDisabled', "All installed extensions are temporarily disabled. Reload the window to return to the previous state."), [{ label: localize('Reload', "Reload"), <del> // Using ReloadWindowAction because depending on IHostService causes cyclic dependency - #108522 run: () => instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL).run() </del> <ins> run: () => hostService.reload() </ins> }]); }); }

import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; <ins> import { IHostService } from 'vs/workbench/services/host/browser/host'; </ins> function createStorageService(instantiationService: TestInstantiationService): IStorageService { let service = instantiationService.get(IStorageService);

instantiationService.get(IUserDataSyncAccountService) || instantiationService.stub(IUserDataSyncAccountService, UserDataSyncAccountService), instantiationService.get(ILifecycleService) || instantiationService.stub(ILifecycleService, new TestLifecycleService()), instantiationService.get(INotificationService) || instantiationService.stub(INotificationService, new TestNotificationService()), <del> instantiationService, </del> <ins> instantiationService.get(IHostService) </ins> ); }

constructor( @ILayoutService private readonly layoutService: ILayoutService, <del> @IEditorService private readonly editorService: IEditorService, </del> @IConfigurationService private readonly configurationService: IConfigurationService, @IFileService private readonly fileService: IFileService, @ILabelService private readonly labelService: ILabelService,

// Handle Folders to Add if (foldersToAdd.length > 0) { this.instantiationService.invokeFunction(accessor => { <del> const workspaceEditingService: IWorkspaceEditingService = accessor.get(IWorkspaceEditingService); </del> <ins> const workspaceEditingService: IWorkspaceEditingService = accessor.get(IWorkspaceEditingService);  // avoid heavy dependencies (https://github.com/microsoft/vscode/issues/108522) </ins> workspaceEditingService.addFolders(foldersToAdd); }); } // Handle Files if (fileOpenables.length > 0) { <del> // Support diffMode if (options?.diffMode && fileOpenables.length === 2) { const editors = await pathsToEditors(fileOpenables, this.fileService); if (editors.length !== 2 || !editors[0].resource || !editors[1].resource) { return; // invalid resources } // Same Window: open via editor service in current window if (this.shouldReuse(options, true /* file */)) { this.editorService.openEditor({ leftResource: editors[0].resource, rightResource: editors[1].resource }); } // New Window: open into empty window else { const environment = new Map<string, string>(); environment.set('diffFileSecondary', editors[0].resource.toString()); environment.set('diffFilePrimary', editors[1].resource.toString()); this.doOpen(undefined, { payload: Array.from(environment.entries()) }); } } // Just open normally else { for (const openable of fileOpenables) { </del> <ins> this.instantiationService.invokeFunction(async accessor => { const editorService = accessor.get(IEditorService); // avoid heavy dependencies (https://github.com/microsoft/vscode/issues/108522) // Support diffMode if (options?.diffMode && fileOpenables.length === 2) { const editors = await pathsToEditors(fileOpenables, this.fileService); if (editors.length !== 2 || !editors[0].resource || !editors[1].resource) { return; // invalid resources } </ins> // Same Window: open via editor service in current window if (this.shouldReuse(options, true /* file */)) { <del> let openables: IPathData[] = []; // Support: --goto parameter to open on line/col if (options?.gotoLineMode) { const pathColumnAware = parseLineAndColumnAware(openable.fileUri.path); openables = [{ fileUri: openable.fileUri.with({ path: pathColumnAware.path }), lineNumber: pathColumnAware.line, columnNumber: pathColumnAware.column }]; } else { openables = [openable]; } this.editorService.openEditors(await pathsToEditors(openables, this.fileService)); </del> <ins> editorService.openEditor({ leftResource: editors[0].resource, rightResource: editors[1].resource }); </ins> } // New Window: open into empty window else { const environment = new Map<string, string>(); <del> environment.set('openFile', openable.fileUri.toString()); </del> <ins> environment.set('diffFileSecondary', editors[0].resource.toString()); environment.set('diffFilePrimary', editors[1].resource.toString()); </ins> <del> if (options?.gotoLineMode) { environment.set('gotoLineMode', 'true'); </del> <ins> this.doOpen(undefined, { payload: Array.from(environment.entries()) }); } } // Just open normally else { for (const openable of fileOpenables) { // Same Window: open via editor service in current window if (this.shouldReuse(options, true /* file */)) { let openables: IPathData[] = []; // Support: --goto parameter to open on line/col if (options?.gotoLineMode) { const pathColumnAware = parseLineAndColumnAware(openable.fileUri.path); openables = [{ fileUri: openable.fileUri.with({ path: pathColumnAware.path }), lineNumber: pathColumnAware.line, columnNumber: pathColumnAware.column }]; } else { openables = [openable]; } editorService.openEditors(await pathsToEditors(openables, this.fileService)); </ins> } <del> this.doOpen(undefined, { payload: Array.from(environment.entries()) }); </del> <ins> // New Window: open into empty window else { const environment = new Map<string, string>(); environment.set('openFile', openable.fileUri.toString()); if (options?.gotoLineMode) { environment.set('gotoLineMode', 'true'); } this.doOpen(undefined, { payload: Array.from(environment.entries()) }); } </ins> } } <del> } // Support wait mode const waitMarkerFileURI = options?.waitMarkerFileURI; if (waitMarkerFileURI) { (async () => { </del> <ins> // Support wait mode const waitMarkerFileURI = options?.waitMarkerFileURI; if (waitMarkerFileURI) { (async () => { </ins> <del> // Wait for the resources to be closed in the editor... await this.editorService.whenClosed(fileOpenables.map(openable => ({ resource: openable.fileUri })), { waitForSaved: true }); </del> <ins> // Wait for the resources to be closed in the editor... await editorService.whenClosed(fileOpenables.map(openable => ({ resource: openable.fileUri })), { waitForSaved: true }); </ins> <del> // ...before deleting the wait marker file await this.fileService.del(waitMarkerFileURI); })(); } </del> <ins> // ...before deleting the wait marker file await this.fileService.del(waitMarkerFileURI); })(); } }); </ins> } }