@@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78
1466
1466
+ }
1467
1467
diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts
1468
1468
new file mode 100644
1469
- index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aeebf4bb84c
1469
+ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b3319cc9b
1470
1470
--- /dev/null
1471
1471
+++ b/src/vs/server/node/channel.ts
1472
- @@ -0,0 +1,780 @@
1472
+ @@ -0,0 +1,828 @@
1473
1473
+ import { field, logger } from '@coder/logger';
1474
1474
+ import { Server } from '@coder/node-browser';
1475
1475
+ import * as os from 'os';
@@ -1884,6 +1884,14 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
1884
1884
+ private readonly _onDispose = new Emitter<void>();
1885
1885
+ public get onDispose(): Event<void> { return this._onDispose.event; }
1886
1886
+
1887
+ + // These are replayed when a client reconnects.
1888
+ + private cols: number;
1889
+ + private rows: number;
1890
+ + private replayData: string[] = [];
1891
+ + // This is based on string length and is pretty arbitrary.
1892
+ + private readonly maxReplayData = 10000;
1893
+ + private totalReplayData = 0;
1894
+ +
1887
1895
+ private buffering = false;
1888
1896
+ private readonly _onEvent = new Emitter<terminal.IRemoteTerminalProcessEvent>({
1889
1897
+ // Don't bind to data until something is listening.
@@ -1894,6 +1902,23 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
1894
1902
+ this.bufferer.startBuffering(this.id, this.process.onProcessData);
1895
1903
+ }
1896
1904
+ },
1905
+ +
1906
+ + // Replay stored events.
1907
+ + onFirstListenerDidAdd: () => {
1908
+ + if (this.replayData.length === 0) {
1909
+ + return;
1910
+ + }
1911
+ +
1912
+ + logger.debug('Terminal replaying', field('id', this.id));
1913
+ + this._onEvent.fire({
1914
+ + type: 'replay',
1915
+ + events: [{
1916
+ + cols: this.cols,
1917
+ + rows: this.rows,
1918
+ + data: this.replayData.join(""),
1919
+ + }]
1920
+ + });
1921
+ + }
1897
1922
+ });
1898
1923
+
1899
1924
+ public get onEvent(): Event<terminal.IRemoteTerminalProcessEvent> { return this._onEvent.event; }
@@ -1904,6 +1929,33 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
1904
1929
+ type: 'data',
1905
1930
+ data,
1906
1931
+ });
1932
+ +
1933
+ + this.replayData.push(data);
1934
+ + this.totalReplayData += data.length;
1935
+ +
1936
+ + let overflow = this.totalReplayData - this.maxReplayData;
1937
+ + if (overflow <= 0) {
1938
+ + return;
1939
+ + }
1940
+ +
1941
+ + // Drop events until doing so would put us under budget.
1942
+ + let deleteCount = 0;
1943
+ + for (; deleteCount < this.replayData.length
1944
+ + && this.replayData[deleteCount].length <= overflow; ++deleteCount) {
1945
+ + overflow -= this.replayData[deleteCount].length;
1946
+ + }
1947
+ +
1948
+ + if (deleteCount > 0) {
1949
+ + this.replayData.splice(0, deleteCount);
1950
+ + }
1951
+ +
1952
+ + // Dropping any more events would put us under budget; trim the first event
1953
+ + // instead if still over budget.
1954
+ + if (overflow > 0 && this.replayData.length > 0) {
1955
+ + this.replayData[0] = this.replayData[0].substring(overflow);
1956
+ + }
1957
+ +
1958
+ + this.totalReplayData = this.replayData.reduce((p, c) => p + c.length, 0);
1907
1959
+ });
1908
1960
+
1909
1961
+ public get pid(): number {
@@ -1924,11 +1976,14 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
1924
1976
+ this.workspaceId = args.workspaceId;
1925
1977
+ this.workspaceName = args.workspaceName;
1926
1978
+
1979
+ + this.cols = args.cols;
1980
+ + this.rows = args.rows;
1981
+ +
1927
1982
+ this.process = new TerminalProcess(
1928
1983
+ config,
1929
1984
+ config.cwd,
1930
- + args .cols,
1931
- + args .rows,
1985
+ + this .cols,
1986
+ + this .rows,
1932
1987
+ env,
1933
1988
+ process.env as platform.IProcessEnvironment, // Environment used for `findExecutable`.
1934
1989
+ false, // windowsEnableConpty: boolean,
@@ -1962,10 +2017,6 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
1962
2017
+ this.dispose();
1963
2018
+ });
1964
2019
+
1965
- + // TODO: replay event
1966
- + // type: 'replay';
1967
- + // events: ReplayEntry[];
1968
- +
1969
2020
+ // TODO: exec command event
1970
2021
+ // type: 'execCommand';
1971
2022
+ // reqId: number;
@@ -1977,9 +2028,11 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
1977
2028
+ }
1978
2029
+
1979
2030
+ public dispose() {
2031
+ + logger.debug('Terminal disposing', field('id', this.id));
1980
2032
+ this._onEvent.dispose();
1981
2033
+ this.bufferer.dispose();
1982
2034
+ this.process.dispose();
2035
+ + this.process.shutdown(true);
1983
2036
+ this._onDispose.fire();
1984
2037
+ this._onDispose.dispose();
1985
2038
+ }
@@ -2005,6 +2058,8 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee
2005
2058
+ }
2006
2059
+
2007
2060
+ public resize(cols: number, rows: number): void {
2061
+ + this.cols = cols;
2062
+ + this.rows = rows;
2008
2063
+ return this.process.resize(cols, rows);
2009
2064
+ }
2010
2065
+ }
0 commit comments