Archived
1
0

Merge commit 'be3e8236086165e5e45a5a10783823874b3f3ebd' as 'lib/vscode'

This commit is contained in:
Joe Previte
2020-12-15 15:52:33 -07:00
4649 changed files with 1311795 additions and 0 deletions

View File

@ -0,0 +1,253 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// #######################################################################
// ### ###
// ### electron.d.ts types we need in a common layer for reuse ###
// ### (copied from Electron 9.x) ###
// ### ###
// #######################################################################
export interface MessageBoxOptions {
/**
* Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows,
* `"question"` displays the same icon as `"info"`, unless you set an icon using
* the `"icon"` option. On macOS, both `"warning"` and `"error"` display the same
* warning icon.
*/
type?: string;
/**
* Array of texts for buttons. On Windows, an empty array will result in one button
* labeled "OK".
*/
buttons?: string[];
/**
* Index of the button in the buttons array which will be selected by default when
* the message box opens.
*/
defaultId?: number;
/**
* Title of the message box, some platforms will not show it.
*/
title?: string;
/**
* Content of the message box.
*/
message: string;
/**
* Extra information of the message.
*/
detail?: string;
/**
* If provided, the message box will include a checkbox with the given label.
*/
checkboxLabel?: string;
/**
* Initial checked state of the checkbox. `false` by default.
*/
checkboxChecked?: boolean;
// icon?: NativeImage;
/**
* The index of the button to be used to cancel the dialog, via the `Esc` key. By
* default this is assigned to the first button with "cancel" or "no" as the label.
* If no such labeled buttons exist and this option is not set, `0` will be used as
* the return value.
*/
cancelId?: number;
/**
* On Windows Electron will try to figure out which one of the `buttons` are common
* buttons (like "Cancel" or "Yes"), and show the others as command links in the
* dialog. This can make the dialog appear in the style of modern Windows apps. If
* you don't like this behavior, you can set `noLink` to `true`.
*/
noLink?: boolean;
/**
* Normalize the keyboard access keys across platforms. Default is `false`.
* Enabling this assumes `&` is used in the button labels for the placement of the
* keyboard shortcut access key and labels will be converted so they work correctly
* on each platform, `&` characters are removed on macOS, converted to `_` on
* Linux, and left untouched on Windows. For example, a button label of `Vie&w`
* will be converted to `Vie_w` on Linux and `View` on macOS and can be selected
* via `Alt-W` on Windows and Linux.
*/
normalizeAccessKeys?: boolean;
}
export interface MessageBoxReturnValue {
/**
* The index of the clicked button.
*/
response: number;
/**
* The checked state of the checkbox if `checkboxLabel` was set. Otherwise `false`.
*/
checkboxChecked: boolean;
}
export interface OpenDevToolsOptions {
/**
* Opens the devtools with specified dock state, can be `right`, `bottom`,
* `undocked`, `detach`. Defaults to last used dock state. In `undocked` mode it's
* possible to dock back. In `detach` mode it's not.
*/
mode: ('right' | 'bottom' | 'undocked' | 'detach');
/**
* Whether to bring the opened devtools window to the foreground. The default is
* `true`.
*/
activate?: boolean;
}
export interface SaveDialogOptions {
title?: string;
/**
* Absolute directory path, absolute file path, or file name to use by default.
*/
defaultPath?: string;
/**
* Custom label for the confirmation button, when left empty the default label will
* be used.
*/
buttonLabel?: string;
filters?: FileFilter[];
/**
* Message to display above text fields.
*
* @platform darwin
*/
message?: string;
/**
* Custom label for the text displayed in front of the filename text field.
*
* @platform darwin
*/
nameFieldLabel?: string;
/**
* Show the tags input box, defaults to `true`.
*
* @platform darwin
*/
showsTagField?: boolean;
properties?: Array<'showHiddenFiles' | 'createDirectory' | 'treatPackageAsDirectory' | 'showOverwriteConfirmation' | 'dontAddToRecent'>;
/**
* Create a security scoped bookmark when packaged for the Mac App Store. If this
* option is enabled and the file doesn't already exist a blank file will be
* created at the chosen path.
*
* @platform darwin,mas
*/
securityScopedBookmarks?: boolean;
}
export interface OpenDialogOptions {
title?: string;
defaultPath?: string;
/**
* Custom label for the confirmation button, when left empty the default label will
* be used.
*/
buttonLabel?: string;
filters?: FileFilter[];
/**
* Contains which features the dialog should use. The following values are
* supported:
*/
properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory' | 'dontAddToRecent'>;
/**
* Message to display above input boxes.
*
* @platform darwin
*/
message?: string;
/**
* Create security scoped bookmarks when packaged for the Mac App Store.
*
* @platform darwin,mas
*/
securityScopedBookmarks?: boolean;
}
export interface OpenDialogReturnValue {
/**
* whether or not the dialog was canceled.
*/
canceled: boolean;
/**
* An array of file paths chosen by the user. If the dialog is cancelled this will
* be an empty array.
*/
filePaths: string[];
/**
* An array matching the `filePaths` array of base64 encoded strings which contains
* security scoped bookmark data. `securityScopedBookmarks` must be enabled for
* this to be populated. (For return values, see table here.)
*
* @platform darwin,mas
*/
bookmarks?: string[];
}
export interface SaveDialogReturnValue {
/**
* whether or not the dialog was canceled.
*/
canceled: boolean;
/**
* If the dialog is canceled, this will be `undefined`.
*/
filePath?: string;
/**
* Base64 encoded string which contains the security scoped bookmark data for the
* saved file. `securityScopedBookmarks` must be enabled for this to be present.
* (For return values, see table here.)
*
* @platform darwin,mas
*/
bookmark?: string;
}
export interface FileFilter {
// Docs: http://electronjs.org/docs/api/structures/file-filter
extensions: string[];
name: string;
}
export interface InputEvent {
// Docs: http://electronjs.org/docs/api/structures/input-event
/**
* An array of modifiers of the event, can be `shift`, `control`, `ctrl`, `alt`,
* `meta`, `command`, `cmd`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`,
* `middleButtonDown`, `rightButtonDown`, `capsLock`, `numLock`, `left`, `right`.
*/
modifiers?: Array<'shift' | 'control' | 'ctrl' | 'alt' | 'meta' | 'command' | 'cmd' | 'isKeypad' | 'isAutoRepeat' | 'leftButtonDown' | 'middleButtonDown' | 'rightButtonDown' | 'capsLock' | 'numLock' | 'left' | 'right'>;
}
export interface MouseInputEvent extends InputEvent {
// Docs: http://electronjs.org/docs/api/structures/mouse-input-event
/**
* The button pressed, can be `left`, `middle`, `right`.
*/
button?: ('left' | 'middle' | 'right');
clickCount?: number;
globalX?: number;
globalY?: number;
movementX?: number;
movementY?: number;
/**
* The type of the event, can be `mouseDown`, `mouseUp`, `mouseEnter`,
* `mouseLeave`, `contextMenu`, `mouseWheel` or `mouseMove`.
*/
type: ('mouseDown' | 'mouseUp' | 'mouseEnter' | 'mouseLeave' | 'contextMenu' | 'mouseWheel' | 'mouseMove');
x: number;
y: number;
}

