From 8f8d046ae868b64b29510d93e33fb4de07d20527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Mon, 30 Sep 2024 12:37:51 +0300 Subject: [PATCH 1/2] feat(runtime): add `terminal.input` for writing to stdin --- packages/runtime/src/utils/terminal.ts | 1 + .../src/webcontainer/terminal-config.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/runtime/src/utils/terminal.ts b/packages/runtime/src/utils/terminal.ts index dc88c1e42..c99b1c84d 100644 --- a/packages/runtime/src/utils/terminal.ts +++ b/packages/runtime/src/utils/terminal.ts @@ -4,6 +4,7 @@ export interface ITerminal { reset: () => void; write: (data: string) => void; + input: (data: string) => void; onData: (cb: (data: string) => void) => void; } diff --git a/packages/runtime/src/webcontainer/terminal-config.ts b/packages/runtime/src/webcontainer/terminal-config.ts index 603258789..ecb6279cc 100644 --- a/packages/runtime/src/webcontainer/terminal-config.ts +++ b/packages/runtime/src/webcontainer/terminal-config.ts @@ -67,6 +67,7 @@ export class TerminalPanel implements ITerminal { private _terminal?: ITerminal; private _process?: WebContainerProcess; private _data: string[] = []; + private _input: string[] = []; private _onData?: (data: string) => void; constructor( @@ -127,9 +128,15 @@ export class TerminalPanel implements ITerminal { this._terminal.reset(); } else { this._data = []; + this._input = []; } } + /** + * Write data to stdout. + * + * @internal + */ write(data: string) { if (this._terminal) { this._terminal.write(data); @@ -138,6 +145,20 @@ export class TerminalPanel implements ITerminal { } } + /** Write data to stdin */ + input(data: string) { + if (this.type !== 'terminal') { + throw new Error('Cannot write data to output-only terminal'); + } + + if (this._terminal) { + this._terminal.input(data); + } else { + this._input.push(data); + } + } + + /** Callback invoked when data is written to stdin */ onData(callback: (data: string) => void) { if (this._terminal) { this._terminal.onData(callback); @@ -170,7 +191,12 @@ export class TerminalPanel implements ITerminal { terminal.write(data); } + for (const data of this._input) { + terminal.input(data); + } + this._data = []; + this._input = []; this._terminal = terminal; if (this._onData) { From 3dc666225f1129bbb4822d459ddf01d32dba17f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Mon, 30 Sep 2024 14:38:43 +0300 Subject: [PATCH 2/2] fix: code review --- .../src/webcontainer/terminal-config.ts | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/packages/runtime/src/webcontainer/terminal-config.ts b/packages/runtime/src/webcontainer/terminal-config.ts index ecb6279cc..cdfb8afa4 100644 --- a/packages/runtime/src/webcontainer/terminal-config.ts +++ b/packages/runtime/src/webcontainer/terminal-config.ts @@ -66,8 +66,7 @@ export class TerminalPanel implements ITerminal { private _terminal?: ITerminal; private _process?: WebContainerProcess; - private _data: string[] = []; - private _input: string[] = []; + private _data: { data: string; type: 'input' | 'echo' }[] = []; private _onData?: (data: string) => void; constructor( @@ -128,24 +127,18 @@ export class TerminalPanel implements ITerminal { this._terminal.reset(); } else { this._data = []; - this._input = []; } } - /** - * Write data to stdout. - * - * @internal - */ + /** @internal*/ write(data: string) { if (this._terminal) { this._terminal.write(data); } else { - this._data.push(data); + this._data.push({ data, type: 'echo' }); } } - /** Write data to stdin */ input(data: string) { if (this.type !== 'terminal') { throw new Error('Cannot write data to output-only terminal'); @@ -154,11 +147,10 @@ export class TerminalPanel implements ITerminal { if (this._terminal) { this._terminal.input(data); } else { - this._input.push(data); + this._data.push({ data, type: 'input' }); } } - /** Callback invoked when data is written to stdin */ onData(callback: (data: string) => void) { if (this._terminal) { this._terminal.onData(callback); @@ -187,16 +179,15 @@ export class TerminalPanel implements ITerminal { * @param terminal The terminal. */ attachTerminal(terminal: ITerminal) { - for (const data of this._data) { - terminal.write(data); - } - - for (const data of this._input) { - terminal.input(data); + for (const { type, data } of this._data) { + if (type === 'echo') { + terminal.write(data); + } else { + terminal.input(data); + } } this._data = []; - this._input = []; this._terminal = terminal; if (this._onData) {