用户 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 零问题。
30 lines
1.3 KiB
Dart
30 lines
1.3 KiB
Dart
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')));
|
||
});
|
||
}
|