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,60 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
import { IRemoteConsoleLog } from 'vs/base/common/console';
import { IProcessEnvironment } from 'vs/base/common/platform';
export const IExtensionHostDebugService = createDecorator<IExtensionHostDebugService>('extensionHostDebugService');
export interface IAttachSessionEvent {
sessionId: string;
subId?: string;
port: number;
}
export interface ILogToSessionEvent {
sessionId: string;
log: IRemoteConsoleLog;
}
export interface ITerminateSessionEvent {
sessionId: string;
subId?: string;
}
export interface IReloadSessionEvent {
sessionId: string;
}
export interface ICloseSessionEvent {
sessionId: string;
}
export interface IOpenExtensionWindowResult {
rendererDebugPort?: number;
}
export interface IExtensionHostDebugService {
readonly _serviceBrand: undefined;
reload(sessionId: string): void;
readonly onReload: Event<IReloadSessionEvent>;
close(sessionId: string): void;
readonly onClose: Event<ICloseSessionEvent>;
attachSession(sessionId: string, port: number, subId?: string): void;
readonly onAttachSession: Event<IAttachSessionEvent>;
logToSession(sessionId: string, log: IRemoteConsoleLog): void;
readonly onLogToSession: Event<ILogToSessionEvent>;
terminateSession(sessionId: string, subId?: string): void;
readonly onTerminateSession: Event<ITerminateSessionEvent>;
openExtensionDevelopmentHostWindow(args: string[], env: IProcessEnvironment, debugRenderer: boolean): Promise<IOpenExtensionWindowResult>;
}

View File

@@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IReloadSessionEvent, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent, IExtensionHostDebugService, IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug';
import { Event, Emitter } from 'vs/base/common/event';
import { IRemoteConsoleLog } from 'vs/base/common/console';
import { Disposable } from 'vs/base/common/lifecycle';
import { IProcessEnvironment } from 'vs/base/common/platform';
export class ExtensionHostDebugBroadcastChannel<TContext> implements IServerChannel<TContext> {
static readonly ChannelName = 'extensionhostdebugservice';
private readonly _onCloseEmitter = new Emitter<ICloseSessionEvent>();
private readonly _onReloadEmitter = new Emitter<IReloadSessionEvent>();
private readonly _onTerminateEmitter = new Emitter<ITerminateSessionEvent>();
private readonly _onLogToEmitter = new Emitter<ILogToSessionEvent>();
private readonly _onAttachEmitter = new Emitter<IAttachSessionEvent>();
call(ctx: TContext, command: string, arg?: any): Promise<any> {
switch (command) {
case 'close':
return Promise.resolve(this._onCloseEmitter.fire({ sessionId: arg[0] }));
case 'reload':
return Promise.resolve(this._onReloadEmitter.fire({ sessionId: arg[0] }));
case 'terminate':
return Promise.resolve(this._onTerminateEmitter.fire({ sessionId: arg[0] }));
case 'log':
return Promise.resolve(this._onLogToEmitter.fire({ sessionId: arg[0], log: arg[1] }));
case 'attach':
return Promise.resolve(this._onAttachEmitter.fire({ sessionId: arg[0], port: arg[1], subId: arg[2] }));
}
throw new Error('Method not implemented.');
}
listen(ctx: TContext, event: string, arg?: any): Event<any> {
switch (event) {
case 'close':
return this._onCloseEmitter.event;
case 'reload':
return this._onReloadEmitter.event;
case 'terminate':
return this._onTerminateEmitter.event;
case 'log':
return this._onLogToEmitter.event;
case 'attach':
return this._onAttachEmitter.event;
}
throw new Error('Method not implemented.');
}
}
export class ExtensionHostDebugChannelClient extends Disposable implements IExtensionHostDebugService {
declare readonly _serviceBrand: undefined;
constructor(private channel: IChannel) {
super();
}
reload(sessionId: string): void {
this.channel.call('reload', [sessionId]);
}
get onReload(): Event<IReloadSessionEvent> {
return this.channel.listen('reload');
}
close(sessionId: string): void {
this.channel.call('close', [sessionId]);
}
get onClose(): Event<ICloseSessionEvent> {
return this.channel.listen('close');
}
attachSession(sessionId: string, port: number, subId?: string): void {
this.channel.call('attach', [sessionId, port, subId]);
}
get onAttachSession(): Event<IAttachSessionEvent> {
return this.channel.listen('attach');
}
logToSession(sessionId: string, log: IRemoteConsoleLog): void {
this.channel.call('log', [sessionId, log]);
}
get onLogToSession(): Event<ILogToSessionEvent> {
return this.channel.listen('log');
}
terminateSession(sessionId: string, subId?: string): void {
this.channel.call('terminate', [sessionId, subId]);
}
get onTerminateSession(): Event<ITerminateSessionEvent> {
return this.channel.listen('terminate');
}
openExtensionDevelopmentHostWindow(args: string[], env: IProcessEnvironment, debugRenderer: boolean): Promise<IOpenExtensionWindowResult> {
return this.channel.call('openExtensionDevelopmentHostWindow', [args, env, debugRenderer]);
}
}

