33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import { strictEqual } from 'assert' ;
7- import { Event } from '../../../../../base/common/event.js' ;
6+ import { deepStrictEqual , strictEqual } from 'assert' ;
7+ import { Emitter , Event } from '../../../../../base/common/event.js' ;
88import { Schemas } from '../../../../../base/common/network.js' ;
9+ import { OperatingSystem } from '../../../../../base/common/platform.js' ;
910import { URI } from '../../../../../base/common/uri.js' ;
1011import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js' ;
1112import { IConfigurationService , type IConfigurationChangeEvent } from '../../../../../platform/configuration/common/configuration.js' ;
@@ -51,12 +52,13 @@ class TestTerminalChildProcess implements ITerminalChildProcess {
5152}
5253
5354class TestTerminalInstanceService implements Partial < ITerminalInstanceService > {
55+ readonly ptyHostRestartEmitter = new Emitter < void > ( ) ;
5456 async getBackend ( ) {
5557 return {
5658 onPtyHostExit : Event . None ,
5759 onPtyHostUnresponsive : Event . None ,
5860 onPtyHostResponsive : Event . None ,
59- onPtyHostRestart : Event . None ,
61+ onPtyHostRestart : this . ptyHostRestartEmitter . event ,
6062 onDidMoveWindowInstance : Event . None ,
6163 onDidRequestDetach : Event . None ,
6264 createProcess : (
@@ -77,6 +79,7 @@ class TestTerminalInstanceService implements Partial<ITerminalInstanceService> {
7779
7880suite ( 'Workbench - TerminalProcessManager' , ( ) => {
7981 let manager : TerminalProcessManager ;
82+ let terminalInstanceService : TestTerminalInstanceService ;
8083
8184 const store = ensureNoDisposablesAreLeakedInTestSuite ( ) ;
8285
@@ -96,7 +99,9 @@ suite('Workbench - TerminalProcessManager', () => {
9699 configurationService . onDidChangeConfigurationEmitter . fire ( {
97100 affectsConfiguration : ( ) => true ,
98101 } satisfies Partial < IConfigurationChangeEvent > as unknown as IConfigurationChangeEvent ) ;
99- instantiationService . stub ( ITerminalInstanceService , new TestTerminalInstanceService ( ) ) ;
102+ terminalInstanceService = new TestTerminalInstanceService ( ) ;
103+ store . add ( terminalInstanceService . ptyHostRestartEmitter ) ;
104+ instantiationService . stub ( ITerminalInstanceService , terminalInstanceService ) ;
100105 instantiationService . stub ( ITerminalService , { setNextCommandId : async ( ) => { } } as Partial < ITerminalService > ) ;
101106
102107 manager = store . add ( instantiationService . createInstance ( TerminalProcessManager , 1 , undefined , undefined , undefined ) ) ;
@@ -141,4 +146,39 @@ suite('Workbench - TerminalProcessManager', () => {
141146 } ) ;
142147 } ) ;
143148 } ) ;
149+
150+ suite ( 'pty host restart' , ( ) => {
151+ async function fireRestartAndCaptureData ( os : OperatingSystem , rows : number ) : Promise < string > {
152+ await manager . createProcess ( { } , 80 , rows , false ) ;
153+ manager . os = os ;
154+ let captured : string | undefined ;
155+ store . add ( manager . onProcessData ( e => captured = e . data ) ) ;
156+ terminalInstanceService . ptyHostRestartEmitter . fire ( ) ;
157+ return captured ! ;
158+ }
159+
160+ test ( 'appends viewport-clearing newlines and ESC[H on Windows' , async ( ) => {
161+ const data = await fireRestartAndCaptureData ( OperatingSystem . Windows , 24 ) ;
162+ deepStrictEqual (
163+ { endsWithViewportClear : data . endsWith ( '\r\n' . repeat ( 23 ) + '\x1b[H' ) } ,
164+ { endsWithViewportClear : true }
165+ ) ;
166+ } ) ;
167+
168+ test ( 'does not append viewport-clearing sequence on non-Windows' , async ( ) => {
169+ const data = await fireRestartAndCaptureData ( OperatingSystem . Linux , 24 ) ;
170+ deepStrictEqual (
171+ { containsCursorHome : data . includes ( '\x1b[H' ) } ,
172+ { containsCursorHome : false }
173+ ) ;
174+ } ) ;
175+
176+ test ( 'does not append viewport-clearing sequence on Windows when rows is 0' , async ( ) => {
177+ const data = await fireRestartAndCaptureData ( OperatingSystem . Windows , 0 ) ;
178+ deepStrictEqual (
179+ { containsCursorHome : data . includes ( '\x1b[H' ) } ,
180+ { containsCursorHome : false }
181+ ) ;
182+ } ) ;
183+ } ) ;
144184} ) ;
0 commit comments