chore(vscode): update to 1.56.0

This commit is contained in:
Akash Satheesan
2021-04-30 20:25:17 +05:30
1749 changed files with 88014 additions and 43316 deletions

View File

@@ -72,7 +72,7 @@ export class Client extends IPCClient implements IDisposable {
this.protocol = protocol;
}
dispose(): void {
override dispose(): void {
this.protocol.disconnect();
}
}

View File

@@ -252,7 +252,7 @@ class ProtocolReader extends Disposable {
return this._incomingData.read(this._incomingData.byteLength);
}
public dispose(): void {
public override dispose(): void {
this._isDisposed = true;
super.dispose();
}
@@ -412,7 +412,7 @@ export class Client<TContext = string> extends IPCClient<TContext> {
super(protocol, id, ipcLogger);
}
dispose(): void {
override dispose(): void {
super.dispose();
const socket = this.protocol.getSocket();
this.protocol.sendDisconnect();

View File

@@ -32,7 +32,7 @@ export class Client extends IPCClient implements IDisposable {
this.protocol = protocol;
}
dispose(): void {
override dispose(): void {
this.protocol.disconnect();
}
}

View File

@@ -266,7 +266,7 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
this._register(this.socket.onClose(() => this._onClose.fire()));
}
public dispose(): void {
public override dispose(): void {
if (this._zlibDeflateFlushWaitingCount > 0) {
// Wait for any outstanding writes to finish before disposing
this._register(this._onDidZlibFlush.event(() => {
@@ -581,7 +581,7 @@ export class Server extends IPCServer {
this.server = server;
}
dispose(): void {
override dispose(): void {
super.dispose();
if (this.server) {
this.server.close();

View File

@@ -66,7 +66,7 @@ class TestIPCClient extends IPCClient<string> {
super(protocol, id);
}
dispose(): void {
override dispose(): void {
this._onDidDisconnect.fire();
super.dispose();
}
@@ -253,7 +253,7 @@ suite('Base IPC', function () {
test('call success', async function () {
const r = await ipcService.marco();
return assert.equal(r, 'polo');
return assert.strictEqual(r, 'polo');
});
test('call error', async function () {
@@ -261,7 +261,7 @@ suite('Base IPC', function () {
await ipcService.error('nice error');
return assert.fail('should not reach here');
} catch (err) {
return assert.equal(err.message, 'nice error');
return assert.strictEqual(err.message, 'nice error');
}
});
@@ -304,20 +304,20 @@ suite('Base IPC', function () {
ipcService.onPong(msg => messages.push(msg));
await timeout(0);
assert.deepEqual(messages, []);
assert.deepStrictEqual(messages, []);
service.ping('hello');
await timeout(0);
assert.deepEqual(messages, ['hello']);
assert.deepStrictEqual(messages, ['hello']);
service.ping('world');
await timeout(0);
assert.deepEqual(messages, ['hello', 'world']);
assert.deepStrictEqual(messages, ['hello', 'world']);
});
test('buffers in arrays', async function () {
const r = await ipcService.buffersLength([VSBuffer.alloc(2), VSBuffer.alloc(3)]);
return assert.equal(r, 5);
return assert.strictEqual(r, 5);
});
});
@@ -345,7 +345,7 @@ suite('Base IPC', function () {
test('call success', async function () {
const r = await ipcService.marco();
return assert.equal(r, 'polo');
return assert.strictEqual(r, 'polo');
});
test('call error', async function () {
@@ -353,7 +353,7 @@ suite('Base IPC', function () {
await ipcService.error('nice error');
return assert.fail('should not reach here');
} catch (err) {
return assert.equal(err.message, 'nice error');
return assert.strictEqual(err.message, 'nice error');
}
});
@@ -363,15 +363,15 @@ suite('Base IPC', function () {
ipcService.onPong(msg => messages.push(msg));
await timeout(0);
assert.deepEqual(messages, []);
assert.deepStrictEqual(messages, []);
service.ping('hello');
await timeout(0);
assert.deepEqual(messages, ['hello']);
assert.deepStrictEqual(messages, ['hello']);
service.ping('world');
await timeout(0);
assert.deepEqual(messages, ['hello', 'world']);
assert.deepStrictEqual(messages, ['hello', 'world']);
});
test('marshalling uri', async function () {
@@ -383,7 +383,7 @@ suite('Base IPC', function () {
test('buffers in arrays', async function () {
const r = await ipcService.buffersLength([VSBuffer.alloc(2), VSBuffer.alloc(3)]);
return assert.equal(r, 5);
return assert.strictEqual(r, 5);
});
});
@@ -411,7 +411,7 @@ suite('Base IPC', function () {
test('call extra context', async function () {
const r = await ipcService.context();
return assert.equal(r, 'Super Context');
return assert.strictEqual(r, 'Super Context');
});
});
@@ -461,7 +461,7 @@ suite('Base IPC', function () {
clientService1.ping('hello 1');
await timeout(1);
assert.deepEqual(pings, ['hello 1']);
assert.deepStrictEqual(pings, ['hello 1']);
const client2 = server.createConnection('client2');
const clientService2 = new TestService();
@@ -472,19 +472,19 @@ suite('Base IPC', function () {
clientService2.ping('hello 2');
await timeout(1);
assert.deepEqual(pings, ['hello 1', 'hello 2']);
assert.deepStrictEqual(pings, ['hello 1', 'hello 2']);
client1.dispose();
clientService1.ping('hello 1');
await timeout(1);
assert.deepEqual(pings, ['hello 1', 'hello 2']);
assert.deepStrictEqual(pings, ['hello 1', 'hello 2']);
await timeout(1);
clientService2.ping('hello again 2');
await timeout(1);
assert.deepEqual(pings, ['hello 1', 'hello 2', 'hello again 2']);
assert.deepStrictEqual(pings, ['hello 1', 'hello 2', 'hello again 2']);
client2.dispose();
server.dispose();

View File

@@ -22,8 +22,8 @@ suite('IPC, Child Process', () => {
const service = new TestServiceClient(channel);
const result = service.pong('ping').then(r => {
assert.equal(r.incoming, 'ping');
assert.equal(r.outgoing, 'pong');
assert.strictEqual(r.incoming, 'ping');
assert.strictEqual(r.outgoing, 'pong');
});
return result.finally(() => client.dispose());
@@ -37,7 +37,7 @@ suite('IPC, Child Process', () => {
const event = new Promise((c, e) => {
service.onMarco(({ answer }) => {
try {
assert.equal(answer, 'polo');
assert.strictEqual(answer, 'polo');
c(undefined);
} catch (err) {
e(err);
@@ -60,17 +60,17 @@ suite('IPC, Child Process', () => {
const disposable = service.onMarco(() => count++);
const result = service.marco().then(async answer => {
assert.equal(answer, 'polo');
assert.equal(count, 1);
assert.strictEqual(answer, 'polo');
assert.strictEqual(count, 1);
const answer_1 = await service.marco();
assert.equal(answer_1, 'polo');
assert.equal(count, 2);
assert.strictEqual(answer_1, 'polo');
assert.strictEqual(count, 2);
disposable.dispose();
const answer_2 = await service.marco();
assert.equal(answer_2, 'polo');
assert.equal(count, 2);
assert.strictEqual(answer_2, 'polo');
assert.strictEqual(count, 2);
});
return result.finally(() => client.dispose());

View File

@@ -14,6 +14,7 @@
.quick-input-titlebar {
display: flex;
align-items: center;
}
.quick-input-left-action-bar {
@@ -22,10 +23,6 @@
flex: 1;
}
.quick-input-left-action-bar.monaco-action-bar .actions-container {
justify-content: flex-start;
}
.quick-input-title {
padding: 3px 0px;
text-align: center;
@@ -37,12 +34,14 @@
flex: 1;
}
.quick-input-right-action-bar > .actions-container {
justify-content: flex-end;
}
.quick-input-titlebar .monaco-action-bar .action-label.codicon {
margin: 0;
width: 19px;
height: 100%;
background-position: center;
background-repeat: no-repeat;
padding: 2px;
}
.quick-input-description {
@@ -260,10 +259,8 @@
}
.quick-input-list .quick-input-list-entry-action-bar .action-label.codicon {
margin: 0;
height: 100%;
padding: 0 2px;
vertical-align: middle;
margin-right: 4px;
padding: 2px;
}
.quick-input-list .quick-input-list-entry-action-bar {
@@ -274,10 +271,6 @@
margin-right: 4px; /* separate from scrollbar */
}
.quick-input-list .quick-input-list-entry-action-bar .action-label.codicon {
margin-right: 4px; /* separate actions */
}
.quick-input-list .quick-input-list-entry .quick-input-list-entry-action-bar .action-label.always-visible,
.quick-input-list .quick-input-list-entry:hover .quick-input-list-entry-action-bar .action-label,
.quick-input-list .monaco-list-row.focused .quick-input-list-entry-action-bar .action-label {

View File

@@ -32,6 +32,7 @@ import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { escape } from 'vs/base/common/strings';
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
import { isString } from 'vs/base/common/types';
import { IKeybindingLabelStyles } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
export interface IQuickInputOptions {
idPrefix: string;
@@ -57,6 +58,7 @@ export interface IQuickInputStyles {
countBadge: ICountBadgetyles;
button: IButtonStyles;
progressBar: IProgressBarStyles;
keybindingLabel: IKeybindingLabelStyles;
list: IListStyles & { pickerGroupBorder?: Color; pickerGroupForeground?: Color; };
}
@@ -410,7 +412,7 @@ class QuickInput extends Disposable implements IQuickInput {
readonly onDispose = this.onDisposeEmitter.event;
dispose(): void {
override dispose(): void {
this.hide();
this.onDisposeEmitter.fire();
@@ -694,7 +696,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
}
}
show() {
override show() {
if (!this.visible) {
this.visibleDisposables.add(
this.ui.inputBox.onDidChange(value => {
@@ -884,20 +886,11 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
});
}
protected update() {
protected override update() {
if (!this.visible) {
return;
}
let hideInput = false;
let inputShownJustForScreenReader = false;
if (!!this._hideInput && this._items.length > 0) {
if (this.ui.isScreenReaderOptimized()) {
// Always show input if screen reader attached https://github.com/microsoft/vscode/issues/94360
inputShownJustForScreenReader = true;
} else {
hideInput = true;
}
}
const hideInput = !!this._hideInput && this._items.length > 0;
this.ui.container.classList.toggle('hidden-input', hideInput && !this.description);
const visibilities: Visibilities = {
title: !!this.title || !!this.step || !!this.buttons.length,
@@ -925,13 +918,9 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
if (this.ui.inputBox.placeholder !== (this.placeholder || '')) {
this.ui.inputBox.placeholder = (this.placeholder || '');
}
if (inputShownJustForScreenReader) {
this.ui.inputBox.ariaLabel = '';
} else {
const ariaLabel = this.ariaLabel || this.placeholder || QuickPick.DEFAULT_ARIA_LABEL;
if (this.ui.inputBox.ariaLabel !== ariaLabel) {
this.ui.inputBox.ariaLabel = ariaLabel;
}
const ariaLabel = this.ariaLabel || this.placeholder || QuickPick.DEFAULT_ARIA_LABEL;
if (this.ui.inputBox.ariaLabel !== ariaLabel) {
this.ui.inputBox.ariaLabel = ariaLabel;
}
this.ui.list.matchOnDescription = this.matchOnDescription;
this.ui.list.matchOnDetail = this.matchOnDetail;
@@ -1063,7 +1052,7 @@ class InputBox extends QuickInput implements IInputBox {
readonly onDidAccept = this.onDidAcceptEmitter.event;
show() {
override show() {
if (!this.visible) {
this.visibleDisposables.add(
this.ui.inputBox.onDidChange(value => {
@@ -1079,7 +1068,7 @@ class InputBox extends QuickInput implements IInputBox {
super.show();
}
protected update() {
protected override update() {
if (!this.visible) {
return;
}
@@ -1388,8 +1377,12 @@ export class QuickInputController extends Disposable {
const index = input.items.indexOf(event.item);
if (index !== -1) {
const items = input.items.slice();
items.splice(index, 1);
const removed = items.splice(index, 1);
const activeItems = input.activeItems.filter((ai) => ai !== removed[0]);
input.items = items;
if (activeItems) {
input.activeItems = activeItems;
}
}
}
})),
@@ -1729,6 +1722,34 @@ export class QuickInputController extends Disposable {
if (this.styles.list.pickerGroupForeground) {
content.push(`.quick-input-list .quick-input-list-separator { color: ${this.styles.list.pickerGroupForeground}; }`);
}
if (
this.styles.keybindingLabel.keybindingLabelBackground ||
this.styles.keybindingLabel.keybindingLabelBorder ||
this.styles.keybindingLabel.keybindingLabelBottomBorder ||
this.styles.keybindingLabel.keybindingLabelShadow ||
this.styles.keybindingLabel.keybindingLabelForeground
) {
content.push('.quick-input-list .monaco-keybinding > .monaco-keybinding-key {');
if (this.styles.keybindingLabel.keybindingLabelBackground) {
content.push(`background-color: ${this.styles.keybindingLabel.keybindingLabelBackground};`);
}
if (this.styles.keybindingLabel.keybindingLabelBorder) {
// Order matters here. `border-color` must come before `border-bottom-color`.
content.push(`border-color: ${this.styles.keybindingLabel.keybindingLabelBorder};`);
}
if (this.styles.keybindingLabel.keybindingLabelBottomBorder) {
content.push(`border-bottom-color: ${this.styles.keybindingLabel.keybindingLabelBottomBorder};`);
}
if (this.styles.keybindingLabel.keybindingLabelShadow) {
content.push(`box-shadow: inset 0 -1px 0 ${this.styles.keybindingLabel.keybindingLabelShadow};`);
}
if (this.styles.keybindingLabel.keybindingLabelForeground) {
content.push(`color: ${this.styles.keybindingLabel.keybindingLabelForeground};`);
}
content.push('}');
}
const newStyles = content.join('\n');
if (newStyles !== this.ui.styleSheet.textContent) {
this.ui.styleSheet.textContent = newStyles;

View File

@@ -27,6 +27,7 @@ import { IQuickInputOptions } from 'vs/base/parts/quickinput/browser/quickInput'
import { IListOptions, List, IListStyles, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
import { localize } from 'vs/nls';
import { getCodiconAriaLabel } from 'vs/base/common/codicons';
const $ = dom.$;
@@ -427,7 +428,7 @@ export class QuickInputList {
const saneDescription = item.description && item.description.replace(/\r?\n/g, ' ');
const saneDetail = item.detail && item.detail.replace(/\r?\n/g, ' ');
const saneAriaLabel = item.ariaLabel || [saneLabel, saneDescription, saneDetail]
.map(s => s && parseLabelWithIcons(s).text)
.map(s => getCodiconAriaLabel(s))
.filter(s => !!s)
.join(', ');
@@ -603,6 +604,7 @@ export class QuickInputList {
// Filter by value (since we support icons in labels, use $(..) aware fuzzy matching)
else {
let currentSeparator: IQuickPickSeparator | undefined;
this.elements.forEach(element => {
const labelHighlights = this.matchOnLabel ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneLabel))) : undefined;
const descriptionHighlights = this.matchOnDescription ? withNullAsUndefined(matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneDescription || ''))) : undefined;
@@ -621,6 +623,16 @@ export class QuickInputList {
element.hidden = !element.item.alwaysShow;
}
element.separator = undefined;
// we can show the separator unless the list gets sorted by match
if (!this.sortByLabel) {
const previous = element.index && this.inputElements[element.index - 1];
currentSeparator = previous && previous.type === 'separator' ? previous : currentSeparator;
if (currentSeparator && !element.hidden) {
element.separator = currentSeparator;
currentSeparator = undefined;
}
}
});
}

View File

@@ -363,7 +363,7 @@ export interface IQuickPickItemButtonContext<T extends IQuickPickItem> extends I
export type QuickPickInput<T = IQuickPickItem> = T | IQuickPickSeparator;
//region Fuzzy Scorer Support
//#region Fuzzy Scorer Support
export type IQuickPickItemWithResource = IQuickPickItem & { resource?: URI };

View File

@@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IProcessEnvironment } from 'vs/base/common/platform';
import { IProductConfiguration } from 'vs/base/common/product';
// #######################################################################
// ### ###
// ### Types we need in a common layer for reuse ###
// ### ###
// #######################################################################
/**
* The common properties required for any sandboxed
* renderer to function.
*/
export interface ISandboxConfiguration {
/**
* Identifier of the sandboxed renderer.
*/
windowId: number;
/**
* Absolute installation path.
*/
appRoot: string;
/**
* Per window process environment.
*/
userEnv: IProcessEnvironment;
/**
* Product configuration.
*/
product: IProductConfiguration;
/**
* Configured zoom level.
*/
zoomLevel?: number;
/**
* @deprecated to be removed soon
*/
nodeCachedDataDir?: string;
}

View File

@@ -9,6 +9,122 @@
const { ipcRenderer, webFrame, crashReporter, contextBridge } = require('electron');
//#region Utilities
/**
* @param {string} channel
* @returns {true | never}
*/
function validateIPC(channel) {
if (!channel || !channel.startsWith('vscode:')) {
throw new Error(`Unsupported event IPC channel '${channel}'`);
}
return true;
}
/**
* @param {string} type
* @returns {type is 'uncaughtException'}
*/
function validateProcessEventType(type) {
if (type !== 'uncaughtException') {
throw new Error(`Unsupported process event '${type}'`);
}
return true;
}
/**
* @param {string} key the name of the process argument to parse
* @returns {string | undefined}
*/
function parseArgv(key) {
for (const arg of process.argv) {
if (arg.indexOf(`--${key}=`) === 0) {
return arg.split('=')[1];
}
}
return undefined;
}
//#endregion
//#region Resolve Configuration
/**
* @typedef {import('../common/sandboxTypes').ISandboxConfiguration} ISandboxConfiguration
*/
/** @type {ISandboxConfiguration | undefined} */
let configuration = undefined;
/** @type {Promise<ISandboxConfiguration>} */
const resolveConfiguration = (async () => {
const windowConfigIpcChannel = parseArgv('vscode-window-config');
if (!windowConfigIpcChannel) {
throw new Error('Preload: did not find expected vscode-window-config in renderer process arguments list.');
}
try {
if (validateIPC(windowConfigIpcChannel)) {
// Resolve configuration from electron-main
configuration = await ipcRenderer.invoke(windowConfigIpcChannel);
// Apply `userEnv` directly
Object.assign(process.env, configuration.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);
return configuration;
}
} catch (error) {
throw new Error(`Preload: unable to fetch vscode-window-config: ${error}`);
}
})();
//#endregion
//#region Resolve Shell Environment
/**
* If VSCode is not run from a terminal, we should resolve additional
* shell specific environment from the OS shell to ensure we are seeing
* all development related environment variables. We do this from the
* main process because it may involve spawning a shell.
*
* @type {Promise<typeof process.env>}
*/
const resolveShellEnv = (async () => {
// Resolve `userEnv` from configuration and
// `shellEnv` from the main side
const [userEnv, shellEnv] = await Promise.all([
(async () => (await resolveConfiguration).userEnv)(),
ipcRenderer.invoke('vscode:fetchShellEnv')
]);
if (!process.env['VSCODE_SKIP_PROCESS_ENV_PATCHING'] /* TODO@bpasero for https://github.com/microsoft/vscode/issues/108804 */) {
// Assign all keys of the shell environment to our process environment
// But make sure that the user environment wins in the end over shell environment
Object.assign(process.env, shellEnv, userEnv);
}
return { ...process.env, ...shellEnv, ...userEnv };
})();
//#endregion
//#region Globals Definition
// #######################################################################
// ### ###
// ### !!! DO NOT USE GET/SET PROPERTIES ANYWHERE HERE !!! ###
@@ -17,14 +133,21 @@
// ### ###
// #######################################################################
/**
* @type {import('../electron-sandbox/globals')}
*/
const globals = {
/**
* A minimal set of methods exposed from Electron's `ipcRenderer`
* to support communication to main process.
*
* @type {import('../electron-sandbox/electronTypes').IpcRenderer}
* @typedef {import('../electron-sandbox/electronTypes').IpcRenderer} IpcRenderer
* @typedef {import('electron').IpcRendererEvent} IpcRendererEvent
*
* @type {IpcRenderer}
*/
ipcRenderer: {
/**
@@ -50,8 +173,8 @@
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
* @param {(event: IpcRendererEvent, ...args: any[]) => void} listener
* @returns {IpcRenderer}
*/
on(channel, listener) {
if (validateIPC(channel)) {
@@ -63,8 +186,8 @@
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
* @param {(event: IpcRendererEvent, ...args: any[]) => void} listener
* @returns {IpcRenderer}
*/
once(channel, listener) {
if (validateIPC(channel)) {
@@ -76,8 +199,8 @@
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
* @param {(event: IpcRendererEvent, ...args: any[]) => void} listener
* @returns {IpcRenderer}
*/
removeListener(channel, listener) {
if (validateIPC(channel)) {
@@ -100,7 +223,7 @@
*/
connect(channelRequest, channelResponse, requestNonce) {
if (validateIPC(channelRequest) && validateIPC(channelResponse)) {
const responseListener = (/** @type {import('electron').IpcRendererEvent} */ e, /** @type {string} */ responseNonce) => {
const responseListener = (/** @type {IpcRendererEvent} */ e, /** @type {string} */ responseNonce) => {
// validate that the nonce from the response is the same
// as when requested. and if so, use `postMessage` to
// send the `MessagePort` safely over, even when context
@@ -157,7 +280,9 @@
* Note: when `sandbox` is enabled, the only properties available
* are https://github.com/electron/electron/blob/master/docs/api/process.md#sandbox
*
* @type {import('../electron-sandbox/globals').ISandboxNodeProcess}
* @typedef {import('../electron-sandbox/globals').ISandboxNodeProcess} ISandboxNodeProcess
*
* @type {ISandboxNodeProcess}
*/
process: {
get platform() { return process.platform; },
@@ -178,16 +303,8 @@
/**
* @returns {Promise<typeof process.env>}
*/
getShellEnv() {
return shellEnv;
},
/**
* @param {{[key: string]: string}} userEnv
* @returns {Promise<void>}
*/
resolveEnv(userEnv) {
return resolveEnv(userEnv);
shellEnv() {
return resolveShellEnv;
},
/**
@@ -200,7 +317,7 @@
/**
* @param {string} type
* @param {Function} callback
* @returns {import('../electron-sandbox/globals').ISandboxNodeProcess}
* @returns {ISandboxNodeProcess}
*/
on(type, callback) {
if (validateProcessEventType(type)) {
@@ -210,6 +327,37 @@
return this;
}
}
},
/**
* Some information about the context we are running in.
*
* @type {import('../electron-sandbox/globals').ISandboxContext}
*/
context: {
/**
* A configuration object made accessible from the main side
* to configure the sandbox browser window.
*
* Note: intentionally not using a getter here because the
* actual value will be set after `resolveConfiguration`
* has finished.
*
* @returns {ISandboxConfiguration | undefined}
*/
configuration() {
return configuration;
},
/**
* Allows to await the resolution of the configuration object.
*
* @returns {Promise<ISandboxConfiguration>}
*/
async resolveConfiguration() {
return resolveConfiguration;
}
}
};
@@ -231,69 +379,4 @@
// @ts-ignore
window.vscode = globals;
}
//#region Utilities
/**
* @param {string} channel
* @returns {true | never}
*/
function validateIPC(channel) {
if (!channel || !channel.startsWith('vscode:')) {
throw new Error(`Unsupported event IPC channel '${channel}'`);
}
return true;
}
/**
* @param {string} type
* @returns {type is 'uncaughtException'}
*/
function validateProcessEventType(type) {
if (type !== 'uncaughtException') {
throw new Error(`Unsupported process event '${type}'`);
}
return true;
}
/** @type {Promise<typeof process.env> | undefined} */
let shellEnv = undefined;
/**
* If VSCode is not run from a terminal, we should resolve additional
* shell specific environment from the OS shell to ensure we are seeing
* all development related environment variables. We do this from the
* main process because it may involve spawning a shell.
*
* @param {{[key: string]: string}} userEnv
* @returns {Promise<void>}
*/
async function resolveEnv(userEnv) {
if (!shellEnv) {
// Apply `userEnv` directly
Object.assign(process.env, userEnv);
// Resolve `shellEnv` from the main side
shellEnv = new Promise(function (resolve) {
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnvResult) {
if (!process.env['VSCODE_SKIP_PROCESS_ENV_PATCHING'] /* TODO@bpasero for https://github.com/microsoft/vscode/issues/108804 */) {
// Assign all keys of the shell environment to our process environment
// But make sure that the user environment wins in the end over shell environment
Object.assign(process.env, shellEnvResult, userEnv);
}
resolve({ ...process.env, ...shellEnvResult, ...userEnv });
});
ipcRenderer.send('vscode:fetchShellEnv');
});
}
await shellEnv;
}
//#endregion
}());

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { globals, INodeProcess, IProcessEnvironment } from 'vs/base/common/platform';
import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes';
import { ProcessMemoryInfo, CrashReporter, IpcRenderer, WebFrame } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
/**
@@ -74,8 +75,8 @@ export interface ISandboxNodeProcess extends INodeProcess {
getProcessMemoryInfo: () => Promise<ProcessMemoryInfo>;
/**
* A custom method we add to `process`: Resolve the true process environment to use and
* apply it to `process.env`.
* Returns a process environment that includes all shell environment variables even if
* the application was not started from a shell / terminal / console.
*
* There are different layers of environment that will apply:
* - `process.env`: this is the actual environment of the process before this method
@@ -86,17 +87,8 @@ export interface ISandboxNodeProcess extends INodeProcess {
* from a terminal and changed certain variables
*
* The order of overwrites is `process.env` < `shellEnv` < `userEnv`.
*
* It is critical that every process awaits this method early on startup to get the right
* set of environment in `process.env`.
*/
resolveEnv(userEnv: IProcessEnvironment): Promise<void>;
/**
* Returns a process environment that includes any shell environment even if the application
* was not started from a shell / terminal / console.
*/
getShellEnv(): Promise<IProcessEnvironment>;
shellEnv(): Promise<IProcessEnvironment>;
}
export interface IpcMessagePort {
@@ -114,8 +106,24 @@ export interface IpcMessagePort {
connect(channelRequest: string, channelResponse: string, requestNonce: string): void;
}
export interface ISandboxContext {
/**
* A configuration object made accessible from the main side
* to configure the sandbox browser window. Will be `undefined`
* for as long as `resolveConfiguration` is not awaited.
*/
configuration(): ISandboxConfiguration | undefined;
/**
* Allows to await the resolution of the configuration object.
*/
resolveConfiguration(): Promise<ISandboxConfiguration>;
}
export const ipcRenderer: IpcRenderer = globals.vscode.ipcRenderer;
export const ipcMessagePort: IpcMessagePort = globals.vscode.ipcMessagePort;
export const webFrame: WebFrame = globals.vscode.webFrame;
export const crashReporter: CrashReporter = globals.vscode.crashReporter;
export const process: ISandboxNodeProcess = globals.vscode.process;
export const context: ISandboxContext = globals.vscode.context;

View File

@@ -4,13 +4,17 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ipcRenderer, crashReporter, webFrame, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { ipcRenderer, crashReporter, webFrame, context, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
suite('Sandbox', () => {
test('globals', () => {
test('globals', async () => {
assert.ok(typeof ipcRenderer.send === 'function');
assert.ok(typeof crashReporter.addExtraParameter === 'function');
assert.ok(typeof webFrame.setZoomLevel === 'function');
assert.ok(typeof process.platform === 'string');
const config = await context.resolveConfiguration();
assert.ok(config);
assert.ok(context.configuration());
});
});

View File

@@ -320,7 +320,7 @@ export class Storage extends Disposable implements IStorage {
return new Promise(resolve => this.whenFlushedCallbacks.push(resolve));
}
dispose(): void {
override dispose(): void {
this.flushDelayer.cancel(); // workaround https://github.com/microsoft/vscode/issues/116777
this.flushDelayer.dispose();

View File

@@ -111,7 +111,7 @@ flakySuite('Storage Library', function () {
class TestSQLiteStorageDatabase extends SQLiteStorageDatabase {
private readonly _onDidChangeItemsExternal = new Emitter<IStorageItemsChangeEvent>();
get onDidChangeItemsExternal(): Event<IStorageItemsChangeEvent> { return this._onDidChangeItemsExternal.event; }
override get onDidChangeItemsExternal(): Event<IStorageItemsChangeEvent> { return this._onDidChangeItemsExternal.event; }
fireDidChangeItemsExternal(event: IStorageItemsChangeEvent): void {
this._onDidChangeItemsExternal.fire(event);