View File

@ -0,0 +1,250 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// @ts-check
(function () {
'use strict';
const { ipcRenderer, webFrame, crashReporter, contextBridge } = require('electron');
// #######################################################################
// ### ###
// ### !!! DO NOT USE GET/SET PROPERTIES ANYWHERE HERE !!! ###
// ### !!! UNLESS THE ACCESS IS WITHOUT SIDE EFFECTS !!! ###
// ### (https://github.com/electron/electron/issues/25516) ###
// ### ###
// #######################################################################
const globals = {
/**
* A minimal set of methods exposed from Electron's `ipcRenderer`
* to support communication to main process.
*/
ipcRenderer: {
/**
* @param {string} channel
* @param {any[]} args
*/
send(channel, ...args) {
if (validateIPC(channel)) {
ipcRenderer.send(channel, ...args);
}
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
*/
on(channel, listener) {
if (validateIPC(channel)) {
ipcRenderer.on(channel, listener);
}
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
*/
once(channel, listener) {
if (validateIPC(channel)) {
ipcRenderer.once(channel, listener);
}
},
/**
* @param {string} channel
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
*/
removeListener(channel, listener) {
if (validateIPC(channel)) {
ipcRenderer.removeListener(channel, listener);
}
}
},
/**
* Support for subset of methods of Electron's `webFrame` type.
*/
webFrame: {
/**
* @param {number} level
*/
setZoomLevel(level) {
if (typeof level === 'number') {
webFrame.setZoomLevel(level);
}
}
},
/**
* Support for subset of methods of Electron's `crashReporter` type.
*/
crashReporter: {
/**
* @param {string} key
* @param {string} value
*/
addExtraParameter(key, value) {
crashReporter.addExtraParameter(key, value);
}
},
/**
* Support for a subset of access to node.js global `process`.
*/
process: {
get platform() { return process.platform; },
get env() { return process.env; },
get versions() { return process.versions; },
get type() { return 'renderer'; },
_whenEnvResolved: undefined,
whenEnvResolved:
/**
* @returns when the shell environment has been resolved.
*/
function () {
if (!this._whenEnvResolved) {
this._whenEnvResolved = resolveEnv();
}
return this._whenEnvResolved;
},
nextTick:
/**
* Adds callback to the "next tick queue". This queue is fully drained
* after the current operation on the JavaScript stack runs to completion
* and before the event loop is allowed to continue.
*
* @param {Function} callback
* @param {any[]} args
*/
function nextTick(callback, ...args) {
return process.nextTick(callback, ...args);
},
cwd:
/**
* @returns the current working directory.
*/
function () {
return process.cwd();
},
getuid:
/**
* @returns the numeric user identity of the process
*/
function () {
return process.getuid();
},
getProcessMemoryInfo:
/**
* @returns {Promise<import('electron').ProcessMemoryInfo>}
*/
function () {
return process.getProcessMemoryInfo();
},
on:
/**
* @param {string} type
* @param {() => void} callback
*/
function (type, callback) {
if (validateProcessEventType(type)) {
process.on(type, callback);
}
}
},
/**
* Some information about the context we are running in.
*/
context: {
get sandbox() { return process.argv.includes('--enable-sandbox'); }
}
};
// Use `contextBridge` APIs to expose globals to VSCode
// only if context isolation is enabled, otherwise just
// add to the DOM global.
let useContextBridge = process.argv.includes('--context-isolation');
if (useContextBridge) {
try {
contextBridge.exposeInMainWorld('vscode', globals);
} catch (error) {
console.error(error);
useContextBridge = false;
}
}
if (!useContextBridge) {
// @ts-ignore
window.vscode = globals;
}
//#region Utilities
/**
* @param {string} channel
*/
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;
}
/**
* 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.
*/
function resolveEnv() {
return new Promise(function (resolve) {
const handle = setTimeout(function () {
console.warn('Preload: Unable to resolve shell environment in a reasonable time');
// It took too long to fetch the shell environment, return
resolve();
}, 3000);
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
clearTimeout(handle);
// Assign all keys of the shell environment to our process environment
Object.assign(process.env, shellEnv);
resolve();
});
ipcRenderer.send('vscode:fetchShellEnv');
});
}
//#endregion
}());

