@theia/core 1.26.0 → 1.27.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +6 -7
  2. package/lib/browser/messaging/ws-connection-provider.d.ts +5 -4
  3. package/lib/browser/messaging/ws-connection-provider.d.ts.map +1 -1
  4. package/lib/browser/messaging/ws-connection-provider.js +30 -23
  5. package/lib/browser/messaging/ws-connection-provider.js.map +1 -1
  6. package/lib/browser/progress-status-bar-item.d.ts +1 -1
  7. package/lib/browser/progress-status-bar-item.d.ts.map +1 -1
  8. package/lib/browser/tree/tree-compression/compressed-tree-widget.js +2 -2
  9. package/lib/browser/tree/tree-compression/compressed-tree-widget.js.map +1 -1
  10. package/lib/browser/widgets/select-component.d.ts +4 -1
  11. package/lib/browser/widgets/select-component.d.ts.map +1 -1
  12. package/lib/browser/widgets/select-component.js +30 -16
  13. package/lib/browser/widgets/select-component.js.map +1 -1
  14. package/lib/common/cancellation.d.ts +1 -0
  15. package/lib/common/cancellation.d.ts.map +1 -1
  16. package/lib/common/cancellation.js +8 -0
  17. package/lib/common/cancellation.js.map +1 -1
  18. package/lib/common/index.d.ts +2 -0
  19. package/lib/common/index.d.ts.map +1 -1
  20. package/lib/common/index.js +2 -0
  21. package/lib/common/index.js.map +1 -1
  22. package/lib/common/message-rpc/channel.d.ts +106 -0
  23. package/lib/common/message-rpc/channel.d.ts.map +1 -0
  24. package/lib/common/message-rpc/channel.js +195 -0
  25. package/lib/common/message-rpc/channel.js.map +1 -0
  26. package/lib/common/message-rpc/channel.spec.d.ts +9 -0
  27. package/lib/common/message-rpc/channel.spec.d.ts.map +1 -0
  28. package/lib/common/message-rpc/channel.spec.js +80 -0
  29. package/lib/common/message-rpc/channel.spec.js.map +1 -0
  30. package/lib/common/message-rpc/index.d.ts +4 -0
  31. package/lib/common/message-rpc/index.d.ts.map +1 -0
  32. package/lib/{node/messaging/logger.js → common/message-rpc/index.js} +6 -19
  33. package/lib/common/message-rpc/index.js.map +1 -0
  34. package/lib/common/message-rpc/message-buffer.d.ts +50 -0
  35. package/lib/common/message-rpc/message-buffer.d.ts.map +1 -0
  36. package/lib/common/message-rpc/message-buffer.js +56 -0
  37. package/lib/common/message-rpc/message-buffer.js.map +1 -0
  38. package/lib/common/message-rpc/rpc-message-encoder.d.ts +159 -0
  39. package/lib/common/message-rpc/rpc-message-encoder.d.ts.map +1 -0
  40. package/lib/common/message-rpc/rpc-message-encoder.js +362 -0
  41. package/lib/common/message-rpc/rpc-message-encoder.js.map +1 -0
  42. package/lib/common/message-rpc/rpc-message-encoder.spec.d.ts +2 -0
  43. package/lib/common/message-rpc/rpc-message-encoder.spec.d.ts.map +1 -0
  44. package/lib/common/message-rpc/rpc-message-encoder.spec.js +37 -0
  45. package/lib/common/message-rpc/rpc-message-encoder.spec.js.map +1 -0
  46. package/lib/common/message-rpc/rpc-protocol.d.ts +61 -0
  47. package/lib/common/message-rpc/rpc-protocol.d.ts.map +1 -0
  48. package/lib/common/message-rpc/rpc-protocol.js +183 -0
  49. package/lib/common/message-rpc/rpc-protocol.js.map +1 -0
  50. package/lib/common/message-rpc/uint8-array-message-buffer.d.ts +52 -0
  51. package/lib/common/message-rpc/uint8-array-message-buffer.d.ts.map +1 -0
  52. package/lib/common/message-rpc/uint8-array-message-buffer.js +169 -0
  53. package/lib/common/message-rpc/uint8-array-message-buffer.js.map +1 -0
  54. package/lib/common/message-rpc/uint8-array-message-buffer.spec.d.ts +2 -0
  55. package/lib/common/message-rpc/uint8-array-message-buffer.spec.d.ts.map +1 -0
  56. package/lib/common/message-rpc/uint8-array-message-buffer.spec.js +39 -0
  57. package/lib/common/message-rpc/uint8-array-message-buffer.spec.js.map +1 -0
  58. package/lib/common/messaging/abstract-connection-provider.d.ts +9 -8
  59. package/lib/common/messaging/abstract-connection-provider.d.ts.map +1 -1
  60. package/lib/common/messaging/abstract-connection-provider.js +20 -35
  61. package/lib/common/messaging/abstract-connection-provider.js.map +1 -1
  62. package/lib/common/messaging/connection-error-handler.d.ts +1 -2
  63. package/lib/common/messaging/connection-error-handler.d.ts.map +1 -1
  64. package/lib/common/messaging/connection-error-handler.js +1 -1
  65. package/lib/common/messaging/connection-error-handler.js.map +1 -1
  66. package/lib/common/messaging/handler.d.ts +2 -2
  67. package/lib/common/messaging/handler.d.ts.map +1 -1
  68. package/lib/common/messaging/proxy-factory.d.ts +13 -7
  69. package/lib/common/messaging/proxy-factory.d.ts.map +1 -1
  70. package/lib/common/messaging/proxy-factory.js +18 -13
  71. package/lib/common/messaging/proxy-factory.js.map +1 -1
  72. package/lib/common/messaging/proxy-factory.spec.js +4 -15
  73. package/lib/common/messaging/proxy-factory.spec.js.map +1 -1
  74. package/lib/common/messaging/web-socket-channel.d.ts +54 -48
  75. package/lib/common/messaging/web-socket-channel.d.ts.map +1 -1
  76. package/lib/common/messaging/web-socket-channel.js +41 -105
  77. package/lib/common/messaging/web-socket-channel.js.map +1 -1
  78. package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts +2 -2
  79. package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts.map +1 -1
  80. package/lib/electron-browser/messaging/electron-ipc-connection-provider.js +18 -7
  81. package/lib/electron-browser/messaging/electron-ipc-connection-provider.js.map +1 -1
  82. package/lib/electron-browser/messaging/electron-ws-connection-provider.d.ts +2 -2
  83. package/lib/electron-browser/messaging/electron-ws-connection-provider.d.ts.map +1 -1
  84. package/lib/electron-browser/messaging/electron-ws-connection-provider.js +5 -7
  85. package/lib/electron-browser/messaging/electron-ws-connection-provider.js.map +1 -1
  86. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +37 -9
  87. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts.map +1 -1
  88. package/lib/electron-main/messaging/electron-messaging-contribution.js +83 -68
  89. package/lib/electron-main/messaging/electron-messaging-contribution.js.map +1 -1
  90. package/lib/electron-main/messaging/electron-messaging-service.d.ts +2 -8
  91. package/lib/electron-main/messaging/electron-messaging-service.d.ts.map +1 -1
  92. package/lib/electron-main/messaging/electron-messaging-service.js.map +1 -1
  93. package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
  94. package/lib/electron-main/theia-electron-window.js +11 -8
  95. package/lib/electron-main/theia-electron-window.js.map +1 -1
  96. package/lib/node/messaging/binary-message-pipe.d.ts +45 -0
  97. package/lib/node/messaging/binary-message-pipe.d.ts.map +1 -0
  98. package/lib/node/messaging/binary-message-pipe.js +152 -0
  99. package/lib/node/messaging/binary-message-pipe.js.map +1 -0
  100. package/lib/node/messaging/ipc-bootstrap.js +2 -11
  101. package/lib/node/messaging/ipc-bootstrap.js.map +1 -1
  102. package/lib/node/messaging/ipc-channel.d.ts +26 -0
  103. package/lib/node/messaging/ipc-channel.d.ts.map +1 -0
  104. package/lib/node/messaging/ipc-channel.js +86 -0
  105. package/lib/node/messaging/ipc-channel.js.map +1 -0
  106. package/lib/node/messaging/ipc-connection-provider.d.ts +3 -5
  107. package/lib/node/messaging/ipc-connection-provider.d.ts.map +1 -1
  108. package/lib/node/messaging/ipc-connection-provider.js +14 -31
  109. package/lib/node/messaging/ipc-connection-provider.js.map +1 -1
  110. package/lib/node/messaging/ipc-protocol.d.ts +2 -2
  111. package/lib/node/messaging/ipc-protocol.d.ts.map +1 -1
  112. package/lib/node/messaging/messaging-contribution.d.ts +6 -9
  113. package/lib/node/messaging/messaging-contribution.d.ts.map +1 -1
  114. package/lib/node/messaging/messaging-contribution.js +23 -68
  115. package/lib/node/messaging/messaging-contribution.js.map +1 -1
  116. package/lib/node/messaging/messaging-service.d.ts +4 -23
  117. package/lib/node/messaging/messaging-service.d.ts.map +1 -1
  118. package/lib/node/messaging/messaging-service.js +1 -15
  119. package/lib/node/messaging/messaging-service.js.map +1 -1
  120. package/lib/node/messaging/test/test-web-socket-channel.d.ts +4 -2
  121. package/lib/node/messaging/test/test-web-socket-channel.d.ts.map +1 -1
  122. package/lib/node/messaging/test/test-web-socket-channel.js +25 -12
  123. package/lib/node/messaging/test/test-web-socket-channel.js.map +1 -1
  124. package/package.json +5 -8
  125. package/src/browser/messaging/ws-connection-provider.ts +34 -25
  126. package/src/browser/progress-status-bar-item.ts +1 -1
  127. package/src/browser/style/menus.css +1 -0
  128. package/src/browser/tree/tree-compression/compressed-tree-widget.tsx +2 -2
  129. package/src/browser/widgets/select-component.tsx +37 -17
  130. package/src/common/cancellation.ts +8 -0
  131. package/src/common/index.ts +2 -0
  132. package/src/common/message-rpc/channel.spec.ts +88 -0
  133. package/src/common/message-rpc/channel.ts +260 -0
  134. package/src/{node/messaging/logger.ts → common/message-rpc/index.ts} +4 -23
  135. package/src/common/message-rpc/message-buffer.ts +99 -0
  136. package/src/common/message-rpc/rpc-message-encoder.spec.ts +42 -0
  137. package/src/common/message-rpc/rpc-message-encoder.ts +497 -0
  138. package/src/common/message-rpc/rpc-protocol.ts +217 -0
  139. package/src/common/message-rpc/uint8-array-message-buffer.spec.ts +41 -0
  140. package/src/common/message-rpc/uint8-array-message-buffer.ts +206 -0
  141. package/src/common/messaging/abstract-connection-provider.ts +28 -37
  142. package/src/common/messaging/connection-error-handler.ts +1 -2
  143. package/src/common/messaging/handler.ts +2 -2
  144. package/src/common/messaging/proxy-factory.spec.ts +4 -17
  145. package/src/common/messaging/proxy-factory.ts +27 -16
  146. package/src/common/messaging/web-socket-channel.ts +79 -135
  147. package/src/electron-browser/messaging/electron-ipc-connection-provider.ts +21 -7
  148. package/src/electron-browser/messaging/electron-ws-connection-provider.ts +5 -8
  149. package/src/electron-main/messaging/electron-messaging-contribution.ts +87 -65
  150. package/src/electron-main/messaging/electron-messaging-service.ts +2 -8
  151. package/src/electron-main/theia-electron-window.ts +12 -9
  152. package/src/node/messaging/binary-message-pipe.ts +168 -0
  153. package/src/node/messaging/ipc-bootstrap.ts +3 -11
  154. package/src/node/messaging/ipc-channel.ts +97 -0
  155. package/src/node/messaging/ipc-connection-provider.ts +18 -35
  156. package/src/node/messaging/ipc-protocol.ts +2 -2
  157. package/src/node/messaging/messaging-contribution.ts +29 -74
  158. package/src/node/messaging/messaging-service.ts +4 -31
  159. package/src/node/messaging/test/test-web-socket-channel.ts +26 -17
  160. package/lib/node/messaging/logger.d.ts +0 -8
  161. package/lib/node/messaging/logger.d.ts.map +0 -1
  162. package/lib/node/messaging/logger.js.map +0 -1
  163. package/shared/vscode-ws-jsonrpc/index.d.ts +0 -1
  164. package/shared/vscode-ws-jsonrpc/index.js +0 -1
