mirror of
https://github.com/coder/code-server.git
synced 2026-05-11 06:47:25 +02:00
Refactor evaluations (#285)
* Replace evaluations with proxies and messages * Return proxies synchronously Otherwise events can be lost. * Ensure events cannot be missed * Refactor remaining fills * Use more up-to-date version of util For callbackify. * Wait for dispose to come back before removing This prevents issues with the "done" event not always being the last event fired. For example a socket might close and then end, but only if the caller called end. * Remove old node-pty tests * Fix emitting events twice on duplex streams * Preserve environment when spawning processes * Throw a better error if the proxy doesn't exist * Remove rimraf dependency from ide * Update net.Server.listening * Use exit event instead of killed Doesn't look like killed is even a thing. * Add response timeout to server * Fix trash * Require node-pty & spdlog after they get unpackaged This fixes an error when running in the binary. * Fix errors in down emitter preventing reconnecting * Fix disposing proxies when nothing listens to "error" event * Refactor event tests to use jest.fn() * Reject proxy call when disconnected Otherwise it'll wait for the timeout which is a waste of time since we already know the connection is dead. * Use nbin for binary packaging * Remove additional module requires * Attempt to remove require for local bootstrap-fork * Externalize fsevents
This commit is contained in:
107
packages/protocol/src/node/modules/stream.ts
Normal file
107
packages/protocol/src/node/modules/stream.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import * as stream from "stream";
|
||||
import { ServerProxy } from "../../common/proxy";
|
||||
|
||||
export class WritableProxy<T extends stream.Writable = stream.Writable> implements ServerProxy {
|
||||
public constructor(protected readonly stream: T) {}
|
||||
|
||||
public async destroy(): Promise<void> {
|
||||
this.stream.destroy();
|
||||
}
|
||||
|
||||
// tslint:disable-next-line no-any
|
||||
public async end(data?: any, encoding?: string): Promise<void> {
|
||||
return new Promise((resolve): void => {
|
||||
this.stream.end(data, encoding, () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async setDefaultEncoding(encoding: string): Promise<void> {
|
||||
this.stream.setDefaultEncoding(encoding);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line no-any
|
||||
public async write(data: any, encoding?: string): Promise<void> {
|
||||
return new Promise((resolve, reject): void => {
|
||||
this.stream.write(data, encoding, (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async dispose(): Promise<void> {
|
||||
this.stream.end();
|
||||
this.stream.removeAllListeners();
|
||||
}
|
||||
|
||||
public async onDone(cb: () => void): Promise<void> {
|
||||
this.stream.on("close", cb);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line no-any
|
||||
public async onEvent(cb: (event: string, ...args: any[]) => void): Promise<void> {
|
||||
// Sockets have an extra argument on "close".
|
||||
// tslint:disable-next-line no-any
|
||||
this.stream.on("close", (...args: any[]) => cb("close", ...args));
|
||||
this.stream.on("drain", () => cb("drain"));
|
||||
this.stream.on("error", (error) => cb("error", error));
|
||||
this.stream.on("finish", () => cb("finish"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This noise is because we can't do multiple extends and we also can't seem to
|
||||
* do `extends WritableProxy<T> implement ReadableProxy<T>` (for `DuplexProxy`).
|
||||
*/
|
||||
export interface IReadableProxy extends ServerProxy {
|
||||
destroy(): Promise<void>;
|
||||
setEncoding(encoding: string): Promise<void>;
|
||||
dispose(): Promise<void>;
|
||||
onDone(cb: () => void): Promise<void>;
|
||||
}
|
||||
|
||||
export class ReadableProxy<T extends stream.Readable = stream.Readable> implements IReadableProxy {
|
||||
public constructor(protected readonly stream: T) {}
|
||||
|
||||
public async destroy(): Promise<void> {
|
||||
this.stream.destroy();
|
||||
}
|
||||
|
||||
public async setEncoding(encoding: string): Promise<void> {
|
||||
this.stream.setEncoding(encoding);
|
||||
}
|
||||
|
||||
public async dispose(): Promise<void> {
|
||||
this.stream.destroy();
|
||||
}
|
||||
|
||||
public async onDone(cb: () => void): Promise<void> {
|
||||
this.stream.on("close", cb);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line no-any
|
||||
public async onEvent(cb: (event: string, ...args: any[]) => void): Promise<void> {
|
||||
this.stream.on("close", () => cb("close"));
|
||||
this.stream.on("data", (chunk) => cb("data", chunk));
|
||||
this.stream.on("end", () => cb("end"));
|
||||
this.stream.on("error", (error) => cb("error", error));
|
||||
}
|
||||
}
|
||||
|
||||
export class DuplexProxy<T extends stream.Duplex = stream.Duplex> extends WritableProxy<T> implements IReadableProxy {
|
||||
public async setEncoding(encoding: string): Promise<void> {
|
||||
this.stream.setEncoding(encoding);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line no-any
|
||||
public async onEvent(cb: (event: string, ...args: any[]) => void): Promise<void> {
|
||||
super.onEvent(cb);
|
||||
this.stream.on("data", (chunk) => cb("data", chunk));
|
||||
this.stream.on("end", () => cb("end"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user