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

1.9 KiB
Raw Permalink Blame History

异步 Browser Script 支持设计

问题

collect_lineloss.jsbuildBrowserEntrypointResult 是 async 函数,但 build_eval_js 生成的执行代码是同步的,导致 Promise 被 JSON.stringify 序列化为 {}

日志表现

[execute_browser_script_impl]   返回成功, payload 长度: 4

返回 {}(4字符) 而不是实际的报表数据。

根本原因

callback_backend.rsbuild_eval_js 函数:

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.rsbuild_eval_js 函数:

(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 脚本本身