@@ -49,6 +49,14 @@ export namespace CancellationToken {
49
49
  isCancellationRequested: true,
50
50
  onCancellationRequested: shortcutEvent
51
51
  });
52
+
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ export function is(value: any): value is CancellationToken {
55
+ const candidate = value as CancellationToken;
56
+ return candidate && (candidate === CancellationToken.None
57
+ || candidate === CancellationToken.Cancelled
58
+ || (typeof candidate.isCancellationRequested === 'boolean' && !!candidate.onCancellationRequested));
59
+ }
52
60
  }
53
61
 
54
62
  export class CancellationError extends Error {
@@ -29,10 +29,12 @@ export * from './contribution-provider';
29
29
  export * from './path';
30
30
  export * from './logger';
31
31
  export * from './messaging';
32
+ export * from './message-rpc';
32
33
  export * from './message-service';
33
34
  export * from './message-service-protocol';
34
35
  export * from './progress-service';
35
36
  export * from './progress-service-protocol';
37
+ export * from './quick-pick-service';
36
38
  export * from './selection';
37
39
  export * from './strings';
38
40
  export * from './application-error';
@@ -0,0 +1,88 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2021 Red Hat, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { assert, expect, spy, use } from 'chai';
18
+ import * as spies from 'chai-spies';
19
+ import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from './uint8-array-message-buffer';
20
+ import { ChannelMultiplexer, ForwardingChannel, MessageProvider } from './channel';
21
+
22
+ use(spies);
23
+
24
+ /**
25
+ * A pipe with two channels at each end for testing.
26
+ */
27
+ export class ChannelPipe {
28
+ readonly left: ForwardingChannel = new ForwardingChannel('left', () => this.right.onCloseEmitter.fire({ reason: 'Left channel has been closed' }), () => {
29
+ const leftWrite = new Uint8ArrayWriteBuffer();
30
+ leftWrite.onCommit(buffer => {
31
+ this.right.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(buffer));
32
+ });
33
+ return leftWrite;
34
+ });
35
+ readonly right: ForwardingChannel = new ForwardingChannel('right', () => this.left.onCloseEmitter.fire({ reason: 'Right channel has been closed' }), () => {
36
+ const rightWrite = new Uint8ArrayWriteBuffer();
37
+ rightWrite.onCommit(buffer => {
38
+ this.left.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(buffer));
39
+ });
40
+ return rightWrite;
41
+ });
42
+ }
43
+ describe('Message Channel', () => {
44
+ describe('Channel multiplexer', () => {
45
+ it('should forward messages to intended target channel', async () => {
46
+ const pipe = new ChannelPipe();
47
+
48
+ const leftMultiplexer = new ChannelMultiplexer(pipe.left);
49
+ const rightMultiplexer = new ChannelMultiplexer(pipe.right);
50
+ const openChannelSpy = spy(() => {
51
+ });
52
+
53
+ rightMultiplexer.onDidOpenChannel(openChannelSpy);
54
+ leftMultiplexer.onDidOpenChannel(openChannelSpy);
55
+
56
+ const leftFirst = await leftMultiplexer.open('first');
57
+ const leftSecond = await leftMultiplexer.open('second');
58
+
59
+ const rightFirst = rightMultiplexer.getOpenChannel('first');
60
+ const rightSecond = rightMultiplexer.getOpenChannel('second');
61
+
62
+ assert.isNotNull(rightFirst);
63
+ assert.isNotNull(rightSecond);
64
+
65
+ const leftSecondSpy = spy((buf: MessageProvider) => {
66
+ const message = buf().readString();
67
+ expect(message).equal('message for second');
68
+ });
69
+
70
+ leftSecond.onMessage(leftSecondSpy);
71
+
72
+ const rightFirstSpy = spy((buf: MessageProvider) => {
73
+ const message = buf().readString();
74
+ expect(message).equal('message for first');
75
+ });
76
+
77
+ rightFirst!.onMessage(rightFirstSpy);
78
+
79
+ leftFirst.getWriteBuffer().writeString('message for first').commit();
80
+ rightSecond!.getWriteBuffer().writeString('message for second').commit();
81
+
82
+ expect(leftSecondSpy).to.be.called();
83
+ expect(rightFirstSpy).to.be.called();
84
+
85
+ expect(openChannelSpy).to.be.called.exactly(4);
86
+ });
87
+ });
88
+ });
@@ -0,0 +1,260 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2021 Red Hat, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { Disposable, DisposableCollection } from '../disposable';
18
+ import { Emitter, Event } from '../event';
19
+ import { ReadBuffer, WriteBuffer } from './message-buffer';
20
+
21
+ /**
22
+ * A channel is a bidirectional communications channel with lifecycle and
23
+ * error signalling. Note that creation of channels is specific to particular
24
+ * implementations and thus not part of the protocol.
25
+ */
26
+ export interface Channel {
27
+
28
+ /**
29
+ * The remote side has closed the channel
30
+ */
31
+ onClose: Event<ChannelCloseEvent>;
32
+
33
+ /**
34
+ * An error has occurred while writing to or reading from the channel
35
+ */
36
+ onError: Event<unknown>;
37
+
38
+ /**
39
+ * A message has arrived and can be read by listeners using a {@link MessageProvider}.
40
+ */
41
+ onMessage: Event<MessageProvider>;
42
+
43
+ /**
44
+ * Obtain a {@link WriteBuffer} to write a message to the channel.
45
+ */
46
+ getWriteBuffer(): WriteBuffer;
47
+
48
+ /**
49
+ * Close this channel. No {@link onClose} event should be sent
50
+ */
51
+ close(): void;
52
+ }
53
+
54
+ /**
55
+ * The event that is emitted when a channel is closed from the remote side.
56
+ */
57
+ export interface ChannelCloseEvent {
58
+ reason: string,
59
+ code?: number
60
+ };
61
+
62
+ /**
63
+ * The `MessageProvider` is emitted when a channel receives a new message.
64
+ * Listeners can invoke the provider to obtain a new {@link ReadBuffer} for the received message.
65
+ * This ensures that each listener has its own isolated {@link ReadBuffer} instance.
66
+ *
67
+ */
68
+ export type MessageProvider = () => ReadBuffer;
69
+
70
+ /**
71
+ * Helper class to implement the single channels on a {@link ChannelMultiplexer}. Simply forwards write requests to
72
+ * the given write buffer source i.e. the main channel of the {@link ChannelMultiplexer}.
73
+ */
74
+ export class ForwardingChannel implements Channel {
75
+
76
+ protected toDispose = new DisposableCollection();
77
+ constructor(readonly id: string, protected readonly closeHandler: () => void, protected readonly writeBufferSource: () => WriteBuffer) {
78
+ this.toDispose.pushAll([this.onCloseEmitter, this.onErrorEmitter, this.onMessageEmitter]);
79
+ }
80
+
81
+ onCloseEmitter: Emitter<ChannelCloseEvent> = new Emitter();
82
+ get onClose(): Event<ChannelCloseEvent> {
83
+ return this.onCloseEmitter.event;
84
+ };
85
+
86
+ onErrorEmitter: Emitter<unknown> = new Emitter();
87
+ get onError(): Event<unknown> {
88
+ return this.onErrorEmitter.event;
89
+ };
90
+
91
+ onMessageEmitter: Emitter<MessageProvider> = new Emitter();
92
+ get onMessage(): Event<MessageProvider> {
93
+ return this.onMessageEmitter.event;
94
+ };
95
+
96
+ getWriteBuffer(): WriteBuffer {
97
+ return this.writeBufferSource();
98
+ }
99
+
100
+ close(): void {
101
+ this.closeHandler();
102
+ this.toDispose.dispose();
103
+ }
104
+ }
105
+
106
+ /**
107
+ * The different message types used in the messaging protocol of the {@link ChannelMultiplexer}
108
+ */
109
+ export enum MessageTypes {
110
+ Open = 1,
111
+ Close = 2,
112
+ AckOpen = 3,
113
+ Data = 4
114
+ }
115
+
116
+ /**
117
+ * The write buffers in this implementation immediately write to the underlying
118
+ * channel, so we rely on writers to the multiplexed channels to always commit their
119
+ * messages and always in one go.
120
+ */
121
+ export class ChannelMultiplexer implements Disposable {
122
+ protected pendingOpen: Map<string, (channel: ForwardingChannel) => void> = new Map();
123
+ protected openChannels: Map<string, ForwardingChannel> = new Map();
124
+
125
+ protected readonly onOpenChannelEmitter = new Emitter<{ id: string, channel: Channel }>();
126
+ get onDidOpenChannel(): Event<{ id: string, channel: Channel }> {
127
+ return this.onOpenChannelEmitter.event;
128
+ }
129
+
130
+ protected toDispose = new DisposableCollection();
131
+
132
+ constructor(protected readonly underlyingChannel: Channel) {
133
+ this.toDispose.pushAll([
134
+ this.underlyingChannel.onMessage(buffer => this.handleMessage(buffer())),
135
+ this.underlyingChannel.onClose(event => this.onUnderlyingChannelClose(event)),
136
+ this.underlyingChannel.onError(error => this.handleError(error)),
137
+ this.onOpenChannelEmitter
138
+ ]);
139
+ }
140
+
141
+ protected handleError(error: unknown): void {
142
+ this.openChannels.forEach(channel => {
143
+ channel.onErrorEmitter.fire(error);
144
+ });
145
+ }
146
+
147
+ onUnderlyingChannelClose(event?: ChannelCloseEvent): void {
148
+ if (!this.toDispose.disposed) {
149
+ this.toDispose.push(Disposable.create(() => {
150
+ this.pendingOpen.clear();
151
+ this.openChannels.forEach(channel => {
152
+ channel.onCloseEmitter.fire(event ?? { reason: 'Multiplexer main channel has been closed from the remote side!' });
153
+ });
154
+
155
+ this.openChannels.clear();
156
+ }));
157
+ this.dispose();
158
+ }
159
+
160
+ }
161
+
162
+ protected handleMessage(buffer: ReadBuffer): void {
163
+ const type = buffer.readUint8();
164
+ const id = buffer.readString();
165
+ switch (type) {
166
+ case MessageTypes.AckOpen: {
167
+ return this.handleAckOpen(id);
168
+ }
169
+ case MessageTypes.Open: {
170
+ return this.handleOpen(id);
171
+ }
172
+ case MessageTypes.Close: {
173
+ return this.handleClose(id);
174
+ }
175
+ case MessageTypes.Data: {
176
+ return this.handleData(id, buffer.sliceAtReadPosition());
177
+ }
178
+ }
179
+ }
180
+
181
+ protected handleAckOpen(id: string): void {
182
+ // edge case: both side try to open a channel at the same time.
183
+ const resolve = this.pendingOpen.get(id);
184
+ if (resolve) {
185
+ const channel = this.createChannel(id);
186
+ this.pendingOpen.delete(id);
187
+ this.openChannels.set(id, channel);
188
+ resolve!(channel);
189
+ this.onOpenChannelEmitter.fire({ id, channel });
190
+ }
191
+ }
192
+
193
+ protected handleOpen(id: string): void {
194
+ if (!this.openChannels.has(id)) {
195
+ const channel = this.createChannel(id);
196
+ this.openChannels.set(id, channel);
197
+ const resolve = this.pendingOpen.get(id);
198
+ if (resolve) {
199
+ // edge case: both side try to open a channel at the same time.
200
+ resolve(channel);
201
+ }
202
+ this.underlyingChannel.getWriteBuffer().writeUint8(MessageTypes.AckOpen).writeString(id).commit();
203
+ this.onOpenChannelEmitter.fire({ id, channel });
204
+ }
205
+ }
206
+
207
+ protected handleClose(id: string): void {
208
+ const channel = this.openChannels.get(id);
209
+ if (channel) {
210
+ channel.onCloseEmitter.fire({ reason: 'Channel has been closed from the remote side' });
211
+ this.openChannels.delete(id);
212
+ }
213
+ }
214
+
215
+ protected handleData(id: string, data: ReadBuffer): void {
216
+ const channel = this.openChannels.get(id);
217
+ if (channel) {
218
+ channel.onMessageEmitter.fire(() => data);
219
+ }
220
+ }
221
+
222
+ protected createChannel(id: string): ForwardingChannel {
223
+ return new ForwardingChannel(id, () => this.closeChannel(id), () => this.prepareWriteBuffer(id));
224
+ }
225
+
226
+ // Prepare the write buffer for the channel with the give, id. The channel id has to be encoded
227
+ // and written to the buffer before the actual message.
228
+ protected prepareWriteBuffer(id: string): WriteBuffer {
229
+ const underlying = this.underlyingChannel.getWriteBuffer();
230
+ underlying.writeUint8(MessageTypes.Data);
231
+ underlying.writeString(id);
232
+ return underlying;
233
+ }
234
+
235
+ protected closeChannel(id: string): void {
236
+ this.underlyingChannel.getWriteBuffer()
237
+ .writeUint8(MessageTypes.Close)
238
+ .writeString(id)
239
+ .commit();
240
+
241
+ this.openChannels.delete(id);
242
+ }
243
+
244
+ open(id: string): Promise<Channel> {
245
+ const result = new Promise<Channel>((resolve, reject) => {
246
+ this.pendingOpen.set(id, resolve);
247
+ });
248
+ this.underlyingChannel.getWriteBuffer().writeUint8(MessageTypes.Open).writeString(id).commit();
249
+ return result;
250
+ }
251
+
252
+ getOpenChannel(id: string): Channel | undefined {
253
+ return this.openChannels.get(id);
254
+ }
255
+
256
+ dispose(): void {
257
+ this.toDispose.dispose();
258
+ }
259
+ }
260
+
@@ -1,5 +1,5 @@
1
1
  // *****************************************************************************
