xtermjs / xterm.js

A terminal for the web
https://xtermjs.org/
MIT License
17.65k stars 1.63k forks source link

The terminal instance cannot be rendered correctly after calling `.open()` for the second time. #4978

Open 1zilc opened 8 months ago

1zilc commented 8 months ago

I am new to using xtermjs. I am not sure whether the terminal instance can call the open() method multiple times. According to the official documentation and https://github.com/xtermjs/xterm.js/issues/1323, I tried it. When I removed the dom and mounted again, and used terminal.open(), xterm did not render after the second open.

Details

Steps to reproduce

Reproduce

  1. Click the toggle button, xterm renders correctly.
  2. Click the toggle button, remove dom
  3. Click the toggle button, mount dom, xterm did not render after the second open

I'm sorry if there's something wrong with my usage

jerch commented 8 months ago

I am not very deep into the browser side of the code, @Tyriar has more insights here. Still I think it is not possible to move an already DOM-attached terminal to another DOM node by calling open again.

@Tyriar Do we need an attach/detach cycling for the DOM hooking? It never came to me before, that someone would want to move an existing terminal to another DOM node, so this might be just a wild idea of limited use. Loosely linked or more generalized to this would be support of a copy ctor like const term2 = new Terminal(term1), where the new terminal could start over in DOM-detached mode, but has inherited all VT-related settings/data. This has some intersections with the serialize addon, so might not be worth either the trouble.

jonmcgill commented 2 weeks ago

+1 to this. I have the same use case in our work application which has multiple kinds of terminals in various drawers that can be opened/closed at will.

Tyriar commented 2 weeks ago

Calling open multiple times was never really supported that well and I think can be a little finicky, but it definitely does work as that's what VS Code does in order to move the terminal around the workbench.

If we can get a repro case without React it will be a lot more clear how to action this.

jonmcgill commented 2 weeks ago

Here's a little codesandbox (no React). The Open button mounts the terminal instance to the DOM and writes a line. The Replace button removes the DOM and replaces it with a new div. Running Open again results in no line being written.

https://codesandbox.io/p/sandbox/fz8kq2?file=%2Fsrc%2Findex.ts

https://github.com/user-attachments/assets/324bf07f-eec8-40c2-99ed-23e6782db565

jonmcgill commented 2 weeks ago

FWIW, my workaround for now has been to register when the terminal mount DOM has been changed and/or removed. If so, I dispose the terminal instance and any addons. The next time that terminal's container mounts, I re-initiate the instances and run open from a fresh terminal instance.

akphi commented 3 hours ago

Just wanted to mention that .open() works fine for xterm@5.3.0