cross-tab-worker-databus 0.21.5 → 0.21.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,19 +2,19 @@
2
2
 
3
3
  # 浏览器基准趋势
4
4
 
5
- > 数据截至 2026-09-22,基于 49 份归档的 `bench-results/browser-*.json` 报告(运行 `pnpm bench:browser` 追加一份;用 `node scripts/bench-trend.mjs` 重新生成本文档)。
5
+ > 数据截至 2026-09-22,基于 54 份归档的 `bench-results/browser-*.json` 报告(运行 `pnpm bench:browser` 追加一份;用 `node scripts/bench-trend.mjs` 重新生成本文档)。
6
6
 
7
7
  发布门禁的对比基线是 `pnpm bench:compare --fail-above-pct 50`:将最新报告与其之前若干报告中同一指标的中位数比较(50% 上限用于吸收共享 runner 的噪声;此前只看"上一份报告"并不稳定,因为页内热路径指标在同一份代码上会在快/慢两档之间来回跳)。本文记录长期趋势:数值为逐指标延迟,越低越好;最后一列是最近 5 份报告内的最优值,而不是历史纪录——页内基准矩阵在 2026 年 9 月初变更过测量语义,更早的报告不可比。
8
8
 
9
9
  <!-- BENCH-TREND:BEGIN (machine-generated table) -->
10
10
  | 指标 | 上次 (ms) | 本次 (ms) | Δ | 近 5 次最优 (ms) |
11
11
  |---|---|---|---|---|
12
- | publish per-message (ms, lower is better) — dedicated | 63.4052 | 51.1936 | -12.21 | 51.1936 |
13
- | publish per-message (ms, lower is better) — shared | 66.7386 | 38.8451 | -27.89 | 37.1139 |
14
- | wildcard dispatch ×1000 (ms, lower is better) | 6.8 | 6.7 | -0.10 | 6.2 |
15
- | publishBatch ×1000 (ms, lower is better) | 4.7 | 4.6 | -0.10 | 4.1 |
16
- | dedup ×1000 (ms, lower is better) | 14.7 | 12.8 | -1.90 | 12.1 |
17
- | trace + publish ×1000 (ms, lower is better) | 5.3 | 4.9 | -0.40 | 4.8 |
12
+ | publish per-message (ms, lower is better) — dedicated | 41.1434 | 40.0685 | -1.07 | 40.0685 |
13
+ | publish per-message (ms, lower is better) — shared | 33.7695 | 34.3097 | +0.54 | 33.7695 |
14
+ | wildcard dispatch ×1000 (ms, lower is better) | 5.6 | 6.1 | +0.50 | 5.5 |
15
+ | publishBatch ×1000 (ms, lower is better) | 3.5 | 4.1 | +0.60 | 3.5 |
16
+ | dedup ×1000 (ms, lower is better) | 24 | 10.9 | -13.10 | 10.9 |
17
+ | trace + publish ×1000 (ms, lower is better) | 7 | 4.7 | -2.30 | 4.7 |
18
18
  | first-packet cold dispatch (ms, lower is better) | 0 | 0 | +0.00 | 0 |
19
19
  <!-- BENCH-TREND:END -->
20
20
 
@@ -11,7 +11,7 @@
11
11
 
12
12
  ## 自动化门禁(CI)
13
13
 
