Skip to content

✨ 支持 @exclude-match 元数据 - #1798

Open
CodFrm wants to merge 2 commits into
mainfrom
feat/1714-exclude-match
Open

CodFrm wants to merge 2 commits into
mainfrom
feat/1714-exclude-match

Conversation

@CodFrm

@CodFrm CodFrm commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

背景

@exclude-match 之前在脚本猫里不生效:extractUrlPatterns 只认 @match/@include/@exclude,命中 @exclude-match 的网址脚本照样执行。

本次改动

  • @exclude-match 按 @match 的同一套 match pattern 规则解析(包括 TM 兼容写法:省略 scheme、端口、http*、*),生成 MATCH_EXCLUDE 规则。解析失败的取值直接丢弃,不会像 @exclude 那样退化成 glob/正则。@exclude 行为不变。
  • 生效规则会到达所有消费方:原生注册(excludeMatches)、early-start 与 unwrap 的页内检查、Popup 原始规则(originalMetadata/originalUrlPatterns),以及 Popup「不在此站点执行」的判断(excludeFromMatch)。作者已用 @exclude-match 排除的网址不会再被重复写入排除。
  • 缓存失效:页面加载缓存键加入 exclude-match,同时更新 CompiledResourceNamespace。否则升级前已安装的带 @exclude-match 的脚本,重启后会继续复用不含排除的旧编译规则。
  • 兼容性表:exclude-match 加入已消费指令;解析不出规则的取值和 @match 一样报为不生效(安装页/编辑器共用)。
  • VM 备份导入:excludeMatch/origExcludeMatch 改为独立映射到 selfMetadata["exclude-match"]。原来它们被并入 exclude,而且 origExcludeMatch=false 会连作者的 @exclude 一起替换。现在作者的 @exclude-match 已真正生效,不独立映射的话,用户在 VM 里关掉的作者规则导入后会复活。

已知限制

  • 编辑器设置页的匹配/排除列表、安装页权限卡、synchronize.ts 的 TM 格式 orig_excludes、External Access scripts.metadata.get 的 excludes 都还不展示/导出 exclude-match(@exclude 在安装页同样没有展示)。这几处只是展示或导出,不影响执行结果;External Access 的字段需要与 sctl 仓 protocol 同步修改,留作后续。
  • Popup「允许在此执行」不会移除作者的 @exclude-match,与作者 @exclude 的现有行为一致。

建议审查重点

  • url_matcher.ts 中 @exclude-match 复用 @match 的归一化逻辑:省略 scheme 的 www.a.com/* 会补成 *://www.a.com/*。这里按「与 @match 同义」处理,不算扩大匹配范围。
  • VM 导入里 origExcludeMatch 语义的变化(self_metadata.ts)。

关联

close #1714

验证

  • TDD:先写的 16 个用例在实现前全部失败,实现后通过。覆盖解析、声明顺序(两种顺序)、通配网域/scheme、非法取值不退化、嵌入式检查器、SW 生效/原始规则、注册 excludeMatches、early-start 规则、缓存键、excludeFromMatch、VM 导入映射、兼容性表。
  • pnpm exec vitest run --no-coverage src/pkg src/app/service/service_worker src/app/service/content src/pages/install src/pages/import src/pages/popup:2119 passed / 25 failed。失败的都在未改动的文件(popup preload/usePopupData、PermissionCard 移动端、synchronize、openUpdatePageByUUID、BackgroundPrompt);逐个文件单独运行全部通过(popup 67/67、script.test 90/90、synchronize 86/86、PermissionCard 31/31、BackgroundPrompt 5/5)。
  • 全量 pnpm run test:ci 在本机不可用作信号:未改动的 origin/main 基线同样失败 80 个文件 / 138 个用例(机器负载约 9–17,isolate:false 共享 worker 的 mock 串扰),每次失败的集合也不同。请以 CI 结果为准。
  • 安装页:src/pages/install/compat.test.ts 新增用例。合法的 @exclude-match 不产生标记;*admin* 这类解析不出规则的取值在「其他声明」里连同取值和行号标出,不混进运行网站行。该用例在 main 的兼容性表上会失败。
  • pnpm run typecheck、prettier --check、改动文件 eslint 均通过(pre-commit hook 同样通过)。
  • 真实浏览器验证(pnpm run build + e2e/session.mjs 无头会话,本地 http://127.0.0.1:18714):普通 / early-start + 正则 @include / @unwrap 三个脚本都带 @exclude-match http://127.0.0.1/admin/*。chrome.userScripts.getScripts() 中三者的 excludeMatches 都是 ["http://127.0.0.1/admin/*"];/home/ 上三者都执行,/admin/ 上都不执行(看 dataset 与 console 输出)。未在浏览器里验证「升级后重启复用旧编译规则」这一路径,它依赖 CompiledResourceNamespace 更新后启动时的清理重建。

@exclude-match 按 @match 的 match pattern 规则解析为 MATCH_EXCLUDE,进入原生注册的
excludeMatches、early-start/unwrap 的页内检查、Popup 原始规则与站点排除判断;
解析失败的取值直接丢弃,不退化成 @exclude 的 glob/正则,并在兼容性检查中报为不生效。
页面加载缓存键纳入 exclude-match,并更新 CompiledResourceNamespace 让旧的编译规则重建;
VM 备份的 excludeMatch/origExcludeMatch 改为独立映射到 selfMetadata["exclude-match"]。
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.

[Compatibility] Add support for @exclude-match

1 participant