Repository navigation
fix(captcha): 墓碑到期后留惰性存根,不再硬删全局 - #44
Merged
TriDefender merged 1 commit intoSep 6, 2026
Merged
Conversation
5fcb778 给 window 类全局加了 30 秒宽限期,让滞留的 FeiLin 指纹回调能平稳落地 (feilin005.js 的 "Text is not defined")。但宽限期结束时仍然是 delete,所以 它推迟了崩溃而没有消除崩溃:活得比 30 秒更久的残留回调照样把一次全局读取变成 uncaughtException。 FeiLin 的心跳恰好属于这一类。tE 每 2 秒重新武装自己一次 (feilin008.js:170382 `tV=setInterval(tE,2e3)`),函数体里读 `moveBy` (:169658 `Math.pow(!navigator*!moveBy,0)`)。宽限期过后这一读就是致命的: ReferenceError: moveBy is not defined at tE (https://g.alicdn.com/…/feilin008….js:1:169658) 改为不 delete,而是留下惰性值:EXTRA_WINDOW_PROPS 里的窗口方法 (moveBy/scrollTo/…)留一个 no-op —— 真实浏览器里它们本来也几乎是 no-op; 其余名字留 undefined。引用得以解析,调用无害完成,且存根不指向已关闭的窗口, 不会把它钉在 globalThis 上。 验证:让一个不朽心跳持续读 moveBy 跨越宽限期,改动前每次触发都产生一条 uncaughtException,改动后为 0。
TriDefender
approved these changes
Sep 6, 2026
TriDefender
left a comment
Owner
There was a problem hiding this comment.
已验证并合入:CI 绿 + 本地 worktree 复跑 tsc 0 错 / 733 pass(与声明一致)。存根不指向已关闭窗口、不把 closed window 钉在 globalThis 上,实现干净。注意:#46 的分支已逐字节包含本改动(INERT_WINDOW_METHODS + removeGlobalWindowAlias 的 stub 逻辑完全一致),两者谁先合入都不会冲突。
非阻塞 follow-up:INERT_WINDOW_METHODS 的注释说自己是 EXTRA_WINDOW_PROPS 的 "Subset",实际是全集;另外 undefined 存根对构造器类名(如 straggler 调 new Text())仍会 TypeError——只是从 ReferenceError 换了形态,#43 的分类器会兜底,记录在案即可。
LX2000WASD
added a commit
to LX2000WASD/zcode-api
that referenced
this pull request
Sep 6, 2026
审阅指出这段文档写的是一个被推翻的中间方案——"Wrapping in an arrow-bodied
IIFE that RETURNS the inner expression"——而实现返回的是裸
`with(scope){…}` 语句,两者矛盾。
真实机制:`with` 是语句而非表达式,`eval` 返回它的块完成值,而块以最后一个
表达式语句完成,因此编译器交来的 `(function anonymous($happy_dom){…})`
原样流出,无需任何 IIFE 包装。(声明不产生完成值,所以以声明结尾的脚本同样
安全,沿用前一个表达式的值。)
注释同时保留选择 `with` 而非函数包装的另一半理由:`with` 引入的是对象环境
而非变量环境,guest 的顶层 var/function 声明得以继续外泄到全局对象。
顺带删除一处 rebase 到已合并的 TriDefender#44 之上时产生的 INERT_WINDOW_METHODS 重复
声明(tsc 不报此错,但运行时解析失败:"has already been declared")。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
v4.5.5 TUI 模式下反复崩溃(实际使用中间隔 2m47s / 14m37s / 27m15s / 29m15s):
崩溃链条:
tE是个 2 秒心跳,会自我重新武装(feilin008.js:170382tV=setInterval(tE,2e3))happyDOM.close()收不走 → 不朽定时器delete掉moveBy,心跳下次触发即ReferenceErroruncaughtException处理器对一切exit(1)→ 代理进程死亡本 PR 切断第 3 环,与其余三个 PR 互不依赖,可单独合入。
问题
5fcb778 给 window 类全局加了 30 秒宽限期,让滞留的 FeiLin 指纹回调能平稳落地(feilin005.js 的
Text is not defined)。方向是对的。但宽限期结束时仍然是
delete,所以它推迟了崩溃而没有消除崩溃:活得比 30 秒更久的残留回调,照样把一次全局读取变成uncaughtException。FeiLin 的心跳恰好属于这一类 —— 它每 2 秒重新武装自己,函数体里读
moveBy:只要这个心跳还活着,宽限期一到就是必然崩溃,只是把时刻从「拆解瞬间」推到了「拆解后 30 秒」。这与现场观测到的崩溃间隔分布一致。
改动
不再
delete,而是留下惰性值:EXTRA_WINDOW_PROPS里的窗口方法(moveBy/scrollTo/…)留一个 no-op —— 真实浏览器里它们本来也几乎是 no-opundefined引用得以解析,调用无害完成。存根不指向已关闭的窗口,因此不会把它钉在
globalThis上。验证
让一个不朽心跳持续读
moveBy跨越宽限期:uncaughtException最坏情况下的直接调用也已确认无害:
bun x tsc --noEmit0 错误bun test733 pass / 0 fail(上游基线 732,本 PR 新增 1 条回归测试)