@@ -23,28 +23,30 @@ import { Emitter, Event } from '../event';
23
23
import { Channel } from '../message-rpc/channel' ;
24
24
import { RequestHandler , RpcProtocol } from '../message-rpc/rpc-protocol' ;
25
25
import { ConnectionHandler } from './handler' ;
26
+ import { Deferred } from '../promise-util' ;
26
27
27
- export type JsonRpcServer < Client > = Disposable & {
28
+ export type RpcServer < Client > = Disposable & {
28
29
/**
29
30
* If this server is a proxy to a remote server then
30
31
* a client is used as a local object
31
- * to handle JSON- RPC messages from the remote server.
32
+ * to handle RPC messages from the remote server.
32
33
*/
33
34
setClient ( client : Client | undefined ) : void ;
34
35
getClient ?( ) : Client | undefined ;
35
36
} ;
36
37
37
- export interface JsonRpcConnectionEventEmitter {
38
+ export interface RpcConnectionEventEmitter {
38
39
readonly onDidOpenConnection : Event < void > ;
39
40
readonly onDidCloseConnection : Event < void > ;
40
41
}
41
- export type JsonRpcProxy < T > = T & JsonRpcConnectionEventEmitter ;
42
42
43
- export class JsonRpcConnectionHandler < T extends object > implements ConnectionHandler {
43
+ export type RpcProxy < T > = T & RpcConnectionEventEmitter ;
44
+
45
+ export class RpcConnectionHandler < T extends object > implements ConnectionHandler {
44
46
constructor (
45
47
readonly path : string ,
46
- readonly targetFactory : ( proxy : JsonRpcProxy < T > ) => any ,
47
- readonly factoryConstructor : new ( ) => JsonRpcProxyFactory < T > = JsonRpcProxyFactory
48
+ readonly targetFactory : ( proxy : RpcProxy < T > ) => any ,
49
+ readonly factoryConstructor : new ( ) => RpcProxyFactory < T > = RpcProxyFactory
48
50
) { }
49
51
50
52
onConnection ( connection : Channel ) : void {
@@ -54,20 +56,30 @@ export class JsonRpcConnectionHandler<T extends object> implements ConnectionHan
54
56
factory . listen ( connection ) ;
55
57
}
56
58
}
59
+
57
60
/**
58
- * Factory for creating a new {@link RpcConnection } for a given chanel and {@link RequestHandler}.
61
+ * Factory for creating a new {@link RpcProtocol } for a given chanel and {@link RequestHandler}.
59
62
*/
60
- export type RpcConnectionFactory = ( channel : Channel , requestHandler : RequestHandler ) => RpcProtocol ;
63
+ export type RpcProtocolFactory = ( channel : Channel , requestHandler : RequestHandler ) => RpcProtocol ;
61
64
62
- const defaultRPCConnectionFactory : RpcConnectionFactory = ( channel , requestHandler ) => new RpcProtocol ( channel , requestHandler ) ;
65
+ const defaultRpcProtocolFactory : RpcProtocolFactory = ( channel , requestHandler ) => new RpcProtocol ( channel , requestHandler ) ;
66
+
67
+ export interface RpcProxyFactoryOptions {
68
+ rpcProtocolFactory ?: RpcProtocolFactory ,
69
+ /**
70
+ * Used to identify proxy calls that should be sent as notification. If method starts with one of the given
71
+ * keys it is treated as a notification
72
+ */
73
+ notificationKeys ?: string [ ]
74
+ }
63
75
64
76
/**
65
- * Factory for JSON- RPC proxy objects.
77
+ * Factory for RPC proxy objects.
66
78
*
67
- * A JSON- RPC proxy exposes the programmatic interface of an object through
68
- * JSON- RPC. This allows remote programs to call methods of this objects by
69
- * sending JSON- RPC requests. This takes place over a bi-directional stream,
70
- * where both ends can expose an object and both can call methods each other's
79
+ * A RPC proxy exposes the programmatic interface of an object through
80
+ * Theia's RPC protocol. This allows remote programs to call methods of this objects by
81
+ * sending RPC requests. This takes place over a bi-directional stream,
82
+ * where both ends can expose an object and both can call methods on each other's
71
83
* exposed object.
72
84
*
73
85
* For example, assuming we have an object of the following type on one end:
@@ -76,87 +88,87 @@ const defaultRPCConnectionFactory: RpcConnectionFactory = (channel, requestHandl
76
88
* bar(baz: number): number { return baz + 1 }
77
89
* }
78
90
*
79
- * which we want to expose through a JSON-RPC interface. We would do:
91
+ * which we want to expose through a JSON interface. We would do:
80
92
*
81
93
* let target = new Foo()
82
- * let factory = new JsonRpcProxyFactory <Foo>('/foo', target)
94
+ * let factory = new RpcProxyFactory <Foo>('/foo', target)
83
95
* factory.onConnection(connection)
84
96
*
85
97
* The party at the other end of the `connection`, in order to remotely call
86
98
* methods on this object would do:
87
99
*
88
- * let factory = new JsonRpcProxyFactory <Foo>('/foo')
100
+ * let factory = new RpcProxyFactory <Foo>('/foo')
89
101
* factory.onConnection(connection)
90
102
* let proxy = factory.createProxy();
91
103
* let result = proxy.bar(42)
92
104
* // result is equal to 43
93
105
*
94
106
* One the wire, it would look like this:
95
- *
96
- * --> {"jsonrpc": "2.0", "id": 0, "method": "bar", "params": {"baz": 42}}
97
- * <-- {"jsonrpc": "2.0", "id": 0, "result": 43}
107
+ * --> { "type":"1", "id": 1, "method": "bar", "args": [42]}
108
+ * <-- { "type":"3", "id": 1, "res": 43}
98
109
*
99
110
* Note that in the code of the caller, we didn't pass a target object to
100
- * JsonRpcProxyFactory , because we don't want/need to expose an object.
111
+ * RpcProxyFactory , because we don't want/need to expose an object.
101
112
* If we had passed a target object, the other side could've called methods on
102
113
* it.
103
114
*
104
- * @param <T> - The type of the object to expose to JSON- RPC.
115
+ * @param <T> - The type of the object to expose to RPC.
105
116
*/
106
117
107
- export class JsonRpcProxyFactory < T extends object > implements ProxyHandler < T > {
118
+ export class RpcProxyFactory < T extends object > implements ProxyHandler < T > {
108
119
109
120
protected readonly onDidOpenConnectionEmitter = new Emitter < void > ( ) ;
110
121
protected readonly onDidCloseConnectionEmitter = new Emitter < void > ( ) ;
111
122
112
- protected connectionPromiseResolve : ( connection : RpcProtocol ) => void ;
113
- protected connectionPromise : Promise < RpcProtocol > ;
123
+ protected rpcDeferred = new Deferred < RpcProtocol > ( ) ;
114
124
115
125
/**
116
- * Build a new JsonRpcProxyFactory .
126
+ * Build a new RpcProxyFactory .
117
127
*
118
- * @param target - The object to expose to JSON- RPC methods calls. If this
128
+ * @param target - The object to expose to RPC methods calls. If this
119
129
* is omitted, the proxy won't be able to handle requests, only send them.
120
130
*/
121
- constructor ( public target ?: any , protected rpcConnectionFactory = defaultRPCConnectionFactory ) {
131
+ constructor ( public target ?: any , protected rpcProtocolFactory = defaultRpcProtocolFactory ) {
122
132
this . waitForConnection ( ) ;
123
133
}
124
134
125
135
protected waitForConnection ( ) : void {
126
- this . connectionPromise = new Promise ( resolve =>
127
- this . connectionPromiseResolve = resolve
128
- ) ;
129
- this . connectionPromise . then ( connection => {
130
- connection . channel . onClose ( ( ) => {
136
+ this . rpcDeferred . promise . then ( protocol => {
137
+ protocol . channel . onClose ( ( ) => {
131
138
this . onDidCloseConnectionEmitter . fire ( undefined ) ;
132
139
// Wait for connection in case the backend reconnects
133
140
this . waitForConnection ( ) ;
134
141
} ) ;
142
+ protocol . channel . onError ( err => {
143
+ if ( this . rpcDeferred . state !== 'resolved' ) {
144
+ this . rpcDeferred . reject ( err ) ;
145
+ }
146
+ } ) ;
135
147
this . onDidOpenConnectionEmitter . fire ( undefined ) ;
136
148
} ) ;
137
149
}
138
150
139
151
/**
140
- * Connect a MessageConnection to the factory.
152
+ * Connect a { @link Channel} to the factory by creating an { @link RpcProtocol} on top of it .
141
153
*
142
- * This connection will be used to send/receive JSON- RPC requests and
154
+ * This protocol will be used to send/receive RPC requests and
143
155
* response.
144
156
*/
145
157
listen ( channel : Channel ) : void {
146
- const connection = this . rpcConnectionFactory ( channel , ( meth , args ) => this . onRequest ( meth , ...args ) ) ;
147
- connection . onNotification ( event => this . onNotification ( event . method , ...event . args ) ) ;
158
+ const protocol = this . rpcProtocolFactory ( channel , ( meth , args ) => this . onRequest ( meth , ...args ) ) ;
159
+ protocol . onNotification ( event => this . onNotification ( event . method , ...event . args ) ) ;
148
160
149
- this . connectionPromiseResolve ( connection ) ;
161
+ this . rpcDeferred . resolve ( protocol ) ;
150
162
}
151
163
152
164
/**
153
- * Process an incoming JSON- RPC method call.
165
+ * Process an incoming RPC method call.
154
166
*
155
- * onRequest is called when the JSON- RPC connection received a method call
156
- * request. It calls the corresponding method on [[target]].
167
+ * onRequest is called when the RPC connection received a method call
168
+ * request. It calls the corresponding method on [[target]].
157
169
*
158
170
* The return value is a Promise object that is resolved with the return
159
- * value of the method call, if it is successful. The promise is rejected
171
+ * value of the method call, if it is successful. The promise is rejected
160
172
* if the called method does not exist or if it throws.
161
173
*
162
174
* @returns A promise of the method call completion.
@@ -181,7 +193,7 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
181
193
}
182
194
183
195
/**
184
- * Process an incoming JSON- RPC notification.
196
+ * Process an incoming RPC notification.
185
197
*
186
198
* Same as [[onRequest]], but called on incoming notifications rather than
187
199
* methods calls.
@@ -194,37 +206,37 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
194
206
195
207
/**
196
208
* Create a Proxy exposing the interface of an object of type T. This Proxy
197
- * can be used to do JSON- RPC method calls on the remote target object as
209
+ * can be used to do RPC method calls on the remote target object as
198
210
* if it was local.
199
211
*
200
- * If `T` implements `JsonRpcServer ` then a client is used as a target object for a remote target object.
212
+ * If `T` implements `RpcServer ` then a client is used as a target object for a remote target object.
201
213
*/
202
- createProxy ( ) : JsonRpcProxy < T > {
214
+ createProxy ( ) : RpcProxy < T > {
203
215
const result = new Proxy < T > ( this as any , this ) ;
204
216
return result as any ;
205
217
}
206
218
207
219
/**
208
- * Get a callable object that executes a JSON- RPC method call.
220
+ * Get a callable object that executes a RPC method call.
209
221
*
210
222
* Getting a property on the Proxy object returns a callable that, when
211
- * called, executes a JSON- RPC call. The name of the property defines the
223
+ * called, executes a RPC call. The name of the property defines the
212
224
* method to be called. The callable takes a variable number of arguments,
213
- * which are passed in the JSON- RPC method call.
225
+ * which are passed in the RPC method call.
214
226
*
215
227
* For example, if you have a Proxy object:
216
228
*
217
- * let fooProxyFactory = JsonRpcProxyFactory <Foo>('/foo')
229
+ * let fooProxyFactory = RpcProxyFactory <Foo>('/foo')
218
230
* let fooProxy = fooProxyFactory.createProxy()
219
231
*
220
232
* accessing `fooProxy.bar` will return a callable that, when called,
221
- * executes a JSON- RPC method call to method `bar`. Therefore, doing
233
+ * executes a RPC method call to method `bar`. Therefore, doing
222
234
* `fooProxy.bar()` will call the `bar` method on the remote Foo object.
223
235
*
224
236
* @param target - unused.
225
237
* @param p - The property accessed on the Proxy object.
226
238
* @param receiver - unused.
227
- * @returns A callable that executes the JSON- RPC call.
239
+ * @returns A callable that executes the RPC call.
228
240
*/
229
241
get ( target : T , p : PropertyKey , receiver : any ) : any {
230
242
if ( p === 'setClient' ) {
@@ -249,7 +261,7 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
249
261
return ( ...args : any [ ] ) => {
250
262
const method = p . toString ( ) ;
251
263
const capturedError = new Error ( `Request '${ method } ' failed` ) ;
252
- return this . connectionPromise . then ( connection =>
264
+ return this . rpcDeferred . promise . then ( connection =>
253
265
new Promise < void > ( ( resolve , reject ) => {
254
266
try {
255
267
if ( isNotify ) {
@@ -308,3 +320,32 @@ export class JsonRpcProxyFactory<T extends object> implements ProxyHandler<T> {
308
320
309
321
}
310
322
323
+ /**
324
+ * @deprecated since 1.39.0 use `RpcConnectionEventEmitter` instead
325
+ */
326
+ export type JsonRpcConnectionEventEmitter = RpcConnectionEventEmitter ;
327
+
328
+ /**
329
+ * @deprecated since 1.39.0 use `RpcServer` instead
330
+ */
331
+ export type JsonRpcServer < Client > = RpcServer < Client > ;
332
+
333
+ /**
334
+ * @deprecated since 1.39.0 use `RpcProxy` instead
335
+ */
336
+ export type JsonRpcProxy < T > = RpcProxy < T > ;
337
+
338
+ /**
339
+ * @deprecated since 1.39.0 use `RpcConnectionHandler` instead
340
+ */
341
+ export class JsonRpcConnectionHandler < T extends object > extends RpcConnectionHandler < T > {
342
+
343
+ }
344
+
345
+ /**
346
+ * @deprecated since 1.39.0 use `JsonRpcProxyFactory` instead
347
+ */
348
+ export class JsonRpcProxyFactory < T extends object > extends RpcProxyFactory < T > {
349
+
350
+ }
351
+
0 commit comments