(webcontainer: WebContainer, terminal: ITerminal)
| 3 | import { withResolvers } from './promises'; |
| 4 | |
| 5 | export async function newShellProcess(webcontainer: WebContainer, terminal: ITerminal) { |
| 6 | const args: string[] = []; |
| 7 | |
| 8 | // we spawn a JSH process with a fallback cols and rows in case the process is not attached yet to a visible terminal |
| 9 | const process = await webcontainer.spawn('/bin/jsh', ['--osc', ...args], { |
| 10 | terminal: { |
| 11 | cols: terminal.cols ?? 80, |
| 12 | rows: terminal.rows ?? 15, |
| 13 | }, |
| 14 | }); |
| 15 | |
| 16 | const input = process.input.getWriter(); |
| 17 | const output = process.output; |
| 18 | |
| 19 | const jshReady = withResolvers<void>(); |
| 20 | |
| 21 | let isInteractive = false; |
| 22 | |
| 23 | output.pipeTo( |
| 24 | new WritableStream({ |
| 25 | write(data) { |
| 26 | if (!isInteractive) { |
| 27 | const [, osc] = data.match(/\x1b\]654;([^\x07]+)\x07/) || []; |
| 28 | |
| 29 | if (osc === 'interactive') { |
| 30 | // wait until we see the interactive OSC |
| 31 | isInteractive = true; |
| 32 | |
| 33 | jshReady.resolve(); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | terminal.write(data); |
| 38 | }, |
| 39 | }), |
| 40 | ); |
| 41 | |
| 42 | terminal.onData((data) => { |
| 43 | if (isInteractive) { |
| 44 | input.write(data); |
| 45 | } |
| 46 | }); |
| 47 | |
| 48 | await jshReady.promise; |
| 49 | |
| 50 | return process; |
| 51 | } |
no test coverage detected