未验证 提交 d259a977 编写于 作者: J João Moreno 提交者: GitHub

Merge pull request #56820 from Microsoft/joao/ipc-buffers

IPC protocol should be buffer based, not JSON based
......@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import { fromNodeEventEmitter } from 'vs/base/common/event';
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron';
import { IPCClient } from 'vs/base/parts/ipc/node/ipc';
import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron';
import { ipcRenderer } from 'electron';
export class Client extends IPCClient {
private static createProtocol(): Protocol {
const onMessage = fromNodeEventEmitter<string>(ipcRenderer, 'ipc:message', (_, message) => message);
const onMessage = fromNodeEventEmitter<string>(ipcRenderer, 'ipc:message', (_, message: string) => message);
ipcRenderer.send('ipc:hello');
return new Protocol(ipcRenderer, onMessage);
}
......
......@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { Event, filterEvent, mapEvent, fromNodeEventEmitter } from 'vs/base/common/event';
import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/common/ipc';
import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron';
import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/node/ipc';
import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron';
import { ipcMain } from 'electron';
interface WebContents extends Electron.WebContents {
......@@ -17,8 +17,8 @@ interface IIPCEvent {
message: string;
}
function createScopedOnMessageEvent(senderId: number): Event<any> {
const onMessage = fromNodeEventEmitter<IIPCEvent>(ipcMain, 'ipc:message', (event, message) => ({ event, message }));
function createScopedOnMessageEvent(senderId: number): Event<string> {
const onMessage = fromNodeEventEmitter<IIPCEvent>(ipcMain, 'ipc:message', (event, message: string) => ({ event, message }));
const onMessageFromSender = filterEvent(onMessage, ({ event }) => event.sender.getId() === senderId);
return mapEvent(onMessageFromSender, ({ message }) => message);
}
......
......@@ -10,14 +10,19 @@ import { Delayer } from 'vs/base/common/async';
import { deepClone, assign } from 'vs/base/common/objects';
import { Emitter, fromNodeEventEmitter, Event } from 'vs/base/common/event';
import { createQueuedSender } from 'vs/base/node/processes';
import { ChannelServer as IPCServer, ChannelClient as IPCClient, IChannelClient, IChannel } from 'vs/base/parts/ipc/common/ipc';
import { ChannelServer as IPCServer, ChannelClient as IPCClient, IChannelClient, IChannel } from 'vs/base/parts/ipc/node/ipc';
import { isRemoteConsoleLog, log } from 'vs/base/node/console';
/**
* This implementation doesn't perform well since it uses base64 encoding for buffers.
* We should move all implementations to use named ipc.net, so we stop depending on cp.fork.
*/
export class Server extends IPCServer {
constructor() {
super({
send: r => { try { process.send(r); } catch (e) { /* not much to do */ } },
onMessage: fromNodeEventEmitter(process, 'message', msg => msg)
send: r => { try { process.send(r.toString('base64')); } catch (e) { /* not much to do */ } },
onMessage: fromNodeEventEmitter(process, 'message', msg => Buffer.from(msg, 'base64'))
});
process.once('disconnect', () => this.dispose());
......@@ -185,7 +190,7 @@ export class Client implements IChannelClient, IDisposable {
this.child = fork(this.modulePath, args, forkOpts);
const onMessageEmitter = new Emitter<any>();
const onMessageEmitter = new Emitter<Buffer>();
const onRawMessage = fromNodeEventEmitter(this.child, 'message', msg => msg);
onRawMessage(msg => {
......@@ -197,11 +202,11 @@ export class Client implements IChannelClient, IDisposable {
}
// Anything else goes to the outside
onMessageEmitter.fire(msg);
onMessageEmitter.fire(Buffer.from(msg, 'base64'));
});
const sender = this.options.useQueue ? createQueuedSender(this.child) : this.child;
const send = r => this.child && this.child.connected && sender.send(r);
const send = (r: Buffer) => this.child && this.child.connected && sender.send(r.toString('base64'));
const onMessage = onMessageEmitter.event;
const protocol = { send, onMessage };
......
......@@ -4,29 +4,32 @@
*--------------------------------------------------------------------------------------------*/
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
/**
* This implementation doesn't perform well since it uses base64 encoding for buffers.
* Electron 3.0 should have suport for buffers in IPC: https://github.com/electron/electron/pull/13055
*/
export interface Sender {
send(channel: string, ...args: any[]): void;
send(channel: string, msg: string): void;
}
export class Protocol implements IMessagePassingProtocol {
private listener: IDisposable;
private _onMessage: Event<any>;
get onMessage(): Event<any> { return this._onMessage; }
private _onMessage = new Emitter<Buffer>();
get onMessage(): Event<Buffer> { return this._onMessage.event; }
constructor(private sender: Sender, onMessageEvent: Event<any>) {
const emitter = new Emitter<any>();
onMessageEvent(msg => emitter.fire(msg));
this._onMessage = emitter.event;
constructor(private sender: Sender, onMessageEvent: Event<string>) {
onMessageEvent(msg => this._onMessage.fire(Buffer.from(msg, 'base64')));
}
send(message: any): void {
send(message: Buffer): void {
try {
this.sender.send('ipc:message', message);
this.sender.send('ipc:message', message.toString('base64'));
} catch (e) {
// systems are going down
}
......
......@@ -8,7 +8,7 @@
import { Socket, Server as NetServer, createConnection, createServer } from 'net';
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter, once, mapEvent, fromNodeEventEmitter } from 'vs/base/common/event';
import { IMessagePassingProtocol, ClientConnectionEvent, IPCServer, IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol, ClientConnectionEvent, IPCServer, IPCClient } from 'vs/base/parts/ipc/node/ipc';
import { join } from 'path';
import { tmpdir } from 'os';
import { generateUuid } from 'vs/base/common/uuid';
......@@ -25,9 +25,17 @@ export function generateRandomPipeName(): string {
}
}
/**
* A message has the following format:
*
* [bodyLen|message]
* [header^|data^^^]
* [u32be^^|buffer^]
*/
export class Protocol implements IDisposable, IMessagePassingProtocol {
private static readonly _headerLen = 5;
private static readonly _headerLen = 4;
private _isDisposed: boolean;
private _chunks: Buffer[];
......@@ -37,8 +45,8 @@ export class Protocol implements IDisposable, IMessagePassingProtocol {
private _socketEndListener: () => void;
private _socketCloseListener: () => void;
private _onMessage = new Emitter<any>();
readonly onMessage: Event<any> = this._onMessage.event;
private _onMessage = new Emitter<Buffer>();
readonly onMessage: Event<Buffer> = this._onMessage.event;
private _onClose = new Emitter<void>();
readonly onClose: Event<void> = this._onClose.event;
......@@ -51,7 +59,6 @@ export class Protocol implements IDisposable, IMessagePassingProtocol {
const state = {
readHead: true,
bodyIsJson: false,
bodyLen: -1,
};
......@@ -68,8 +75,7 @@ export class Protocol implements IDisposable, IMessagePassingProtocol {
if (totalLength >= Protocol._headerLen) {
const all = Buffer.concat(this._chunks);
state.bodyIsJson = all.readInt8(0) === 1;
state.bodyLen = all.readInt32BE(1);
state.bodyLen = all.readUInt32BE(0);
state.readHead = false;
const rest = all.slice(Protocol._headerLen);
......@@ -87,21 +93,17 @@ export class Protocol implements IDisposable, IMessagePassingProtocol {
if (totalLength >= state.bodyLen) {
const all = Buffer.concat(this._chunks);
let message = all.toString('utf8', 0, state.bodyLen);
if (state.bodyIsJson) {
message = JSON.parse(message);
}
const buffer = all.slice(0, state.bodyLen);
// ensure the public getBuffer returns a valid value if invoked from the event listeners
// ensure the getBuffer returns a valid value if invoked from the event listeners
const rest = all.slice(state.bodyLen);
totalLength = rest.length;
this._chunks = [rest];
state.bodyIsJson = false;
state.bodyLen = -1;
state.readHead = true;
this._onMessage.fire(message);
this._onMessage.fire(buffer);
if (this._isDisposed) {
// check if an event listener lead to our disposal
......@@ -145,7 +147,7 @@ export class Protocol implements IDisposable, IMessagePassingProtocol {
_socket.once('close', this._socketCloseListener);
}
public dispose(): void {
dispose(): void {
this._isDisposed = true;
this._firstChunkTimer.dispose();
this._socket.removeListener('data', this._socketDataListener);
......@@ -153,30 +155,18 @@ export class Protocol implements IDisposable, IMessagePassingProtocol {
this._socket.removeListener('close', this._socketCloseListener);
}
public end(): void {
end(): void {
this._socket.end();
}
public getBuffer(): Buffer {
getBuffer(): Buffer {
return Buffer.concat(this._chunks);
}
public send(message: any): void {
// [bodyIsJson|bodyLen|message]
// |^header^^^^^^^^^^^|^data^^]
send(buffer: Buffer): void {
const header = Buffer.alloc(Protocol._headerLen);
// ensure string
if (typeof message !== 'string') {
message = JSON.stringify(message);
header.writeInt8(1, 0, true);
}
const data = Buffer.from(message);
header.writeInt32BE(data.length, 1, true);
this._writeSoon(header, data);
header.writeUInt32BE(buffer.length, 0, true);
this._writeSoon(header, buffer);
}
private _writeBuffer = new class {
......@@ -241,7 +231,7 @@ export class Server extends IPCServer {
export class Client extends IPCClient {
public static fromSocket(socket: Socket, id: string): Client {
static fromSocket(socket: Socket, id: string): Client {
return new Client(new Protocol(socket), id);
}
......
......@@ -9,54 +9,46 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { Event, Emitter, once, filterEvent, toPromise, Relay } from 'vs/base/common/event';
enum MessageType {
RequestPromise,
RequestPromiseCancel,
ResponseInitialize,
ResponsePromiseSuccess,
ResponsePromiseError,
ResponsePromiseErrorObj,
RequestEventListen,
RequestEventDispose,
ResponseEventFire,
export enum RequestType {
Promise = 100,
PromiseCancel = 101,
EventListen = 102,
EventDispose = 103
}
function isResponse(messageType: MessageType): boolean {
return messageType === MessageType.ResponseInitialize
|| messageType === MessageType.ResponsePromiseSuccess
|| messageType === MessageType.ResponsePromiseError
|| messageType === MessageType.ResponsePromiseErrorObj
|| messageType === MessageType.ResponseEventFire;
}
interface IRawMessage {
id: number;
type: MessageType;
}
interface IRawRequest extends IRawMessage {
channelName?: string;
name?: string;
arg?: any;
}
type IRawPromiseRequest = { type: RequestType.Promise; id: number; channelName: string; name: string; arg: any; };
type IRawPromiseCancelRequest = { type: RequestType.PromiseCancel, id: number };
type IRawEventListenRequest = { type: RequestType.EventListen; id: number; channelName: string; name: string; arg: any; };
type IRawEventDisposeRequest = { type: RequestType.EventDispose, id: number };
type IRawRequest = IRawPromiseRequest | IRawPromiseCancelRequest | IRawEventListenRequest | IRawEventDisposeRequest;
interface IRequest {
raw: IRawRequest;
flush?: () => void;
}
interface IRawResponse extends IRawMessage {
data: any;
export enum ResponseType {
Initialize = 200,
PromiseSuccess = 201,
PromiseError = 202,
PromiseErrorObj = 203,
EventFire = 204
}
type IRawInitializeResponse = { type: ResponseType.Initialize };
type IRawPromiseSuccessResponse = { type: ResponseType.PromiseSuccess; id: number; data: any };
type IRawPromiseErrorResponse = { type: ResponseType.PromiseError; id: number; data: { message: string, name: string, stack: string[] | undefined } };
type IRawPromiseErrorObjResponse = { type: ResponseType.PromiseErrorObj; id: number; data: any };
type IRawEventFireResponse = { type: ResponseType.EventFire; id: number; data: any };
type IRawResponse = IRawInitializeResponse | IRawPromiseSuccessResponse | IRawPromiseErrorResponse | IRawPromiseErrorObjResponse | IRawEventFireResponse;
interface IHandler {
(response: IRawResponse): void;
}
export interface IMessagePassingProtocol {
send(request: any): void;
onMessage: Event<any>;
send(buffer: Buffer): void;
onMessage: Event<Buffer>;
}
enum State {
......@@ -112,7 +104,54 @@ export interface IRoutingChannelClient {
getChannel<T extends IChannel>(channelName: string, router: IClientRouter): T;
}
// TODO@joao cleanup this mess!
enum BodyType {
Undefined,
String,
Buffer,
Object
}
const empty = new Buffer(0);
function serializeBody(body: any): { buffer: Buffer, type: BodyType } {
if (typeof body === 'undefined') {
return { buffer: empty, type: BodyType.Undefined };
} else if (typeof body === 'string') {
return { buffer: Buffer.from(body), type: BodyType.String };
} else if (Buffer.isBuffer(body)) {
return { buffer: body, type: BodyType.Buffer };
} else {
return { buffer: Buffer.from(JSON.stringify(body)), type: BodyType.Object };
}
}
function serialize(header: any, body: any = undefined): Buffer {
const headerSizeBuffer = new Buffer(4);
const { buffer: bodyBuffer, type: bodyType } = serializeBody(body);
const headerBuffer = Buffer.from(JSON.stringify([header, bodyType]));
headerSizeBuffer.writeUInt32BE(headerBuffer.byteLength, 0);
return Buffer.concat([headerSizeBuffer, headerBuffer, bodyBuffer]);
}
function deserializeBody(bodyBuffer: Buffer, bodyType: BodyType): any {
switch (bodyType) {
case BodyType.Undefined: return undefined;
case BodyType.String: return bodyBuffer.toString();
case BodyType.Buffer: return bodyBuffer;
case BodyType.Object: return JSON.parse(bodyBuffer.toString());
}
}
function deserialize(buffer: Buffer): { header: any, body: any } {
const headerSize = buffer.readUInt32BE(0);
const headerBuffer = buffer.slice(4, 4 + headerSize);
const bodyBuffer = buffer.slice(4 + headerSize);
const [header, bodyType] = JSON.parse(headerBuffer.toString());
const body = deserializeBody(bodyBuffer, bodyType);
return { header, body };
}
export class ChannelServer implements IChannelServer, IDisposable {
......@@ -121,32 +160,15 @@ export class ChannelServer implements IChannelServer, IDisposable {
private protocolListener: IDisposable;
constructor(private protocol: IMessagePassingProtocol) {
this.protocolListener = this.protocol.onMessage(r => this.onMessage(r));
this.protocol.send(<IRawResponse>{ type: MessageType.ResponseInitialize });
this.protocolListener = this.protocol.onMessage(msg => this.onRawMessage(msg));
this.sendResponse({ type: ResponseType.Initialize });
}
registerChannel(channelName: string, channel: IChannel): void {
this.channels[channelName] = channel;
}
private onMessage(request: IRawRequest): void {
switch (request.type) {
case MessageType.RequestPromise:
this.onPromise(request);
break;
case MessageType.RequestEventListen:
this.onEventListen(request);
break;
case MessageType.RequestPromiseCancel:
case MessageType.RequestEventDispose:
this.disposeActiveRequest(request);
break;
}
}
private onPromise(request: IRawRequest): void {
private onPromise(request: IRawPromiseRequest): void {
const channel = this.channels[request.channelName];
let promise: Promise;
......@@ -159,19 +181,19 @@ export class ChannelServer implements IChannelServer, IDisposable {
const id = request.id;
const requestPromise = promise.then(data => {
this.protocol.send(<IRawResponse>{ id, data, type: MessageType.ResponsePromiseSuccess });
this.sendResponse(<IRawResponse>{ id, data, type: ResponseType.PromiseSuccess });
delete this.activeRequests[request.id];
}, data => {
if (data instanceof Error) {
this.protocol.send(<IRawResponse>{
this.sendResponse(<IRawResponse>{
id, data: {
message: data.message,
name: data.name,
stack: data.stack ? (data.stack.split ? data.stack.split('\n') : data.stack) : void 0
}, type: MessageType.ResponsePromiseError
}, type: ResponseType.PromiseError
});
} else {
this.protocol.send(<IRawResponse>{ id, data, type: MessageType.ResponsePromiseErrorObj });
this.sendResponse(<IRawResponse>{ id, data, type: ResponseType.PromiseErrorObj });
}
delete this.activeRequests[request.id];
......@@ -180,12 +202,12 @@ export class ChannelServer implements IChannelServer, IDisposable {
this.activeRequests[request.id] = toDisposable(() => requestPromise.cancel());
}
private onEventListen(request: IRawRequest): void {
private onEventListen(request: IRawEventListenRequest): void {
const channel = this.channels[request.channelName];
const id = request.id;
const event = channel.listen(request.name, request.arg);
const disposable = event(data => this.protocol.send(<IRawResponse>{ id, data, type: MessageType.ResponseEventFire }));
const disposable = event(data => this.sendResponse(<IRawResponse>{ id, data, type: ResponseType.EventFire }));
this.activeRequests[request.id] = disposable;
}
......@@ -199,6 +221,70 @@ export class ChannelServer implements IChannelServer, IDisposable {
}
}
private onRawMessage(message: Buffer): void {
const { header, body } = deserialize(message);
const type: RequestType = header[0];
let request: IRawRequest;
switch (type) {
case RequestType.Promise:
case RequestType.EventListen:
request = { type: header[0], id: header[1], channelName: header[2], name: header[3], arg: body };
break;
case RequestType.PromiseCancel:
case RequestType.EventDispose:
request = { type: header[0], id: header[1] };
break;
default:
return;
}
this.onRequest(request);
}
private onRequest(request: IRawRequest): void {
switch (request.type) {
case RequestType.Promise:
this.onPromise(request);
break;
case RequestType.EventListen:
this.onEventListen(request);
break;
case RequestType.PromiseCancel:
case RequestType.EventDispose:
this.disposeActiveRequest(request);
break;
}
}
private sendResponse(response: IRawResponse) {
let buffer: Buffer;
switch (response.type) {
case ResponseType.Initialize:
buffer = serialize([response.type]);
break;
case ResponseType.PromiseSuccess:
case ResponseType.PromiseError:
case ResponseType.EventFire:
case ResponseType.PromiseErrorObj:
buffer = serialize([response.type, response.id], response.data);
break;
}
this.sendRawMessage(buffer);
}
private sendRawMessage(message: Buffer) {
try {
this.protocol.send(message);
} catch (err) {
// noop
}
}
public dispose(): void {
this.protocolListener.dispose();
this.protocolListener = null;
......@@ -224,7 +310,7 @@ export class ChannelClient implements IChannelClient, IDisposable {
readonly onDidInitialize = this._onDidInitialize.event;
constructor(private protocol: IMessagePassingProtocol) {
this.protocolListener = this.protocol.onMessage(r => this.onMessage(r));
this.protocolListener = this.protocol.onMessage(msg => this.onRawMessage(msg));
}
getChannel<T extends IChannel>(channelName: string): T {
......@@ -236,8 +322,8 @@ export class ChannelClient implements IChannelClient, IDisposable {
private requestPromise(channelName: string, name: string, arg: any): TPromise<any> {
const id = this.lastRequestId++;
const type = MessageType.RequestPromise;
const request = { raw: { id, type, channelName, name, arg } };
const type = RequestType.Promise;
const request: IRequest = { raw: { id, type, channelName, name, arg } };
const activeRequest = this.state === State.Uninitialized
? this.bufferRequest(request)
......@@ -255,8 +341,9 @@ export class ChannelClient implements IChannelClient, IDisposable {
private requestEvent(channelName: string, name: string, arg: any): Event<any> {
const id = this.lastRequestId++;
const type = MessageType.RequestEventListen;
const request = { raw: { id, type, channelName, name, arg } };
const type = RequestType.EventListen;
const raw: IRawRequest = { id, type, channelName, name, arg };
const request: IRequest = { raw };
let uninitializedPromise: TPromise<any> | null = null;
const emitter = new Emitter<any>({
......@@ -264,7 +351,7 @@ export class ChannelClient implements IChannelClient, IDisposable {
uninitializedPromise = this.whenInitialized();
uninitializedPromise.then(() => {
uninitializedPromise = null;
this.send(request.raw);
this.sendRequest(request.raw);
});
},
onLastListenerRemove: () => {
......@@ -272,12 +359,12 @@ export class ChannelClient implements IChannelClient, IDisposable {
uninitializedPromise.cancel();
uninitializedPromise = null;
} else {
this.send({ id, type: MessageType.RequestEventDispose });
this.sendRequest({ id, type: RequestType.EventDispose });
}
}
});
this.handlers[id] = response => emitter.fire(response.data);
this.handlers[id] = (response: IRawEventFireResponse) => emitter.fire(response.data);
return emitter.event;
}
......@@ -287,12 +374,12 @@ export class ChannelClient implements IChannelClient, IDisposable {
return new TPromise((c, e) => {
this.handlers[id] = response => {
switch (response.type) {
case MessageType.ResponsePromiseSuccess:
case ResponseType.PromiseSuccess:
delete this.handlers[id];
c(response.data);
break;
case MessageType.ResponsePromiseError:
case ResponseType.PromiseError:
delete this.handlers[id];
const error = new Error(response.data.message);
(<any>error).stack = response.data.stack;
......@@ -300,16 +387,16 @@ export class ChannelClient implements IChannelClient, IDisposable {
e(error);
break;
case MessageType.ResponsePromiseErrorObj:
case ResponseType.PromiseErrorObj:
delete this.handlers[id];
e(response.data);
break;
}
};
this.send(request.raw);
this.sendRequest(request.raw);
},
() => this.send({ id, type: MessageType.RequestPromiseCancel }));
() => this.sendRequest({ id, type: RequestType.PromiseCancel }));
}
private bufferRequest(request: IRequest): Promise {
......@@ -344,12 +431,30 @@ export class ChannelClient implements IChannelClient, IDisposable {
});
}
private onMessage(response: IRawResponse): void {
if (!isResponse(response.type)) {
return;
private onRawMessage(message: Buffer): void {
const { header, body } = deserialize(message);
const type: ResponseType = header[0];
let response: IRawResponse;
switch (type) {
case ResponseType.Initialize:
response = { type: header[0] };
break;
case ResponseType.PromiseSuccess:
case ResponseType.PromiseError:
case ResponseType.EventFire:
case ResponseType.PromiseErrorObj:
response = { type: header[0], id: header[1], data: body };
break;
default:
return;
}
if (this.state === State.Uninitialized && response.type === MessageType.ResponseInitialize) {
this.onResponse(response);
}
private onResponse(response: IRawResponse): void {
if (response.type === ResponseType.Initialize) {
this.state = State.Idle;
this._onDidInitialize.fire();
this.bufferedRequests.forEach(r => r.flush && r.flush());
......@@ -363,9 +468,26 @@ export class ChannelClient implements IChannelClient, IDisposable {
}
}
private send(raw: IRawRequest) {
private sendRequest(request: IRawRequest) {
let buffer: Buffer;
switch (request.type) {
case RequestType.Promise:
case RequestType.EventListen:
buffer = serialize([request.type, request.id, request.channelName, request.name], request.arg);
break;
case RequestType.PromiseCancel:
case RequestType.EventDispose:
buffer = serialize([request.type, request.id]);
break;
}
this.sendRawMessage(buffer);
}
private sendRawMessage(message: Buffer) {
try {
this.protocol.send(raw);
this.protocol.send(message);
} catch (err) {
// noop
}
......@@ -410,13 +532,14 @@ export class IPCServer implements IChannelServer, IRoutingChannelClient, IDispos
onDidClientConnect(({ protocol, onDidClientDisconnect }) => {
const onFirstMessage = once(protocol.onMessage);
onFirstMessage(id => {
onFirstMessage(rawId => {
const channelServer = new ChannelServer(protocol);
const channelClient = new ChannelClient(protocol);
Object.keys(this.channels)
.forEach(name => channelServer.registerChannel(name, this.channels[name]));
const id = rawId.toString();
this.channelClients[id] = channelClient;
this.onClientAdded.fire(id);
......@@ -492,7 +615,7 @@ export class IPCClient implements IChannelClient, IChannelServer, IDisposable {
private channelServer: ChannelServer;
constructor(protocol: IMessagePassingProtocol, id: string) {
protocol.send(id);
protocol.send(Buffer.from(id));
this.channelClient = new ChannelClient(protocol);
this.channelServer = new ChannelServer(protocol);
}
......
......@@ -49,18 +49,20 @@ suite('IPC, Socket Protocol', () => {
return new TPromise(resolve => {
const sub = b.onMessage(data => {
sub.dispose();
assert.equal(data, 'foobarfarboo');
assert.equal(data.toString(), 'foobarfarboo');
resolve(null);
});
a.send('foobarfarboo');
a.send(Buffer.from('foobarfarboo'));
}).then(() => {
return new TPromise(resolve => {
const sub = b.onMessage(data => {
sub.dispose();
assert.equal(data, 123);
assert.equal(data.readInt8(0), 123);
resolve(null);
});
a.send(123);
const buffer = new Buffer(1);
buffer.writeInt8(123, 0);
a.send(buffer);
});
});
});
......@@ -78,11 +80,11 @@ suite('IPC, Socket Protocol', () => {
data: 'Hello World'.split('')
};
a.send(data);
a.send(Buffer.from(JSON.stringify(data)));
return new TPromise(resolve => {
b.onMessage(msg => {
assert.deepEqual(msg, data);
assert.deepEqual(JSON.parse(msg.toString()), data);
resolve(null);
});
});
......@@ -100,7 +102,7 @@ suite('IPC, Socket Protocol', () => {
assert.equal(stream.listenerCount('end'), 2);
receiver1.onMessage((msg) => {
assert.equal(msg.value, 1);
assert.equal(JSON.parse(msg.toString()).value, 1);
let buffer = receiver1.getBuffer();
receiver1.dispose();
......@@ -110,15 +112,15 @@ suite('IPC, Socket Protocol', () => {
const receiver2 = new Protocol(stream, buffer);
receiver2.onMessage((msg) => {
assert.equal(msg.value, 2);
assert.equal(JSON.parse(msg.toString()).value, 2);
resolve(void 0);
});
});
const msg1 = { value: 1 };
const msg2 = { value: 2 };
sender.send(msg1);
sender.send(msg2);
sender.send(Buffer.from(JSON.stringify(msg1)));
sender.send(Buffer.from(JSON.stringify(msg2)));
return result;
});
......
......@@ -5,7 +5,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
export interface IMarcoPoloEvent {
......
......@@ -2299,8 +2299,8 @@
/users/foo/src/vs/base/parts/ipc/test/node/ipc.test.ts
/users/foo/src/vs/base/parts/ipc/test/node/testService.ts
/users/foo/src/vs/base/parts/ipc/common
/users/foo/src/vs/base/parts/ipc/common/ipc.electron.ts
/users/foo/src/vs/base/parts/ipc/common/ipc.ts
/users/foo/src/vs/base/parts/ipc/node/ipc.electron.ts
/users/foo/src/vs/base/parts/ipc/node/ipc.ts
/users/foo/src/vs/base/parts/ipc/electron-browser
/users/foo/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts
/users/foo/src/vs/base/parts/ipc/node
......
......@@ -19,25 +19,25 @@ import { debounce } from 'vs/base/common/decorators';
import * as platform from 'vs/base/common/platform';
import { Disposable } from 'vs/base/common/lifecycle';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/common/windows';
import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
import { IssueReporterData, IssueReporterStyles, IssueType, ISettingsSearchIssueReporterData, IssueReporterFeatures } from 'vs/platform/issue/common/issue';
import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage';
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc';
import { ILogService, getLogLevel } from 'vs/platform/log/common/log';
import { OcticonLabel } from 'vs/base/browser/ui/octiconLabel/octiconLabel';
import { normalizeGitHubUrl } from 'vs/code/electron-browser/issue/issueReporterUtil';
......
......@@ -16,7 +16,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
......@@ -27,20 +27,20 @@ import { RequestService } from 'vs/platform/request/electron-browser/requestServ
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { combinedAppender, NullTelemetryService, ITelemetryAppender, NullAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
import { IWindowsService, ActiveWindowManager } from 'vs/platform/windows/common/windows';
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { ipcRenderer } from 'electron';
import { createSharedProcessContributions } from 'vs/code/electron-browser/sharedProcess/contrib/contributions';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsChannel } from 'vs/platform/localizations/common/localizationsIpc';
import { DialogChannelClient } from 'vs/platform/dialogs/common/dialogIpc';
import { LocalizationsChannel } from 'vs/platform/localizations/node/localizationsIpc';
import { DialogChannelClient } from 'vs/platform/dialogs/node/dialogIpc';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
......
......@@ -9,12 +9,12 @@ import { app, ipcMain as ipc, systemPreferences } from 'electron';
import * as platform from 'vs/base/common/platform';
import { WindowsManager } from 'vs/code/electron-main/windows';
import { IWindowsService, OpenContext, ActiveWindowManager } from 'vs/platform/windows/common/windows';
import { WindowsChannel } from 'vs/platform/windows/common/windowsIpc';
import { WindowsChannel } from 'vs/platform/windows/node/windowsIpc';
import { WindowsService } from 'vs/platform/windows/electron-main/windowsService';
import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { getShellEnvironment } from 'vs/code/node/shellEnv';
import { IUpdateService } from 'vs/platform/update/common/update';
import { UpdateChannel } from 'vs/platform/update/common/updateIpc';
import { UpdateChannel } from 'vs/platform/update/node/updateIpc';
import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron-main';
import { Server, connect, Client } from 'vs/base/parts/ipc/node/ipc.net';
import { SharedProcess } from 'vs/code/electron-main/sharedProcess';
......@@ -28,13 +28,13 @@ import { IStateService } from 'vs/platform/state/common/state';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IURLService } from 'vs/platform/url/common/url';
import { URLHandlerChannelClient, URLServiceChannel } from 'vs/platform/url/common/urlIpc';
import { URLHandlerChannelClient, URLServiceChannel } from 'vs/platform/url/node/urlIpc';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import { ProxyAuthHandler } from './auth';
......@@ -47,22 +47,22 @@ import { isUndefinedOrNull } from 'vs/base/common/types';
import { CodeWindow } from 'vs/code/electron-main/window';
import { KeyboardLayoutMonitor } from 'vs/code/electron-main/keyboard';
import URI from 'vs/base/common/uri';
import { WorkspacesChannel } from 'vs/platform/workspaces/common/workspacesIpc';
import { WorkspacesChannel } from 'vs/platform/workspaces/node/workspacesIpc';
import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { getMachineId } from 'vs/base/node/id';
import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32';
import { LinuxUpdateService } from 'vs/platform/update/electron-main/updateService.linux';
import { DarwinUpdateService } from 'vs/platform/update/electron-main/updateService.darwin';
import { IIssueService } from 'vs/platform/issue/common/issue';
import { IssueChannel } from 'vs/platform/issue/common/issueIpc';
import { IssueChannel } from 'vs/platform/issue/node/issueIpc';
import { IssueService } from 'vs/platform/issue/electron-main/issueService';
import { LogLevelSetterChannel } from 'vs/platform/log/common/logIpc';
import { LogLevelSetterChannel } from 'vs/platform/log/node/logIpc';
import * as errors from 'vs/base/common/errors';
import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener';
import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { MenubarService } from 'vs/platform/menubar/electron-main/menubarService';
import { MenubarChannel } from 'vs/platform/menubar/common/menubarIpc';
import { MenubarChannel } from 'vs/platform/menubar/node/menubarIpc';
import { IUriLabelService } from 'vs/platform/uriLabel/common/uriLabel';
import { CodeMenu } from 'vs/code/electron-main/menus';
import { hasArgs } from 'vs/platform/environment/node/argv';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { ILogService } from 'vs/platform/log/common/log';
import { IURLService } from 'vs/platform/url/common/url';
import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
import Severity from 'vs/base/common/severity';
import { Event } from 'vs/base/common/event';
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
export const ID = 'driverService';
export const IDriver = createDecorator<IDriver>(ID);
// !! Do not remove the following START and END markers, they are parsed by the smoketest build
//*START
export interface IElement {
tagName: string;
className: string;
textContent: string;
attributes: { [name: string]: string; };
children: IElement[];
top: number;
left: number;
}
export interface IDriver {
_serviceBrand: any;
getWindowIds(): TPromise<number[]>;
capturePage(windowId: number): TPromise<string>;
reloadWindow(windowId: number): TPromise<void>;
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void>;
click(windowId: number, selector: string, xoffset?: number | undefined, yoffset?: number | undefined): TPromise<void>;
doubleClick(windowId: number, selector: string): TPromise<void>;
setValue(windowId: number, selector: string, text: string): TPromise<void>;
getTitle(windowId: number): TPromise<string>;
isActiveElement(windowId: number, selector: string): TPromise<boolean>;
getElements(windowId: number, selector: string, recursive?: boolean): TPromise<IElement[]>;
typeInEditor(windowId: number, selector: string, text: string): TPromise<void>;
getTerminalBuffer(windowId: number, selector: string): TPromise<string[]>;
writeInTerminal(windowId: number, selector: string, text: string): TPromise<void>;
}
//*END
export interface IDriverChannel extends IChannel {
call(command: 'getWindowIds'): TPromise<number[]>;
call(command: 'capturePage'): TPromise<string>;
call(command: 'reloadWindow', arg: number): TPromise<void>;
call(command: 'dispatchKeybinding', arg: [number, string]): TPromise<void>;
call(command: 'click', arg: [number, string, number | undefined, number | undefined]): TPromise<void>;
call(command: 'doubleClick', arg: [number, string]): TPromise<void>;
call(command: 'setValue', arg: [number, string, string]): TPromise<void>;
call(command: 'getTitle', arg: [number]): TPromise<string>;
call(command: 'isActiveElement', arg: [number, string]): TPromise<boolean>;
call(command: 'getElements', arg: [number, string, boolean]): TPromise<IElement[]>;
call(command: 'typeInEditor', arg: [number, string, string]): TPromise<void>;
call(command: 'getTerminalBuffer', arg: [number, string]): TPromise<string[]>;
call(command: 'writeInTerminal', arg: [number, string, string]): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class DriverChannel implements IDriverChannel {
constructor(private driver: IDriver) { }
listen<T>(event: string): Event<T> {
throw new Error('No event found');
}
call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'getWindowIds': return this.driver.getWindowIds();
case 'capturePage': return this.driver.capturePage(arg);
case 'reloadWindow': return this.driver.reloadWindow(arg);
case 'dispatchKeybinding': return this.driver.dispatchKeybinding(arg[0], arg[1]);
case 'click': return this.driver.click(arg[0], arg[1], arg[2], arg[3]);
case 'doubleClick': return this.driver.doubleClick(arg[0], arg[1]);
case 'setValue': return this.driver.setValue(arg[0], arg[1], arg[2]);
case 'getTitle': return this.driver.getTitle(arg[0]);
case 'isActiveElement': return this.driver.isActiveElement(arg[0], arg[1]);
case 'getElements': return this.driver.getElements(arg[0], arg[1], arg[2]);
case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1], arg[2]);
case 'getTerminalBuffer': return this.driver.getTerminalBuffer(arg[0], arg[1]);
case 'writeInTerminal': return this.driver.writeInTerminal(arg[0], arg[1], arg[2]);
}
return undefined;
}
}
export class DriverChannelClient implements IDriver {
_serviceBrand: any;
constructor(private channel: IDriverChannel) { }
getWindowIds(): TPromise<number[]> {
return this.channel.call('getWindowIds');
}
capturePage(windowId: number): TPromise<string> {
return this.channel.call('capturePage', windowId);
}
reloadWindow(windowId: number): TPromise<void> {
return this.channel.call('reloadWindow', windowId);
}
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void> {
return this.channel.call('dispatchKeybinding', [windowId, keybinding]);
}
click(windowId: number, selector: string, xoffset: number | undefined, yoffset: number | undefined): TPromise<void> {
return this.channel.call('click', [windowId, selector, xoffset, yoffset]);
}
doubleClick(windowId: number, selector: string): TPromise<void> {
return this.channel.call('doubleClick', [windowId, selector]);
}
setValue(windowId: number, selector: string, text: string): TPromise<void> {
return this.channel.call('setValue', [windowId, selector, text]);
}
getTitle(windowId: number): TPromise<string> {
return this.channel.call('getTitle', [windowId]);
}
isActiveElement(windowId: number, selector: string): TPromise<boolean> {
return this.channel.call('isActiveElement', [windowId, selector]);
}
getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]> {
return this.channel.call('getElements', [windowId, selector, recursive]);
}
typeInEditor(windowId: number, selector: string, text: string): TPromise<void> {
return this.channel.call('typeInEditor', [windowId, selector, text]);
}
getTerminalBuffer(windowId: number, selector: string): TPromise<string[]> {
return this.channel.call('getTerminalBuffer', [windowId, selector]);
}
writeInTerminal(windowId: number, selector: string, text: string): TPromise<void> {
return this.channel.call('writeInTerminal', [windowId, selector, text]);
}
}
export interface IDriverOptions {
verbose: boolean;
}
export interface IWindowDriverRegistry {
registerWindowDriver(windowId: number): TPromise<IDriverOptions>;
reloadWindowDriver(windowId: number): TPromise<void>;
}
export interface IWindowDriverRegistryChannel extends IChannel {
call(command: 'registerWindowDriver', arg: number): TPromise<IDriverOptions>;
call(command: 'reloadWindowDriver', arg: number): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class WindowDriverRegistryChannel implements IWindowDriverRegistryChannel {
constructor(private registry: IWindowDriverRegistry) { }
listen<T>(event: string): Event<T> {
throw new Error('No event found');
}
call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'registerWindowDriver': return this.registry.registerWindowDriver(arg);
case 'reloadWindowDriver': return this.registry.reloadWindowDriver(arg);
}
return undefined;
}
}
export class WindowDriverRegistryChannelClient implements IWindowDriverRegistry {
_serviceBrand: any;
constructor(private channel: IWindowDriverRegistryChannel) { }
registerWindowDriver(windowId: number): TPromise<IDriverOptions> {
return this.channel.call('registerWindowDriver', windowId);
}
reloadWindowDriver(windowId: number): TPromise<void> {
return this.channel.call('reloadWindowDriver', windowId);
}
}
export interface IWindowDriver {
click(selector: string, xoffset?: number | undefined, yoffset?: number | undefined): TPromise<void>;
doubleClick(selector: string): TPromise<void>;
setValue(selector: string, text: string): TPromise<void>;
getTitle(): TPromise<string>;
isActiveElement(selector: string): TPromise<boolean>;
getElements(selector: string, recursive: boolean): TPromise<IElement[]>;
typeInEditor(selector: string, text: string): TPromise<void>;
getTerminalBuffer(selector: string): TPromise<string[]>;
writeInTerminal(selector: string, text: string): TPromise<void>;
}
export interface IWindowDriverChannel extends IChannel {
call(command: 'click', arg: [string, number | undefined, number | undefined]): TPromise<void>;
call(command: 'doubleClick', arg: string): TPromise<void>;
call(command: 'setValue', arg: [string, string]): TPromise<void>;
call(command: 'getTitle'): TPromise<string>;
call(command: 'isActiveElement', arg: string): TPromise<boolean>;
call(command: 'getElements', arg: [string, boolean]): TPromise<IElement[]>;
call(command: 'typeInEditor', arg: [string, string]): TPromise<void>;
call(command: 'getTerminalBuffer', arg: string): TPromise<string[]>;
call(command: 'writeInTerminal', arg: [string, string]): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class WindowDriverChannel implements IWindowDriverChannel {
constructor(private driver: IWindowDriver) { }
listen<T>(event: string): Event<T> {
throw new Error('No event found');
}
call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'click': return this.driver.click(arg[0], arg[1], arg[2]);
case 'doubleClick': return this.driver.doubleClick(arg);
case 'setValue': return this.driver.setValue(arg[0], arg[1]);
case 'getTitle': return this.driver.getTitle();
case 'isActiveElement': return this.driver.isActiveElement(arg);
case 'getElements': return this.driver.getElements(arg[0], arg[1]);
case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1]);
case 'getTerminalBuffer': return this.driver.getTerminalBuffer(arg);
case 'writeInTerminal': return this.driver.writeInTerminal(arg[0], arg[1]);
}
return undefined;
}
}
export class WindowDriverChannelClient implements IWindowDriver {
_serviceBrand: any;
constructor(private channel: IWindowDriverChannel) { }
click(selector: string, xoffset?: number, yoffset?: number): TPromise<void> {
return this.channel.call('click', [selector, xoffset, yoffset]);
}
doubleClick(selector: string): TPromise<void> {
return this.channel.call('doubleClick', selector);
}
setValue(selector: string, text: string): TPromise<void> {
return this.channel.call('setValue', [selector, text]);
}
getTitle(): TPromise<string> {
return this.channel.call('getTitle');
}
isActiveElement(selector: string): TPromise<boolean> {
return this.channel.call('isActiveElement', selector);
}
getElements(selector: string, recursive: boolean): TPromise<IElement[]> {
return this.channel.call('getElements', [selector, recursive]);
}
typeInEditor(selector: string, text: string): TPromise<void> {
return this.channel.call('typeInEditor', [selector, text]);
}
getTerminalBuffer(selector: string): TPromise<string[]> {
return this.channel.call('getTerminalBuffer', selector);
}
writeInTerminal(selector: string, text: string): TPromise<void> {
return this.channel.call('writeInTerminal', [selector, text]);
}
}
\ No newline at end of file
......@@ -7,8 +7,8 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/common/driver';
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { IWindowDriver, IElement, WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/node/driver';
import { IPCClient } from 'vs/base/parts/ipc/node/ipc';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { getTopLeftOffset, getClientArea } from 'vs/base/browser/dom';
import * as electron from 'electron';
......
......@@ -6,12 +6,12 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDriver, DriverChannel, IElement, IWindowDriverChannel, WindowDriverChannelClient, IWindowDriverRegistry, WindowDriverRegistryChannel, IWindowDriver, IDriverOptions } from 'vs/platform/driver/common/driver';
import { IDriver, DriverChannel, IElement, IWindowDriverChannel, WindowDriverChannelClient, IWindowDriverRegistry, WindowDriverRegistryChannel, IWindowDriver, IDriverOptions } from 'vs/platform/driver/node/driver';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { serve as serveNet } from 'vs/base/parts/ipc/node/ipc.net';
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IPCServer, IClientRouter } from 'vs/base/parts/ipc/common/ipc';
import { IPCServer, IClientRouter } from 'vs/base/parts/ipc/node/ipc';
import { SimpleKeybinding, KeyCode } from 'vs/base/common/keyCodes';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
import { OS } from 'vs/base/common/platform';
......
......@@ -5,8 +5,292 @@
'use strict';
import { IDriver, DriverChannelClient } from 'vs/platform/driver/common/driver';
import { connect as connectNet, Client } from 'vs/base/parts/ipc/node/ipc.net';
import { TPromise } from 'vs/base/common/winjs.base';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event } from 'vs/base/common/event';
export const ID = 'driverService';
export const IDriver = createDecorator<IDriver>(ID);
// !! Do not remove the following START and END markers, they are parsed by the smoketest build
//*START
export interface IElement {
tagName: string;
className: string;
textContent: string;
attributes: { [name: string]: string; };
children: IElement[];
top: number;
left: number;
}
export interface IDriver {
_serviceBrand: any;
getWindowIds(): TPromise<number[]>;
capturePage(windowId: number): TPromise<string>;
reloadWindow(windowId: number): TPromise<void>;
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void>;
click(windowId: number, selector: string, xoffset?: number | undefined, yoffset?: number | undefined): TPromise<void>;
doubleClick(windowId: number, selector: string): TPromise<void>;
setValue(windowId: number, selector: string, text: string): TPromise<void>;
getTitle(windowId: number): TPromise<string>;
isActiveElement(windowId: number, selector: string): TPromise<boolean>;
getElements(windowId: number, selector: string, recursive?: boolean): TPromise<IElement[]>;
typeInEditor(windowId: number, selector: string, text: string): TPromise<void>;
getTerminalBuffer(windowId: number, selector: string): TPromise<string[]>;
writeInTerminal(windowId: number, selector: string, text: string): TPromise<void>;
}
//*END
export interface IDriverChannel extends IChannel {
call(command: 'getWindowIds'): TPromise<number[]>;
call(command: 'capturePage'): TPromise<string>;
call(command: 'reloadWindow', arg: number): TPromise<void>;
call(command: 'dispatchKeybinding', arg: [number, string]): TPromise<void>;
call(command: 'click', arg: [number, string, number | undefined, number | undefined]): TPromise<void>;
call(command: 'doubleClick', arg: [number, string]): TPromise<void>;
call(command: 'setValue', arg: [number, string, string]): TPromise<void>;
call(command: 'getTitle', arg: [number]): TPromise<string>;
call(command: 'isActiveElement', arg: [number, string]): TPromise<boolean>;
call(command: 'getElements', arg: [number, string, boolean]): TPromise<IElement[]>;
call(command: 'typeInEditor', arg: [number, string, string]): TPromise<void>;
call(command: 'getTerminalBuffer', arg: [number, string]): TPromise<string[]>;
call(command: 'writeInTerminal', arg: [number, string, string]): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class DriverChannel implements IDriverChannel {
constructor(private driver: IDriver) { }
listen<T>(event: string): Event<T> {
throw new Error('No event found');
}
call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'getWindowIds': return this.driver.getWindowIds();
case 'capturePage': return this.driver.capturePage(arg);
case 'reloadWindow': return this.driver.reloadWindow(arg);
case 'dispatchKeybinding': return this.driver.dispatchKeybinding(arg[0], arg[1]);
case 'click': return this.driver.click(arg[0], arg[1], arg[2], arg[3]);
case 'doubleClick': return this.driver.doubleClick(arg[0], arg[1]);
case 'setValue': return this.driver.setValue(arg[0], arg[1], arg[2]);
case 'getTitle': return this.driver.getTitle(arg[0]);
case 'isActiveElement': return this.driver.isActiveElement(arg[0], arg[1]);
case 'getElements': return this.driver.getElements(arg[0], arg[1], arg[2]);
case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1], arg[2]);
case 'getTerminalBuffer': return this.driver.getTerminalBuffer(arg[0], arg[1]);
case 'writeInTerminal': return this.driver.writeInTerminal(arg[0], arg[1], arg[2]);
}
return undefined;
}
}
export class DriverChannelClient implements IDriver {
_serviceBrand: any;
constructor(private channel: IDriverChannel) { }
getWindowIds(): TPromise<number[]> {
return this.channel.call('getWindowIds');
}
capturePage(windowId: number): TPromise<string> {
return this.channel.call('capturePage', windowId);
}
reloadWindow(windowId: number): TPromise<void> {
return this.channel.call('reloadWindow', windowId);
}
dispatchKeybinding(windowId: number, keybinding: string): TPromise<void> {
return this.channel.call('dispatchKeybinding', [windowId, keybinding]);
}
click(windowId: number, selector: string, xoffset: number | undefined, yoffset: number | undefined): TPromise<void> {
return this.channel.call('click', [windowId, selector, xoffset, yoffset]);
}
doubleClick(windowId: number, selector: string): TPromise<void> {
return this.channel.call('doubleClick', [windowId, selector]);
}
setValue(windowId: number, selector: string, text: string): TPromise<void> {
return this.channel.call('setValue', [windowId, selector, text]);
}
getTitle(windowId: number): TPromise<string> {
return this.channel.call('getTitle', [windowId]);
}
isActiveElement(windowId: number, selector: string): TPromise<boolean> {
return this.channel.call('isActiveElement', [windowId, selector]);
}
getElements(windowId: number, selector: string, recursive: boolean): TPromise<IElement[]> {
return this.channel.call('getElements', [windowId, selector, recursive]);
}
typeInEditor(windowId: number, selector: string, text: string): TPromise<void> {
return this.channel.call('typeInEditor', [windowId, selector, text]);
}
getTerminalBuffer(windowId: number, selector: string): TPromise<string[]> {
return this.channel.call('getTerminalBuffer', [windowId, selector]);
}
writeInTerminal(windowId: number, selector: string, text: string): TPromise<void> {
return this.channel.call('writeInTerminal', [windowId, selector, text]);
}
}
export interface IDriverOptions {
verbose: boolean;
}
export interface IWindowDriverRegistry {
registerWindowDriver(windowId: number): TPromise<IDriverOptions>;
reloadWindowDriver(windowId: number): TPromise<void>;
}
export interface IWindowDriverRegistryChannel extends IChannel {
call(command: 'registerWindowDriver', arg: number): TPromise<IDriverOptions>;
call(command: 'reloadWindowDriver', arg: number): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class WindowDriverRegistryChannel implements IWindowDriverRegistryChannel {
constructor(private registry: IWindowDriverRegistry) { }
listen<T>(event: string): Event<T> {
throw new Error('No event found');
}
call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'registerWindowDriver': return this.registry.registerWindowDriver(arg);
case 'reloadWindowDriver': return this.registry.reloadWindowDriver(arg);
}
return undefined;
}
}
export class WindowDriverRegistryChannelClient implements IWindowDriverRegistry {
_serviceBrand: any;
constructor(private channel: IWindowDriverRegistryChannel) { }
registerWindowDriver(windowId: number): TPromise<IDriverOptions> {
return this.channel.call('registerWindowDriver', windowId);
}
reloadWindowDriver(windowId: number): TPromise<void> {
return this.channel.call('reloadWindowDriver', windowId);
}
}
export interface IWindowDriver {
click(selector: string, xoffset?: number | undefined, yoffset?: number | undefined): TPromise<void>;
doubleClick(selector: string): TPromise<void>;
setValue(selector: string, text: string): TPromise<void>;
getTitle(): TPromise<string>;
isActiveElement(selector: string): TPromise<boolean>;
getElements(selector: string, recursive: boolean): TPromise<IElement[]>;
typeInEditor(selector: string, text: string): TPromise<void>;
getTerminalBuffer(selector: string): TPromise<string[]>;
writeInTerminal(selector: string, text: string): TPromise<void>;
}
export interface IWindowDriverChannel extends IChannel {
call(command: 'click', arg: [string, number | undefined, number | undefined]): TPromise<void>;
call(command: 'doubleClick', arg: string): TPromise<void>;
call(command: 'setValue', arg: [string, string]): TPromise<void>;
call(command: 'getTitle'): TPromise<string>;
call(command: 'isActiveElement', arg: string): TPromise<boolean>;
call(command: 'getElements', arg: [string, boolean]): TPromise<IElement[]>;
call(command: 'typeInEditor', arg: [string, string]): TPromise<void>;
call(command: 'getTerminalBuffer', arg: string): TPromise<string[]>;
call(command: 'writeInTerminal', arg: [string, string]): TPromise<void>;
call(command: string, arg: any): TPromise<any>;
}
export class WindowDriverChannel implements IWindowDriverChannel {
constructor(private driver: IWindowDriver) { }
listen<T>(event: string): Event<T> {
throw new Error('No event found');
}
call(command: string, arg?: any): TPromise<any> {
switch (command) {
case 'click': return this.driver.click(arg[0], arg[1], arg[2]);
case 'doubleClick': return this.driver.doubleClick(arg);
case 'setValue': return this.driver.setValue(arg[0], arg[1]);
case 'getTitle': return this.driver.getTitle();
case 'isActiveElement': return this.driver.isActiveElement(arg);
case 'getElements': return this.driver.getElements(arg[0], arg[1]);
case 'typeInEditor': return this.driver.typeInEditor(arg[0], arg[1]);
case 'getTerminalBuffer': return this.driver.getTerminalBuffer(arg);
case 'writeInTerminal': return this.driver.writeInTerminal(arg[0], arg[1]);
}
return undefined;
}
}
export class WindowDriverChannelClient implements IWindowDriver {
_serviceBrand: any;
constructor(private channel: IWindowDriverChannel) { }
click(selector: string, xoffset?: number, yoffset?: number): TPromise<void> {
return this.channel.call('click', [selector, xoffset, yoffset]);
}
doubleClick(selector: string): TPromise<void> {
return this.channel.call('doubleClick', selector);
}
setValue(selector: string, text: string): TPromise<void> {
return this.channel.call('setValue', [selector, text]);
}
getTitle(): TPromise<string> {
return this.channel.call('getTitle');
}
isActiveElement(selector: string): TPromise<boolean> {
return this.channel.call('isActiveElement', selector);
}
getElements(selector: string, recursive: boolean): TPromise<IElement[]> {
return this.channel.call('getElements', [selector, recursive]);
}
typeInEditor(selector: string, text: string): TPromise<void> {
return this.channel.call('typeInEditor', [selector, text]);
}
getTerminalBuffer(selector: string): TPromise<string[]> {
return this.channel.call('getTerminalBuffer', selector);
}
writeInTerminal(selector: string, text: string): TPromise<void> {
return this.channel.call('writeInTerminal', [selector, text]);
}
}
export async function connect(handle: string): Promise<{ client: Client, driver: IDriver }> {
const client = await connectNet(handle, 'driverClient');
......
......@@ -6,8 +6,8 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension } from './extensionManagement';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension } from '../common/extensionManagement';
import { Event, buffer, mapEvent } from 'vs/base/common/event';
import URI from 'vs/base/common/uri';
import { IURITransformer } from 'vs/base/common/uriIpc';
......
......@@ -6,8 +6,8 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IIssueService, IssueReporterData, ProcessExplorerData } from './issue';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IIssueService, IssueReporterData, ProcessExplorerData } from '../common/issue';
import { Event } from 'vs/base/common/event';
export interface IIssueChannel extends IChannel {
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, buffer } from 'vs/base/common/event';
import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations';
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { TPromise } from 'vs/base/common/winjs.base';
import { LogLevel, ILogService, DelegatedLogService } from 'vs/platform/log/common/log';
import { Event, buffer } from 'vs/base/common/event';
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { TPromise } from 'vs/base/common/winjs.base';
import { IMenubarService, IMenubarData, IMenubarKeybinding } from 'vs/platform/menubar/common/menubar';
import { Event } from 'vs/base/common/event';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { Event } from 'vs/base/common/event';
......
......@@ -6,10 +6,10 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { Event, Emitter } from 'vs/base/common/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IUpdateService, State } from './update';
import { IUpdateService, State } from 'vs/platform/update/common/update';
export interface IUpdateChannel extends IChannel {
listen(event: 'onStateChange'): Event<State>;
......
......@@ -6,11 +6,11 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IURLHandler, IURLService } from './url';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import URI from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event';
import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
export interface IURLServiceChannel extends IChannel {
call(command: 'open', url: string): TPromise<boolean>;
......
......@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, buffer } from 'vs/base/common/event';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWorkspacesService, IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import URI from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export enum MessageType {
Initialized,
Ready,
Terminate
}
export function createMessageOfType(type: MessageType): Buffer {
const result = new Buffer(1);
switch (type) {
case MessageType.Initialized: result.writeUInt8(1, 0); break;
case MessageType.Ready: result.writeUInt8(2, 0); break;
case MessageType.Terminate: result.writeUInt8(3, 0); break;
}
return result;
}
export function isMessageOfType(message: Buffer, type: MessageType): boolean {
if (message.length !== 1) {
return false;
}
switch (message.readUInt8(0)) {
case 1: return type === MessageType.Initialized;
case 2: return type === MessageType.Ready;
case 3: return type === MessageType.Terminate;
default: return false;
}
}
\ No newline at end of file
......@@ -26,26 +26,26 @@ import { EnvironmentService } from 'vs/platform/environment/node/environmentServ
import * as gracefulFs from 'graceful-fs';
import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/common/windows';
import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc';
import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { StorageService, inMemoryLocalStorageInstance, IStorage } from 'vs/platform/storage/common/storageService';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { webFrame } from 'electron';
import { UpdateChannelClient } from 'vs/platform/update/common/updateIpc';
import { UpdateChannelClient } from 'vs/platform/update/node/updateIpc';
import { IUpdateService } from 'vs/platform/update/common/update';
import { URLHandlerChannel, URLServiceChannelClient } from 'vs/platform/url/common/urlIpc';
import { URLHandlerChannel, URLServiceChannelClient } from 'vs/platform/url/node/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
import { WorkspacesChannelClient } from 'vs/platform/workspaces/common/workspacesIpc';
import { WorkspacesChannelClient } from 'vs/platform/workspaces/node/workspacesIpc';
import { IWorkspacesService, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import * as fs from 'fs';
import { ConsoleLogService, MultiplexLogService, ILogService } from 'vs/platform/log/common/log';
import { IssueChannelClient } from 'vs/platform/issue/common/issueIpc';
import { IssueChannelClient } from 'vs/platform/issue/node/issueIpc';
import { IIssueService } from 'vs/platform/issue/common/issue';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc';
import { RelayURLService } from 'vs/platform/url/common/urlService';
import { MenubarChannelClient } from 'vs/platform/menubar/common/menubarIpc';
import { MenubarChannelClient } from 'vs/platform/menubar/node/menubarIpc';
import { IMenubarService } from 'vs/platform/menubar/common/menubar';
import { Schemas } from 'vs/base/common/network';
......
......@@ -19,7 +19,7 @@ import pkg from 'vs/platform/node/package';
import { Workbench, IWorkbenchStartedInfo } from 'vs/workbench/electron-browser/workbench';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService, configurationTelemetry, combinedAppender, LogAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
import { ElectronWindow } from 'vs/workbench/electron-browser/window';
......@@ -57,10 +57,9 @@ import { WorkbenchModeServiceImpl } from 'vs/workbench/services/mode/common/work
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ICrashReporterService, NullCrashReporterService, CrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
import { getDelayedChannel, IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { getDelayedChannel, IPCClient } from 'vs/base/parts/ipc/node/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { DefaultURITransformer } from 'vs/base/common/uriIpc';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/node/extensionManagementIpc';
import { IExtensionManagementService, IExtensionEnablementService, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
......@@ -81,7 +80,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
import { stat } from 'fs';
import { join } from 'path';
import { ILocalizationsChannel, LocalizationsChannelClient } from 'vs/platform/localizations/common/localizationsIpc';
import { ILocalizationsChannel, LocalizationsChannelClient } from 'vs/platform/localizations/node/localizationsIpc';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue';
import { WorkbenchIssueService } from 'vs/workbench/services/issue/electron-browser/workbenchIssueService';
......@@ -89,13 +88,14 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { NotificationService } from 'vs/workbench/services/notification/common/notificationService';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { DialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
import { DialogChannel } from 'vs/platform/dialogs/common/dialogIpc';
import { DialogChannel } from 'vs/platform/dialogs/node/dialogIpc';
import { EventType, addDisposableListener, addClass } from 'vs/base/browser/dom';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { OpenerService } from 'vs/editor/browser/services/openerService';
import { SearchHistoryService } from 'vs/workbench/services/search/node/searchHistoryService';
import { MulitExtensionManagementService } from 'vs/platform/extensionManagement/common/multiExtensionManagement';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
import { DefaultURITransformer } from 'vs/base/common/uriIpc';
/**
* Services that we require for the Shell
......
......@@ -103,7 +103,7 @@ import { NotificationsAlerts } from 'vs/workbench/browser/parts/notifications/no
import { NotificationsStatus } from 'vs/workbench/browser/parts/notifications/notificationsStatus';
import { registerNotificationCommands } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
import { NotificationsToasts } from 'vs/workbench/browser/parts/notifications/notificationsToasts';
import { IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { IPCClient } from 'vs/base/parts/ipc/node/ipc';
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService';
......
......@@ -20,7 +20,7 @@ import * as errors from 'vs/base/common/errors';
import * as glob from 'vs/base/common/glob';
import { ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol';
import URI from 'vs/base/common/uri';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
......
......@@ -8,10 +8,11 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { ExtensionHostMain, exit } from 'vs/workbench/node/extensionHostMain';
import { IInitData } from 'vs/workbench/api/node/extHost.protocol';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { Protocol } from 'vs/base/parts/ipc/node/ipc.net';
import { createConnection } from 'net';
import { Event, filterEvent } from 'vs/base/common/event';
import { createMessageOfType, MessageType, isMessageOfType } from 'vs/workbench/common/extensionHostProtocol';
// With Electron 2.x and node.js 8.x the "natives" module
// can cause a native crash (see https://github.com/nodejs/node/issues/19891 and
......@@ -61,7 +62,7 @@ function createExtHostProtocol(): Promise<IMessagePassingProtocol> {
private _terminating = false;
readonly onMessage: Event<any> = filterEvent(protocol.onMessage, msg => {
if (msg.type !== '__$terminate') {
if (!isMessageOfType(msg, MessageType.Terminate)) {
return true;
}
this._terminating = true;
......@@ -85,7 +86,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
const first = protocol.onMessage(raw => {
first.dispose();
const initData = <IInitData>JSON.parse(raw);
const initData = <IInitData>JSON.parse(raw.toString());
// Print a console message when rejection isn't handled within N seconds. For details:
// see https://nodejs.org/api/process.html#process_event_unhandledrejection
......@@ -128,13 +129,13 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
}, 5000);
// Tell the outside that we are initialized
protocol.send('initialized');
protocol.send(createMessageOfType(MessageType.Initialized));
c({ protocol, initData });
});
// Tell the outside that we are ready to receive messages
protocol.send('ready');
protocol.send(createMessageOfType(MessageType.Ready));
});
}
......
......@@ -8,7 +8,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Client as TelemetryClient } from 'vs/base/parts/ipc/node/ipc.cp';
import * as strings from 'vs/base/common/strings';
import * as objects from 'vs/base/common/objects';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IConfig, IDebuggerContribution, IAdapterExecutable, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, IDebugConfiguration, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug';
......
......@@ -5,7 +5,7 @@
import { Server } from 'vs/base/parts/ipc/node/ipc.cp';
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/node/telemetryIpc';
const appender = new AppInsightsAppender(process.argv[2], JSON.parse(process.argv[3]), process.argv[4]);
process.once('exit', () => appender.dispose());
......
......@@ -19,7 +19,7 @@ import { ChildProcess, fork } from 'child_process';
import { ipcRenderer as ipc } from 'electron';
import product from 'vs/platform/node/product';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { generateRandomPipeName, Protocol } from 'vs/base/parts/ipc/node/ipc.net';
import { createServer, Server, Socket } from 'net';
import { Event, Emitter, debounceEvent, mapEvent, anyEvent, fromNodeEventEmitter } from 'vs/base/common/event';
......@@ -37,6 +37,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { timeout } from 'vs/base/common/async';
import { isMessageOfType, MessageType, createMessageOfType } from 'vs/workbench/common/extensionHostProtocol';
export interface IExtensionHostStarter {
readonly onCrashed: Event<[number, string]>;
......@@ -340,13 +341,13 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
const disposable = protocol.onMessage(msg => {
if (msg === 'ready') {
if (isMessageOfType(msg, MessageType.Ready)) {
// 1) Extension Host is ready to receive messages, initialize it
this._createExtHostInitData().then(data => protocol.send(JSON.stringify(data)));
this._createExtHostInitData().then(data => protocol.send(Buffer.from(JSON.stringify(data))));
return;
}
if (msg === 'initialized') {
if (isMessageOfType(msg, MessageType.Initialized)) {
// 2) Extension Host is initialized
clearTimeout(handle);
......@@ -470,9 +471,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
// Send the extension host a request to terminate itself
// (graceful termination)
protocol.send({
type: '__$terminate'
});
protocol.send(createMessageOfType(MessageType.Terminate));
// Give the extension host 60s, after which we will
// try to kill the process and release any resources
......
......@@ -28,7 +28,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ExtensionHostProcessWorker, IExtensionHostStarter } from 'vs/workbench/services/extensions/electron-browser/extensionHost';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { ExtHostCustomersRegistry } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
......
......@@ -6,7 +6,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import * as errors from 'vs/base/common/errors';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise';
import { ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { CharCode } from 'vs/base/common/charCode';
......@@ -159,12 +159,12 @@ export class RPCProtocol implements IRPCProtocol {
}
}
private _receiveOneMessage(rawmsg: string): void {
private _receiveOneMessage(rawmsg: Buffer): void {
if (this._isDisposed) {
return;
}
let msg = <RPCMessage>JSON.parse(rawmsg);
let msg = <RPCMessage>JSON.parse(rawmsg.toString());
if (this._uriTransformer) {
msg = transformIncomingURIs(msg, this._uriTransformer);
}
......@@ -196,10 +196,10 @@ export class RPCProtocol implements IRPCProtocol {
if (this._uriTransformer) {
r = transformOutgoingURIs(r, this._uriTransformer);
}
this._multiplexor.send(MessageFactory.replyOK(callId, r));
this._multiplexor.send(Buffer.from(MessageFactory.replyOK(callId, r)));
}, (err) => {
delete this._invokedHandlers[callId];
this._multiplexor.send(MessageFactory.replyErr(callId, err));
this._multiplexor.send(Buffer.from(MessageFactory.replyErr(callId, err)));
});
}
......@@ -268,14 +268,14 @@ export class RPCProtocol implements IRPCProtocol {
const callId = String(++this._lastMessageId);
const result = new LazyPromise(() => {
this._multiplexor.send(MessageFactory.cancel(callId));
this._multiplexor.send(Buffer.from(MessageFactory.cancel(callId)));
});
this._pendingRPCReplies[callId] = result;
if (this._uriTransformer) {
args = transformOutgoingURIs(args, this._uriTransformer);
}
this._multiplexor.send(MessageFactory.request(callId, proxyId, methodName, args));
this._multiplexor.send(Buffer.from(MessageFactory.request(callId, proxyId, methodName, args)));
return result;
}
}
......@@ -290,28 +290,41 @@ class RPCMultiplexer {
private readonly _protocol: IMessagePassingProtocol;
private readonly _sendAccumulatedBound: () => void;
private _messagesToSend: string[];
private _messagesToSend: Buffer[];
constructor(protocol: IMessagePassingProtocol, onMessage: (msg: string) => void) {
constructor(protocol: IMessagePassingProtocol, onMessage: (msg: Buffer) => void) {
this._protocol = protocol;
this._sendAccumulatedBound = this._sendAccumulated.bind(this);
this._messagesToSend = [];
this._protocol.onMessage(data => {
for (let i = 0, len = data.length; i < len; i++) {
onMessage(data[i]);
let i = 0;
while (i < data.length) {
const size = data.readUInt32BE(i);
onMessage(data.slice(i + 4, i + 4 + size));
i += 4 + size;
}
});
}
private _sendAccumulated(): void {
const tmp = this._messagesToSend;
const size = this._messagesToSend.reduce((r, b) => r + 4 + b.byteLength, 0);
const buffer = new Buffer(size);
let i = 0;
for (const msg of this._messagesToSend) {
buffer.writeUInt32BE(msg.byteLength, i);
msg.copy(buffer, i + 4);
i += 4 + msg.byteLength;
}
this._messagesToSend = [];
this._protocol.send(tmp);
this._protocol.send(buffer);
}
public send(msg: string): void {
public send(msg: Buffer): void {
if (this._messagesToSend.length === 0) {
process.nextTick(this._sendAccumulatedBound);
}
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWatcherRequest, IWatcherService, IWatcherOptions, IWatchError } from './watcher';
import { Event } from 'vs/base/common/event';
import { IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
......
......@@ -5,7 +5,7 @@
'use strict';
import { getNextTickChannel } from 'vs/base/parts/ipc/common/ipc';
import { getNextTickChannel } from 'vs/base/parts/ipc/node/ipc';
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
import { toFileChangesEvent, IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
import { IWatcherChannel, WatcherChannelClient } from 'vs/workbench/services/files/node/watcher/nsfw/watcherIpc';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IWatcherRequest, IWatcherService, IWatcherOptions, IWatchError } from './watcher';
import { Event } from 'vs/base/common/event';
import { IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
......
......@@ -5,7 +5,7 @@
'use strict';
import { getNextTickChannel } from 'vs/base/parts/ipc/common/ipc';
import { getNextTickChannel } from 'vs/base/parts/ipc/node/ipc';
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
import { toFileChangesEvent, IRawFileChange } from 'vs/workbench/services/files/node/watcher/common';
import { IWatcherChannel, WatcherChannelClient } from 'vs/workbench/services/files/node/watcher/unix/watcherIpc';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { IRawSearchService, IRawSearch, ISerializedSearchComplete, ISerializedSearchProgressItem, ITelemetryEvent } from './search';
import { Event } from 'vs/base/common/event';
......
......@@ -14,7 +14,7 @@ import * as strings from 'vs/base/common/strings';
import uri from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import * as pfs from 'vs/base/node/pfs';
import { getNextTickChannel } from 'vs/base/parts/ipc/common/ipc';
import { getNextTickChannel } from 'vs/base/parts/ipc/node/ipc';
import { Client, IIPCOptions } from 'vs/base/parts/ipc/node/ipc.cp';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
......
......@@ -7,7 +7,7 @@
import * as os from 'os';
import * as ipc from 'vs/base/parts/ipc/common/ipc';
import * as ipc from 'vs/base/parts/ipc/node/ipc';
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
import { ISearchWorker, ISearchWorkerChannel, SearchWorkerChannelClient } from './worker/searchWorkerIpc';
......
......@@ -6,7 +6,7 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel } from 'vs/base/parts/ipc/node/ipc';
import { ISerializedFileMatch } from '../search';
import { IPatternInfo } from 'vs/platform/search/common/search';
import { SearchWorker } from './searchWorker';
......
......@@ -7,7 +7,7 @@ const fs = require('fs');
const path = require('path');
const root = path.dirname(path.dirname(path.dirname(__dirname)));
const driverPath = path.join(root, 'src/vs/platform/driver/common/driver.ts');
const driverPath = path.join(root, 'src/vs/platform/driver/node/driver.ts');
let contents = fs.readFileSync(driverPath, 'utf8');
contents = /\/\/\*START([\s\S]*)\/\/\*END/mi.exec(contents)[1].trim();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册