@hyzyn/dsh-tty 0.20.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +112 -1
- package/lib/index.js +233 -11
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/screen-crash-repro.mjs +62 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyzyn/dsh-tty",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "DSH Web GUI 的终端面板插件:侧边栏「终端」大弹窗,xterm.js + PTY 全交互终端(路线1),ssh2 原生 SSH 远程连接(方案 C),tmux 会话持久化(0.10.0),连接栏扩展点 ttyConnbar(0.13.0)、终端服务 ttyTerminal(0.14.0 open / 0.15.0 mount 就地嵌入)、面板内挂载位 ttyPanel(0.16.0 右侧 dock)、服务器状态条(0.17.0:按标签可见性采端主机 CPU / 内存 / 磁盘 / 在线时长 / TCP / 网速 / 温度,SSH 走同连接的非 PTY exec channel、本地走 os/proc,best-effort、不碰 PTY 流)、连接密码存入官方凭据存储(0.18.0:字段里只留 env: 引用、引用名按资源身份派生、候选来自凭据存储 ∪ 连接簿;设置卡片的连接编辑与连接对话框共用同一套表单)、Windows 宿主支持(0.18.1:默认 shell = %COMSPEC%、不做 POSIX 包装层、PowerShell 走 -NoLogo/-Command;shell 集成 / tmux / 状态条三项在 Windows 本地不适用,README 有完整边界)。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 复现:`@xterm/headless` 在「`scrollback: 0`(= D57 修复前 dsh-tty 虚拟屏的构造参数)
|
|
3
|
+
* + 输出与 resize 交错」下抛出未捕获 TypeError,**杀掉整个 Node 宿主进程**。
|
|
4
|
+
*
|
|
5
|
+
* TypeError: Cannot set properties of undefined (setting 'isWrapped')
|
|
6
|
+
* at E.lineFeed (.../@xterm/headless/lib-headless/xterm-headless.js:1:28221)
|
|
7
|
+
* at c.parse … at n._action … at n._innerWrite … at Timeout._onTimeout
|
|
8
|
+
*
|
|
9
|
+
* 与线上 `~/.dsh/dsh-safe/last-failure-web.log` 里那次宿主崩溃的堆栈逐帧一致。
|
|
10
|
+
*
|
|
11
|
+
* 运行(`packages/tty` 下):
|
|
12
|
+
* node scripts/screen-crash-repro.mjs # 用本包解析到的 @xterm/headless
|
|
13
|
+
* node scripts/screen-crash-repro.mjs <另一个 headless.js> # 换版本对比(如 6.0.0,仍然崩)
|
|
14
|
+
*
|
|
15
|
+
* 期望输出:`exit=1` + 上面那段堆栈(进程被未捕获异常打死)。
|
|
16
|
+
* 若打印 `no uncaught exception`,说明该版本已修 —— 这时该复核 SCREEN_SCROLLBACK 这条护栏。
|
|
17
|
+
*
|
|
18
|
+
* 这是**排查用**的一次性脚本;日常回归看 `test/screen-crash.test.ts`(D57)。
|
|
19
|
+
*/
|
|
20
|
+
import { createRequire } from 'node:module'
|
|
21
|
+
import { existsSync } from 'node:fs'
|
|
22
|
+
|
|
23
|
+
const require = createRequire(import.meta.url)
|
|
24
|
+
// 默认用本包依赖解析出来的 @xterm/headless(`packages/tty` 下运行即为本包版本)
|
|
25
|
+
const defaultXterm = require.resolve('@xterm/headless')
|
|
26
|
+
const xtermPath = process.argv[2] ?? defaultXterm
|
|
27
|
+
if (!existsSync(xtermPath)) {
|
|
28
|
+
console.error('xterm headless 不存在:' + xtermPath)
|
|
29
|
+
process.exit(2)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const { Terminal } = require(xtermPath)
|
|
33
|
+
|
|
34
|
+
// 刻意不装 uncaughtException 处理器 —— 与修复前的 dsh-tty / dsh 宿主现状一致,
|
|
35
|
+
// 异常在 setTimeout 回调里逃逸,Node 直接打死进程(正是线上那次的表现)。
|
|
36
|
+
const terminal = new Terminal({ cols: 60, rows: 3, scrollback: 0, allowProposedApi: true })
|
|
37
|
+
const tick = () => new Promise((resolve) => setTimeout(resolve, 0))
|
|
38
|
+
|
|
39
|
+
// D57 的 10 步最小复现序列:输出 → 设滚动区 → 反复 resize(触发 reflow)→ 末尾一个 '\n'
|
|
40
|
+
const ops = [
|
|
41
|
+
['write', 'A'.repeat(300)],
|
|
42
|
+
['write', '\x1b[3;9r'],
|
|
43
|
+
['write', '\r\n'],
|
|
44
|
+
['resize', 70, 40],
|
|
45
|
+
['write', '\r\n'],
|
|
46
|
+
['resize', 33, 5],
|
|
47
|
+
['resize', 118, 8],
|
|
48
|
+
['write', 'A'.repeat(300)],
|
|
49
|
+
['resize', 21, 11],
|
|
50
|
+
['write', '\n'], // ← 崩在这一步:lineFeed 里 lines.get() 返回 undefined
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
for (const op of ops) {
|
|
54
|
+
if (op[0] === 'write') terminal.write(op[1])
|
|
55
|
+
else terminal.resize(op[1], op[2])
|
|
56
|
+
await tick()
|
|
57
|
+
}
|
|
58
|
+
for (let i = 0; i < 5; i++) await tick()
|
|
59
|
+
|
|
60
|
+
// 只有没崩才会走到这里
|
|
61
|
+
console.log('no uncaught exception')
|
|
62
|
+
process.exit(0)
|