From 0d9c18d4292e6503b5e5a9f0611c40e3e8751d0a Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:10:15 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E9=85=8D=E5=90=88=20Firefox=20MV3=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=20addSessionRules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/service_worker/dnr.ts | 26 +++++++++++++++++++ .../service/service_worker/gm_api/gm_api.ts | 14 ++-------- src/app/service/service_worker/script.ts | 16 ++---------- 3 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 src/app/service/service_worker/dnr.ts diff --git a/src/app/service/service_worker/dnr.ts b/src/app/service/service_worker/dnr.ts new file mode 100644 index 000000000..2409814cc --- /dev/null +++ b/src/app/service/service_worker/dnr.ts @@ -0,0 +1,26 @@ +/** + * scheduler 用于 Service Worker 或 Event Page, Chrome 94+, Firefox 142+ + */ +const scheduler_ = + //@ts-ignore + typeof scheduler !== "undefined" && typeof scheduler?.postTask === "function" && typeof scheduler.yield === "function" + ? //@ts-ignore + scheduler + : null; + +// 用于扩充初始化时新增 SessionRules. FireFox 需要等一等才加,否则会失效。 +export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[]) => { + await scheduler_?.yield?.(); + chrome.declarativeNetRequest.updateSessionRules( + { + removeRuleIds: [...rules.map((rule) => rule.id)], + addRules: rules, + }, + () => { + const lastError = chrome.runtime.lastError; + if (lastError) { + console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); + } + } + ); +}; diff --git a/src/app/service/service_worker/gm_api/gm_api.ts b/src/app/service/service_worker/gm_api/gm_api.ts index 755096d21..6fd411378 100644 --- a/src/app/service/service_worker/gm_api/gm_api.ts +++ b/src/app/service/service_worker/gm_api/gm_api.ts @@ -54,6 +54,7 @@ import { headerModifierMap, headersReceivedMap } from "./gm_xhr"; import { BgGMXhr } from "@App/pkg/utils/xhr/bg_gm_xhr"; import { mightPrepareSetClipboard, setClipboard } from "../clipboard"; import { nativePageWindowOpen } from "../../offscreen/gm_api"; +import { addSessionRules } from "../dnr"; let generatedUniqueMarkerIDs = ""; let generatedUniqueMarkerIDWhen = ""; @@ -1650,18 +1651,7 @@ export default class GMApi { tabIds: [chrome.tabs.TAB_ID_NONE], // 只限于后台 service_worker / offscreen }, } as chrome.declarativeNetRequest.Rule; - chrome.declarativeNetRequest.updateSessionRules( - { - removeRuleIds: [ruleId], - addRules: [rule], - }, - () => { - const lastError = chrome.runtime.lastError; - if (lastError) { - console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); - } - } - ); + addSessionRules([rule]); } start() { diff --git a/src/app/service/service_worker/script.ts b/src/app/service/service_worker/script.ts index ca6b6da2b..b2aeb931e 100644 --- a/src/app/service/service_worker/script.ts +++ b/src/app/service/service_worker/script.ts @@ -47,6 +47,7 @@ import { getSimilarityScore, ScriptUpdateCheck } from "./script_update_check"; import { LocalStorageDAO } from "@App/app/repo/localStorage"; import { CompiledResourceDAO } from "@App/app/repo/resource"; import { initRegularUpdateCheck } from "./regular_updatecheck"; +import { addSessionRules } from "./dnr"; export type TCheckScriptUpdateOption = Partial< { checkType: "user"; noUpdateCheck?: number } | ({ checkType: "system" } & Record) @@ -299,20 +300,7 @@ export class ScriptService { } } ); - chrome.declarativeNetRequest.updateSessionRules( - { - removeRuleIds: [...rules.map((rule) => rule.id)], - addRules: rules, - }, - () => { - if (chrome.runtime.lastError) { - console.error( - "chrome.runtime.lastError in chrome.declarativeNetRequest.updateSessionRules:", - chrome.runtime.lastError - ); - } - } - ); + addSessionRules(rules); } public async openInstallPageByUrl( From 8c15b78f7bf9f4866f6492815b688f57d71f976f Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:26:23 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/service_worker/gm_api/gm_api.ts | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/app/service/service_worker/gm_api/gm_api.ts b/src/app/service/service_worker/gm_api/gm_api.ts index 6fd411378..8a812f1b7 100644 --- a/src/app/service/service_worker/gm_api/gm_api.ts +++ b/src/app/service/service_worker/gm_api/gm_api.ts @@ -197,6 +197,37 @@ export const getConnectMatched = ( return ConnectMatch.NONE; }; +const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve?: any) => { + chrome.declarativeNetRequest.updateSessionRules( + { + removeRuleIds: [rule.id], + addRules: [rule], + }, + () => { + const lastError = chrome.runtime.lastError; + if (lastError) { + console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); + } + resolve(); + } + ); +}; + +const sessionRuleDynamicRemove = (ruleId: number, resolve?: any) => { + chrome.declarativeNetRequest.updateSessionRules( + { + removeRuleIds: [ruleId], + }, + () => { + const lastError = chrome.runtime.lastError; + if (lastError) { + console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); + } + resolve(); + } + ); +}; + type NotificationData = { uuid: string; details: GMTypes.NotificationDetails; @@ -713,10 +744,7 @@ export default class GMApi { }, } as chrome.declarativeNetRequest.Rule; headerModifierMap.set(markerID, { rule, redirectNotManual }); - await chrome.declarativeNetRequest.updateSessionRules({ - removeRuleIds: [ruleId], - addRules: [rule], - }); + await new Promise((resolve) => sessionRuleDynamicAdd(rule, resolve)); } return true; } @@ -1595,32 +1623,11 @@ export default class GMApi { }, }; headerModifierMap.set(markerID, { rule: newRule, redirectNotManual }); - chrome.declarativeNetRequest.updateSessionRules( - { - removeRuleIds: [rule.id], - addRules: [newRule], - }, - () => { - const lastError = chrome.runtime.lastError; - if (lastError) { - console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); - } - } - ); + sessionRuleDynamicAdd(newRule); } else { // 删除关联与DNR headerModifierMap.delete(markerID); - chrome.declarativeNetRequest.updateSessionRules( - { - removeRuleIds: [rule.id], - }, - () => { - const lastError = chrome.runtime.lastError; - if (lastError) { - console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); - } - } - ); + sessionRuleDynamicRemove(rule.id); } } } From 9827cc7d2af68b3838f915329da453d65f2cd3f9 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:27:01 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/service_worker/dnr.ts | 3 ++- src/app/service/service_worker/gm_api/gm_api.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/service/service_worker/dnr.ts b/src/app/service/service_worker/dnr.ts index 2409814cc..2b943292a 100644 --- a/src/app/service/service_worker/dnr.ts +++ b/src/app/service/service_worker/dnr.ts @@ -9,7 +9,7 @@ const scheduler_ = : null; // 用于扩充初始化时新增 SessionRules. FireFox 需要等一等才加,否则会失效。 -export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[]) => { +export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[], resolve?: any) => { await scheduler_?.yield?.(); chrome.declarativeNetRequest.updateSessionRules( { @@ -21,6 +21,7 @@ export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[] if (lastError) { console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); } + resolve?.(); } ); }; diff --git a/src/app/service/service_worker/gm_api/gm_api.ts b/src/app/service/service_worker/gm_api/gm_api.ts index 8a812f1b7..573cd87a5 100644 --- a/src/app/service/service_worker/gm_api/gm_api.ts +++ b/src/app/service/service_worker/gm_api/gm_api.ts @@ -208,7 +208,7 @@ const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve? if (lastError) { console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); } - resolve(); + resolve?.(); } ); }; @@ -223,7 +223,7 @@ const sessionRuleDynamicRemove = (ruleId: number, resolve?: any) => { if (lastError) { console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); } - resolve(); + resolve?.(); } ); }; From 9a7cf2dc53b776aa6485791cc9d0c5753d426002 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:28:52 +0900 Subject: [PATCH 4/7] `ResolveFn` --- src/app/service/service_worker/dnr.ts | 2 +- src/app/service/service_worker/gm_api/gm_api.ts | 4 ++-- src/types/main.d.ts | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/service/service_worker/dnr.ts b/src/app/service/service_worker/dnr.ts index 2b943292a..ba4125381 100644 --- a/src/app/service/service_worker/dnr.ts +++ b/src/app/service/service_worker/dnr.ts @@ -9,7 +9,7 @@ const scheduler_ = : null; // 用于扩充初始化时新增 SessionRules. FireFox 需要等一等才加,否则会失效。 -export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[], resolve?: any) => { +export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[], resolve?: ResolveFn) => { await scheduler_?.yield?.(); chrome.declarativeNetRequest.updateSessionRules( { diff --git a/src/app/service/service_worker/gm_api/gm_api.ts b/src/app/service/service_worker/gm_api/gm_api.ts index 573cd87a5..6412ff092 100644 --- a/src/app/service/service_worker/gm_api/gm_api.ts +++ b/src/app/service/service_worker/gm_api/gm_api.ts @@ -197,7 +197,7 @@ export const getConnectMatched = ( return ConnectMatch.NONE; }; -const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve?: any) => { +const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve?: ResolveFn) => { chrome.declarativeNetRequest.updateSessionRules( { removeRuleIds: [rule.id], @@ -213,7 +213,7 @@ const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve? ); }; -const sessionRuleDynamicRemove = (ruleId: number, resolve?: any) => { +const sessionRuleDynamicRemove = (ruleId: number, resolve?: ResolveFn) => { chrome.declarativeNetRequest.updateSessionRules( { removeRuleIds: [ruleId], diff --git a/src/types/main.d.ts b/src/types/main.d.ts index 0b9624821..2994c36ab 100644 --- a/src/types/main.d.ts +++ b/src/types/main.d.ts @@ -7,6 +7,7 @@ declare module "@App/app/types.d.ts"; type Override = Omit & U; type ValueOf = T[keyof T]; type ReactStateSetter = (value: T | ((prev: T) => T)) => void; +type ResolveFn = (val: T) => void; declare const sandbox: Window; From 1404c6d017a7cabfc21b7bdd12c103cbf933afdd Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:30:35 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=E7=B5=B1=E4=B8=80=E5=9C=A8=20`dnr.ts`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/service_worker/dnr.ts | 31 +++++++++++++++++ .../service/service_worker/gm_api/gm_api.ts | 33 +------------------ 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/app/service/service_worker/dnr.ts b/src/app/service/service_worker/dnr.ts index ba4125381..4a3ca8484 100644 --- a/src/app/service/service_worker/dnr.ts +++ b/src/app/service/service_worker/dnr.ts @@ -25,3 +25,34 @@ export const addSessionRules = async (rules: chrome.declarativeNetRequest.Rule[] } ); }; + +export const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve?: ResolveFn) => { + chrome.declarativeNetRequest.updateSessionRules( + { + removeRuleIds: [rule.id], + addRules: [rule], + }, + () => { + const lastError = chrome.runtime.lastError; + if (lastError) { + console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); + } + resolve?.(); + } + ); +}; + +export const sessionRuleDynamicRemove = (ruleId: number, resolve?: ResolveFn) => { + chrome.declarativeNetRequest.updateSessionRules( + { + removeRuleIds: [ruleId], + }, + () => { + const lastError = chrome.runtime.lastError; + if (lastError) { + console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); + } + resolve?.(); + } + ); +}; diff --git a/src/app/service/service_worker/gm_api/gm_api.ts b/src/app/service/service_worker/gm_api/gm_api.ts index 6412ff092..f4c89820d 100644 --- a/src/app/service/service_worker/gm_api/gm_api.ts +++ b/src/app/service/service_worker/gm_api/gm_api.ts @@ -54,7 +54,7 @@ import { headerModifierMap, headersReceivedMap } from "./gm_xhr"; import { BgGMXhr } from "@App/pkg/utils/xhr/bg_gm_xhr"; import { mightPrepareSetClipboard, setClipboard } from "../clipboard"; import { nativePageWindowOpen } from "../../offscreen/gm_api"; -import { addSessionRules } from "../dnr"; +import { addSessionRules, sessionRuleDynamicAdd, sessionRuleDynamicRemove } from "../dnr"; let generatedUniqueMarkerIDs = ""; let generatedUniqueMarkerIDWhen = ""; @@ -197,37 +197,6 @@ export const getConnectMatched = ( return ConnectMatch.NONE; }; -const sessionRuleDynamicAdd = (rule: chrome.declarativeNetRequest.Rule, resolve?: ResolveFn) => { - chrome.declarativeNetRequest.updateSessionRules( - { - removeRuleIds: [rule.id], - addRules: [rule], - }, - () => { - const lastError = chrome.runtime.lastError; - if (lastError) { - console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); - } - resolve?.(); - } - ); -}; - -const sessionRuleDynamicRemove = (ruleId: number, resolve?: ResolveFn) => { - chrome.declarativeNetRequest.updateSessionRules( - { - removeRuleIds: [ruleId], - }, - () => { - const lastError = chrome.runtime.lastError; - if (lastError) { - console.error("chrome.declarativeNetRequest.updateSessionRules:", lastError); - } - resolve?.(); - } - ); -}; - type NotificationData = { uuid: string; details: GMTypes.NotificationDetails; From 9b81878ed84a1c022ac87a887804c9c1303c6177 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:42:06 +0900 Subject: [PATCH 6/7] typescript --- src/app/service/service_worker/dnr.ts | 9 +++++---- src/types/main.d.ts | 13 +++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/app/service/service_worker/dnr.ts b/src/app/service/service_worker/dnr.ts index 4a3ca8484..c26df3771 100644 --- a/src/app/service/service_worker/dnr.ts +++ b/src/app/service/service_worker/dnr.ts @@ -2,10 +2,11 @@ * scheduler 用于 Service Worker 或 Event Page, Chrome 94+, Firefox 142+ */ const scheduler_ = - //@ts-ignore - typeof scheduler !== "undefined" && typeof scheduler?.postTask === "function" && typeof scheduler.yield === "function" - ? //@ts-ignore - scheduler + typeof scheduler !== "undefined" && + typeof scheduler?.postTask === "function" && + typeof scheduler?.yield === "function" && + process.env.VI_TESTING !== "true" + ? scheduler : null; // 用于扩充初始化时新增 SessionRules. FireFox 需要等一等才加,否则会失效。 diff --git a/src/types/main.d.ts b/src/types/main.d.ts index 2994c36ab..a50ba249d 100644 --- a/src/types/main.d.ts +++ b/src/types/main.d.ts @@ -9,6 +9,19 @@ type ValueOf = T[keyof T]; type ReactStateSetter = (value: T | ((prev: T) => T)) => void; type ResolveFn = (val: T) => void; +interface SchedulerPostTaskOptions { + delay?: number; + priority?: "user-blocking" | "user-visible" | "background"; + signal?: AbortSignal; +} + +interface Scheduler { + postTask(callback: () => T | Promise, options?: SchedulerPostTaskOptions): Promise; + yield(): Promise; +} + +declare let scheduler: Scheduler | undefined; + declare const sandbox: Window; declare const self: ServiceWorkerGlobalScope; From 56e3c049b1f5cd8068bd08dee05b638fe15137c1 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:46:48 +0900 Subject: [PATCH 7/7] vitest fix --- packages/chrome-extension-mock/declarativ_net_request.ts | 3 ++- src/app/service/service_worker/dnr.ts | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/chrome-extension-mock/declarativ_net_request.ts b/packages/chrome-extension-mock/declarativ_net_request.ts index abbf15c3e..c7610a93f 100644 --- a/packages/chrome-extension-mock/declarativ_net_request.ts +++ b/packages/chrome-extension-mock/declarativ_net_request.ts @@ -30,9 +30,10 @@ export default class DeclarativeNetRequest { OTHER: "other", }; - updateSessionRules() { + updateSessionRules(rule: any, callback?: any) { return new Promise((resolve) => { resolve(); + callback?.(); }); } } diff --git a/src/app/service/service_worker/dnr.ts b/src/app/service/service_worker/dnr.ts index c26df3771..43feef7d0 100644 --- a/src/app/service/service_worker/dnr.ts +++ b/src/app/service/service_worker/dnr.ts @@ -4,8 +4,7 @@ const scheduler_ = typeof scheduler !== "undefined" && typeof scheduler?.postTask === "function" && - typeof scheduler?.yield === "function" && - process.env.VI_TESTING !== "true" + typeof scheduler?.yield === "function" ? scheduler : null;