# 异步 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 脚本本身