2
- // Copyright (C) 2017 TypeFox and others.
2
+ // Copyright (C) 2022 STMicroelectronics and others.
3
3
  //
4
4
  // This program and the accompanying materials are made available under the
5
5
  // terms of the Eclipse Public License v. 2.0 which is available at
@@ -13,25 +13,6 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
-
17
- import { Logger } from 'vscode-ws-jsonrpc';
18
-
19
- export class ConsoleLogger implements Logger {
20
-
21
- error(message: string): void {
22
- console.log(message);
23
- }
24
-
25
- warn(message: string): void {
26
- console.log(message);
27
- }
28
-
29
- info(message: string): void {
30
- console.log(message);
31
- }
32
-
33
- log(message: string): void {
34
- console.log(message);
35
- }
36
-
37
- }
16
+ export { RequestHandler, RpcProtocol, RpcProtocolOptions } from './rpc-protocol';
17
+ export { Channel, ChannelCloseEvent, MessageProvider } from './channel';
18
+ export { ReadBuffer, WriteBuffer } from './message-buffer';
@@ -0,0 +1,99 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2021 Red Hat, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ /**
18
+ * A buffer maintaining a write position capable of writing primitive values
19
+ */
20
+ export interface WriteBuffer {
21
+ writeUint8(byte: number): this
22
+ writeUint16(value: number): this
23
+ writeUint32(value: number): this
24
+ writeString(value: string): this
25
+ writeBytes(value: Uint8Array): this
26
+ writeNumber(value: number): this
27
+ writeLength(value: number): this
28
+ /**
29
+ * Makes any writes to the buffer permanent, for example by sending the writes over a channel.
30
+ * You must obtain a new write buffer after committing
31
+ */
32
+ commit(): void;
33
+ }
34
+
35
+ export class ForwardingWriteBuffer implements WriteBuffer {
36
+ constructor(protected readonly underlying: WriteBuffer) {
37
+ }
38
+
39
+ writeUint8(byte: number): this {
40
+ this.underlying.writeUint8(byte);
41
+ return this;
42
+ }
43
+
44
+ writeUint16(value: number): this {
45
+ this.underlying.writeUint16(value);
46
+ return this;
47
+ }
48
+
49
+ writeUint32(value: number): this {
50
+ this.underlying.writeUint32(value);
51
+ return this;
52
+ }
53
+
54
+ writeLength(value: number): this {
55
+ this.underlying.writeLength(value);
56
+ return this;
57
+ }
58
+
59
+ writeString(value: string): this {
60
+ this.underlying.writeString(value);
61
+ return this;
62
+ }
63
+
64
+ writeBytes(value: Uint8Array): this {
65
+ this.underlying.writeBytes(value);
66
+ return this;
67
+ }
68
+
69
+ writeNumber(value: number): this {
70
+ this.underlying.writeNumber(value);
71
+ return this;
72
+ }
73
+
74
+ commit(): void {
75
+ this.underlying.commit();
76
+ }
77
+ }
78
+
79
+ /**
80
+ * A buffer maintaining a read position in a buffer containing a received message capable of
81
+ * reading primitive values.
82
+ */
83
+ export interface ReadBuffer {
84
+ readUint8(): number;
85
+ readUint16(): number;
86
+ readUint32(): number;
87
+ readString(): string;
88
+ readNumber(): number,
89
+ readLength(): number,
90
+ readBytes(): Uint8Array;
91
+
92
+ /**
93
+ * Returns a new read buffer whose starting read position is the current read position of this buffer.
94
+ * This is useful to create read buffers sub messages.
95
+ * (e.g. when using a multiplexer the beginning of the message might contain some protocol overhead which should not be part
96
+ * of the message reader that is sent to the target channel)
97
+ */
98
+ sliceAtReadPosition(): ReadBuffer
99
+ }
@@ -0,0 +1,42 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2021 Red Hat, Inc. and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { expect } from 'chai';
18
+ import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from './uint8-array-message-buffer';
19
+ import { RpcMessageDecoder, RpcMessageEncoder } from './rpc-message-encoder';
20
+
21
+ describe('PPC Message Codex', () => {
22
+ describe('RPC Message Encoder & Decoder', () => {
23
+ it('should encode object into binary message and decode the message back into the original object', () => {
24
+ const buffer = new Uint8Array(1024);
25
+ const writer = new Uint8ArrayWriteBuffer(buffer);
26
+
27
+ const encoder = new RpcMessageEncoder();
28
+ const jsonMangled = JSON.parse(JSON.stringify(encoder));
29
+
30
+ encoder.writeTypedValue(writer, encoder);
31
+
32
+ const written = writer.getCurrentContents();
33
+
34
+ const reader = new Uint8ArrayReadBuffer(written);
35
+
36
+ const decoder = new RpcMessageDecoder();
37
+ const decoded = decoder.readTypedValue(reader);
38
+
39
+ expect(decoded).deep.equal(jsonMangled);
40
+ });
41
+ });
42
+ });