View File

@@ -0,0 +1,111 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { createServer, AddressInfo } from 'net';
import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { OpenContext } from 'vs/platform/windows/node/window';
export class ElectronExtensionHostDebugBroadcastChannel<TContext> extends ExtensionHostDebugBroadcastChannel<TContext> {
constructor(private windowsMainService: IWindowsMainService) {
super();
}
call(ctx: TContext, command: string, arg?: any): Promise<any> {
if (command === 'openExtensionDevelopmentHostWindow') {
return this.openExtensionDevelopmentHostWindow(arg[0], arg[1], arg[2]);
} else {
return super.call(ctx, command, arg);
}
}
private async openExtensionDevelopmentHostWindow(args: string[], env: IProcessEnvironment, debugRenderer: boolean): Promise<IOpenExtensionWindowResult> {
const pargs = parseArgs(args, OPTIONS);
pargs.debugRenderer = debugRenderer;
const extDevPaths = pargs.extensionDevelopmentPath;
if (!extDevPaths) {
return {};
}
const [codeWindow] = this.windowsMainService.openExtensionDevelopmentHostWindow(extDevPaths, {
context: OpenContext.API,
cli: pargs,
userEnv: Object.keys(env).length > 0 ? env : undefined
});
if (!debugRenderer) {
return {};
}
const debug = codeWindow.win.webContents.debugger;
let listeners = debug.isAttached() ? Infinity : 0;
const server = createServer(listener => {
if (listeners++ === 0) {
debug.attach();
}
let closed = false;
const writeMessage = (message: object) => {
if (!closed) { // in case sendCommand promises settle after closed
listener.write(JSON.stringify(message) + '\0'); // null-delimited, CDP-compatible
}
};
const onMessage = (_event: Event, method: string, params: unknown, sessionId?: string) =>
writeMessage(({ method, params, sessionId }));
codeWindow.win.on('close', () => {
debug.removeListener('message', onMessage);
listener.end();
closed = true;
});
debug.addListener('message', onMessage);
let buf = Buffer.alloc(0);
listener.on('data', data => {
buf = Buffer.concat([buf, data]);
for (let delimiter = buf.indexOf(0); delimiter !== -1; delimiter = buf.indexOf(0)) {
let data: { id: number; sessionId: string; params: {} };
try {
const contents = buf.slice(0, delimiter).toString('utf8');
buf = buf.slice(delimiter + 1);
data = JSON.parse(contents);
} catch (e) {
console.error('error reading cdp line', e);
}
// depends on a new API for which electron.d.ts has not been updated:
// @ts-ignore
debug.sendCommand(data.method, data.params, data.sessionId)
.then((result: object) => writeMessage({ id: data.id, sessionId: data.sessionId, result }))
.catch((error: Error) => writeMessage({ id: data.id, sessionId: data.sessionId, error: { code: 0, message: error.message } }));
}
});
listener.on('error', err => {
console.error('error on cdp pipe:', err);
});
listener.on('close', () => {
closed = true;
if (--listeners === 0) {
debug.detach();
}
});
});
await new Promise<void>(r => server.listen(0, r));
codeWindow.win.on('close', () => server.close());
return { rendererDebugPort: (server.address() as AddressInfo).port };
}
}