View File

@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// #######################################################################
// ### ###
// ### electron.d.ts types we expose from electron-sandbox ###
// ### (copied from Electron 9.x) ###
// ### ###
// #######################################################################
export interface IpcRenderer {
/**
* Listens to `channel`, when a new message arrives `listener` would be called with
* `listener(event, args...)`.
*/
on(channel: string, listener: (event: unknown, ...args: any[]) => void): void;
/**
* Adds a one time `listener` function for the event. This `listener` is invoked
* only the next time a message is sent to `channel`, after which it is removed.
*/
once(channel: string, listener: (event: unknown, ...args: any[]) => void): void;
/**
* Removes the specified `listener` from the listener array for the specified
* `channel`.
*/
removeListener(channel: string, listener: (event: unknown, ...args: any[]) => void): void;
/**
* Send an asynchronous message to the main process via `channel`, along with
* arguments. Arguments will be serialized with the Structured Clone Algorithm,
* just like `postMessage`, so prototype chains will not be included. Sending
* Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.
*
* > **NOTE**: Sending non-standard JavaScript types such as DOM objects or special
* Electron objects is deprecated, and will begin throwing an exception starting
* with Electron 9.
*
* The main process handles it by listening for `channel` with the `ipcMain`
* module.
*/
send(channel: string, ...args: any[]): void;
}
export interface WebFrame {
/**
* Changes the zoom level to the specified level. The original size is 0 and each
* increment above or below represents zooming 20% larger or smaller to default
* limits of 300% and 50% of original size, respectively.
*/
setZoomLevel(level: number): void;
}
export interface CrashReporter {
/**
* Set an extra parameter to be sent with the crash report. The values specified
* here will be sent in addition to any values set via the `extra` option when
* `start` was called.
*
* Parameters added in this fashion (or via the `extra` parameter to
* `crashReporter.start`) are specific to the calling process. Adding extra
* parameters in the main process will not cause those parameters to be sent along
* with crashes from renderer or other child processes. Similarly, adding extra
* parameters in a renderer process will not result in those parameters being sent
* with crashes that occur in other renderer processes or in the main process.
*
* **Note:** Parameters have limits on the length of the keys and values. Key names
* must be no longer than 39 bytes, and values must be no longer than 127 bytes.
* Keys with names longer than the maximum will be silently ignored. Key values
* longer than the maximum length will be truncated.
*/
addExtraParameter(key: string, value: string): void;
}
export interface ProcessMemoryInfo {
// Docs: http://electronjs.org/docs/api/structures/process-memory-info
/**
* The amount of memory not shared by other processes, such as JS heap or HTML
* content in Kilobytes.
*/
private: number;
/**
* The amount of memory currently pinned to actual physical RAM in Kilobytes.
*
* @platform linux,win32
*/
residentSet: number;
/**
* The amount of memory shared between processes, typically memory consumed by the
* Electron code itself in Kilobytes.
*/
shared: number;
}
export interface CrashReporterStartOptions {
/**
* URL that crash reports will be sent to as POST.
*/
submitURL: string;
/**
* Defaults to `app.name`.
*/
productName?: string;
/**
* Deprecated alias for `{ globalExtra: { _companyName: ... } }`.
*
* @deprecated
*/
companyName?: string;
/**
* Whether crash reports should be sent to the server. If false, crash reports will
* be collected and stored in the crashes directory, but not uploaded. Default is
* `true`.
*/
uploadToServer?: boolean;
/**
* If true, crashes generated in the main process will not be forwarded to the
* system crash handler. Default is `false`.
*/
ignoreSystemCrashHandler?: boolean;
/**
* If true, limit the number of crashes uploaded to 1/hour. Default is `false`.
*
* @platform darwin,win32
*/
rateLimit?: boolean;
/**
* If true, crash reports will be compressed and uploaded with `Content-Encoding:
* gzip`. Not all collection servers support compressed payloads. Default is
* `false`.
*
* @platform darwin,win32
*/
compress?: boolean;
/**
* Extra string key/value annotations that will be sent along with crash reports
* that are generated in the main process. Only string values are supported.
* Crashes generated in child processes will not contain these extra parameters to
* crash reports generated from child processes, call `addExtraParameter` from the
* child process.
*/
extra?: Record<string, string>;
/**
* Extra string key/value annotations that will be sent along with any crash
* reports generated in any process. These annotations cannot be changed once the
* crash reporter has been started. If a key is present in both the global extra
* parameters and the process-specific extra parameters, then the global one will
* take precedence. By default, `productName` and the app version are included, as
* well as the Electron version.
*/
globalExtra?: Record<string, string>;
}
/**
* Additional information around a `app.on('login')` event.
*/
export interface AuthInfo {
isProxy: boolean;
scheme: string;
host: string;
port: number;
realm: string;
}

