From 033042f7eb80d931916fda5d25a3af8efb5f11cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Thu, 8 Oct 2026 14:22:27 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20GM=5Finfo=20=E6=9A=B4=E9=9C=B2?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E8=84=9A=E6=9C=AC=20UUID=20(GM=5Finfo.uuid)?= =?UTF-8?q?=EF=BC=8C=E4=B8=8E=20Violentmonkey=20=E4=B8=80=E8=87=B4=20(#178?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/content/exec_script.test.ts | 17 +++++++++++++++-- src/app/service/content/gm_api/gm_info.ts | 2 ++ src/template/scriptcat.d.tpl | 1 + src/types/scriptcat.d.ts | 2 ++ src/types/scriptcat.zh-CN.d.ts | 2 ++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/app/service/content/exec_script.test.ts b/src/app/service/content/exec_script.test.ts index 528999b35..0392fb781 100644 --- a/src/app/service/content/exec_script.test.ts +++ b/src/app/service/content/exec_script.test.ts @@ -35,8 +35,12 @@ function setExecCode(exec: ExecScript, script: ScriptLoadInfo, code: string): vo exec.scriptFunc = compileScript(compileScriptCode(script)); } -function makeExec(code: string, grant?: string[]): { exec: ExecScript; script: ScriptLoadInfo } { - const script = makeScript({ code, metadata: { grant, version: ["1.0.0"] } }); +function makeExec( + code: string, + grant?: string[], + overrides: Partial = {} +): { exec: ExecScript; script: ScriptLoadInfo } { + const script = makeScript({ code, metadata: { grant, version: ["1.0.0"] }, ...overrides }); const message = {} as Message; const exec = new ExecScript(script, { envPrefix: "scripting", @@ -68,6 +72,15 @@ describe.concurrent("GM_info", () => { expect(ret.GM_info.script.version).toEqual("1.0.0"); expect(ret._this).not.toEqual(global); }); + it.concurrent.each([ + ["none", ["none"]], + ["sandbox", undefined], + ])("GM_info.uuid 与 GM.info.uuid 返回当前脚本 UUID(%s)", async (_mode, grant) => { + const { exec } = makeExec("return {GM_info, GM};", grant, { uuid: "4b1c2d3e-5f60-4718-8a9b-0c1d2e3f4a5b" }); + const ret = await exec.exec(); + expect(ret.GM_info.uuid).toBe("4b1c2d3e-5f60-4718-8a9b-0c1d2e3f4a5b"); + expect(ret.GM.info.uuid).toBe("4b1c2d3e-5f60-4718-8a9b-0c1d2e3f4a5b"); + }); }); describe.concurrent("unsafeWindow", () => { diff --git a/src/app/service/content/gm_api/gm_info.ts b/src/app/service/content/gm_api/gm_info.ts index 44ca42d25..983169b40 100644 --- a/src/app/service/content/gm_api/gm_info.ts +++ b/src/app/service/content/gm_api/gm_info.ts @@ -29,6 +29,8 @@ export function evaluateGMInfo(envInfo: GMInfoEnv, script: TScriptInfo) { scriptMetaStr: script.metadataStr, userConfig: script.userConfig, userConfigStr: script.userConfigStr, + // 与 Violentmonkey 一致,在顶层暴露当前脚本 UUID + uuid: script.uuid, version: ExtVersion, script: { // TODO: 更多完整的信息(为了兼容Tampermonkey,后续待定) diff --git a/src/template/scriptcat.d.tpl b/src/template/scriptcat.d.tpl index e89cb2b05..3c6dc113c 100644 --- a/src/template/scriptcat.d.tpl +++ b/src/template/scriptcat.d.tpl @@ -31,6 +31,7 @@ declare const GM_info: { scriptMetaStr?: string; userConfig?: UserConfig; userConfigStr?: string; + uuid: string; isIncognito: boolean; sandboxMode: "raw"; // "js" | "raw" | "none"; userAgentData: { diff --git a/src/types/scriptcat.d.ts b/src/types/scriptcat.d.ts index f0d1214dc..936f16b27 100644 --- a/src/types/scriptcat.d.ts +++ b/src/types/scriptcat.d.ts @@ -44,6 +44,8 @@ declare const GM_info: { scriptMetaStr?: string; userConfig?: UserConfig; userConfigStr?: string; + /** UUID of the current script, stable across updates (same as Violentmonkey). */ + uuid: string; /** Whether running in an incognito/private window. */ isIncognito: boolean; /** Sandbox mode (ScriptCat always uses `"raw"`). */ diff --git a/src/types/scriptcat.zh-CN.d.ts b/src/types/scriptcat.zh-CN.d.ts index 1d1eb8507..78690c738 100644 --- a/src/types/scriptcat.zh-CN.d.ts +++ b/src/types/scriptcat.zh-CN.d.ts @@ -49,6 +49,8 @@ declare const GM_info: { scriptMetaStr?: string; userConfig?: UserConfig; userConfigStr?: string; + /** 当前脚本的 UUID,脚本更新后保持不变(与 Violentmonkey 一致)。 */ + uuid: string; /** 是否在隐私/无痕窗口中运行。 */ isIncognito: boolean; /** 沙箱模式(ScriptCat 始终使用 `"raw"`)。 */