Skip to content

🐛 修复 GM_download 传入空 url 时未触发 onerror 的兼容性问题#1619

Open
cyfung1031 wants to merge 2 commits into
scriptscat:mainfrom
cyfung1031:claude/scriptcat-gm-download-empty-url-d65147
Open

🐛 修复 GM_download 传入空 url 时未触发 onerror 的兼容性问题#1619
cyfung1031 wants to merge 2 commits into
scriptscat:mainfrom
cyfung1031:claude/scriptcat-gm-download-empty-url-d65147

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes ... / 已修复或实现 ...
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

背景

GM_download 传入空字符串 url 时,ScriptCat 与 Tampermonkey 行为不一致:TM 会同步报错或触发 onerror;ScriptCat 既不抛错也不触发 onerror,而是触发 onload

根因:src/app/service/content/gm_api/gm_xhr.tsnew URL(urlResolved, window.location.href) 对空字符串不会抛错,而是按 WHATWG URL 规范解析为当前页面自身的地址。_GM_downloadhandle() 在此之前没有对空 url 做拦截,导致空 url 被当作合法地址,静默对当前页面发起"下载"请求并触发 onload

复现脚本见 #1618(仅用于该 issue/本 PR 的说明,未加入自动化测试用例)。

本次改动

  • src/app/service/content/gm_api/gm_api.ts:在 _GM_downloadhandle() 内,await urlPromiseLike 得到 url 后立即校验;url 为空时直接触发 details.onerror?.({ error: "unknown" }) 并 reject retPromise,不再进入 browser/native 下载分支。该校验位于 downloadMode 分支之前,因此同时覆盖 nativebrowser 两种模式。
  • src/app/service/content/gm_api/gm_api.test.ts:新增 @grant GM_download 用例,分别验证 GM_download(回调形式)触发 onerror 且不触发 onload,以及 GM.download(Promise 形式)会 reject。

已知限制

  • example/tests/gm_download_test.js 已覆盖空 url 场景的手动/E2E 测试,本次未新增额外的手动测试脚本(按要求)。
  • Service worker 侧 src/app/service/service_worker/gm_api/gm_api.tsbrowser downloadMode 下的空 url 兜底分支(发送 data: nullonerror)仍保留原状,未做改动;该分支在本次修复后不再是空 url 场景下唯一的兜底路径,但作为纵深防御原样保留,属既有代码,不在本次改动范围内。

建议审查重点

  • _GM_download 中新增的空 url 判断是否会误伤合法但"假值"的 url(例如 urlconvObjectToURL 转换 Blob/File 后是否可能为空字符串)——convObjectToURL 产出的应始终是非空的 blob:/data URL,故不受影响。
  • error: "unknown" 是否是合适的错误码选择:GMTypes.DownloadError.error 的取值中没有专门的"url 为空/不合法"错误码,unknown 与本文件其余兜底错误路径(如后台连接失败、onMessage 收到 onerror)保持一致。

关联

Fixes #1618

验证

  • pnpm vitest run src/app/service/content/gm_api/gm_api.test.ts src/app/service/service_worker/gm_api/gm_api.test.ts — 54 passed
  • 回归验证:在应用修复前 git stash 掉实现改动后重跑新增用例,两条用例均按预期失败(onerror 未触发 / GM.download 超时未 reject),证明用例确实覆盖了该缺陷。
  • pnpm exec tsc --noEmit -p tsconfig.json — 无输出,通过
  • pnpm exec eslint src/app/service/content/gm_api/gm_api.ts src/app/service/content/gm_api/gm_api.test.ts — 无输出,通过

new URL("", location.href) 不会抛错而是解析为当前页面地址,导致空 url
被当作有效地址发起下载,与 TM 触发 onerror 的行为不一致。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GM_download 传入空 url 时行为与 Tampermonkey 不一致(触发 onload 而非 onerror)

1 participant