vscode-jsonrpc
Advanced tools
Comparing version 3.3.0-alpha.1 to 3.3.0-alpha.2
/// <reference path="thenable.d.ts" /> | ||
/// <reference types="node" /> | ||
import { Message, MessageType, RequestMessage, RequestType, RequestType0, RequestType1, RequestType2, RequestType3, RequestType4, RequestType5, RequestType6, RequestType7, RequestType8, RequestType9, ResponseError, ErrorCodes, NotificationMessage, NotificationType, NotificationType0, NotificationType1, NotificationType2, NotificationType3, NotificationType4, NotificationType5, NotificationType6, NotificationType7, NotificationType8, NotificationType9 } from './messages'; | ||
import { Message, MessageType, RequestMessage, RequestType, RequestType0, RequestType1, RequestType2, RequestType3, RequestType4, RequestType5, RequestType6, RequestType7, RequestType8, RequestType9, ResponseMessage, ResponseError, ErrorCodes, NotificationMessage, NotificationType, NotificationType0, NotificationType1, NotificationType2, NotificationType3, NotificationType4, NotificationType5, NotificationType6, NotificationType7, NotificationType8, NotificationType9 } from './messages'; | ||
import { MessageReader, DataCallback, StreamMessageReader, IPCMessageReader, SocketMessageReader } from './messageReader'; | ||
@@ -8,40 +8,48 @@ import { MessageWriter, StreamMessageWriter, IPCMessageWriter, SocketMessageWriter } from './messageWriter'; | ||
import { CancellationTokenSource, CancellationToken } from './cancellation'; | ||
import { LinkedMap } from './linkedMap'; | ||
export { Message, MessageType, ErrorCodes, ResponseError, RequestMessage, RequestType, RequestType0, RequestType1, RequestType2, RequestType3, RequestType4, RequestType5, RequestType6, RequestType7, RequestType8, RequestType9, NotificationMessage, NotificationType, NotificationType0, NotificationType1, NotificationType2, NotificationType3, NotificationType4, NotificationType5, NotificationType6, NotificationType7, NotificationType8, NotificationType9, MessageReader, DataCallback, StreamMessageReader, IPCMessageReader, SocketMessageReader, MessageWriter, StreamMessageWriter, IPCMessageWriter, SocketMessageWriter, CancellationTokenSource, CancellationToken, Disposable, Event, Emitter }; | ||
export * from './pipeSupport'; | ||
export declare type HandlerResult<R, E> = R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
export interface StarRequestHandler { | ||
(method: string, ...params: any[]): HandlerResult<any, any>; | ||
} | ||
export interface GenericRequestHandler<R, E> { | ||
(...params: any[]): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(...params: any[]): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler0<R, E> { | ||
(token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler<P, R, E> { | ||
(params: P, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(params: P, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler1<P1, R, E> { | ||
(p1: P1, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler2<P1, P2, R, E> { | ||
(p1: P1, p2: P2, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler3<P1, P2, P3, R, E> { | ||
(p1: P1, p2: P2, p3: P3, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler4<P1, P2, P3, P4, R, E> { | ||
(p1: P1, p2: P2, p3: P3, p4: P4, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler5<P1, P2, P3, P4, P5, R, E> { | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler6<P1, P2, P3, P4, P5, P6, R, E> { | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler7<P1, P2, P3, P4, P5, P6, P7, R, E> { | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler8<P1, P2, P3, P4, P5, P6, P7, P8, R, E> { | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface RequestHandler9<P1, P2, P3, P4, P5, P6, P7, P8, P9, R, E> { | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, token: CancellationToken): R | ResponseError<E> | Thenable<R> | Thenable<ResponseError<E>>; | ||
(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, token: CancellationToken): HandlerResult<R, E>; | ||
} | ||
export interface StarNotificationHandler { | ||
(method: string, ...params: any[]): void; | ||
} | ||
export interface GenericNotificationHandler { | ||
@@ -133,2 +141,9 @@ (...params: any[]): void; | ||
} | ||
export declare type MessageQueue = LinkedMap<string, Message>; | ||
export declare type ConnectionStrategy = { | ||
cancelUndispatched?: (message: Message, next: (message: Message) => ResponseMessage | undefined) => ResponseMessage | undefined; | ||
}; | ||
export declare namespace ConnectionStrategy { | ||
function is(value: any): value is ConnectionStrategy; | ||
} | ||
export interface MessageConnection { | ||
@@ -159,2 +174,3 @@ sendRequest<R, E, RO>(type: RequestType0<R, E, RO>, token?: CancellationToken): Thenable<R>; | ||
onRequest<R, E>(method: string, handler: GenericRequestHandler<R, E>): void; | ||
onRequest(handler: StarRequestHandler): void; | ||
sendNotification<RO>(type: NotificationType0<RO>): void; | ||
@@ -184,2 +200,3 @@ sendNotification<P, RO>(type: NotificationType<P, RO>, params?: P): void; | ||
onNotification(method: string, handler: GenericNotificationHandler): void; | ||
onNotification(handler: StarNotificationHandler): void; | ||
trace(value: Trace, tracer: Tracer, sendNotification?: boolean): void; | ||
@@ -192,4 +209,5 @@ onError: Event<[Error, Message, number]>; | ||
dispose(): void; | ||
inspect(): void; | ||
} | ||
export declare function createMessageConnection(reader: MessageReader, writer: MessageWriter, logger: Logger): MessageConnection; | ||
export declare function createMessageConnection(inputStream: NodeJS.ReadableStream, outputStream: NodeJS.WritableStream, logger: Logger): MessageConnection; | ||
export declare function createMessageConnection(reader: MessageReader, writer: MessageWriter, logger: Logger, strategy?: ConnectionStrategy): MessageConnection; | ||
export declare function createMessageConnection(inputStream: NodeJS.ReadableStream, outputStream: NodeJS.WritableStream, logger: Logger, strategy?: ConnectionStrategy): MessageConnection; |
203
lib/main.js
@@ -21,3 +21,3 @@ /* -------------------------------------------------------------------------------------------- | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var is = require("./is"); | ||
var Is = require("./is"); | ||
var messages_1 = require("./messages"); | ||
@@ -63,2 +63,3 @@ exports.RequestType = messages_1.RequestType; | ||
exports.CancellationToken = cancellation_1.CancellationToken; | ||
var linkedMap_1 = require("./linkedMap"); | ||
__export(require("./pipeSupport")); | ||
@@ -138,2 +139,10 @@ var CancelNotification; | ||
exports.ConnectionError = ConnectionError; | ||
var ConnectionStrategy; | ||
(function (ConnectionStrategy) { | ||
function is(value) { | ||
var candidate = value; | ||
return candidate && Is.func(candidate.cancelUndispatched); | ||
} | ||
ConnectionStrategy.is = is; | ||
})(ConnectionStrategy = exports.ConnectionStrategy || (exports.ConnectionStrategy = {})); | ||
var ConnectionState; | ||
@@ -146,7 +155,12 @@ (function (ConnectionState) { | ||
})(ConnectionState || (ConnectionState = {})); | ||
function _createMessageConnection(messageReader, messageWriter, logger) { | ||
function _createMessageConnection(messageReader, messageWriter, logger, strategy) { | ||
var sequenceNumber = 0; | ||
var notificationSquenceNumber = 0; | ||
var version = '2.0'; | ||
var starRequestHandler = undefined; | ||
var requestHandlers = Object.create(null); | ||
var starNotificationHandler = undefined; | ||
var notificationHandlers = Object.create(null); | ||
var timer; | ||
var messageQueue = new linkedMap_1.LinkedMap(); | ||
var responsePromises = Object.create(null); | ||
@@ -161,2 +175,17 @@ var requestTokens = Object.create(null); | ||
var disposeEmitter = new events_1.Emitter(); | ||
function addMessageToQueue(queue, message) { | ||
if (messages_1.isRequestMessage(message)) { | ||
queue.set(message.id.toString(), message); | ||
} | ||
else if (messages_1.isReponseMessage(message) && message.id != null) { | ||
queue.set(message.id.toString(), message); | ||
} | ||
else { | ||
var id = 'n' + (++notificationSquenceNumber).toString(); | ||
queue.set(id, message); | ||
} | ||
} | ||
function cancelUndispatched(_message) { | ||
return undefined; | ||
} | ||
function isListening() { | ||
@@ -189,2 +218,58 @@ return state === ConnectionState.Listening; | ||
messageWriter.onError(writeErrorHandler); | ||
function triggerMessageQueue() { | ||
if (timer || messageQueue.size === 0) { | ||
return; | ||
} | ||
timer = setImmediate(function () { | ||
timer = undefined; | ||
processMessageQueue(); | ||
}); | ||
} | ||
function processMessageQueue() { | ||
if (messageQueue.size === 0) { | ||
return; | ||
} | ||
var message = messageQueue.shift(); | ||
try { | ||
if (messages_1.isRequestMessage(message)) { | ||
handleRequest(message); | ||
} | ||
else if (messages_1.isNotificationMessage(message)) { | ||
handleNotification(message); | ||
} | ||
else if (messages_1.isReponseMessage(message)) { | ||
handleResponse(message); | ||
} | ||
else { | ||
handleInvalidMessage(message); | ||
} | ||
} | ||
finally { | ||
triggerMessageQueue(); | ||
} | ||
} | ||
var callback = function (message) { | ||
try { | ||
// We have recevied a cancellation message. Check if the message is still in the queue | ||
// and cancel it if allowed to do so. | ||
if (messages_1.isNotificationMessage(message) && message.method === CancelNotification.type.method) { | ||
var key = message.params.id.toString(); | ||
var toCancel = messageQueue.get(key); | ||
if (messages_1.isRequestMessage(toCancel)) { | ||
var response = strategy && strategy.cancelUndispatched ? strategy.cancelUndispatched(toCancel, cancelUndispatched) : cancelUndispatched(toCancel); | ||
if (response && (response.error !== void 0 || response.result !== void 0)) { | ||
messageQueue.delete(key); | ||
response.id = toCancel.id; | ||
traceSendingResponse(response, message.method, Date.now()); | ||
messageWriter.write(response); | ||
return; | ||
} | ||
} | ||
} | ||
addMessageToQueue(messageQueue, message); | ||
} | ||
finally { | ||
triggerMessageQueue(); | ||
} | ||
}; | ||
function handleRequest(requestMessage) { | ||
@@ -233,6 +318,12 @@ if (isDisposed()) { | ||
} | ||
traceReceviedRequest(requestMessage); | ||
var requestHandler = requestHandlers[requestMessage.method]; | ||
traceReceivedRequest(requestMessage); | ||
var element = requestHandlers[requestMessage.method]; | ||
var type; | ||
var requestHandler; | ||
if (element) { | ||
type = element.type; | ||
requestHandler = element.handler; | ||
} | ||
var startTime = Date.now(); | ||
if (requestHandler) { | ||
if (requestHandler || starRequestHandler) { | ||
var cancellationSource = new cancellation_1.CancellationTokenSource(); | ||
@@ -243,10 +334,15 @@ var tokenKey_1 = String(requestMessage.id); | ||
var handlerResult = void 0; | ||
if (!requestMessage.params) { | ||
handlerResult = requestHandler(cancellationSource.token); | ||
if (requestMessage.params === void 0 || (type !== void 0 && type.numberOfParams === 0)) { | ||
handlerResult = requestHandler | ||
? requestHandler(cancellationSource.token) | ||
: starRequestHandler(requestMessage.method, cancellationSource.token); | ||
} | ||
else if (is.array(requestMessage.params)) { | ||
handlerResult = requestHandler.apply(void 0, requestMessage.params.concat([cancellationSource.token])); | ||
else if (Is.array(requestMessage.params) && (type === void 0 || type.numberOfParams > 1)) { | ||
handlerResult = requestHandler | ||
? requestHandler.apply(void 0, requestMessage.params.concat([cancellationSource.token])) : starRequestHandler.apply(void 0, [requestMessage.method].concat(requestMessage.params, [cancellationSource.token])); | ||
} | ||
else { | ||
handlerResult = requestHandler(requestMessage.params, cancellationSource.token); | ||
handlerResult = requestHandler | ||
? requestHandler(requestMessage.params, cancellationSource.token) | ||
: starRequestHandler(requestMessage.method, requestMessage.params, cancellationSource.token); | ||
} | ||
@@ -267,3 +363,3 @@ var promise = handlerResult; | ||
} | ||
else if (error && is.string(error.message)) { | ||
else if (error && Is.string(error.message)) { | ||
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, "Request " + requestMessage.method + " failed with message: " + error.message), requestMessage.method, startTime); | ||
@@ -286,3 +382,3 @@ } | ||
} | ||
else if (error && is.string(error.message)) { | ||
else if (error && Is.string(error.message)) { | ||
replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, "Request " + requestMessage.method + " failed with message: " + error.message), requestMessage.method, startTime); | ||
@@ -315,3 +411,3 @@ } | ||
var responsePromise = responsePromises[key]; | ||
traceReceviedResponse(responseMessage, responsePromise); | ||
traceReceivedResponse(responseMessage, responsePromise); | ||
if (responsePromise) { | ||
@@ -347,2 +443,3 @@ delete responsePromises[key]; | ||
} | ||
var type = undefined; | ||
var notificationHandler; | ||
@@ -359,15 +456,19 @@ if (message.method === CancelNotification.type.method) { | ||
else { | ||
notificationHandler = notificationHandlers[message.method]; | ||
var element = notificationHandlers[message.method]; | ||
if (element) { | ||
notificationHandler = element.handler; | ||
type = element.type; | ||
} | ||
} | ||
if (notificationHandler) { | ||
if (notificationHandler || starNotificationHandler) { | ||
try { | ||
traceReceivedNotification(message); | ||
if (!message.params) { | ||
notificationHandler(); | ||
if (message.params === void 0 || (type !== void 0 && type.numberOfParams === 0)) { | ||
notificationHandler ? notificationHandler() : starNotificationHandler(message.method); | ||
} | ||
else if (is.array(message.params)) { | ||
notificationHandler.apply(void 0, message.params); | ||
else if (Is.array(message.params) && (type === void 0 || type.numberOfParams > 1)) { | ||
notificationHandler ? notificationHandler.apply(void 0, message.params) : starNotificationHandler.apply(void 0, [message.method].concat(message.params)); | ||
} | ||
else { | ||
notificationHandler(message.params); | ||
notificationHandler ? notificationHandler(message.params) : starNotificationHandler(message.method, message.params); | ||
} | ||
@@ -396,3 +497,3 @@ } | ||
var responseMessage = message; | ||
if (is.string(responseMessage.id) || is.number(responseMessage.id)) { | ||
if (Is.string(responseMessage.id) || Is.number(responseMessage.id)) { | ||
var key = String(responseMessage.id); | ||
@@ -450,3 +551,3 @@ var responseHandler = responsePromises[key]; | ||
} | ||
function traceReceviedRequest(message) { | ||
function traceReceivedRequest(message) { | ||
if (trace === Trace.Off || !tracer) { | ||
@@ -476,3 +577,3 @@ return; | ||
} | ||
function traceReceviedResponse(message, responsePromise) { | ||
function traceReceivedResponse(message, responsePromise) { | ||
if (trace === Trace.Off || !tracer) { | ||
@@ -503,16 +604,2 @@ return; | ||
} | ||
var callback = function (message) { | ||
if (messages_1.isRequestMessage(message)) { | ||
handleRequest(message); | ||
} | ||
else if (messages_1.isReponseMessage(message)) { | ||
handleResponse(message); | ||
} | ||
else if (messages_1.isNotificationMessage(message)) { | ||
handleNotification(message); | ||
} | ||
else { | ||
handleInvalidMessage(message); | ||
} | ||
}; | ||
function throwIfClosedOrDisposed() { | ||
@@ -569,3 +656,3 @@ if (isClosed()) { | ||
var messageParams; | ||
if (is.string(type)) { | ||
if (Is.string(type)) { | ||
method = type; | ||
@@ -590,3 +677,3 @@ switch (params.length) { | ||
jsonrpc: version, | ||
method: is.string(type) ? type : type.method, | ||
method: Is.string(type) ? type : type.method, | ||
params: messageParams | ||
@@ -599,3 +686,13 @@ }; | ||
throwIfClosedOrDisposed(); | ||
notificationHandlers[is.string(type) ? type : type.method] = handler; | ||
if (Is.func(type)) { | ||
starNotificationHandler = type; | ||
} | ||
else if (handler) { | ||
if (Is.string(type)) { | ||
notificationHandlers[type] = { type: undefined, handler: handler }; | ||
} | ||
else { | ||
notificationHandlers[type.method] = { type: type, handler: handler }; | ||
} | ||
} | ||
}, | ||
@@ -612,3 +709,3 @@ sendRequest: function (type) { | ||
var token = undefined; | ||
if (is.string(type)) { | ||
if (Is.string(type)) { | ||
method = type; | ||
@@ -683,3 +780,13 @@ switch (params.length) { | ||
throwIfClosedOrDisposed(); | ||
requestHandlers[is.string(type) ? type : type.method] = handler; | ||
if (Is.func(type)) { | ||
starRequestHandler = type; | ||
} | ||
else if (handler) { | ||
if (Is.string(type)) { | ||
requestHandlers[type] = { type: undefined, handler: handler }; | ||
} | ||
else { | ||
requestHandlers[type.method] = { type: type, handler: handler }; | ||
} | ||
} | ||
}, | ||
@@ -715,7 +822,8 @@ trace: function (_value, _tracer, sendNotification) { | ||
requestTokens = Object.create(null); | ||
messageQueue = new linkedMap_1.LinkedMap(); | ||
// Test for backwards compatibility | ||
if (is.func(messageWriter.dispose)) { | ||
if (Is.func(messageWriter.dispose)) { | ||
messageWriter.dispose(); | ||
} | ||
if (is.func(messageReader.dispose)) { | ||
if (Is.func(messageReader.dispose)) { | ||
messageReader.dispose(); | ||
@@ -729,2 +837,5 @@ } | ||
messageReader.listen(callback); | ||
}, | ||
inspect: function () { | ||
console.log("inspect"); | ||
} | ||
@@ -746,7 +857,7 @@ }; | ||
} | ||
function createMessageConnection(input, output, logger) { | ||
function createMessageConnection(input, output, logger, strategy) { | ||
var reader = isMessageReader(input) ? input : new messageReader_1.StreamMessageReader(input); | ||
var writer = isMessageWriter(output) ? output : new messageWriter_1.StreamMessageWriter(output); | ||
return _createMessageConnection(reader, writer, logger); | ||
return _createMessageConnection(reader, writer, logger, strategy); | ||
} | ||
exports.createMessageConnection = createMessageConnection; |
@@ -214,10 +214,10 @@ /** | ||
*/ | ||
export declare function isRequestMessage(message: Message): message is RequestMessage; | ||
export declare function isRequestMessage(message: Message | undefined): message is RequestMessage; | ||
/** | ||
* Tests if the given message is a notification message | ||
*/ | ||
export declare function isNotificationMessage(message: Message): message is NotificationMessage; | ||
export declare function isNotificationMessage(message: Message | undefined): message is NotificationMessage; | ||
/** | ||
* Tests if the given message is a response message | ||
*/ | ||
export declare function isReponseMessage(message: Message): message is ResponseMessage; | ||
export declare function isReponseMessage(message: Message | undefined): message is ResponseMessage; |
{ | ||
"name": "vscode-jsonrpc", | ||
"description": "A json rpc implementation over streams", | ||
"version": "3.3.0-alpha.1", | ||
"version": "3.3.0-alpha.2", | ||
"author": "Microsoft Corporation", | ||
@@ -20,6 +20,6 @@ "license": "MIT", | ||
"devDependencies": { | ||
"mocha": "^3.2.0", | ||
"typescript": "^2.3.0", | ||
"@types/node": "^6.0.68", | ||
"@types/mocha": "^2.2.40" | ||
"mocha": "^3.3.0", | ||
"typescript": "^2.3.2", | ||
"@types/node": "^6.0.73", | ||
"@types/mocha": "^2.2.41" | ||
}, | ||
@@ -26,0 +26,0 @@ "scripts": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
122469
25
2907