ipc.ts ×43

Frontier kind: Code frontier

unlabeled · c_87461a3b2016

20 tests · 8496 LOC · 37 files · introduces 0 tests · 236 LOC · 3 files

Introduces — evidence that enters the hierarchy at this concept

Code
45 ranges236 lines · 3 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1284 ranges8496 lines · 37 files · Browse complete extent
All tests (intent)
20 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

3 files ranked by introduced lines: 236 introduced LOC across 45 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/base/parts/ipc/common/ipc.ts 233 introduced LOC · 43 ranges

Open complete file

170 * @see https://en.wikipedia.org/wiki/Variable-length_quantity
171 */
172 > function readIntVQL(reader: IReader) { ipc.ts
173 > let value = 0;
174 > for (let n = 0; ; n += 7) {
175 > const next = reader.read(1);
176 > value |= (next.buffer[0] & 0b01111111) << n;
177 > if (!(next.buffer[0] & 0b10000000)) {
178 > return value;
179 > }
180 > }
181 }
182
186 * @see https://en.wikipedia.org/wiki/Variable-length_quantity
187 */
188 > function writeInt32VQL(writer: IWriter, value: number) { ipc.ts
189 > if (value === 0) {
190 writer.write(vqlZero);
191 return;
192 }
193 > ipc.ts
194 > let len = 0;
195 > for (let v2 = value; v2 !== 0; v2 = v2 >>> 7) {
196 > len++;
197 > }
198 >
199 > const scratch = VSBuffer.alloc(len);
200 > for (let i = 0; value !== 0; i++) {
201 > scratch.buffer[i] = value & 0b01111111;
202 > value = value >>> 7;
203 > if (value > 0) {
204 > scratch.buffer[i] |= 0b10000000;
205 > }
206 > }
207 >
208 > writer.write(scratch);
209 > }
210
211 export class BufferReader implements IReader {
216
217 read(bytes: number): VSBuffer {
218 > const result = this.buffer.slice(this.pos, this.pos + bytes); ipc.ts
219 > this.pos += result.byteLength;
220 > return result;
221 > }
222 }
223
224 export class BufferWriter implements IWriter, IDisposable {
225 > ipc.ts
226 > private buffers: VSBuffer[] = [];
227
228 get buffer(): VSBuffer {
229 > return VSBuffer.concat(this.buffers); ipc.ts
230 > }
231
232 write(buffer: VSBuffer): void {
233 > this.buffers.push(buffer); ipc.ts
234 > }
235
236 dispose(): void {
237 > // Release the buffers so a thrown serialization error's stack can't pin them. ipc.ts
238 > this.buffers.length = 0;
239 > }
240 }
241
267
268 export function serialize(writer: IWriter, data: any): void {
269 > if (typeof data === 'undefined') { ipc.ts
270 > writer.write(BufferPresets.Undefined);
271 > } else if (typeof data === 'string') {
272 > const buffer = VSBuffer.fromString(data);
273 > writer.write(BufferPresets.String);
274 > writeInt32VQL(writer, buffer.byteLength);
275 > writer.write(buffer);
276 > } else if (VSBuffer.isNativeBuffer(data)) {
277 const buffer = VSBuffer.wrap(data);
278 writer.write(BufferPresets.Buffer);
279 writeInt32VQL(writer, buffer.byteLength);
280 writer.write(buffer);
281 > } else if (data instanceof VSBuffer) { ipc.ts
282 writer.write(BufferPresets.VSBuffer);
283 writeInt32VQL(writer, data.byteLength);
284 writer.write(data);
285 > } else if (Array.isArray(data)) { ipc.ts
286 > writer.write(BufferPresets.Array);
287 > writeInt32VQL(writer, data.length);
288 >
289 > for (const el of data) {
290 > serialize(writer, el);
291 > }
292 > } else if (typeof data === 'number' && (data | 0) === data) {
293 > // write a vql if it's a number that we can do bitwise operations on
294 > writer.write(BufferPresets.Uint);
295 > writeInt32VQL(writer, data);
296 > } else {
297 const buffer = VSBuffer.fromString(JSON.stringify(data));
298 writer.write(BufferPresets.Object);
300 writer.write(buffer);
301 }
302 > } ipc.ts
303
304 export function deserialize(reader: IReader): any {
305 > const type = reader.read(1).readUInt8(0); ipc.ts
306 >
307 > switch (type) {
308 > case DataType.Undefined: return undefined;
309 > case DataType.String: return reader.read(readIntVQL(reader)).toString();
310 > case DataType.Buffer: return reader.read(readIntVQL(reader)).buffer;
311 > case DataType.VSBuffer: return reader.read(readIntVQL(reader));
312 > case DataType.Array: {
313 > const length = readIntVQL(reader);
314 > const result: any[] = [];
315 >
316 > for (let i = 0; i < length; i++) {
317 > result.push(deserialize(reader));
318 > }
319 >
320 > return result;
321 > }
322 > case DataType.Object: return JSON.parse(reader.read(readIntVQL(reader)).toString());
323 > case DataType.Int: return readIntVQL(reader);
324 > }
325 > }
326
327 interface PendingRequest {
341
342 constructor(private protocol: IMessagePassingProtocol, private ctx: TContext, private logger: IIPCLogger | null = null, private timeoutDelay = 1000) {
343 > this.protocolListener = this.protocol.onMessage(msg => this.onRawMessage(msg)); ipc.ts
344 > this.sendResponse({ type: ResponseType.Initialize });
345 > }
346
347 registerChannel(channelName: string, channel: IServerChannel<TContext>): void {
348 > this.channels.set(channelName, channel); ipc.ts
349 >
350 > // https://github.com/microsoft/vscode/issues/72531
351 > setTimeout(() => this.flushPendingRequests(channelName), 0);
352 > }
353
354 private sendResponse(response: IRawResponse): void {
355 > switch (response.type) { ipc.ts
356 > case ResponseType.Initialize: {
357 > const msgLength = this.send([response.type]);
358 > this.logger?.logOutgoing(msgLength, 0, RequestInitiator.OtherSide, responseTypeToStr(response.type));
359 > return;
360 > }
361 >
362 > case ResponseType.PromiseSuccess:
363 > case ResponseType.PromiseError:
364 > case ResponseType.EventFire:
365 > case ResponseType.PromiseErrorObj: {
366 const msgLength = this.send([response.type, response.id], response.data);
367 this.logger?.logOutgoing(msgLength, response.id, RequestInitiator.OtherSide, responseTypeToStr(response.type), response.data);
368 return;
369 }
370 > } ipc.ts
371 > }
372
373 private send(header: unknown, body: any = undefined): number {
374 > const writer = new BufferWriter(); ipc.ts
375 > try {
376 > serialize(writer, header);
377 > serialize(writer, body);
378 > return this.sendBuffer(writer.buffer);
379 > } finally {
380 > writer.dispose();
381 > }
382 > }
383
384 private sendBuffer(message: VSBuffer): number {
385 > try { ipc.ts
386 > this.protocol.send(message);
387 > return message.byteLength;
388 > } catch (err) {
389 // noop
390 return 0;
391 }
392 > } ipc.ts
393
394 private onRawMessage(message: VSBuffer): void {
395 > const reader = new BufferReader(message); ipc.ts
396 > const header = deserialize(reader);
397 > const body = deserialize(reader);
398 > const type = header[0] as RequestType;
399 >
400 > switch (type) {
401 > case RequestType.Promise:
402 this.logger?.logIncoming(message.byteLength, header[1], RequestInitiator.OtherSide, `${requestTypeToStr(type)}: ${header[2]}.${header[3]}`, body);
403 return this.onPromise({ type, id: header[1], channelName: header[2], name: header[3], arg: body });
404 > case RequestType.EventListen: ipc.ts
405 this.logger?.logIncoming(message.byteLength, header[1], RequestInitiator.OtherSide, `${requestTypeToStr(type)}: ${header[2]}.${header[3]}`, body);
406 return this.onEventListen({ type, id: header[1], channelName: header[2], name: header[3], arg: body });
407 > case RequestType.PromiseCancel: ipc.ts
408 this.logger?.logIncoming(message.byteLength, header[1], RequestInitiator.OtherSide, `${requestTypeToStr(type)}`);
409 return this.disposeActiveRequest({ type, id: header[1] });
410 > case RequestType.EventDispose: ipc.ts
411 this.logger?.logIncoming(message.byteLength, header[1], RequestInitiator.OtherSide, `${requestTypeToStr(type)}`);
412 return this.disposeActiveRequest({ type, id: header[1] });
413 > } ipc.ts
414 > }
415
416 private onPromise(request: IRawPromiseRequest): void {
504
505 private flushPendingRequests(channelName: string): void {
506 > const requests = this.pendingRequests.get(channelName); ipc.ts
507 >
508 > if (requests) {
509 for (const request of requests) {
510 clearTimeout(request.timeoutTimer);
518 this.pendingRequests.delete(channelName);
519 }
520 > } ipc.ts
521
522 public dispose(): void {
523 > if (this.protocolListener) { ipc.ts
524 > this.protocolListener.dispose();
525 > this.protocolListener = null;
526 > }
527 > dispose(this.activeRequests.values());
528 > this.activeRequests.clear();
529 > }
530 }
531
554
555 constructor(private protocol: IMessagePassingProtocol, logger: IIPCLogger | null = null) {
556 > this.protocolListener = this.protocol.onMessage(msg => this.onBuffer(msg)); ipc.ts
557 > this.logger = logger;
558 > }
559
560 getChannel<T extends IChannel>(channelName: string): T {
561 > const that = this; ipc.ts
562 >
563 > // eslint-disable-next-line local/code-no-dangerous-type-assertions
564 > return {
565 > call(command: string, arg?: any, cancellationToken?: CancellationToken) {
566 if (that.isDisposed) {
567 return Promise.reject(new CancellationError());
569 return that.requestPromise(channelName, command, arg, cancellationToken);
570 },
571 > listen(event: string, arg: any) { ipc.ts
572 if (that.isDisposed) {
573 return Event.None;
575 return that.requestEvent(channelName, event, arg);
576 }
577 > } as T; ipc.ts
578 > }
579
580 private requestPromise(channelName: string, name: string, arg?: any, cancellationToken = CancellationToken.None): Promise<unknown> {
752
753 private onBuffer(message: VSBuffer): void {
754 > const reader = new BufferReader(message); ipc.ts
755 > const header = deserialize(reader);
756 > const body = deserialize(reader);
757 > const type: ResponseType = header[0];
758 >
759 > switch (type) {
760 > case ResponseType.Initialize:
761 > this.logger?.logIncoming(message.byteLength, 0, RequestInitiator.LocalSide, responseTypeToStr(type));
762 > return this.onResponse({ type: header[0] });
763 >
764 > case ResponseType.PromiseSuccess:
765 > case ResponseType.PromiseError:
766 > case ResponseType.EventFire:
767 > case ResponseType.PromiseErrorObj:
768 this.logger?.logIncoming(message.byteLength, header[1], RequestInitiator.LocalSide, responseTypeToStr(type), body);
769 return this.onResponse({ type: header[0], id: header[1], data: body });
770 > } ipc.ts
771 > }
772
773 private onResponse(response: IRawResponse): void {
774 > if (response.type === ResponseType.Initialize) { ipc.ts
775 > this.state = State.Idle;
776 > this._onDidInitialize.fire();
777 > return;
778 > }
779
780 const handler = this.handlers.get(response.id);
781
782 handler?.(response);
783 > } ipc.ts
784
785 @memoize
797
798 dispose(): void {
799 > this.isDisposed = true; ipc.ts
800 > if (this.protocolListener) {
801 > this.protocolListener.dispose();
802 > this.protocolListener = null;
803 > }
804 > dispose(this.activeRequests.values());
805 > this.activeRequests.clear();
806 > this._onDidInitialize.dispose();
807 > }
808 }
809
846
847 constructor(onDidClientConnect: Event<ClientConnectionEvent>, ipcLogger?: IIPCLogger | null, timeoutDelay?: number) {
848 > this.disposables.add(onDidClientConnect(({ protocol, onDidClientDisconnect }) => { ipc.ts
849 > const onFirstMessage = Event.once(protocol.onMessage);
850 >
851 > const connectionDisposables = new DisposableStore();
852 >
853 > const onFirstMessageDisposable = onFirstMessage(msg => {
854 > const reader = new BufferReader(msg);
855 > const ctx = deserialize(reader) as TContext;
856 >
857 > const channelServer = new ChannelServer(protocol, ctx, ipcLogger, timeoutDelay);
858 > const channelClient = new ChannelClient(protocol, ipcLogger);
859 >
860 > this.channels.forEach((channel, name) => channelServer.registerChannel(name, channel));
861 >
862 > const connection: Connection<TContext> = { channelServer, channelClient, ctx };
863 > this._connections.add(connection);
864 > this._onDidAddConnection.fire(connection);
865 >
866 > connectionDisposables.add(onDidClientDisconnect(() => {
867 channelServer.dispose();
868 channelClient.dispose();
871 this.disposables.delete(connectionDisposables);
872 connectionDisposables.dispose();
873 > })); ipc.ts
874 > });
875 >
876 > connectionDisposables.add(onFirstMessageDisposable);
877 > this.disposables.add(connectionDisposables);
878 > }));
879 > }
880
881 /**
992
993 dispose(): void {
994 > this.disposables.dispose(); ipc.ts
995 >
996 > for (const connection of this._connections) {
997 connection.channelClient.dispose();
998 connection.channelServer.dispose();
999 }
1000 > ipc.ts
1001 > this._connections.clear();
1002 > this.channels.clear();
1003 > this._onDidAddConnection.dispose();
1004 > this._onDidRemoveConnection.dispose();
1005 > }
1006 }
1007
1019
1020 constructor(protocol: IMessagePassingProtocol, ctx: TContext, ipcLogger: IIPCLogger | null = null) {
1021 > const writer = new BufferWriter(); ipc.ts
1022 > try {
1023 > serialize(writer, ctx);
1024 > protocol.send(writer.buffer);
1025 > } finally {
1026 > writer.dispose();
1027 > }
1028 >
1029 > this.channelClient = new ChannelClient(protocol, ipcLogger);
1030 > this.channelServer = new ChannelServer(protocol, ctx, ipcLogger);
1031 > }
1032
1033 getChannel<T extends IChannel>(channelName: string): T {
1040
1041 dispose(): void {
1042 > this.channelClient.dispose(); ipc.ts
1043 > this.channelServer.dispose();
1044 > }
1045 }
1046
src/vs/base/common/buffer.ts 2 introduced LOC · 1 range

Open complete file

102
103 static isNativeBuffer(buffer: unknown): boolean {
104 > return hasBuffer && Buffer.isBuffer(buffer); buffer.ts
105 > }
106
107 readonly buffer: Uint8Array;
src/vs/base/common/event.ts 1 introduced LOC · 1 range

Open complete file

101 result = event(e => {
102 if (didFire) {
103 > return; event.ts
104 } else if (result) {
105 result.dispose();