View File

@ -0,0 +1,88 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { globals, INodeProcess, IProcessEnvironment } from 'vs/base/common/platform';
import { ProcessMemoryInfo, CrashReporter, IpcRenderer, WebFrame } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
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.
*/
platform: 'win32' | 'linux' | 'darwin';
/**
* The type will always be Electron renderer.
*/
type: 'renderer';
/**
* A list of versions for the current node.js/electron configuration.
*/
versions: { [key: string]: string | undefined };
/**
* The process.env property returns an object containing the user environment.
*/
env: IProcessEnvironment;
/**
* The current working directory.
*/
cwd(): string;
/**
* Returns the numeric user identity of the process.
*/
getuid(): number;
/**
* Allows to await resolving the full process environment by checking for the shell environment
* of the OS in certain cases (e.g. when the app is started from the Dock on macOS).
*/
whenEnvResolved(): Promise<void>;
/**
* Adds callback to the "next tick queue". This queue is fully drained
* after the current operation on the JavaScript stack runs to completion
* and before the event loop is allowed to continue.
*/
nextTick(callback: (...args: any[]) => void, ...args: any[]): void;
/**
* A listener on the process. Only a small subset of listener types are allowed.
*/
on: (type: string, callback: Function) => void;
/**
* Resolves with a ProcessMemoryInfo
*
* Returns an object giving memory usage statistics about the current process. Note
* that all statistics are reported in Kilobytes. This api should be called after
* app ready.
*
* Chromium does not provide `residentSet` value for macOS. This is because macOS
* performs in-memory compression of pages that haven't been recently used. As a
* result the resident set size value is not what one would expect. `private`
* memory is more representative of the actual pre-compression memory usage of the
* process on macOS.
*/
getProcessMemoryInfo: () => Promise<ProcessMemoryInfo>;
}
export interface ISandboxContext {
/**
* Wether the renderer runs with `sandbox` enabled or not.
*/
sandbox: boolean;
}
export const ipcRenderer: IpcRenderer = globals.vscode.ipcRenderer;
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

@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ipcRenderer, crashReporter, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals';
suite('Sandbox', () => {
test('globals', () => {
assert.ok(ipcRenderer);
assert.ok(crashReporter);
assert.ok(webFrame);
});
});