chore(vscode): update to 1.55.2
This commit is contained in:
@@ -18,13 +18,31 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Platform, platform } from 'vs/base/common/platform';
|
||||
|
||||
export class NodeSocket implements ISocket {
|
||||
|
||||
public readonly socket: Socket;
|
||||
private readonly _errorListener: (err: any) => void;
|
||||
|
||||
constructor(socket: Socket) {
|
||||
this.socket = socket;
|
||||
this._errorListener = (err: any) => {
|
||||
if (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// An EPIPE exception at the wrong time can lead to a renderer process crash
|
||||
// so ignore the error since the socket will fire the close event soon anyways:
|
||||
// > https://nodejs.org/api/errors.html#errors_common_system_errors
|
||||
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
|
||||
// > process to read the data. Commonly encountered at the net and http layers,
|
||||
// > indicative that the remote side of the stream being written to has been closed.
|
||||
return;
|
||||
}
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
};
|
||||
this.socket.on('error', this._errorListener);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.socket.off('error', this._errorListener);
|
||||
this.socket.destroy();
|
||||
}
|
||||
|
||||
@@ -62,7 +80,20 @@ export class NodeSocket implements ISocket {
|
||||
// > However, the false return value is only advisory and the writable stream will unconditionally
|
||||
// > accept and buffer chunk even if it has not been allowed to drain.
|
||||
try {
|
||||
this.socket.write(<Buffer>buffer.buffer);
|
||||
this.socket.write(<Buffer>buffer.buffer, (err: any) => {
|
||||
if (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// An EPIPE exception at the wrong time can lead to a renderer process crash
|
||||
// so ignore the error since the socket will fire the close event soon anyways:
|
||||
// > https://nodejs.org/api/errors.html#errors_common_system_errors
|
||||
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
|
||||
// > process to read the data. Commonly encountered at the net and http layers,
|
||||
// > indicative that the remote side of the stream being written to has been closed.
|
||||
return;
|
||||
}
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// An EPIPE exception at the wrong time can lead to a renderer process crash
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
|
||||
import { TestServiceClient } from './testService';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
|
||||
|
||||
function createClient(): Client {
|
||||
return new Client(getPathFromAmdModule(require, 'bootstrap-fork'), {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
position: absolute;
|
||||
width: 600px;
|
||||
z-index: 2000;
|
||||
padding-bottom: 6px;
|
||||
padding: 0 1px 6px 1px;
|
||||
left: 50%;
|
||||
margin-left: -300px;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/quickInput';
|
||||
import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation, QuickInputHideReason, IQuickInputHideEvent } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { QuickInputList, QuickInputListFocus } from './quickInputList';
|
||||
@@ -31,6 +31,7 @@ import { registerCodicon, Codicon } from 'vs/base/common/codicons';
|
||||
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';
|
||||
|
||||
export interface IQuickInputOptions {
|
||||
idPrefix: string;
|
||||
@@ -133,6 +134,7 @@ type Visibilities = {
|
||||
};
|
||||
|
||||
class QuickInput extends Disposable implements IQuickInput {
|
||||
protected static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel");
|
||||
|
||||
private _title: string | undefined;
|
||||
private _description: string | undefined;
|
||||
@@ -144,9 +146,14 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
private _busy = false;
|
||||
private _ignoreFocusOut = false;
|
||||
private _buttons: IQuickInputButton[] = [];
|
||||
protected noValidationMessage = QuickInput.noPromptMessage;
|
||||
private _validationMessage: string | undefined;
|
||||
private _lastValidationMessage: string | undefined;
|
||||
private _severity: Severity = Severity.Ignore;
|
||||
private _lastSeverity: Severity | undefined;
|
||||
private buttonsUpdated = false;
|
||||
private readonly onDidTriggerButtonEmitter = this._register(new Emitter<IQuickInputButton>());
|
||||
private readonly onDidHideEmitter = this._register(new Emitter<void>());
|
||||
private readonly onDidHideEmitter = this._register(new Emitter<IQuickInputHideEvent>());
|
||||
private readonly onDisposeEmitter = this._register(new Emitter<void>());
|
||||
|
||||
protected readonly visibleDisposables = this._register(new DisposableStore());
|
||||
@@ -241,6 +248,24 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
this.update();
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._validationMessage;
|
||||
}
|
||||
|
||||
set validationMessage(validationMessage: string | undefined) {
|
||||
this._validationMessage = validationMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get severity() {
|
||||
return this._severity;
|
||||
}
|
||||
|
||||
set severity(severity: Severity) {
|
||||
this._severity = severity;
|
||||
this.update();
|
||||
}
|
||||
|
||||
readonly onDidTriggerButton = this.onDidTriggerButtonEmitter.event;
|
||||
|
||||
show(): void {
|
||||
@@ -266,10 +291,10 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
this.ui.hide();
|
||||
}
|
||||
|
||||
didHide(): void {
|
||||
didHide(reason = QuickInputHideReason.Other): void {
|
||||
this.visible = false;
|
||||
this.visibleDisposables.clear();
|
||||
this.onDidHideEmitter.fire();
|
||||
this.onDidHideEmitter.fire({ reason });
|
||||
}
|
||||
|
||||
readonly onDidHide = this.onDidHideEmitter.event;
|
||||
@@ -328,6 +353,16 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
this.ui.ignoreFocusOut = this.ignoreFocusOut;
|
||||
this.ui.setEnabled(this.enabled);
|
||||
this.ui.setContextKey(this.contextKey);
|
||||
|
||||
const validationMessage = this.validationMessage || this.noValidationMessage;
|
||||
if (this._lastValidationMessage !== validationMessage) {
|
||||
this._lastValidationMessage = validationMessage;
|
||||
dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage)));
|
||||
}
|
||||
if (this._lastSeverity !== this.severity) {
|
||||
this._lastSeverity = this.severity;
|
||||
this.showMessageDecoration(this.severity);
|
||||
}
|
||||
}
|
||||
|
||||
private getTitle() {
|
||||
@@ -359,7 +394,7 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
|
||||
protected showMessageDecoration(severity: Severity) {
|
||||
this.ui.inputBox.showDecoration(severity);
|
||||
if (severity === Severity.Error) {
|
||||
if (severity !== Severity.Ignore) {
|
||||
const styles = this.ui.inputBox.stylesForType(severity);
|
||||
this.ui.message.style.color = styles.foreground ? `${styles.foreground}` : '';
|
||||
this.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : '';
|
||||
@@ -414,8 +449,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
private readonly onDidTriggerItemButtonEmitter = this._register(new Emitter<IQuickPickItemButtonEvent<T>>());
|
||||
private _valueSelection: Readonly<[number, number]> | undefined;
|
||||
private valueSelectionUpdated = true;
|
||||
private _validationMessage: string | undefined;
|
||||
private _lastValidationMessage: string | undefined;
|
||||
private _ok: boolean | 'default' = 'default';
|
||||
private _customButton = false;
|
||||
private _customButtonLabel: string | undefined;
|
||||
@@ -587,15 +620,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this.update();
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._validationMessage;
|
||||
}
|
||||
|
||||
set validationMessage(validationMessage: string | undefined) {
|
||||
this._validationMessage = validationMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get customButton() {
|
||||
return this._customButton;
|
||||
}
|
||||
@@ -964,12 +988,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this.selectedItemsToConfirm = null;
|
||||
}
|
||||
}
|
||||
const validationMessage = this.validationMessage || '';
|
||||
if (this._lastValidationMessage !== validationMessage) {
|
||||
this._lastValidationMessage = validationMessage;
|
||||
dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage)));
|
||||
this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore);
|
||||
}
|
||||
this.ui.customButton.label = this.customLabel || '';
|
||||
this.ui.customButton.element.title = this.customHover || '';
|
||||
this.ui.setComboboxAccessibility(true);
|
||||
@@ -987,18 +1005,12 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
}
|
||||
|
||||
class InputBox extends QuickInput implements IInputBox {
|
||||
|
||||
private static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel");
|
||||
|
||||
private _value = '';
|
||||
private _valueSelection: Readonly<[number, number]> | undefined;
|
||||
private valueSelectionUpdated = true;
|
||||
private _placeholder: string | undefined;
|
||||
private _password = false;
|
||||
private _prompt: string | undefined;
|
||||
private noValidationMessage = InputBox.noPromptMessage;
|
||||
private _validationMessage: string | undefined;
|
||||
private _lastValidationMessage: string | undefined;
|
||||
private readonly onDidValueChangeEmitter = this._register(new Emitter<string>());
|
||||
private readonly onDidAcceptEmitter = this._register(new Emitter<void>());
|
||||
|
||||
@@ -1043,16 +1055,7 @@ class InputBox extends QuickInput implements IInputBox {
|
||||
this._prompt = prompt;
|
||||
this.noValidationMessage = prompt
|
||||
? localize('inputModeEntryDescription', "{0} (Press 'Enter' to confirm or 'Escape' to cancel)", prompt)
|
||||
: InputBox.noPromptMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._validationMessage;
|
||||
}
|
||||
|
||||
set validationMessage(validationMessage: string | undefined) {
|
||||
this._validationMessage = validationMessage;
|
||||
: QuickInput.noPromptMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
@@ -1100,12 +1103,7 @@ class InputBox extends QuickInput implements IInputBox {
|
||||
if (this.ui.inputBox.password !== this.password) {
|
||||
this.ui.inputBox.password = this.password;
|
||||
}
|
||||
const validationMessage = this.validationMessage || this.noValidationMessage;
|
||||
if (this._lastValidationMessage !== validationMessage) {
|
||||
this._lastValidationMessage = validationMessage;
|
||||
dom.reset(this.ui.message, ...renderLabelWithIcons(validationMessage));
|
||||
this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1222,9 +1220,6 @@ export class QuickInputController extends Disposable {
|
||||
|
||||
const message = dom.append(extraContainer, $(`#${this.idPrefix}message.quick-input-message`));
|
||||
|
||||
const progressBar = new ProgressBar(container);
|
||||
progressBar.getContainer().classList.add('quick-input-progress');
|
||||
|
||||
const list = this._register(new QuickInputList(container, this.idPrefix + 'list', this.options));
|
||||
this._register(list.onChangedAllVisibleChecked(checked => {
|
||||
checkAll.checked = checked;
|
||||
@@ -1250,6 +1245,9 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
}));
|
||||
|
||||
const progressBar = new ProgressBar(container);
|
||||
progressBar.getContainer().classList.add('quick-input-progress');
|
||||
|
||||
const focusTracker = dom.trackFocus(container);
|
||||
this._register(focusTracker);
|
||||
this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, e => {
|
||||
@@ -1257,7 +1255,7 @@ export class QuickInputController extends Disposable {
|
||||
}, true));
|
||||
this._register(focusTracker.onDidBlur(() => {
|
||||
if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) {
|
||||
this.hide();
|
||||
this.hide(QuickInputHideReason.Blur);
|
||||
}
|
||||
this.previousFocusElement = undefined;
|
||||
}));
|
||||
@@ -1273,7 +1271,7 @@ export class QuickInputController extends Disposable {
|
||||
break;
|
||||
case KeyCode.Escape:
|
||||
dom.EventHelper.stop(e, true);
|
||||
this.hide();
|
||||
this.hide(QuickInputHideReason.Gesture);
|
||||
break;
|
||||
case KeyCode.Tab:
|
||||
if (!event.altKey && !event.ctrlKey && !event.metaKey) {
|
||||
@@ -1320,8 +1318,8 @@ export class QuickInputController extends Disposable {
|
||||
message,
|
||||
customButtonContainer,
|
||||
customButton,
|
||||
progressBar,
|
||||
list,
|
||||
progressBar,
|
||||
onDidAccept: this.onDidAcceptEmitter.event,
|
||||
onDidCustom: this.onDidCustomEmitter.event,
|
||||
onDidTriggerButton: this.onDidTriggerButtonEmitter.event,
|
||||
@@ -1408,6 +1406,7 @@ export class QuickInputController extends Disposable {
|
||||
resolve(undefined);
|
||||
}),
|
||||
];
|
||||
input.title = options.title;
|
||||
input.canSelectMany = !!options.canPickMany;
|
||||
input.placeholder = options.placeHolder;
|
||||
input.ignoreFocusOut = !!options.ignoreFocusLost;
|
||||
@@ -1438,6 +1437,22 @@ export class QuickInputController extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private setValidationOnInput(input: IInputBox, validationResult: string | {
|
||||
content: string;
|
||||
severity: Severity;
|
||||
} | null | undefined) {
|
||||
if (validationResult && isString(validationResult)) {
|
||||
input.severity = Severity.Error;
|
||||
input.validationMessage = validationResult;
|
||||
} else if (validationResult && !isString(validationResult)) {
|
||||
input.severity = validationResult.severity;
|
||||
input.validationMessage = validationResult.content;
|
||||
} else {
|
||||
input.severity = Severity.Ignore;
|
||||
input.validationMessage = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
input(options: IInputOptions = {}, token: CancellationToken = CancellationToken.None): Promise<string | undefined> {
|
||||
return new Promise<string | undefined>((resolve) => {
|
||||
if (token.isCancellationRequested) {
|
||||
@@ -1458,7 +1473,7 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
validation.then(result => {
|
||||
if (value === validationValue) {
|
||||
input.validationMessage = result || undefined;
|
||||
this.setValidationOnInput(input, result);
|
||||
}
|
||||
});
|
||||
}),
|
||||
@@ -1469,11 +1484,11 @@ export class QuickInputController extends Disposable {
|
||||
validationValue = value;
|
||||
}
|
||||
validation.then(result => {
|
||||
if (!result) {
|
||||
if (!result || (!isString(result) && result.severity !== Severity.Error)) {
|
||||
resolve(value);
|
||||
input.hide();
|
||||
} else if (value === validationValue) {
|
||||
input.validationMessage = result;
|
||||
this.setValidationOnInput(input, result);
|
||||
}
|
||||
});
|
||||
}),
|
||||
@@ -1485,6 +1500,8 @@ export class QuickInputController extends Disposable {
|
||||
resolve(undefined);
|
||||
}),
|
||||
];
|
||||
|
||||
input.title = options.title;
|
||||
input.value = options.value || '';
|
||||
input.valueSelection = options.valueSelection;
|
||||
input.prompt = options.prompt;
|
||||
@@ -1600,7 +1617,7 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
hide() {
|
||||
hide(reason?: QuickInputHideReason) {
|
||||
const controller = this.controller;
|
||||
if (controller) {
|
||||
const focusChanged = !this.ui?.container.contains(document.activeElement);
|
||||
@@ -1615,7 +1632,7 @@ export class QuickInputController extends Disposable {
|
||||
this.options.returnFocus();
|
||||
}
|
||||
}
|
||||
controller.didHide();
|
||||
controller.didHide(reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IMatch } from 'vs/base/common/filters';
|
||||
import { IItemAccessor } from 'vs/base/common/fuzzyScorer';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
export interface IQuickPickItemHighlights {
|
||||
label?: IMatch[];
|
||||
@@ -58,6 +59,11 @@ export interface IQuickNavigateConfiguration {
|
||||
|
||||
export interface IPickOptions<T extends IQuickPickItem> {
|
||||
|
||||
/**
|
||||
* an optional string to show as the title of the quick input
|
||||
*/
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* an optional string to show as placeholder in the input box to guide the user what she picks on
|
||||
*/
|
||||
@@ -115,6 +121,11 @@ export interface IPickOptions<T extends IQuickPickItem> {
|
||||
|
||||
export interface IInputOptions {
|
||||
|
||||
/**
|
||||
* an optional string to show as the title of the quick input
|
||||
*/
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* the value to prefill in the input box
|
||||
*/
|
||||
@@ -145,12 +156,34 @@ export interface IInputOptions {
|
||||
/**
|
||||
* an optional function that is used to validate user input.
|
||||
*/
|
||||
validateInput?: (input: string) => Promise<string | null | undefined>;
|
||||
validateInput?: (input: string) => Promise<string | null | undefined | { content: string, severity: Severity }>;
|
||||
}
|
||||
|
||||
export enum QuickInputHideReason {
|
||||
|
||||
/**
|
||||
* Focus moved away from the quick input.
|
||||
*/
|
||||
Blur = 1,
|
||||
|
||||
/**
|
||||
* An explicit user gesture, e.g. pressing Escape key.
|
||||
*/
|
||||
Gesture,
|
||||
|
||||
/**
|
||||
* Anything else.
|
||||
*/
|
||||
Other
|
||||
}
|
||||
|
||||
export interface IQuickInputHideEvent {
|
||||
reason: QuickInputHideReason;
|
||||
}
|
||||
|
||||
export interface IQuickInput extends IDisposable {
|
||||
|
||||
readonly onDidHide: Event<void>;
|
||||
readonly onDidHide: Event<IQuickInputHideEvent>;
|
||||
readonly onDispose: Event<void>;
|
||||
|
||||
title: string | undefined;
|
||||
@@ -301,6 +334,8 @@ export interface IInputBox extends IQuickInput {
|
||||
prompt: string | undefined;
|
||||
|
||||
validationMessage: string | undefined;
|
||||
|
||||
severity: Severity;
|
||||
}
|
||||
|
||||
export interface IQuickInputButton {
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
/**
|
||||
* A minimal set of methods exposed from Electron's `ipcRenderer`
|
||||
* to support communication to main process.
|
||||
*
|
||||
* @type {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
ipcRenderer: {
|
||||
|
||||
@@ -49,34 +51,46 @@
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
|
||||
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
on(channel, listener) {
|
||||
if (validateIPC(channel)) {
|
||||
ipcRenderer.on(channel, listener);
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
|
||||
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
once(channel, listener) {
|
||||
if (validateIPC(channel)) {
|
||||
ipcRenderer.once(channel, listener);
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
|
||||
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
removeListener(channel, listener) {
|
||||
if (validateIPC(channel)) {
|
||||
ipcRenderer.removeListener(channel, listener);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../electron-sandbox/globals').IpcMessagePort}
|
||||
*/
|
||||
ipcMessagePort: {
|
||||
|
||||
/**
|
||||
@@ -106,6 +120,8 @@
|
||||
|
||||
/**
|
||||
* Support for subset of methods of Electron's `webFrame` type.
|
||||
*
|
||||
* @type {import('../electron-sandbox/electronTypes').WebFrame}
|
||||
*/
|
||||
webFrame: {
|
||||
|
||||
@@ -121,6 +137,8 @@
|
||||
|
||||
/**
|
||||
* Support for subset of methods of Electron's `crashReporter` type.
|
||||
*
|
||||
* @type {import('../electron-sandbox/electronTypes').CrashReporter}
|
||||
*/
|
||||
crashReporter: {
|
||||
|
||||
@@ -138,6 +156,8 @@
|
||||
*
|
||||
* 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}
|
||||
*/
|
||||
process: {
|
||||
get platform() { return process.platform; },
|
||||
@@ -146,6 +166,21 @@
|
||||
get versions() { return process.versions; },
|
||||
get type() { return 'renderer'; },
|
||||
get execPath() { return process.execPath; },
|
||||
get sandboxed() { return process.sandboxed; },
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
cwd() {
|
||||
return process.env['VSCODE_CWD'] || process.execPath.substr(0, process.execPath.lastIndexOf(process.platform === 'win32' ? '\\' : '/'));
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {Promise<typeof process.env>}
|
||||
*/
|
||||
getShellEnv() {
|
||||
return shellEnv;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{[key: string]: string}} userEnv
|
||||
@@ -164,20 +199,17 @@
|
||||
|
||||
/**
|
||||
* @param {string} type
|
||||
* @param {() => void} callback
|
||||
* @param {Function} callback
|
||||
* @returns {import('../electron-sandbox/globals').ISandboxNodeProcess}
|
||||
*/
|
||||
on(type, callback) {
|
||||
if (validateProcessEventType(type)) {
|
||||
// @ts-ignore
|
||||
process.on(type, callback);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Some information about the context we are running in.
|
||||
*/
|
||||
context: {
|
||||
get sandbox() { return process.sandboxed; }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -226,8 +258,8 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @type {Promise<void> | undefined} */
|
||||
let resolvedEnv = undefined;
|
||||
/** @type {Promise<typeof process.env> | undefined} */
|
||||
let shellEnv = undefined;
|
||||
|
||||
/**
|
||||
* If VSCode is not run from a terminal, we should resolve additional
|
||||
@@ -238,28 +270,29 @@
|
||||
* @param {{[key: string]: string}} userEnv
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function resolveEnv(userEnv) {
|
||||
if (!resolvedEnv) {
|
||||
async function resolveEnv(userEnv) {
|
||||
if (!shellEnv) {
|
||||
|
||||
// Apply `userEnv` directly
|
||||
Object.assign(process.env, userEnv);
|
||||
|
||||
// Resolve `shellEnv` from the main side
|
||||
resolvedEnv = new Promise(function (resolve) {
|
||||
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
|
||||
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);
|
||||
}
|
||||
|
||||
// Assign all keys of the shell environment to our process environment
|
||||
// But make sure that the user environment wins in the end
|
||||
Object.assign(process.env, shellEnv, userEnv);
|
||||
|
||||
resolve();
|
||||
resolve({ ...process.env, ...shellEnvResult, ...userEnv });
|
||||
});
|
||||
|
||||
ipcRenderer.send('vscode:fetchShellEnv');
|
||||
});
|
||||
}
|
||||
|
||||
return resolvedEnv;
|
||||
await shellEnv;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { globals, IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { globals, INodeProcess, IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { ProcessMemoryInfo, CrashReporter, IpcRenderer, WebFrame } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
|
||||
|
||||
/**
|
||||
* In sandboxed renderers we cannot expose all of the `process` global of node.js
|
||||
*/
|
||||
export interface IPartialNodeProcess {
|
||||
export interface ISandboxNodeProcess extends INodeProcess {
|
||||
|
||||
/**
|
||||
* The process.platform property returns a string identifying the operating system platform
|
||||
* on which the Node.js process is running.
|
||||
*/
|
||||
readonly platform: 'win32' | 'linux' | 'darwin';
|
||||
readonly platform: string;
|
||||
|
||||
/**
|
||||
* The process.arch property returns a string identifying the CPU architecture
|
||||
@@ -24,9 +24,14 @@ export interface IPartialNodeProcess {
|
||||
readonly arch: string;
|
||||
|
||||
/**
|
||||
* The type will always be Electron renderer.
|
||||
* The type will always be `renderer`.
|
||||
*/
|
||||
readonly type: 'renderer';
|
||||
readonly type: string;
|
||||
|
||||
/**
|
||||
* Whether the process is sandboxed or not.
|
||||
*/
|
||||
readonly sandboxed: boolean;
|
||||
|
||||
/**
|
||||
* A list of versions for the current node.js/electron configuration.
|
||||
@@ -48,6 +53,11 @@ export interface IPartialNodeProcess {
|
||||
*/
|
||||
on: (type: string, callback: Function) => void;
|
||||
|
||||
/**
|
||||
* The current working directory of the process.
|
||||
*/
|
||||
cwd: () => string;
|
||||
|
||||
/**
|
||||
* Resolves with a ProcessMemoryInfo
|
||||
*
|
||||
@@ -62,9 +72,6 @@ export interface IPartialNodeProcess {
|
||||
* process on macOS.
|
||||
*/
|
||||
getProcessMemoryInfo: () => Promise<ProcessMemoryInfo>;
|
||||
}
|
||||
|
||||
export interface ISandboxNodeProcess extends IPartialNodeProcess {
|
||||
|
||||
/**
|
||||
* A custom method we add to `process`: Resolve the true process environment to use and
|
||||
@@ -84,14 +91,12 @@ export interface ISandboxNodeProcess extends IPartialNodeProcess {
|
||||
* set of environment in `process.env`.
|
||||
*/
|
||||
resolveEnv(userEnv: IProcessEnvironment): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ISandboxContext {
|
||||
|
||||
/**
|
||||
* Whether the renderer runs with `sandbox` enabled or not.
|
||||
* Returns a process environment that includes any shell environment even if the application
|
||||
* was not started from a shell / terminal / console.
|
||||
*/
|
||||
sandbox: boolean;
|
||||
getShellEnv(): Promise<IProcessEnvironment>;
|
||||
}
|
||||
|
||||
export interface IpcMessagePort {
|
||||
@@ -114,4 +119,3 @@ 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;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ipcRenderer, crashReporter, webFrame, process } from 'vs/base/parts/san
|
||||
|
||||
suite('Sandbox', () => {
|
||||
test('globals', () => {
|
||||
assert.ok(typeof ipcRenderer.invoke === 'function');
|
||||
assert.ok(typeof ipcRenderer.send === 'function');
|
||||
assert.ok(typeof crashReporter.addExtraParameter === 'function');
|
||||
assert.ok(typeof webFrame.setZoomLevel === 'function');
|
||||
assert.ok(typeof process.platform === 'string');
|
||||
|
||||
Reference in New Issue
Block a user