mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028)
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
||||
|
||||
@@ -26,14 +25,22 @@ export interface ITerminateSessionEvent {
|
||||
subId?: string;
|
||||
}
|
||||
|
||||
export interface IReloadSessionEvent {
|
||||
sessionId: string;
|
||||
}
|
||||
|
||||
export interface ICloseSessionEvent {
|
||||
sessionId: string;
|
||||
}
|
||||
|
||||
export interface IExtensionHostDebugService {
|
||||
_serviceBrand: any;
|
||||
|
||||
reload(resource: URI): void;
|
||||
onReload: Event<URI>;
|
||||
reload(sessionId: string): void;
|
||||
onReload: Event<IReloadSessionEvent>;
|
||||
|
||||
close(resource: URI): void;
|
||||
onClose: Event<URI>;
|
||||
close(sessionId: string): void;
|
||||
onClose: Event<ICloseSessionEvent>;
|
||||
|
||||
attachSession(sessionId: string, port: number, subId?: string): void;
|
||||
onAttachSession: Event<IAttachSessionEvent>;
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ExtHostCustomersRegistry } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ExtHostContext, ExtHostExtensionServiceShape, IExtHostContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import { IRPCProtocolLogger, RPCProtocol, RequestInitiator, ResponsiveState } from 'vs/workbench/services/extensions/common/rpcProtocol';
|
||||
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IUntitledResourceInput } from 'vs/workbench/common/editor';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IExtensionHostStarter } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
// Enable to see detailed message communication between window and extension host
|
||||
const LOG_EXTENSION_HOST_COMMUNICATION = false;
|
||||
const LOG_USE_COLORS = true;
|
||||
|
||||
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
|
||||
|
||||
export class ExtensionHostProcessManager extends Disposable {
|
||||
|
||||
public readonly onDidCrash: Event<[number, string | null]>;
|
||||
|
||||
private readonly _onDidChangeResponsiveState: Emitter<ResponsiveState> = this._register(new Emitter<ResponsiveState>());
|
||||
public readonly onDidChangeResponsiveState: Event<ResponsiveState> = this._onDidChangeResponsiveState.event;
|
||||
|
||||
/**
|
||||
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
|
||||
*/
|
||||
private readonly _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; };
|
||||
private _extensionHostProcessRPCProtocol: RPCProtocol | null;
|
||||
private readonly _extensionHostProcessCustomers: IDisposable[];
|
||||
private readonly _extensionHostProcessWorker: IExtensionHostStarter;
|
||||
/**
|
||||
* winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object.
|
||||
*/
|
||||
private _extensionHostProcessProxy: Promise<{ value: ExtHostExtensionServiceShape; } | null> | null;
|
||||
|
||||
constructor(
|
||||
extensionHostProcessWorker: IExtensionHostStarter,
|
||||
private readonly _remoteAuthority: string,
|
||||
initialActivationEvents: string[],
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
|
||||
) {
|
||||
super();
|
||||
this._extensionHostProcessFinishedActivateEvents = Object.create(null);
|
||||
this._extensionHostProcessRPCProtocol = null;
|
||||
this._extensionHostProcessCustomers = [];
|
||||
|
||||
this._extensionHostProcessWorker = extensionHostProcessWorker;
|
||||
this.onDidCrash = this._extensionHostProcessWorker.onCrashed;
|
||||
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start()!.then(
|
||||
(protocol) => {
|
||||
return { value: this._createExtensionHostCustomers(protocol) };
|
||||
},
|
||||
(err) => {
|
||||
console.error('Error received from starting extension host');
|
||||
console.error(err);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
this._extensionHostProcessProxy.then(() => {
|
||||
initialActivationEvents.forEach((activationEvent) => this.activateByEvent(activationEvent));
|
||||
this._register(registerLatencyTestProvider({
|
||||
measure: () => this.measure()
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this._extensionHostProcessWorker) {
|
||||
this._extensionHostProcessWorker.dispose();
|
||||
}
|
||||
if (this._extensionHostProcessRPCProtocol) {
|
||||
this._extensionHostProcessRPCProtocol.dispose();
|
||||
}
|
||||
for (let i = 0, len = this._extensionHostProcessCustomers.length; i < len; i++) {
|
||||
const customer = this._extensionHostProcessCustomers[i];
|
||||
try {
|
||||
customer.dispose();
|
||||
} catch (err) {
|
||||
errors.onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
this._extensionHostProcessProxy = null;
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private async measure(): Promise<ExtHostLatencyResult | null> {
|
||||
const proxy = await this._getExtensionHostProcessProxy();
|
||||
if (!proxy) {
|
||||
return null;
|
||||
}
|
||||
const latency = await this._measureLatency(proxy);
|
||||
const down = await this._measureDown(proxy);
|
||||
const up = await this._measureUp(proxy);
|
||||
return {
|
||||
remoteAuthority: this._remoteAuthority,
|
||||
latency,
|
||||
down,
|
||||
up
|
||||
};
|
||||
}
|
||||
|
||||
private async _getExtensionHostProcessProxy(): Promise<ExtHostExtensionServiceShape | null> {
|
||||
if (!this._extensionHostProcessProxy) {
|
||||
return null;
|
||||
}
|
||||
const p = await this._extensionHostProcessProxy;
|
||||
if (!p) {
|
||||
return null;
|
||||
}
|
||||
return p.value;
|
||||
}
|
||||
|
||||
private async _measureLatency(proxy: ExtHostExtensionServiceShape): Promise<number> {
|
||||
const COUNT = 10;
|
||||
|
||||
let sum = 0;
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
const sw = StopWatch.create(true);
|
||||
await proxy.$test_latency(i);
|
||||
sw.stop();
|
||||
sum += sw.elapsed();
|
||||
}
|
||||
return (sum / COUNT);
|
||||
}
|
||||
|
||||
private static _convert(byteCount: number, elapsedMillis: number): number {
|
||||
return (byteCount * 1000 * 8) / elapsedMillis;
|
||||
}
|
||||
|
||||
private async _measureUp(proxy: ExtHostExtensionServiceShape): Promise<number> {
|
||||
const SIZE = 10 * 1024 * 1024; // 10MB
|
||||
|
||||
let b = Buffer.alloc(SIZE, Math.random() % 256);
|
||||
const sw = StopWatch.create(true);
|
||||
await proxy.$test_up(VSBuffer.wrap(b));
|
||||
sw.stop();
|
||||
return ExtensionHostProcessManager._convert(SIZE, sw.elapsed());
|
||||
}
|
||||
|
||||
private async _measureDown(proxy: ExtHostExtensionServiceShape): Promise<number> {
|
||||
const SIZE = 10 * 1024 * 1024; // 10MB
|
||||
|
||||
const sw = StopWatch.create(true);
|
||||
await proxy.$test_down(SIZE);
|
||||
sw.stop();
|
||||
return ExtensionHostProcessManager._convert(SIZE, sw.elapsed());
|
||||
}
|
||||
|
||||
private _createExtensionHostCustomers(protocol: IMessagePassingProtocol): ExtHostExtensionServiceShape {
|
||||
|
||||
let logger: IRPCProtocolLogger | null = null;
|
||||
if (LOG_EXTENSION_HOST_COMMUNICATION || this._environmentService.logExtensionHostCommunication) {
|
||||
logger = new RPCLogger();
|
||||
}
|
||||
|
||||
this._extensionHostProcessRPCProtocol = new RPCProtocol(protocol, logger);
|
||||
this._register(this._extensionHostProcessRPCProtocol.onDidChangeResponsiveState((responsiveState: ResponsiveState) => this._onDidChangeResponsiveState.fire(responsiveState)));
|
||||
const extHostContext: IExtHostContext = {
|
||||
remoteAuthority: this._remoteAuthority,
|
||||
getProxy: <T>(identifier: ProxyIdentifier<T>): T => this._extensionHostProcessRPCProtocol!.getProxy(identifier),
|
||||
set: <T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R => this._extensionHostProcessRPCProtocol!.set(identifier, instance),
|
||||
assertRegistered: (identifiers: ProxyIdentifier<any>[]): void => this._extensionHostProcessRPCProtocol!.assertRegistered(identifiers),
|
||||
};
|
||||
|
||||
// Named customers
|
||||
const namedCustomers = ExtHostCustomersRegistry.getNamedCustomers();
|
||||
for (let i = 0, len = namedCustomers.length; i < len; i++) {
|
||||
const [id, ctor] = namedCustomers[i];
|
||||
const instance = this._instantiationService.createInstance(ctor, extHostContext);
|
||||
this._extensionHostProcessCustomers.push(instance);
|
||||
this._extensionHostProcessRPCProtocol.set(id, instance);
|
||||
}
|
||||
|
||||
// Customers
|
||||
const customers = ExtHostCustomersRegistry.getCustomers();
|
||||
for (const ctor of customers) {
|
||||
const instance = this._instantiationService.createInstance(ctor, extHostContext);
|
||||
this._extensionHostProcessCustomers.push(instance);
|
||||
}
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = Object.keys(MainContext).map((key) => (<any>MainContext)[key]);
|
||||
this._extensionHostProcessRPCProtocol.assertRegistered(expected);
|
||||
|
||||
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
|
||||
}
|
||||
|
||||
public async activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
|
||||
const proxy = await this._getExtensionHostProcessProxy();
|
||||
if (!proxy) {
|
||||
return false;
|
||||
}
|
||||
return proxy.$activate(extension, activationEvent);
|
||||
}
|
||||
|
||||
public activateByEvent(activationEvent: string): Promise<void> {
|
||||
if (this._extensionHostProcessFinishedActivateEvents[activationEvent] || !this._extensionHostProcessProxy) {
|
||||
return NO_OP_VOID_PROMISE;
|
||||
}
|
||||
return this._extensionHostProcessProxy.then((proxy) => {
|
||||
if (!proxy) {
|
||||
// this case is already covered above and logged.
|
||||
// i.e. the extension host could not be started
|
||||
return NO_OP_VOID_PROMISE;
|
||||
}
|
||||
return proxy.value.$activateByEvent(activationEvent);
|
||||
}).then(() => {
|
||||
this._extensionHostProcessFinishedActivateEvents[activationEvent] = true;
|
||||
});
|
||||
}
|
||||
|
||||
public getInspectPort(): number {
|
||||
if (this._extensionHostProcessWorker) {
|
||||
let port = this._extensionHostProcessWorker.getInspectPort();
|
||||
if (port) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public canProfileExtensionHost(): boolean {
|
||||
return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort());
|
||||
}
|
||||
|
||||
public async resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority> {
|
||||
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
||||
if (authorityPlusIndex === -1) {
|
||||
// This authority does not need to be resolved, simply parse the port number
|
||||
const pieces = remoteAuthority.split(':');
|
||||
return Promise.resolve({
|
||||
authority: remoteAuthority,
|
||||
host: pieces[0],
|
||||
port: parseInt(pieces[1], 10)
|
||||
});
|
||||
}
|
||||
const proxy = await this._getExtensionHostProcessProxy();
|
||||
if (!proxy) {
|
||||
throw new Error(`Cannot resolve authority`);
|
||||
}
|
||||
return proxy.$resolveAuthority(remoteAuthority);
|
||||
}
|
||||
|
||||
public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
|
||||
const proxy = await this._getExtensionHostProcessProxy();
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
return proxy.$startExtensionHost(enabledExtensionIds);
|
||||
}
|
||||
|
||||
public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
|
||||
const proxy = await this._getExtensionHostProcessProxy();
|
||||
if (!proxy) {
|
||||
return;
|
||||
}
|
||||
return proxy.$deltaExtensions(toAdd, toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
const colorTables = [
|
||||
['#2977B1', '#FC802D', '#34A13A', '#D3282F', '#9366BA'],
|
||||
['#8B564C', '#E177C0', '#7F7F7F', '#BBBE3D', '#2EBECD']
|
||||
];
|
||||
|
||||
function prettyWithoutArrays(data: any): any {
|
||||
if (Array.isArray(data)) {
|
||||
return data;
|
||||
}
|
||||
if (data && typeof data === 'object' && typeof data.toString === 'function') {
|
||||
let result = data.toString();
|
||||
if (result !== '[object Object]') {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function pretty(data: any): any {
|
||||
if (Array.isArray(data)) {
|
||||
return data.map(prettyWithoutArrays);
|
||||
}
|
||||
return prettyWithoutArrays(data);
|
||||
}
|
||||
|
||||
class RPCLogger implements IRPCProtocolLogger {
|
||||
|
||||
private _totalIncoming = 0;
|
||||
private _totalOutgoing = 0;
|
||||
|
||||
private _log(direction: string, totalLength: number, msgLength: number, req: number, initiator: RequestInitiator, str: string, data: any): void {
|
||||
data = pretty(data);
|
||||
|
||||
const colorTable = colorTables[initiator];
|
||||
const color = LOG_USE_COLORS ? colorTable[req % colorTable.length] : '#000000';
|
||||
let args = [`%c[${direction}]%c[${strings.pad(totalLength, 7, ' ')}]%c[len: ${strings.pad(msgLength, 5, ' ')}]%c${strings.pad(req, 5, ' ')} - ${str}`, 'color: darkgreen', 'color: grey', 'color: grey', `color: ${color}`];
|
||||
if (/\($/.test(str)) {
|
||||
args = args.concat(data);
|
||||
args.push(')');
|
||||
} else {
|
||||
args.push(data);
|
||||
}
|
||||
console.log.apply(console, args as [string, ...string[]]);
|
||||
}
|
||||
|
||||
logIncoming(msgLength: number, req: number, initiator: RequestInitiator, str: string, data?: any): void {
|
||||
this._totalIncoming += msgLength;
|
||||
this._log('Ext \u2192 Win', this._totalIncoming, msgLength, req, initiator, str, data);
|
||||
}
|
||||
|
||||
logOutgoing(msgLength: number, req: number, initiator: RequestInitiator, str: string, data?: any): void {
|
||||
this._totalOutgoing += msgLength;
|
||||
this._log('Win \u2192 Ext', this._totalOutgoing, msgLength, req, initiator, str, data);
|
||||
}
|
||||
}
|
||||
|
||||
interface ExtHostLatencyResult {
|
||||
remoteAuthority: string;
|
||||
up: number;
|
||||
down: number;
|
||||
latency: number;
|
||||
}
|
||||
|
||||
interface ExtHostLatencyProvider {
|
||||
measure(): Promise<ExtHostLatencyResult | null>;
|
||||
}
|
||||
|
||||
let providers: ExtHostLatencyProvider[] = [];
|
||||
function registerLatencyTestProvider(provider: ExtHostLatencyProvider): IDisposable {
|
||||
providers.push(provider);
|
||||
return {
|
||||
dispose: () => {
|
||||
for (let i = 0; i < providers.length; i++) {
|
||||
if (providers[i] === provider) {
|
||||
providers.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getLatencyTestProviders(): ExtHostLatencyProvider[] {
|
||||
return providers.slice(0);
|
||||
}
|
||||
|
||||
export class MeasureExtHostLatencyAction extends Action {
|
||||
public static readonly ID = 'editor.action.measureExtHostLatency';
|
||||
public static readonly LABEL = nls.localize('measureExtHostLatency', "Measure Extension Host Latency");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IEditorService private readonly _editorService: IEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public async run(): Promise<any> {
|
||||
const measurements = await Promise.all(getLatencyTestProviders().map(provider => provider.measure()));
|
||||
this._editorService.openEditor({ contents: measurements.map(MeasureExtHostLatencyAction._print).join('\n\n'), options: { pinned: true } } as IUntitledResourceInput);
|
||||
}
|
||||
|
||||
private static _print(m: ExtHostLatencyResult): string {
|
||||
return `${m.remoteAuthority ? `Authority: ${m.remoteAuthority}\n` : ``}Roundtrip latency: ${m.latency.toFixed(3)}ms\nUp: ${MeasureExtHostLatencyAction._printSpeed(m.up)}\nDown: ${MeasureExtHostLatencyAction._printSpeed(m.down)}\n`;
|
||||
}
|
||||
|
||||
private static _printSpeed(n: number): string {
|
||||
if (n <= 1024) {
|
||||
return `${n} bps`;
|
||||
}
|
||||
if (n < 1024 * 1024) {
|
||||
return `${(n / 1024).toFixed(1)} kbps`;
|
||||
}
|
||||
return `${(n / 1024 / 1024).toFixed(1)} Mbps`;
|
||||
}
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MeasureExtHostLatencyAction, MeasureExtHostLatencyAction.ID, MeasureExtHostLatencyAction.LABEL), 'Developer: Measure Extension Host Latency', nls.localize('developer', "Developer"));
|
||||
@@ -10,6 +10,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||
import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
||||
export const nullExtensionDescription = Object.freeze(<IExtensionDescription>{
|
||||
identifier: new ExtensionIdentifier('nullExtensionDescription'),
|
||||
@@ -82,6 +83,14 @@ export interface IExtensionHostProfile {
|
||||
getAggregatedTimes(): Map<ProfileSegmentId, number>;
|
||||
}
|
||||
|
||||
export interface IExtensionHostStarter {
|
||||
readonly onCrashed: Event<[number, string | null]>;
|
||||
start(): Promise<IMessagePassingProtocol> | null;
|
||||
getInspectPort(): number | undefined;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extension id or one of the four known program states.
|
||||
*/
|
||||
@@ -116,11 +125,10 @@ export interface IWillActivateEvent {
|
||||
}
|
||||
|
||||
export interface IResponsiveStateChangeEvent {
|
||||
target: ICpuProfilerTarget;
|
||||
isResponsive: boolean;
|
||||
}
|
||||
|
||||
export interface IExtensionService extends ICpuProfilerTarget {
|
||||
export interface IExtensionService {
|
||||
_serviceBrand: any;
|
||||
|
||||
/**
|
||||
@@ -200,7 +208,8 @@ export interface IExtensionService extends ICpuProfilerTarget {
|
||||
getExtensionsStatus(): { [id: string]: IExtensionsStatus };
|
||||
|
||||
/**
|
||||
* Return the inspect port or 0.
|
||||
* Return the inspect port or `0`, the latter means inspection
|
||||
* is not possible.
|
||||
*/
|
||||
getInspectPort(): number;
|
||||
|
||||
@@ -227,19 +236,6 @@ export interface IExtensionService extends ICpuProfilerTarget {
|
||||
_onExtensionHostExit(code: number): void;
|
||||
}
|
||||
|
||||
export interface ICpuProfilerTarget {
|
||||
|
||||
/**
|
||||
* Check if the extension host can be profiled.
|
||||
*/
|
||||
canProfileExtensionHost(): boolean;
|
||||
|
||||
/**
|
||||
* Begin an extension host process profile session.
|
||||
*/
|
||||
startExtensionHostProfile(): Promise<ProfileSession>;
|
||||
}
|
||||
|
||||
export interface ProfileSession {
|
||||
stop(): Promise<IExtensionHostProfile>;
|
||||
}
|
||||
@@ -277,9 +273,7 @@ export class NullExtensionService implements IExtensionService {
|
||||
getExtension() { return Promise.resolve(undefined); }
|
||||
readExtensionPointContributions<T>(_extPoint: IExtensionPoint<T>): Promise<ExtensionPointContribution<T>[]> { return Promise.resolve(Object.create(null)); }
|
||||
getExtensionsStatus(): { [id: string]: IExtensionsStatus; } { return Object.create(null); }
|
||||
canProfileExtensionHost(): boolean { return false; }
|
||||
getInspectPort(): number { return 0; }
|
||||
startExtensionHostProfile(): Promise<ProfileSession> { return Promise.resolve(Object.create(null)); }
|
||||
restartExtensionHost(): void { }
|
||||
startExtensionHost(): void { }
|
||||
stopExtensionHost(): void { }
|
||||
|
||||
@@ -258,11 +258,6 @@ export class RPCProtocol extends Disposable implements IRPCProtocol {
|
||||
this._receiveReply(msgLength, req, value);
|
||||
break;
|
||||
}
|
||||
case MessageType.ReplyOKBuffer: {
|
||||
let value = MessageIO.deserializeReplyOKBuffer(buff);
|
||||
this._receiveReply(msgLength, req, value);
|
||||
break;
|
||||
}
|
||||
case MessageType.ReplyOKVSBuffer: {
|
||||
let value = MessageIO.deserializeReplyOKVSBuffer(buff);
|
||||
this._receiveReply(msgLength, req, value);
|
||||
@@ -517,21 +512,11 @@ class MessageBuffer {
|
||||
return str;
|
||||
}
|
||||
|
||||
public static sizeBuffer(buff: VSBuffer): number {
|
||||
return 4 /* buffer length */ + buff.byteLength /* actual buffer */;
|
||||
}
|
||||
|
||||
public writeBuffer(buff: VSBuffer): void {
|
||||
this._buff.writeUint32BE(buff.byteLength, this._offset); this._offset += 4;
|
||||
this._buff.set(buff, this._offset); this._offset += buff.byteLength;
|
||||
}
|
||||
|
||||
public readBuffer(): Buffer {
|
||||
const buffLength = this._buff.readUint32BE(this._offset); this._offset += 4;
|
||||
const buff = this._buff.slice(this._offset, this._offset + buffLength); this._offset += buffLength;
|
||||
return <Buffer>buff.buffer;
|
||||
}
|
||||
|
||||
public static sizeVSBuffer(buff: VSBuffer): number {
|
||||
return 4 /* buffer length */ + buff.byteLength /* actual buffer */;
|
||||
}
|
||||
@@ -556,8 +541,6 @@ class MessageBuffer {
|
||||
size += 1; // arg type
|
||||
if (elType === ArgType.String) {
|
||||
size += this.sizeLongString(el);
|
||||
} else if (elType === ArgType.Buffer) {
|
||||
size += this.sizeBuffer(el);
|
||||
} else {
|
||||
size += this.sizeVSBuffer(el);
|
||||
}
|
||||
@@ -573,9 +556,6 @@ class MessageBuffer {
|
||||
if (elType === ArgType.String) {
|
||||
this.writeUInt8(ArgType.String);
|
||||
this.writeLongString(el);
|
||||
} else if (elType === ArgType.Buffer) {
|
||||
this.writeUInt8(ArgType.Buffer);
|
||||
this.writeVSBuffer(el);
|
||||
} else {
|
||||
this.writeUInt8(ArgType.VSBuffer);
|
||||
this.writeVSBuffer(el);
|
||||
@@ -583,18 +563,15 @@ class MessageBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
public readMixedArray(): Array<string | Buffer | VSBuffer> {
|
||||
public readMixedArray(): Array<string | VSBuffer> {
|
||||
const arrLen = this._buff.readUint8(this._offset); this._offset += 1;
|
||||
let arr: Array<string | Buffer | VSBuffer> = new Array(arrLen);
|
||||
let arr: Array<string | VSBuffer> = new Array(arrLen);
|
||||
for (let i = 0; i < arrLen; i++) {
|
||||
const argType = <ArgType>this.readUInt8();
|
||||
switch (argType) {
|
||||
case ArgType.String:
|
||||
arr[i] = this.readLongString();
|
||||
break;
|
||||
case ArgType.Buffer:
|
||||
arr[i] = this.readBuffer();
|
||||
break;
|
||||
case ArgType.VSBuffer:
|
||||
arr[i] = this.readVSBuffer();
|
||||
break;
|
||||
@@ -608,9 +585,6 @@ class MessageIO {
|
||||
|
||||
private static _arrayContainsBuffer(arr: any[]): boolean {
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
if (Buffer.isBuffer(arr[i])) {
|
||||
return true;
|
||||
}
|
||||
if (arr[i] instanceof VSBuffer) {
|
||||
return true;
|
||||
}
|
||||
@@ -624,10 +598,7 @@ class MessageIO {
|
||||
let massagedArgsType: ArgType[] = [];
|
||||
for (let i = 0, len = args.length; i < len; i++) {
|
||||
const arg = args[i];
|
||||
if (Buffer.isBuffer(arg)) {
|
||||
massagedArgs[i] = VSBuffer.wrap(arg);
|
||||
massagedArgsType[i] = ArgType.Buffer;
|
||||
} else if (arg instanceof VSBuffer) {
|
||||
if (arg instanceof VSBuffer) {
|
||||
massagedArgs[i] = arg;
|
||||
massagedArgsType[i] = ArgType.VSBuffer;
|
||||
} else {
|
||||
@@ -714,9 +685,6 @@ class MessageIO {
|
||||
if (typeof res === 'undefined') {
|
||||
return this._serializeReplyOKEmpty(req);
|
||||
}
|
||||
if (Buffer.isBuffer(res)) {
|
||||
return this._serializeReplyOKBuffer(req, res);
|
||||
}
|
||||
if (res instanceof VSBuffer) {
|
||||
return this._serializeReplyOKVSBuffer(req, res);
|
||||
}
|
||||
@@ -727,17 +695,6 @@ class MessageIO {
|
||||
return MessageBuffer.alloc(MessageType.ReplyOKEmpty, req, 0).buffer;
|
||||
}
|
||||
|
||||
private static _serializeReplyOKBuffer(req: number, res: Buffer): VSBuffer {
|
||||
const buff = VSBuffer.wrap(res);
|
||||
|
||||
let len = 0;
|
||||
len += MessageBuffer.sizeBuffer(buff);
|
||||
|
||||
let result = MessageBuffer.alloc(MessageType.ReplyOKBuffer, req, len);
|
||||
result.writeBuffer(buff);
|
||||
return result.buffer;
|
||||
}
|
||||
|
||||
private static _serializeReplyOKVSBuffer(req: number, res: VSBuffer): VSBuffer {
|
||||
let len = 0;
|
||||
len += MessageBuffer.sizeVSBuffer(res);
|
||||
@@ -747,10 +704,6 @@ class MessageIO {
|
||||
return result.buffer;
|
||||
}
|
||||
|
||||
public static deserializeReplyOKBuffer(buff: MessageBuffer): Buffer {
|
||||
return buff.readBuffer();
|
||||
}
|
||||
|
||||
public static deserializeReplyOKVSBuffer(buff: MessageBuffer): VSBuffer {
|
||||
return buff.readVSBuffer();
|
||||
}
|
||||
@@ -807,15 +760,13 @@ const enum MessageType {
|
||||
Acknowledged = 5,
|
||||
Cancel = 6,
|
||||
ReplyOKEmpty = 7,
|
||||
ReplyOKBuffer = 8,
|
||||
ReplyOKVSBuffer = 9,
|
||||
ReplyOKJSON = 10,
|
||||
ReplyErrError = 11,
|
||||
ReplyErrEmpty = 12,
|
||||
ReplyOKVSBuffer = 8,
|
||||
ReplyOKJSON = 9,
|
||||
ReplyErrError = 10,
|
||||
ReplyErrEmpty = 11,
|
||||
}
|
||||
|
||||
const enum ArgType {
|
||||
String = 1,
|
||||
Buffer = 2,
|
||||
VSBuffer = 3
|
||||
VSBuffer = 2
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user