提交前检查
问题描述
实际发生了什么: Edge Dev 154 上 ScriptCat 管理的全部用户脚本(10 个)静默失效——扩展弹窗仍显示「当前页运行脚本 (1/1)」(静态 URL 匹配),但页面内任何脚本都未执行,无报错、无日志、无提示。重启浏览器、重载扩展均无法恢复。
期望: 脚本正常注入执行。
根因(已定位并验证):
registerUserscripts() 的早退守卫只校验了 chrome.userScripts 侧的注册,未校验 chrome.scripting 侧:
// src/app/service/service_worker/runtime.ts L1077-1088
if (runtimeGlobal.registerState === RuntimeRegisterCode.REGISTER_DONE) {
const res = await chrome.userScripts.getScripts({ ids: ["scriptcat-inject"] });
if (res.length === 1) {
return; // ← 早退时未检查 chrome.scripting.getRegisteredContentScripts()
}
...
}
我机器上实测的状态是:
chrome.userScripts.getScripts() → 12 个脚本全部在册(10 个用户脚本 + scriptcat-inject + scriptcat-content),守卫条件满足,直接 return,永不补注册;
chrome.scripting.getRegisteredContentScripts() → 返回 [],唯一的广播者 scriptcat-scripting(isolated world,负责向 inject/content 双层广播 broadcastEventFlag 并下发脚本清单)已丢失。
于是三层握手链(scripting.js 广播 → inject/content 双 ack → 脚本清单下发)从源头断裂:window['#-<uuid>'] 包装函数虽由 scriptcat-inject 正常定义在 MAIN world,但永远无人调用 → 所有脚本静默失效。
scriptcat-scripting 为何会丢失尚不确定(疑似 Edge Dev 更新/浏览器异常退出时未持久化,或某次 unregisterUserscripts() 只成功了一半),但守卫无法自愈丢失是确定的:registerState 是内存态,只要 userScripts 侧看起来完整,SW 每次唤醒都直接跳过重注册。
复现步骤
- Edge Dev 154.0.4251.0 + ScriptCat v1.4.0,安装若干脚本并确认正常工作;
- 触发
scriptcat-scripting 的 content script 注册丢失(我无法稳定复现丢失动作本身,推测与 Edge Dev 更新或 SW 被杀时序有关;下面第 3 步可直接复现"守卫不自愈");
- 在 SW 控制台手动执行
chrome.scripting.unregisterContentScripts() 模拟丢失——此时 userScripts 侧注册完好、弹窗匹配照常显示;
- 刷新任意脚本匹配页面:脚本不再执行,且无论刷新多少次、重载扩展多少次都不会恢复(SW 唤醒后走早退守卫 return);
- 验证:SW 控制台
await chrome.scripting.getRegisteredContentScripts() 返回 [];
- 手动补注册后立刻恢复:
await chrome.scripting.registerContentScripts([{
id: 'scriptcat-scripting', js: ['/src/scripting.js'],
matches: ['<all_urls>'], allFrames: true, runAt: 'document_start',
persistAcrossSessions: true
}]);
刷新页面后握手链完整走通(广播 → 双 ack → .slc/.elc 下发),脚本全部恢复执行。
ScriptCat 版本
v1.4.0
系统 / 浏览器及版本
Windows 11 + Edge Dev 154.0.4251.0(Chromium 154)
相关脚本 / 日志 / 截图
受影响脚本:GitHub 中文化插件、SteamDB/HuggingFace/OpenRouter 汉化、OCS 网课助手等全部 10 个(与脚本内容无关,纯属注入链断裂)。
建议修复方向(两点):
-
早退守卫补校验:registerUserscripts() 在 registerState === REGISTER_DONE 分支同时检查 chrome.scripting.getRegisteredContentScripts() 是否真的包含 scriptcat-scripting,缺失则走重注册流程(即把 content 列表也纳入健康检查)。这一改动成本低、自愈效果好。
-
(关联隐患)chrome.extension 在 Edge 154 的 isolated world 已为 undefined:scripting.js 顶层直接读 chrome.extension.inIncognitoContext,在 Edge 154 上该 API 不可用(chrome.extension === undefined),一旦注册恢复正常注入,此处存在抛错导致广播者起不来的风险。实测该文件由 chrome.scripting.registerContentScripts 注入(isolated world),建议改用 chrome.runtime 侧能力或加存在性判断。我此前以为此行只在扩展自有页面上下文执行,但实际 scripting.js 会注入到普通网页 isolated world,值得上游关注。
排查过程中的辅助证据:给 MAIN world 手动派发 {action:'broadcastEventFlag'} 事件能收到 inject + content 两层 ack,证明 performance 总线跨 world 通信正常、两层运行时都活着,问题被精确定位在广播者缺位——这也解释了为什么弹窗静态匹配(SW 侧 URL 计算)一切正常而页面侧完全静默。
提交前检查
问题描述
实际发生了什么: Edge Dev 154 上 ScriptCat 管理的全部用户脚本(10 个)静默失效——扩展弹窗仍显示「当前页运行脚本 (1/1)」(静态 URL 匹配),但页面内任何脚本都未执行,无报错、无日志、无提示。重启浏览器、重载扩展均无法恢复。
期望: 脚本正常注入执行。
根因(已定位并验证):
registerUserscripts()的早退守卫只校验了chrome.userScripts侧的注册,未校验chrome.scripting侧:我机器上实测的状态是:
chrome.userScripts.getScripts()→ 12 个脚本全部在册(10 个用户脚本 +scriptcat-inject+scriptcat-content),守卫条件满足,直接 return,永不补注册;chrome.scripting.getRegisteredContentScripts()→ 返回[],唯一的广播者scriptcat-scripting(isolated world,负责向 inject/content 双层广播broadcastEventFlag并下发脚本清单)已丢失。于是三层握手链(scripting.js 广播 → inject/content 双 ack → 脚本清单下发)从源头断裂:
window['#-<uuid>']包装函数虽由 scriptcat-inject 正常定义在 MAIN world,但永远无人调用 → 所有脚本静默失效。scriptcat-scripting为何会丢失尚不确定(疑似 Edge Dev 更新/浏览器异常退出时未持久化,或某次unregisterUserscripts()只成功了一半),但守卫无法自愈丢失是确定的:registerState是内存态,只要 userScripts 侧看起来完整,SW 每次唤醒都直接跳过重注册。复现步骤
scriptcat-scripting的 content script 注册丢失(我无法稳定复现丢失动作本身,推测与 Edge Dev 更新或 SW 被杀时序有关;下面第 3 步可直接复现"守卫不自愈");chrome.scripting.unregisterContentScripts()模拟丢失——此时 userScripts 侧注册完好、弹窗匹配照常显示;await chrome.scripting.getRegisteredContentScripts()返回[];.slc/.elc下发),脚本全部恢复执行。ScriptCat 版本
v1.4.0
系统 / 浏览器及版本
Windows 11 + Edge Dev 154.0.4251.0(Chromium 154)
相关脚本 / 日志 / 截图
受影响脚本:GitHub 中文化插件、SteamDB/HuggingFace/OpenRouter 汉化、OCS 网课助手等全部 10 个(与脚本内容无关,纯属注入链断裂)。
建议修复方向(两点):
早退守卫补校验:
registerUserscripts()在registerState === REGISTER_DONE分支同时检查chrome.scripting.getRegisteredContentScripts()是否真的包含scriptcat-scripting,缺失则走重注册流程(即把content列表也纳入健康检查)。这一改动成本低、自愈效果好。(关联隐患)
chrome.extension在 Edge 154 的 isolated world 已为 undefined:scripting.js顶层直接读chrome.extension.inIncognitoContext,在 Edge 154 上该 API 不可用(chrome.extension === undefined),一旦注册恢复正常注入,此处存在抛错导致广播者起不来的风险。实测该文件由chrome.scripting.registerContentScripts注入(isolated world),建议改用chrome.runtime侧能力或加存在性判断。我此前以为此行只在扩展自有页面上下文执行,但实际scripting.js会注入到普通网页 isolated world,值得上游关注。排查过程中的辅助证据:给 MAIN world 手动派发
{action:'broadcastEventFlag'}事件能收到 inject + content 两层 ack,证明 performance 总线跨 world 通信正常、两层运行时都活着,问题被精确定位在广播者缺位——这也解释了为什么弹窗静态匹配(SW 侧 URL 计算)一切正常而页面侧完全静默。