14
- `CI` 工作流的 `verify` job 在每次 push 与 pull request 上运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`(`vitest.config.ts` 中的下限:语句 96% / 分支 92% / 函数 96% / 行 97%)、`pnpm verify:compat`、`pnpm verify:pack`、`pnpm bench` 与 `pnpm audit`;`browser` job 运行 Playwright E2E 套件。`Release` 工作流在发布前重跑 `verify:compat` 与 `verify:pack`,随后执行阻塞式 `verify:published` 门禁。两个工作流的 checkout 均使用 `fetch-depth: 0` + `fetch-tags: true`,因为 `verify:compat` 需要从最近的发布 tag 解析基线。
14
+ `CI` 工作流的 `verify` job 在每次 push 与 pull request 上运行 `pnpm check`、`pnpm lint`、`pnpm test:coverage`(`vitest.config.ts` 中的下限:语句 98% / 分支 96% / 函数 98% / 行 99%)、`pnpm verify:compat`、`pnpm verify:pack`、`pnpm bench` 与 `pnpm audit`;`browser` job 运行 Playwright E2E 套件。`Release` 工作流在发布前重跑 `verify:compat` 与 `verify:pack`,随后执行阻塞式 `verify:published` 门禁。两个工作流的 checkout 均使用 `fetch-depth: 0` + `fetch-tags: true`,因为 `verify:compat` 需要从最近的发布 tag 解析基线。
15
15
 
16
16
  只有 `pnpm bench:browser` / `pnpm bench:compare` 保持仅本地执行:共享 runner 的计时噪声会让数值型 CI 门禁不可靠。
17
17
 
@@ -1,6 +1,23 @@
1
1
  # 路线图
2
2
 
3
- 0.21.5 已于 2026 年 9 月 22 日发布。项目会先持续完成可靠性发布,再进入 1.0.0 稳定性冻结。
3
+ 0.21.7 已于 2026 年 9 月 23 日发布。项目会先持续完成可靠性发布,再进入 1.0.0 稳定性冻结。
4
+
5
+ ## 0.21.7 已完成范围
6
+
7
+ - 一处随包发布的说明是错的。`docs/api.md` 承诺「该 topic 最后一个 handler 退订时清空重放缓冲」,同时又说通配订阅会回放所有匹配 pattern 的已缓冲 topic——但 pattern 不是一个 topic:历史是按具体发布 topic 归档的,所以退订 `chat.*` 一条都不会清空,而 durable 清理拿到的是一个没有任何记录对应的键。中英文文档现在都写清了每次清理作用的键、`maxPerTopic` 限制的是每条环的深度而非环的数量,以及真正能回收内存的那几个调用。行为没有改动(按 pattern 剪枝会连带丢掉其它仍在线的订阅者拥有的环),并新增一条测试把这个边界钉住,避免文档再次漂回去。
8
+ - 补上一个真实的测试缺口:`ReplayManager` catch 中的 hydration epoch 检查从未执行过。`resetBuffers()` 只抬 epoch 不抬 retry generation,于是重置之后到达的加载失败会替「替换它的那个会话」上报错误,并把完成闩锁置位——那正是会抑制新会话加载的状态:一次幽灵 persistence error,外加该实例整个生命周期内 durable 历史缺失。
9
+ - 接收侧的帧校验规则(0.21.5 / 0.21.6)从维护者笔记搬进了 `docs/architecture.md` 的两个语言版本,包含两条刻意不做的检查,以及非 JS 对端要怎样才能被接受——这些守卫是 fail-closed 的,坏帧被静默丢弃且没有任何回应,对接方不看文档就无从知道。
10
+ - 五个模块里约十条 zero-count 分支用实验而不是推断定了下来:一条被真正钉住,其余的在原地处标注了「谁覆盖了它」以及删掉它的代价。没有删除任何一条,本次发布也没有声称任何未经测量的覆盖率提升。
11
+ - 覆盖率门禁重新变成了门禁:96 / 92 / 96 / 97 的下限已经比实测分支覆盖率低了 4.7 个百分点,意味着丢掉一整个模块的测试仍能通过包括发布门禁在内的所有检查。现在是 98 / 96 / 98 / 99,留出的余量只为唯一一个真正依赖运行机器的因素(模糊测试按墙钟界定深度),并且用「把阈值抬高到超过实测值就会失败」验证过它有牙齿。
12
+ - 本次发布没有改变任何行为、线格式或存储结构。
13
+
14
+
15
+ ## 0.21.6 已完成范围
16
+
17
+ - 0.21.5 的协议修复其实只覆盖了读取这组字段的两个处理器之一。`ROUTE_RELEASED` ACK 的授权方式完全相同——依据 `topicKey` 对应的持久路由——然后把它携带的 `topic` 写入 `assignedTopics` 并让传输层订阅它;因此一个同源脚本只要从 localStorage 读到真实的 key、记录在案的前任 owner 和 generation,就能用任意频道名回应一次正在进行的交接。现在两个点对点处理器都会校验 `createOpaqueKey(topic) === topicKey`;`EVENT` 与 `REGISTRY` 不需要这条检查,因为它们不携带“key + 明文”这一对字段。
18
+ - 批量 `PUBLISH` 帧的 `items` 此前只做了真值加长度的判断,而 `publishBatch()` 的 `Array.prototype.map` 是唯一的产生者。手工构造的 `{ length: 2 }` 会让 `message.items is not iterable` 从集群自己的 `BroadcastChannel` 监听器里抛出;可迭代的 `"ab"` 会变成两条 `data` 为 `undefined` 的发布,并以接收方 worker 的会话发出;空数组则两半条件都不满足,落到单条发布分支上把 `undefined` 发出去一次。现在,携带 `items` 的帧必须给出非空数组。
19
+ - 账目上的一条是通过证明断言本身失效而关闭的:恢复次数耗尽的一次性上报,其第二处“`exhausted` 诊断只有一条”的计数从未进入过对应分支——因为一次失败的重开之后,安装到传输层上的处理器属于已被取代的生命周期。改成用应用在耗尽后真正会走的需求路径去驱动第二次失败,这个钉住才成立——现在删除该保护会让测试套件失败。`data-bus.ts` 未覆盖分支臂 13 → 12。
20
+ - `AGENTS.md` 把流程教训与不变式写在了一起:保护*协议*不变式的守卫属于协议,而不是最初发现违规的那个处理器,因此钉住一条不变式意味着枚举它约束的每个读取点——这正是上一版“修复”漏掉的那一步。
4
21
 
5
22
  ## 0.21.5 已完成范围
6
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cross-tab-worker-databus",
3
- "version": "0.21.5",
3
+ "version": "0.21.7",
4
4
  "description": "Framework-agnostic cross-tab data bus with Dedicated/Shared Worker clustering and Centrifuge support.",
5
5
  "type": "module",
6
6
  "license": "MIT",