@opensumi/ide-connection 2.27.3-next-1706520813.0 → 2.27.3-rc-1706687185.0
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.
- package/lib/browser/ws-channel-handler.d.ts +9 -7
- package/lib/browser/ws-channel-handler.d.ts.map +1 -1
- package/lib/browser/ws-channel-handler.js +65 -64
- package/lib/browser/ws-channel-handler.js.map +1 -1
- package/lib/common/connect.d.ts +6 -57
- package/lib/common/connect.d.ts.map +1 -1
- package/lib/common/connect.js +9 -168
- package/lib/common/connect.js.map +1 -1
- package/lib/common/connection/buffers.d.ts +55 -0
- package/lib/common/connection/buffers.d.ts.map +1 -0
- package/lib/common/connection/buffers.js +244 -0
- package/lib/common/connection/buffers.js.map +1 -0
- package/lib/common/connection/drivers/base.d.ts +9 -0
- package/lib/common/connection/drivers/base.d.ts.map +1 -0
- package/lib/common/connection/drivers/base.js +11 -0
- package/lib/common/connection/drivers/base.js.map +1 -0
- package/lib/common/connection/drivers/empty.d.ts +8 -0
- package/lib/common/connection/drivers/empty.d.ts.map +1 -0
- package/lib/common/connection/drivers/empty.js +21 -0
- package/lib/common/connection/drivers/empty.js.map +1 -0
- package/lib/common/connection/drivers/index.d.ts +6 -0
- package/lib/common/connection/drivers/index.d.ts.map +1 -0
- package/lib/common/connection/drivers/index.js +9 -0
- package/lib/common/connection/drivers/index.js.map +1 -0
- package/lib/common/connection/drivers/node-message-port.d.ts +12 -0
- package/lib/common/connection/drivers/node-message-port.d.ts.map +1 -0
- package/lib/common/connection/drivers/node-message-port.js +31 -0
- package/lib/common/connection/drivers/node-message-port.js.map +1 -0
- package/lib/common/connection/drivers/reconnecting-websocket.d.ts +15 -0
- package/lib/common/connection/drivers/reconnecting-websocket.d.ts.map +1 -0
- package/lib/common/connection/drivers/reconnecting-websocket.js +83 -0
- package/lib/common/connection/drivers/reconnecting-websocket.js.map +1 -0
- package/lib/common/connection/drivers/socket.d.ts +17 -0
- package/lib/common/connection/drivers/socket.d.ts.map +1 -0
- package/lib/common/connection/drivers/socket.js +56 -0
- package/lib/common/connection/drivers/socket.js.map +1 -0
- package/lib/common/connection/drivers/stream-decoder.d.ts +67 -0
- package/lib/common/connection/drivers/stream-decoder.d.ts.map +1 -0
- package/lib/common/connection/drivers/stream-decoder.js +171 -0
- package/lib/common/connection/drivers/stream-decoder.js.map +1 -0
- package/lib/common/connection/drivers/utils.d.ts +12 -0
- package/lib/common/connection/drivers/utils.d.ts.map +1 -0
- package/lib/common/connection/drivers/utils.js +49 -0
- package/lib/common/connection/drivers/utils.js.map +1 -0
- package/lib/common/connection/drivers/ws-websocket.d.ts +11 -0
- package/lib/common/connection/drivers/ws-websocket.d.ts.map +1 -0
- package/lib/common/connection/drivers/ws-websocket.js +31 -0
- package/lib/common/connection/drivers/ws-websocket.js.map +1 -0
- package/lib/common/connection/index.d.ts +2 -0
- package/lib/common/connection/index.d.ts.map +1 -0
- package/lib/common/connection/index.js +5 -0
- package/lib/common/connection/index.js.map +1 -0
- package/lib/common/connection/types.d.ts +7 -0
- package/lib/common/connection/types.d.ts.map +1 -0
- package/lib/common/connection/types.js +3 -0
- package/lib/common/connection/types.js.map +1 -0
- package/lib/common/constants.d.ts +2 -0
- package/lib/common/constants.d.ts.map +1 -0
- package/lib/common/constants.js +5 -0
- package/lib/common/constants.js.map +1 -0
- package/lib/common/{rpcProtocol.d.ts → ext-rpc-protocol.d.ts} +10 -11
- package/lib/common/ext-rpc-protocol.d.ts.map +1 -0
- package/lib/common/{rpcProtocol.js → ext-rpc-protocol.js} +22 -19
- package/lib/common/ext-rpc-protocol.js.map +1 -0
- package/lib/common/index.d.ts +2 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +2 -1
- package/lib/common/index.js.map +1 -1
- package/lib/common/proxy/base.d.ts +22 -0
- package/lib/common/proxy/base.d.ts.map +1 -0
- package/lib/common/proxy/base.js +47 -0
- package/lib/common/proxy/base.js.map +1 -0
- package/lib/common/proxy/index.d.ts +8 -0
- package/lib/common/proxy/index.d.ts.map +1 -0
- package/lib/common/proxy/index.js +12 -0
- package/lib/common/proxy/index.js.map +1 -0
- package/lib/common/proxy/legacy.d.ts +23 -0
- package/lib/common/proxy/legacy.d.ts.map +1 -0
- package/lib/common/proxy/legacy.js +183 -0
- package/lib/common/proxy/legacy.js.map +1 -0
- package/lib/common/rpc-service/center.d.ts +20 -0
- package/lib/common/rpc-service/center.d.ts.map +1 -0
- package/lib/common/rpc-service/center.js +100 -0
- package/lib/common/rpc-service/center.js.map +1 -0
- package/lib/common/rpc-service/index.d.ts +3 -0
- package/lib/common/rpc-service/index.d.ts.map +1 -0
- package/lib/common/rpc-service/index.js +6 -0
- package/lib/common/rpc-service/index.js.map +1 -0
- package/lib/common/rpc-service/stub.d.ts +15 -0
- package/lib/common/rpc-service/stub.d.ts.map +1 -0
- package/lib/common/rpc-service/stub.js +48 -0
- package/lib/common/rpc-service/stub.js.map +1 -0
- package/lib/common/types.d.ts +15 -0
- package/lib/common/types.d.ts.map +1 -0
- package/lib/common/types.js +9 -0
- package/lib/common/types.js.map +1 -0
- package/lib/common/utils.d.ts +4 -2
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +32 -9
- package/lib/common/utils.js.map +1 -1
- package/lib/common/ws-channel.d.ts +104 -27
- package/lib/common/ws-channel.d.ts.map +1 -1
- package/lib/common/ws-channel.js +96 -27
- package/lib/common/ws-channel.js.map +1 -1
- package/lib/node/common-channel-handler.d.ts +18 -16
- package/lib/node/common-channel-handler.d.ts.map +1 -1
- package/lib/node/common-channel-handler.js +42 -59
- package/lib/node/common-channel-handler.js.map +1 -1
- package/lib/node/index.d.ts +0 -3
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +0 -5
- package/lib/node/index.js.map +1 -1
- package/lib/node/ws.d.ts +1 -1
- package/lib/node/ws.d.ts.map +1 -1
- package/lib/node/ws.js +2 -0
- package/lib/node/ws.js.map +1 -1
- package/package.json +9 -7
- package/src/browser/ws-channel-handler.ts +82 -70
- package/src/common/connect.ts +7 -193
- package/src/common/connection/buffers.ts +284 -0
- package/src/common/connection/drivers/base.ts +15 -0
- package/src/common/connection/drivers/empty.ts +19 -0
- package/src/common/connection/drivers/index.ts +5 -0
- package/src/common/connection/drivers/node-message-port.ts +33 -0
- package/src/common/connection/drivers/reconnecting-websocket.ts +86 -0
- package/src/common/connection/drivers/socket.ts +62 -0
- package/src/common/connection/drivers/stream-decoder.ts +196 -0
- package/src/common/connection/drivers/utils.ts +52 -0
- package/src/common/connection/drivers/ws-websocket.ts +31 -0
- package/src/common/connection/index.ts +1 -0
- package/src/common/connection/types.ts +7 -0
- package/src/common/constants.ts +1 -0
- package/src/common/{rpcProtocol.ts → ext-rpc-protocol.ts} +43 -31
- package/src/common/index.ts +2 -1
- package/src/common/proxy/base.ts +67 -0
- package/src/common/proxy/index.ts +10 -0
- package/src/common/proxy/legacy.ts +200 -0
- package/src/common/rpc-service/center.ts +124 -0
- package/src/common/rpc-service/index.ts +2 -0
- package/src/common/rpc-service/stub.ts +49 -0
- package/src/common/types.ts +17 -0
- package/src/common/utils.ts +31 -8
- package/src/common/ws-channel.ts +175 -48
- package/src/node/common-channel-handler.ts +68 -80
- package/src/node/index.ts +0 -5
- package/src/node/ws.ts +3 -1
- package/lib/common/proxy.d.ts +0 -47
- package/lib/common/proxy.d.ts.map +0 -1
- package/lib/common/proxy.js +0 -272
- package/lib/common/proxy.js.map +0 -1
- package/lib/common/rpcProtocol.d.ts.map +0 -1
- package/lib/common/rpcProtocol.js.map +0 -1
- package/lib/node/connect.d.ts +0 -4
- package/lib/node/connect.d.ts.map +0 -1
- package/lib/node/connect.js +0 -9
- package/lib/node/connect.js.map +0 -1
- package/src/common/proxy.ts +0 -303
- package/src/node/connect.ts +0 -11
package/src/common/connect.ts
CHANGED
|
@@ -1,212 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { RPCProxy, NOTREGISTERMETHOD, ILogger } from './proxy';
|
|
4
|
-
|
|
5
|
-
export type RPCServiceMethod = (...args: any[]) => any;
|
|
6
|
-
export type ServiceProxy = any;
|
|
7
|
-
|
|
8
|
-
export enum ServiceType {
|
|
9
|
-
Service,
|
|
10
|
-
Stub,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class RPCServiceStub {
|
|
14
|
-
constructor(private serviceName: string, private center: RPCServiceCenter, private type: ServiceType) {
|
|
15
|
-
if (this.type === ServiceType.Service) {
|
|
16
|
-
this.center.registerService(serviceName, this.type);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async ready() {
|
|
21
|
-
return this.center.when();
|
|
22
|
-
}
|
|
23
|
-
getNotificationName(name: string) {
|
|
24
|
-
return `on:${this.serviceName}:${name}`;
|
|
25
|
-
}
|
|
26
|
-
getRequestName(name: string) {
|
|
27
|
-
return `${this.serviceName}:${name}`;
|
|
28
|
-
}
|
|
29
|
-
// 服务方
|
|
30
|
-
on(name: string, method: RPCServiceMethod) {
|
|
31
|
-
this.onRequest(name, method);
|
|
32
|
-
}
|
|
33
|
-
getServiceMethod(service): string[] {
|
|
34
|
-
let props: any[] = [];
|
|
35
|
-
|
|
36
|
-
if (/^\s*class/.test(service.constructor.toString())) {
|
|
37
|
-
let obj = service;
|
|
38
|
-
do {
|
|
39
|
-
props = props.concat(Object.getOwnPropertyNames(obj));
|
|
40
|
-
} while ((obj = Object.getPrototypeOf(obj)));
|
|
41
|
-
props = props.sort().filter((e, i, arr) => e !== arr[i + 1] && typeof service[e] === 'function');
|
|
42
|
-
} else {
|
|
43
|
-
for (const prop in service) {
|
|
44
|
-
if (service[prop] && typeof service[prop] === 'function') {
|
|
45
|
-
props.push(prop);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return props;
|
|
51
|
-
}
|
|
52
|
-
onRequestService(service: any) {
|
|
53
|
-
const methods = this.getServiceMethod(service);
|
|
54
|
-
for (const method of methods) {
|
|
55
|
-
this.onRequest(method, service[method].bind(service));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
onRequest(name: string, method: RPCServiceMethod) {
|
|
60
|
-
this.center.onRequest(this.getMethodName(name), method);
|
|
61
|
-
}
|
|
62
|
-
broadcast(name: string, ...args): Promise<any> {
|
|
63
|
-
return this.center.broadcast(this.getMethodName(name), ...args);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
getMethodName(name: string) {
|
|
67
|
-
return name.startsWith('on') ? this.getNotificationName(name) : this.getRequestName(name);
|
|
68
|
-
}
|
|
69
|
-
getProxy = <T>() =>
|
|
70
|
-
new Proxy<RPCServiceStub & T>(this as any, {
|
|
71
|
-
// 调用方
|
|
72
|
-
get: (target, prop: string) => {
|
|
73
|
-
if (!target[prop]) {
|
|
74
|
-
if (typeof prop === 'symbol') {
|
|
75
|
-
return Promise.resolve();
|
|
76
|
-
} else {
|
|
77
|
-
return (...args) => this.ready().then(() => this.broadcast(prop, ...args));
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
return target[prop];
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
}
|
|
1
|
+
import { RPCServiceCenter, RPCServiceStub } from './rpc-service';
|
|
2
|
+
import { ServiceType } from './types';
|
|
85
3
|
|
|
86
4
|
export function initRPCService<T = void>(center: RPCServiceCenter) {
|
|
87
5
|
return {
|
|
88
6
|
createRPCService: (name: string, service?: any) => {
|
|
89
|
-
const proxy =
|
|
7
|
+
const proxy = createRPCService<T>(name, center);
|
|
90
8
|
if (service) {
|
|
91
9
|
proxy.onRequestService(service);
|
|
92
10
|
}
|
|
93
11
|
|
|
94
12
|
return proxy;
|
|
95
13
|
},
|
|
96
|
-
getRPCService: (name: string) =>
|
|
14
|
+
getRPCService: (name: string) => getRPCService<T>(name, center),
|
|
97
15
|
};
|
|
98
16
|
}
|
|
99
17
|
|
|
100
|
-
|
|
101
|
-
registerService: (service: string) => void;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export interface RPCMessageConnection extends MessageConnection {
|
|
105
|
-
uid?: string;
|
|
106
|
-
writer?: any;
|
|
107
|
-
reader?: any;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function createRPCService<T = void>(name: string, center: RPCServiceCenter): any {
|
|
18
|
+
export function createRPCService<T = void>(name: string, center: RPCServiceCenter) {
|
|
111
19
|
return new RPCServiceStub(name, center, ServiceType.Service).getProxy<T>();
|
|
112
20
|
}
|
|
113
21
|
|
|
114
|
-
export function getRPCService<T = void>(name: string, center: RPCServiceCenter)
|
|
22
|
+
export function getRPCService<T = void>(name: string, center: RPCServiceCenter) {
|
|
115
23
|
return new RPCServiceStub(name, center, ServiceType.Stub).getProxy<T>();
|
|
116
24
|
}
|
|
117
25
|
|
|
118
|
-
export
|
|
119
|
-
public uid: string;
|
|
120
|
-
public rpcProxy: RPCProxy[] = [];
|
|
121
|
-
public serviceProxy: ServiceProxy[] = [];
|
|
122
|
-
private connection: Array<MessageConnection> = [];
|
|
123
|
-
private serviceMethodMap = { client: undefined };
|
|
124
|
-
|
|
125
|
-
private createService: string[] = [];
|
|
126
|
-
private getService: string[] = [];
|
|
127
|
-
|
|
128
|
-
private connectionPromise: Promise<void>;
|
|
129
|
-
private connectionPromiseResolve: () => void;
|
|
130
|
-
private logger: ILogger;
|
|
131
|
-
|
|
132
|
-
constructor(private bench?: IBench, logger?: ILogger) {
|
|
133
|
-
this.uid = 'RPCServiceCenter:' + process.pid;
|
|
134
|
-
this.connectionPromise = new Promise((resolve) => {
|
|
135
|
-
this.connectionPromiseResolve = resolve;
|
|
136
|
-
});
|
|
137
|
-
this.logger = logger || console;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
registerService(serviceName: string, type: ServiceType): void {
|
|
141
|
-
if (type === ServiceType.Service) {
|
|
142
|
-
this.createService.push(serviceName);
|
|
143
|
-
if (this.bench) {
|
|
144
|
-
this.bench.registerService(serviceName);
|
|
145
|
-
}
|
|
146
|
-
} else if (type === ServiceType.Stub) {
|
|
147
|
-
this.getService.push(serviceName);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
when() {
|
|
152
|
-
return this.connectionPromise;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
setConnection(connection: MessageConnection) {
|
|
156
|
-
if (!this.connection.length) {
|
|
157
|
-
this.connectionPromiseResolve();
|
|
158
|
-
}
|
|
159
|
-
this.connection.push(connection);
|
|
160
|
-
|
|
161
|
-
const rpcProxy = new RPCProxy(this.serviceMethodMap, this.logger);
|
|
162
|
-
rpcProxy.listen(connection);
|
|
163
|
-
this.rpcProxy.push(rpcProxy);
|
|
164
|
-
|
|
165
|
-
const serviceProxy = rpcProxy.createProxy();
|
|
166
|
-
this.serviceProxy.push(serviceProxy);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
removeConnection(connection: MessageConnection) {
|
|
170
|
-
const removeIndex = this.connection.indexOf(connection);
|
|
171
|
-
if (removeIndex !== -1) {
|
|
172
|
-
this.connection.splice(removeIndex, 1);
|
|
173
|
-
this.rpcProxy.splice(removeIndex, 1);
|
|
174
|
-
this.serviceProxy.splice(removeIndex, 1);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return removeIndex !== -1;
|
|
178
|
-
}
|
|
179
|
-
onRequest(name: string, method: RPCServiceMethod) {
|
|
180
|
-
if (!this.connection.length) {
|
|
181
|
-
this.serviceMethodMap[name] = method;
|
|
182
|
-
} else {
|
|
183
|
-
this.rpcProxy.forEach((proxy) => {
|
|
184
|
-
proxy.listenService({ [name]: method });
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
async broadcast(name: string, ...args): Promise<any> {
|
|
189
|
-
const broadcastResult = this.serviceProxy.map((proxy) => proxy[name](...args));
|
|
190
|
-
if (!broadcastResult || broadcastResult.length === 0) {
|
|
191
|
-
throw new Error(`broadcast rpc \`${name}\` error: no remote service can handle this call`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const doubtfulResult = [] as any[];
|
|
195
|
-
const result = [] as any[];
|
|
196
|
-
for (const i of broadcastResult) {
|
|
197
|
-
if (i === NOTREGISTERMETHOD) {
|
|
198
|
-
doubtfulResult.push(i);
|
|
199
|
-
} else {
|
|
200
|
-
result.push(i);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (doubtfulResult.length > 0) {
|
|
205
|
-
this.logger.warn(`broadcast rpc \`${name}\` getting doubtful responses: ${doubtfulResult.join(',')}`);
|
|
206
|
-
}
|
|
207
|
-
// FIXME: this is an unreasonable design, if remote service only returned doubtful result, we will return an empty array.
|
|
208
|
-
// but actually we should throw an error to tell user that no remote service can handle this call.
|
|
209
|
-
// or just return `undefined`.
|
|
210
|
-
return result.length === 1 ? result[0] : result;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
26
|
+
export * from './rpc-service';
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Treat a collection of Buffers as a single contiguous partially mutable Buffer.
|
|
3
|
+
*
|
|
4
|
+
* Where possible, operations execute without creating a new Buffer and copying everything over.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const emptyBuffer = new Uint8Array(0);
|
|
8
|
+
|
|
9
|
+
export function copy(
|
|
10
|
+
source: Uint8Array,
|
|
11
|
+
target: Uint8Array,
|
|
12
|
+
targetStart?: number,
|
|
13
|
+
sourceStart?: number,
|
|
14
|
+
sourceEnd?: number,
|
|
15
|
+
) {
|
|
16
|
+
target.set(source.subarray(sourceStart, sourceEnd), targetStart);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class Buffers {
|
|
20
|
+
buffers = [] as Uint8Array[];
|
|
21
|
+
protected size = 0;
|
|
22
|
+
|
|
23
|
+
get byteLength() {
|
|
24
|
+
return this.size;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
push(buffer: Uint8Array) {
|
|
28
|
+
this.buffers.push(buffer);
|
|
29
|
+
this.size += buffer.length;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
unshift(buffer: Uint8Array) {
|
|
33
|
+
this.buffers.unshift(buffer);
|
|
34
|
+
this.size += buffer.length;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
slice(start?: number, end?: number) {
|
|
38
|
+
const buffers = this.buffers;
|
|
39
|
+
if (end === undefined) {
|
|
40
|
+
end = this.size;
|
|
41
|
+
}
|
|
42
|
+
if (start === undefined) {
|
|
43
|
+
start = 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (end > this.size) {
|
|
47
|
+
end = this.size;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (start >= end) {
|
|
51
|
+
return emptyBuffer;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let startBytes = 0;
|
|
55
|
+
let si = 0;
|
|
56
|
+
for (; si < buffers.length && startBytes + buffers[si].length <= start; si++) {
|
|
57
|
+
startBytes += buffers[si].length;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const target = new Uint8Array(end - start);
|
|
61
|
+
|
|
62
|
+
let ti = 0;
|
|
63
|
+
for (let ii = si; ti < end - start && ii < buffers.length; ii++) {
|
|
64
|
+
const len = buffers[ii].length;
|
|
65
|
+
|
|
66
|
+
const _start = ti === 0 ? start - startBytes : 0;
|
|
67
|
+
const _end = ti + len >= end - start ? Math.min(_start + (end - start) - ti, len) : len;
|
|
68
|
+
copy(buffers[ii], target, ti, _start, _end);
|
|
69
|
+
ti += _end - _start;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return target;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
pos(i: number): { buf: number; offset: number } {
|
|
76
|
+
if (i < 0 || i >= this.size) {
|
|
77
|
+
throw new Error(`out of range, ${i} not in [0, ${this.size})`);
|
|
78
|
+
}
|
|
79
|
+
let l = i;
|
|
80
|
+
let bi = 0;
|
|
81
|
+
let bu: Uint8Array | null = null;
|
|
82
|
+
for (;;) {
|
|
83
|
+
bu = this.buffers[bi];
|
|
84
|
+
if (l < bu.length) {
|
|
85
|
+
return { buf: bi, offset: l };
|
|
86
|
+
} else {
|
|
87
|
+
l -= bu.length;
|
|
88
|
+
}
|
|
89
|
+
bi++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
copy(target: Uint8Array, targetStart = 0, sourceStart = 0, sourceEnd = this.size) {
|
|
94
|
+
return copy(this.slice(sourceStart, sourceEnd), target, targetStart, 0, sourceEnd - sourceStart);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
splice(start: number, deleteCount: number, ...reps: Uint8Array[]) {
|
|
98
|
+
const buffers = this.buffers;
|
|
99
|
+
const index = start >= 0 ? start : this.size - start;
|
|
100
|
+
|
|
101
|
+
if (deleteCount === undefined) {
|
|
102
|
+
deleteCount = this.size - index;
|
|
103
|
+
} else if (deleteCount > this.size - index) {
|
|
104
|
+
deleteCount = this.size - index;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
for (const i of reps) {
|
|
108
|
+
this.size += i.length;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const removed = new Buffers();
|
|
112
|
+
|
|
113
|
+
let startBytes = 0;
|
|
114
|
+
let ii = 0;
|
|
115
|
+
for (; ii < buffers.length && startBytes + buffers[ii].length < index; ii++) {
|
|
116
|
+
startBytes += buffers[ii].length;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (index - startBytes > 0) {
|
|
120
|
+
const start = index - startBytes;
|
|
121
|
+
|
|
122
|
+
if (start + deleteCount < buffers[ii].length) {
|
|
123
|
+
removed.push(buffers[ii].slice(start, start + deleteCount));
|
|
124
|
+
|
|
125
|
+
const orig = buffers[ii];
|
|
126
|
+
const buf0 = new Uint8Array(start);
|
|
127
|
+
for (let i = 0; i < start; i++) {
|
|
128
|
+
buf0[i] = orig[i];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const buf1 = new Uint8Array(orig.length - start - deleteCount);
|
|
132
|
+
for (let i = start + deleteCount; i < orig.length; i++) {
|
|
133
|
+
buf1[i - deleteCount - start] = orig[i];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (reps.length > 0) {
|
|
137
|
+
const reps_ = reps.slice();
|
|
138
|
+
reps_.unshift(buf0);
|
|
139
|
+
reps_.push(buf1);
|
|
140
|
+
buffers.splice.apply(buffers, [ii, 1, ...reps_]);
|
|
141
|
+
ii += reps_.length;
|
|
142
|
+
reps = [];
|
|
143
|
+
} else {
|
|
144
|
+
buffers.splice(ii, 1, buf0, buf1);
|
|
145
|
+
ii += 2;
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
removed.push(buffers[ii].slice(start));
|
|
149
|
+
buffers[ii] = buffers[ii].slice(0, start);
|
|
150
|
+
ii++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (reps.length > 0) {
|
|
155
|
+
buffers.splice.apply(buffers, [ii, 0, ...reps]);
|
|
156
|
+
ii += reps.length;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
while (removed.byteLength < deleteCount) {
|
|
160
|
+
const buf = buffers[ii];
|
|
161
|
+
const len = buf.length;
|
|
162
|
+
const take = Math.min(len, deleteCount - removed.byteLength);
|
|
163
|
+
|
|
164
|
+
if (take === len) {
|
|
165
|
+
removed.push(buf);
|
|
166
|
+
buffers.splice(ii, 1);
|
|
167
|
+
} else {
|
|
168
|
+
removed.push(buf.slice(0, take));
|
|
169
|
+
buffers[ii] = buffers[ii].slice(take);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
this.size -= removed.byteLength;
|
|
174
|
+
|
|
175
|
+
return removed;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
get(i: number) {
|
|
179
|
+
const { buf, offset } = this.pos(i);
|
|
180
|
+
return this.buffers[buf][offset];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
set(i: number, v: number) {
|
|
184
|
+
const { buf, offset } = this.pos(i);
|
|
185
|
+
this.buffers[buf][offset] = v;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
cursor(offset = 0) {
|
|
189
|
+
return new Cursor(this, offset);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
dispose() {
|
|
193
|
+
this.buffers = [];
|
|
194
|
+
this.size = 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Remember the current position in a Buffers.
|
|
200
|
+
*
|
|
201
|
+
* The cursor will always point to the next byte to be read.
|
|
202
|
+
*
|
|
203
|
+
* The cursor is not safe to use after the Buffers is modified.
|
|
204
|
+
*/
|
|
205
|
+
export class Cursor {
|
|
206
|
+
protected chunkIndex = 0;
|
|
207
|
+
protected chunkOffset = 0;
|
|
208
|
+
|
|
209
|
+
constructor(protected buffers: Buffers, public offset = 0) {
|
|
210
|
+
this.updatePosition();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
protected updatePosition() {
|
|
214
|
+
if (this.offset === 0) {
|
|
215
|
+
this.chunkIndex = 0;
|
|
216
|
+
this.chunkOffset = 0;
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const { buf, offset } = this.buffers.pos(this.offset);
|
|
221
|
+
this.chunkIndex = buf;
|
|
222
|
+
this.chunkOffset = offset;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Return this cursor's current line number.
|
|
227
|
+
*/
|
|
228
|
+
get line() {
|
|
229
|
+
return this.chunkIndex;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
get lineWidth() {
|
|
233
|
+
return this.buffers.buffers[this.chunkIndex].byteLength;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
get value() {
|
|
237
|
+
return this.buffers.buffers[this.chunkIndex][this.chunkOffset];
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Return the cursor offset in the current line.
|
|
242
|
+
*/
|
|
243
|
+
get lineOffset() {
|
|
244
|
+
return this.chunkOffset;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
*iterator() {
|
|
248
|
+
while (this.chunkIndex < this.buffers.buffers.length) {
|
|
249
|
+
const chunk = this.buffers.buffers[this.chunkIndex];
|
|
250
|
+
const chunkLength = chunk.byteLength;
|
|
251
|
+
|
|
252
|
+
while (this.chunkOffset < chunkLength) {
|
|
253
|
+
const num = chunk[this.chunkOffset];
|
|
254
|
+
this.chunkOffset++;
|
|
255
|
+
this.offset++;
|
|
256
|
+
|
|
257
|
+
yield num;
|
|
258
|
+
}
|
|
259
|
+
this.chunkOffset = 0;
|
|
260
|
+
this.chunkIndex++;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
move(n: number) {
|
|
265
|
+
this.offset += n;
|
|
266
|
+
this.updatePosition();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
moveTo(n: number) {
|
|
270
|
+
this.offset = n;
|
|
271
|
+
this.updatePosition();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
dispose() {
|
|
275
|
+
this.buffers = null as any;
|
|
276
|
+
this.offset = 0;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
reset() {
|
|
280
|
+
this.offset = 0;
|
|
281
|
+
this.chunkIndex = 0;
|
|
282
|
+
this.chunkOffset = 0;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IDisposable } from '@opensumi/ide-core-common';
|
|
2
|
+
|
|
3
|
+
import { IConnectionShape } from '../types';
|
|
4
|
+
|
|
5
|
+
import { createQueue } from './utils';
|
|
6
|
+
|
|
7
|
+
export abstract class BaseConnection<T> implements IConnectionShape<T> {
|
|
8
|
+
abstract send(data: T): void;
|
|
9
|
+
abstract onMessage(cb: (data: T) => void): IDisposable;
|
|
10
|
+
abstract onceClose(cb: () => void): IDisposable;
|
|
11
|
+
|
|
12
|
+
createQueue(): IConnectionShape<T> {
|
|
13
|
+
return createQueue(this);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IDisposable } from '@opensumi/ide-core-common';
|
|
2
|
+
|
|
3
|
+
import { BaseConnection } from './base';
|
|
4
|
+
|
|
5
|
+
export class EmptyConnection extends BaseConnection<Uint8Array> {
|
|
6
|
+
send(data: Uint8Array): void {
|
|
7
|
+
// do nothing
|
|
8
|
+
}
|
|
9
|
+
onMessage(cb: (data: Uint8Array) => void): IDisposable {
|
|
10
|
+
return {
|
|
11
|
+
dispose: () => {},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
onceClose(cb: () => void): IDisposable {
|
|
15
|
+
return {
|
|
16
|
+
dispose: () => {},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MessagePort } from 'worker_threads';
|
|
2
|
+
|
|
3
|
+
import { IDisposable } from '@opensumi/ide-core-common';
|
|
4
|
+
|
|
5
|
+
import { BaseConnection } from './base';
|
|
6
|
+
|
|
7
|
+
export class NodeMessagePortConnection extends BaseConnection<Uint8Array> {
|
|
8
|
+
constructor(private port: MessagePort) {
|
|
9
|
+
super();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
send(data: Uint8Array): void {
|
|
13
|
+
this.port.postMessage(data);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
onMessage(cb: (data: Uint8Array) => void): IDisposable {
|
|
17
|
+
this.port.on('message', cb);
|
|
18
|
+
return {
|
|
19
|
+
dispose: () => {
|
|
20
|
+
this.port.off('message', cb);
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onceClose(cb: () => void): IDisposable {
|
|
26
|
+
this.port.once('close', cb);
|
|
27
|
+
return {
|
|
28
|
+
dispose: () => {
|
|
29
|
+
this.port.off('close', cb);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import ReconnectingWebSocket, { Options as ReconnectingWebSocketOptions, UrlProvider } from 'reconnecting-websocket';
|
|
2
|
+
import type { ErrorEvent } from 'reconnecting-websocket';
|
|
3
|
+
|
|
4
|
+
import { IDisposable } from '@opensumi/ide-core-common';
|
|
5
|
+
|
|
6
|
+
import { BaseConnection } from './base';
|
|
7
|
+
|
|
8
|
+
export class ReconnectingWebSocketConnection extends BaseConnection<Uint8Array> {
|
|
9
|
+
constructor(private socket: ReconnectingWebSocket) {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
send(data: Uint8Array): void {
|
|
14
|
+
this.socket.send(data);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
isOpen(): boolean {
|
|
18
|
+
return this.socket.readyState === this.socket.OPEN;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
onOpen(cb: () => void): IDisposable {
|
|
22
|
+
this.socket.addEventListener('open', cb);
|
|
23
|
+
return {
|
|
24
|
+
dispose: () => {
|
|
25
|
+
this.socket.removeEventListener('open', cb);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onMessage(cb: (data: Uint8Array) => void): IDisposable {
|
|
31
|
+
const handler = (e: MessageEvent) => {
|
|
32
|
+
let buffer: Promise<ArrayBuffer>;
|
|
33
|
+
if (e.data instanceof Blob) {
|
|
34
|
+
buffer = e.data.arrayBuffer();
|
|
35
|
+
} else if (e.data instanceof ArrayBuffer) {
|
|
36
|
+
buffer = Promise.resolve(e.data);
|
|
37
|
+
} else if (e.data?.constructor?.name === 'Buffer') {
|
|
38
|
+
// Compatibility with nodejs Buffer in test environment
|
|
39
|
+
buffer = Promise.resolve(e.data);
|
|
40
|
+
} else {
|
|
41
|
+
throw new Error('unknown message type, expect Blob or ArrayBuffer, received: ' + typeof e.data);
|
|
42
|
+
}
|
|
43
|
+
buffer.then((v) => cb(new Uint8Array(v)));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
this.socket.addEventListener('message', handler);
|
|
47
|
+
return {
|
|
48
|
+
dispose: () => {
|
|
49
|
+
this.socket.removeEventListener('message', handler);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
onceClose(cb: (code?: number, reason?: string) => void): IDisposable {
|
|
54
|
+
const handler = (e: CloseEvent) => {
|
|
55
|
+
cb(e.code, e.reason);
|
|
56
|
+
this.socket.removeEventListener('close', handler);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
this.socket.addEventListener('close', handler);
|
|
60
|
+
return {
|
|
61
|
+
dispose: () => {
|
|
62
|
+
this.socket.removeEventListener('close', handler);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
onError(cb: (e: Error) => void): IDisposable {
|
|
67
|
+
const handler = (e: ErrorEvent) => {
|
|
68
|
+
cb(e.error);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
this.socket.addEventListener('error', handler);
|
|
72
|
+
return {
|
|
73
|
+
dispose: () => {
|
|
74
|
+
this.socket.removeEventListener('error', handler);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static forURL(url: UrlProvider, protocols?: string | string[], options?: ReconnectingWebSocketOptions) {
|
|
80
|
+
const rawConnection = new ReconnectingWebSocket(url, protocols, options);
|
|
81
|
+
rawConnection.binaryType = 'arraybuffer';
|
|
82
|
+
const connection = new ReconnectingWebSocketConnection(rawConnection);
|
|
83
|
+
|
|
84
|
+
return connection;
|
|
85
|
+
}
|
|
86
|
+
}
|