diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 4ae98a95577..857114fea15 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -64,7 +64,7 @@ const vscodeResources = [ 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', 'out-build/vs/base/browser/ui/codicons/codicon/**', 'out-build/vs/base/parts/sandbox/electron-sandbox/preload.js', - 'out-build/vs/base/parts/sandbox/electron-sandbox/preload-slim.js', + 'out-build/vs/base/parts/sandbox/electron-sandbox/preload-aux.js', 'out-build/vs/workbench/browser/media/*-theme.css', 'out-build/vs/workbench/contrib/debug/**/*.json', 'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt', diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index d0ae5a5ff0e..2fd7a08808a 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -121,31 +121,11 @@ export const webFrame: WebFrame = globals.vscode.webFrame; export const process: ISandboxNodeProcess = globals.vscode.process; export const context: ISandboxContext = globals.vscode.context; -export interface IGlobalsSlim { +/** + * A set of globals that are available in all windows that either + * depend on `preload.js` or `preload-aux.js`. + */ +export interface ISandboxGlobals { readonly ipcRenderer: Pick; readonly webFrame: import('vs/base/parts/sandbox/electron-sandbox/electronTypes').WebFrame; } - -/** - * Get the globals that are available in the given window. Since - * this method supports auxiliary windows, only a subset of globals - * is returned. - */ -export function getGlobals(win: Window): IGlobalsSlim | undefined { - if (win === window) { - return { ipcRenderer, webFrame }; - } - - const auxiliaryWindowCandidate = win as unknown as { - vscode: { - ipcRenderer: Pick; - webFrame: import('vs/base/parts/sandbox/electron-sandbox/electronTypes').WebFrame; - }; - }; - - if (auxiliaryWindowCandidate?.vscode?.ipcRenderer && auxiliaryWindowCandidate?.vscode?.webFrame) { - return auxiliaryWindowCandidate.vscode; - } - - return undefined; -} diff --git a/src/vs/base/parts/sandbox/electron-sandbox/preload-slim.js b/src/vs/base/parts/sandbox/electron-sandbox/preload-aux.js similarity index 93% rename from src/vs/base/parts/sandbox/electron-sandbox/preload-slim.js rename to src/vs/base/parts/sandbox/electron-sandbox/preload-aux.js index 7b6256756ac..c73cabcdfa5 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/preload-slim.js +++ b/src/vs/base/parts/sandbox/electron-sandbox/preload-aux.js @@ -46,12 +46,12 @@ /** * @param {string} channel * @param {any[]} args - * @returns {Promise | never} + * @returns {Promise} */ invoke(channel, ...args) { - if (validateIPC(channel)) { - return ipcRenderer.invoke(channel, ...args); - } + validateIPC(channel); + + return ipcRenderer.invoke(channel, ...args); } }, diff --git a/src/vs/base/parts/sandbox/electron-sandbox/preload.js b/src/vs/base/parts/sandbox/electron-sandbox/preload.js index 0494b7ddda7..90ac940861f 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/preload.js +++ b/src/vs/base/parts/sandbox/electron-sandbox/preload.js @@ -56,24 +56,23 @@ } try { - if (validateIPC(windowConfigIpcChannel)) { + validateIPC(windowConfigIpcChannel); - // Resolve configuration from electron-main - configuration = await ipcRenderer.invoke(windowConfigIpcChannel); + // Resolve configuration from electron-main + const resolvedConfiguration = configuration = await ipcRenderer.invoke(windowConfigIpcChannel); - // Apply `userEnv` directly - Object.assign(process.env, configuration.userEnv); + // Apply `userEnv` directly + Object.assign(process.env, resolvedConfiguration.userEnv); - // Apply zoom level early before even building the - // window DOM elements to avoid UI flicker. We always - // have to set the zoom level from within the window - // because Chrome has it's own way of remembering zoom - // settings per origin (if vscode-file:// is used) and - // we want to ensure that the user configuration wins. - webFrame.setZoomLevel(configuration.zoomLevel ?? 0); + // Apply zoom level early before even building the + // window DOM elements to avoid UI flicker. We always + // have to set the zoom level from within the window + // because Chrome has it's own way of remembering zoom + // settings per origin (if vscode-file:// is used) and + // we want to ensure that the user configuration wins. + webFrame.setZoomLevel(resolvedConfiguration.zoomLevel ?? 0); - return configuration; - } + return resolvedConfiguration; } catch (error) { throw new Error(`Preload: unable to fetch vscode-window-config: ${error}`); } @@ -145,51 +144,51 @@ /** * @param {string} channel * @param {any[]} args - * @returns {Promise | never} + * @returns {Promise} */ invoke(channel, ...args) { - if (validateIPC(channel)) { - return ipcRenderer.invoke(channel, ...args); - } + validateIPC(channel); + + return ipcRenderer.invoke(channel, ...args); }, /** * @param {string} channel * @param {(event: IpcRendererEvent, ...args: any[]) => void} listener - * @returns {IpcRenderer | never} + * @returns {IpcRenderer} */ on(channel, listener) { - if (validateIPC(channel)) { - ipcRenderer.on(channel, listener); + validateIPC(channel); - return this; - } + ipcRenderer.on(channel, listener); + + return this; }, /** * @param {string} channel * @param {(event: IpcRendererEvent, ...args: any[]) => void} listener - * @returns {IpcRenderer | never} + * @returns {IpcRenderer} */ once(channel, listener) { - if (validateIPC(channel)) { - ipcRenderer.once(channel, listener); + validateIPC(channel); - return this; - } + ipcRenderer.once(channel, listener); + + return this; }, /** * @param {string} channel * @param {(event: IpcRendererEvent, ...args: any[]) => void} listener - * @returns {IpcRenderer | never} + * @returns {IpcRenderer} */ removeListener(channel, listener) { - if (validateIPC(channel)) { - ipcRenderer.removeListener(channel, listener); + validateIPC(channel); - return this; - } + ipcRenderer.removeListener(channel, listener); + + return this; } }, diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts index 01718d334cc..983494e1cf6 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts @@ -42,7 +42,7 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService createWindow(): BrowserWindowConstructorOptions { return this.instantiationService.invokeFunction(defaultBrowserWindowOptions, undefined, { webPreferences: { - preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-sandbox/preload-slim.js').fsPath + preload: FileAccess.asFileUri('vs/base/parts/sandbox/electron-sandbox/preload-aux.js').fsPath } }); } diff --git a/src/vs/platform/window/electron-sandbox/window.ts b/src/vs/platform/window/electron-sandbox/window.ts index b4c27b676f0..28968b4f9cc 100644 --- a/src/vs/platform/window/electron-sandbox/window.ts +++ b/src/vs/platform/window/electron-sandbox/window.ts @@ -5,7 +5,7 @@ import { getZoomLevel, setZoomFactor, setZoomLevel } from 'vs/base/browser/browser'; import { getWindows } from 'vs/base/browser/dom'; -import { getGlobals } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ISandboxGlobals, ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { zoomLevelToZoomFactor } from 'vs/platform/window/common/window'; /** @@ -20,6 +20,21 @@ export function applyZoom(zoomLevel: number): void { setZoomLevel(zoomLevel); } +function getGlobals(win: Window): ISandboxGlobals | undefined { + if (win === window) { + // main window + return { ipcRenderer, webFrame }; + } else { + // auxiliary window + const auxiliaryWindow = win as unknown as { vscode: ISandboxGlobals }; + if (auxiliaryWindow?.vscode?.ipcRenderer && auxiliaryWindow?.vscode?.webFrame) { + return auxiliaryWindow.vscode; + } + } + + return undefined; +} + export function zoomIn(): void { applyZoom(getZoomLevel() + 1); } diff --git a/src/vs/workbench/electron-sandbox/actions/windowActions.ts b/src/vs/workbench/electron-sandbox/actions/windowActions.ts index d7471d3cd8f..6535966e5b9 100644 --- a/src/vs/workbench/electron-sandbox/actions/windowActions.ts +++ b/src/vs/workbench/electron-sandbox/actions/windowActions.ts @@ -64,7 +64,7 @@ export class CloseWindowAction extends Action2 { const window = getActiveWindow(); if (isAuxiliaryWindow(window)) { - return nativeHostService.closeWindowById(await window.vscodeWindowId); + return nativeHostService.closeWindowById(window.vscodeWindowId); } return nativeHostService.closeWindow(); @@ -368,7 +368,7 @@ export class ExperimentalSplitWindowAction extends Action2 { let activeWindowId: number; const activeWindow = getActiveWindow(); if (isAuxiliaryWindow(activeWindow)) { - activeWindowId = await activeWindow.vscodeWindowId; + activeWindowId = activeWindow.vscodeWindowId; } else { activeWindowId = environmentService.window.id; } diff --git a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts index 4787b33d38a..717e29eabd9 100644 --- a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts +++ b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts @@ -6,23 +6,23 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { BrowserAuxiliaryWindowService, IAuxiliaryWindowService, AuxiliaryWindow as BaseAuxiliaryWindow } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService'; -import { getGlobals } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ISandboxGlobals } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWindowsConfiguration } from 'vs/platform/window/common/window'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { INativeHostService } from 'vs/platform/native/common/native'; -import { DeferredPromise } from 'vs/base/common/async'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { getActiveWindow } from 'vs/base/browser/dom'; type AuxiliaryWindow = BaseAuxiliaryWindow & { - readonly vscodeWindowId: Promise; + readonly vscode: ISandboxGlobals; + readonly vscodeWindowId: number; }; export function isAuxiliaryWindow(obj: unknown): obj is AuxiliaryWindow { const candidate = obj as AuxiliaryWindow | undefined; - return candidate?.vscodeWindowId instanceof Promise; + return !!candidate?.vscode && Object.hasOwn(candidate, 'vscodeWindowId'); } export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService { @@ -41,7 +41,7 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService // Zoom level const windowConfig = this.configurationService.getValue(); const windowZoomLevel = typeof windowConfig.window?.zoomLevel === 'number' ? windowConfig.window.zoomLevel : 0; - getGlobals(auxiliaryWindow)?.webFrame?.setZoomLevel(windowZoomLevel); + auxiliaryWindow.vscode.webFrame.setZoomLevel(windowZoomLevel); return super.create(auxiliaryWindow, disposables); } @@ -50,17 +50,14 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService super.patchMethods(auxiliaryWindow); // Obtain window identifier - const windowId = new DeferredPromise(); + let resolvedWindowId: number; (async () => { - windowId.complete(await getGlobals(auxiliaryWindow)?.ipcRenderer.invoke('vscode:getWindowId')); + resolvedWindowId = await auxiliaryWindow.vscode.ipcRenderer.invoke('vscode:getWindowId'); })(); // Add a `windowId` property Object.defineProperty(auxiliaryWindow, 'vscodeWindowId', { - value: windowId.p, - writable: false, - enumerable: false, - configurable: false + get: () => resolvedWindowId }); // Enable `window.focus()` to work in Electron by @@ -68,11 +65,11 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService // https://github.com/electron/electron/issues/25578 const that = this; const originalWindowFocus = auxiliaryWindow.focus.bind(auxiliaryWindow); - auxiliaryWindow.focus = async function () { + auxiliaryWindow.focus = function () { originalWindowFocus(); if (getActiveWindow() !== auxiliaryWindow) { - that.nativeHostService.focusWindow({ targetWindowId: await windowId.p }); + that.nativeHostService.focusWindow({ targetWindowId: resolvedWindowId }); } }; } diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 9c1cd113aaf..8909c6bd0f5 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -138,7 +138,7 @@ class WorkbenchHostService extends Disposable implements IHostService { return; // does not apply when only one window is opened } - return this.nativeHostService.moveWindowTop(isAuxiliaryWindow(window) ? { targetWindowId: await window.vscodeWindowId } : undefined); + return this.nativeHostService.moveWindowTop(isAuxiliaryWindow(window) ? { targetWindowId: window.vscodeWindowId } : undefined); } //#endregion