Repository navigation
Conversation
浏览器未启用 WebContentsDiscard 时,丢弃标签页会用新 tabId 替换原标签页, 只触发 tabs.onReplaced、旧 tabId 不再触发 onRemoved。GM_saveTab 数据按 tabId 存放,此前只处理了 onRemoved,切回标签页后用新 tabId 查不到数据。 新增 onReplaced 监听:GM_saveTab 数据随标签页迁移到新 tabId,旧 tabId 的其余 标签页缓存按关闭释放。tab 释放逻辑从 init 闭包提为 PopupService.clearTabData, 便于在服务层测试。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist / 检查清单
背景
fix #1791
浏览器没有启用
WebContentsDiscard时(Chromium 桌面端源码默认关闭,正式版 Chrome 由 Finch 灰度决定,发行版自己编译的 Chromium 通常关闭),丢弃标签页会用新 tabId 替换原标签页:只触发chrome.tabs.onReplaced(addedTabId, removedTabId),旧 tabId 不会再触发onRemoved。GM_saveTab的数据按 tabId 存在GM_getTab:<uuid>里,此前只处理了onRemoved,所以切回标签页后,页面用新 tabId 查不到数据,GM_getTab返回{};GM_getTabs里旧 tabId 的数据一直残留。本次改动
chrome.tabs.onReplaced监听:每个脚本的GM_saveTab数据从旧 tabId 迁移到新 tabId。旧 tabId 的其余标签页缓存(脚本列表、运行计数、菜单、加载标记)按关闭释放,以前这些在替换后会一直留在 session storage 里。init()内的clearData闭包提为PopupService.clearTabData(tabId, replacedByTabId?),三个调用点(onRemoved、onBeforeNavigate、新增的onReplaced)都改为调用它,便于在服务层测试。onRemoved和onBeforeNavigate的行为不变。实现考虑
GM_getTab的语义是数据在标签页打开期间一直保留。Tampermonkey 5.5.0 在同样条件下会把旧数据删掉(实测切回后同样返回{}),这里没有照搬。popup.ts而不是gm_api.ts:GM_saveTab数据只能借助「该标签页运行过的脚本列表」(CACHE_KEY_TAB_SCRIPT)找到,原有的关闭清理就放在这里,并且在同一个事务回调里先读脚本列表再处理数据。如果分开写,两个监听器会争同一份数据。已知限制
onReplaced监听的接线没有单元测试:现有 chrome mock 没有onActivated/webNavigation,测试里调不了init()。接线是靠下面的真实浏览器运行验证的。GM_openInTab的关闭通知(gm_api.ts,缓存键GM_openInTab:<tabId>)有同样的根因:被打开的标签页如果被丢弃后再关闭,脚本收不到onclose。没有实际复现,属于另一个功能,不在本 PR 范围内。验证
基线
58309d5e7406f7f71a26b2e20a63fa3a4a8e1abc,本 PR headf9b66c12772994748f1510bf2a5117c728587996;git diff --stat origin/main...HEAD只有popup.ts、popup.test.ts两个文件。popup.test.ts新增两条用例(替换时迁移到新 tabId;关闭时只删除该 tabId 的数据),改代码前两条都失败。改完后临时去掉迁移那一行,替换用例会失败,确认它能抓到回归。pnpm exec vitest run --no-coverage src/app/service/service_worker/popup.test.ts:59/59 通过。pnpm run typecheck、改动文件的prettier --check和eslint都通过(commit hook 也跑过)。pnpm exec vitest run --no-coverage src/app/service/service_worker:多次运行偶尔有 1~3 条失败,都在script.test.ts(openUpdatePageByUUID)和trash_freeze.test.ts。把本 PR 改动 stash 掉、在基线上跑也会出现同样的失败,单独跑script.test.ts3 次全过,判断为已有的不稳定用例,和本改动无关。pnpm run build后加载dist/ext,在 Chrome for Testing 153 上,由一个辅助扩展执行「打开 →GM_saveTab→ 刷新 → 切到其他标签页 →chrome.tabs.discard→ 切回」:--disable-features=WebContentsDiscard:tabId 变化,触发onReplaced,切回后GM_getTab返回{}。--disable-features=WebContentsDiscard:tabId 597587208 → 597587210,切回后读到原数据。--enable-features=WebContentsDiscard:tabId 不变,数据照常保留。