Files
claw/docs/superpowers/specs/2026-04-13-async-browser-script-support-design.md
木炎 ce6b3e6749 docs: add async browser script support design
Design for fixing Promise serialization issue in build_eval_js.
Async functions return Promise which gets JSON.stringify'd to "{}".

🤖 Generated with [Qoder][https://qoder.com]
2026-04-13 16:06:41 +08:00

70 lines
1.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 异步 Browser Script 支持设计
## 问题
`collect_lineloss.js``buildBrowserEntrypointResult` 是 async 函数,但 `build_eval_js` 生成的执行代码是同步的,导致 Promise 被 JSON.stringify 序列化为 `{}`
**日志表现**
```
[execute_browser_script_impl] 返回成功, payload 长度: 4
```
返回 `{}(4字符)` 而不是实际的报表数据。
## 根本原因
`callback_backend.rs``build_eval_js` 函数:
```javascript
var v=(function(){return {script}})(); // 同步执行
var t=(typeof v==='string')?v:JSON.stringify(v); // Promise -> "{}"
```
当 script 返回 Promise 时,`JSON.stringify(Promise)` 返回 `{}`
## 解决方案
修改 `build_eval_js` 支持 Promise
1.`await` 等待 script 执行结果
2. 检测结果是否为 Promise如果是则等待 resolve
3. 保持对同步脚本的向后兼容
## 实现细节
修改 `src/browser/callback_backend.rs``build_eval_js` 函数:
```javascript
(async function(){
try {
var v = await (function(){return {script}})();
// 等待 Promise resolve
if (v && typeof v.then === 'function') {
v = await v;
}
var t = (typeof v === 'string') ? v : JSON.stringify(v);
// ... 回调逻辑保持不变
} catch(e) {}
})()
```
关键点:
- 包装整个 IIFE 为 async
-`await` 等待 script 执行
- 检测 Promise-like 对象 (`v.then === 'function'`)
- 向后兼容同步脚本直接返回值async 脚本返回 Promise 后被 await
## 影响范围
- `src/browser/callback_backend.rs`: 修改 `build_eval_js` 函数
- 所有 `browser_script` 类型的 skill 自动支持 async
## 测试验证
1. 运行 `cargo test` 确保现有测试通过
2. 端到端测试 `tq-lineloss-report.collect_lineloss` 返回实际数据而非 `{}`
3. 验证同步脚本(如知乎热榜)仍然正常工作
## 不在范围内
- 不修改 `wrap_browser_script`(方案 C 的做法)
- 不修改 skill 脚本本身