Files
desktop-plugin/test/pavo_isolate_test.dart
dzc e00086c01c fix: Pavo 后端 isolate 闭包捕获实例链导致 Windows 状态查询必炸(unsendable)
用户 Windows 实测:未装驱动点跳过后页面报"状态读取失败 Illegal argument in
isolate message: object is unsendable - _Timer"。堆栈定位:

Isolate.run(_statusSync) 的方法 tear-off 会连带 this(PavoPrintBackend)→
_log(agent.log.write tear-off)→ AgentLog → StreamController → UI 日志订阅链
→ 向导轮询 Timer——Timer 不可跨 isolate 发送,消息序列化直接抛错。mac 上
CUPS 后端不走 Isolate.run,从未暴露。

修复:isolate 入口全部改为顶层函数(pavoStatusSync / pavoPrintSync),不捕获
任何实例状态;printOneCard 先解出纯字符串(data URL/份数)再进闭包,最小化
捕获面。新增守护测试 pavo_isolate_test:在活跃日志订阅下调 getStatus,
回归捕获 this 时会立即复现 unsendable。14 测试全过、analyze 零问题。
2026-09-21 16:15:27 +08:00

30 lines
1.3 KiB
Dart
Raw Permalink 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.
import 'package:desktop_plugin/agent.dart';
import 'package:desktop_plugin/print/pavo/pavo_backend.dart';
import 'package:flutter_test/flutter_test.dart';
/// 守护:Pavo 后端的 isolate 闭包不得捕获实例状态。
///
/// 曾经的 bug:Isolate.run(_statusSync) 的方法 tear-off 经 this._log →
/// AgentLog → StreamController → UI 订阅链一路拽到 Timer(unsendable),
/// isolate 消息序列化直接抛 "Illegal argument in isolate message"。
/// Windows 真实 App(UI 监听日志流)必炸;本测试在有活跃日志订阅的环境下调
/// getStatus,若回归捕获 this 会立刻复现 unsendable。
void main() {
test('PavoPrintBackend.getStatus 在活跃日志订阅下 isolate 闭包可发送', () async {
final agent = Agent(AgentOptions(mock: true, port: 38296));
await agent.start();
final sub = agent.log.stream.listen((_) {});
addTearDown(() async {
await sub.cancel();
await agent.stop();
});
final backend = PavoPrintBackend(onLog: agent.log.write);
// mac 上无 PavoApiW_x64.dll:期望走 offline 分支(DLL 加载失败被内部
// catch 转友好文案),而绝不是抛 "unsendable" isolate 消息错误
final status = await backend.getStatus();
expect(status.online, isFalse);
expect(status.statusText, isNot(contains('unsendable')));
});
}