From 73182eb95826d0956c623b980ff0329ad98f3733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Fri, 16 Jan 2026 16:33:58 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=A4=84=E7=90=86value=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20#1141?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/content/gm_api/gm_api.test.ts | 93 +++++++++++++++++++ src/app/service/content/gm_api/gm_api.ts | 12 ++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/src/app/service/content/gm_api/gm_api.test.ts b/src/app/service/content/gm_api/gm_api.test.ts index 64c1a26f4..eb3eeabab 100644 --- a/src/app/service/content/gm_api/gm_api.test.ts +++ b/src/app/service/content/gm_api/gm_api.test.ts @@ -461,6 +461,99 @@ describe.concurrent("GM_value", () => { expect(ret).toEqual({ ret1: 123, ret2: 456 }); }); + it.concurrent("value引用问题 #1141", async () => { + const script = Object.assign({}, scriptRes) as ScriptLoadInfo; + script.metadata.grant = ["GM_getValue", "GM_setValue", "GM_getValues"]; + script.code = ` +const value1 = { + arr: [1], + obj: { + a: "1" + }, + str: "123", +} +GM_setValue("abc", value1); + +const value2 = GM_getValue("abc"); + +value2.arr.push(2); +value2.obj.b = 2; +value2.str = "456"; + +value1.arr.push(3); +value1.obj.b = 3; +value1.str = "789" + +const value3 = GM_getValue("abc"); + +const values1 = GM_getValues(["abc"]); + +const values2 = GM_getValues({"abc":{}}); + +values2.abc.arr.push(2); +values2.abc.obj.b = 2; +values2.abc.str = "456"; + +return { value1, value2, value3, values1,values2 }; + `; + const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 }); + const mockMessage = { + sendMessage: mockSendMessage, + } as unknown as Message; + // @ts-ignore + const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo); + exec.scriptFunc = compileScript(compileScriptCode(script)); + const ret = await exec.exec(); + + expect(mockSendMessage).toHaveBeenCalled(); + expect(mockSendMessage).toHaveBeenCalledTimes(1); + + expect(ret).toEqual({ + value1: { + arr: [1, 3], + obj: { + a: "1", + b: 3, + }, + str: "789", + }, + value2: { + arr: [1, 2], + obj: { + a: "1", + b: 2, + }, + str: "456", + }, + value3: { + arr: [1], + obj: { + a: "1", + }, + str: "123", + }, + values1: { + abc: { + arr: [1], + obj: { + a: "1", + }, + str: "123", + }, + }, + values2: { + abc: { + arr: [1, 2], + obj: { + a: "1", + b: 2, + }, + str: "456", + }, + }, + }); + }); + it.concurrent("GM_setValues", async () => { const script = Object.assign({}, scriptRes) as ScriptLoadInfo; script.metadata.grant = ["GM_getValues", "GM_setValues"]; diff --git a/src/app/service/content/gm_api/gm_api.ts b/src/app/service/content/gm_api/gm_api.ts index 09c3bb205..784b81591 100644 --- a/src/app/service/content/gm_api/gm_api.ts +++ b/src/app/service/content/gm_api/gm_api.ts @@ -235,6 +235,9 @@ export default class GMApi extends GM_Base { if (!a.scriptRes) return undefined; const ret = a.scriptRes.value[key]; if (ret !== undefined) { + if (ret && typeof ret === "object") { + return structuredClone(ret); + } return ret; } return defaultValue; @@ -268,7 +271,7 @@ export default class GMApi extends GM_Base { } // 对object的value进行一次转化 if (value && typeof value === "object") { - value = JSON.parse(JSON.stringify(value)); + value = structuredClone(value); } if (value === undefined) { delete a.scriptRes.value[key]; @@ -375,7 +378,12 @@ export default class GMApi extends GM_Base { for (let index = 0; index < keysOrDefaults.length; index++) { const key = keysOrDefaults[index]; if (key in this.scriptRes.value) { - result[key] = this.scriptRes.value[key]; + // 对object的value进行一次转化 + let value = this.scriptRes.value[key]; + if (value && typeof value === "object") { + value = structuredClone(value); + } + result[key] = value; } } } else { From 41cb81b01a635f62fb9bf922f3cac1587302c035 Mon Sep 17 00:00:00 2001 From: wangyizhi Date: Fri, 16 Jan 2026 16:38:03 +0800 Subject: [PATCH 2/7] Update src/app/service/content/gm_api/gm_api.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/app/service/content/gm_api/gm_api.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/service/content/gm_api/gm_api.test.ts b/src/app/service/content/gm_api/gm_api.test.ts index eb3eeabab..77c0a2b38 100644 --- a/src/app/service/content/gm_api/gm_api.test.ts +++ b/src/app/service/content/gm_api/gm_api.test.ts @@ -482,7 +482,7 @@ value2.str = "456"; value1.arr.push(3); value1.obj.b = 3; -value1.str = "789" +value1.str = "789"; const value3 = GM_getValue("abc"); From 9d8594c1b689ed13d90c0a81d48aa73f497127e3 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 17 Jan 2026 06:07:28 +0900 Subject: [PATCH 3/7] Update gm_api.ts --- src/app/service/content/gm_api/gm_api.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/service/content/gm_api/gm_api.ts b/src/app/service/content/gm_api/gm_api.ts index 784b81591..b8ef290a3 100644 --- a/src/app/service/content/gm_api/gm_api.ts +++ b/src/app/service/content/gm_api/gm_api.ts @@ -297,13 +297,13 @@ export default class GMApi extends GM_Base { const valueStore = a.scriptRes.value; for (const [key, value] of Object.entries(values)) { let value_ = value; - // 对object的value进行一次转化 - if (value_ && typeof value_ === "object") { - value_ = JSON.parse(JSON.stringify(value_)); - } if (value_ === undefined) { if (valueStore[key]) delete valueStore[key]; } else { + // 对object的value进行一次转化 + if (value_ && typeof value_ === "object") { + value_ = structuredClone(value_); + } valueStore[key] = value_; } } @@ -369,7 +369,7 @@ export default class GMApi extends GM_Base { if (!this.scriptRes) return {}; if (!keysOrDefaults) { // Returns all values - return this.scriptRes.value; + return structuredClone(this.scriptRes.value); } const result: TGMKeyValue = {}; if (Array.isArray(keysOrDefaults)) { From 3565944a6a77f219be2ba14ddf73f08f514f9a5d Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sat, 17 Jan 2026 16:02:19 +0900 Subject: [PATCH 4/7] Update gm_api.ts --- src/app/service/content/gm_api/gm_api.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/service/content/gm_api/gm_api.ts b/src/app/service/content/gm_api/gm_api.ts index b8ef290a3..539184992 100644 --- a/src/app/service/content/gm_api/gm_api.ts +++ b/src/app/service/content/gm_api/gm_api.ts @@ -269,14 +269,14 @@ export default class GMApi extends GM_Base { if (promise) { valueChangePromiseMap.set(id, promise); } - // 对object的value进行一次转化 - if (value && typeof value === "object") { - value = structuredClone(value); - } if (value === undefined) { delete a.scriptRes.value[key]; a.sendMessage("GM_setValue", [id, key]); } else { + // 对object的value进行一次转化 + if (value && typeof value === "object") { + value = structuredClone(value); + } a.scriptRes.value[key] = value; a.sendMessage("GM_setValue", [id, key, value]); } From ed2f48e98178f8ef2c7503fcd0cd23b8f27f01fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Sat, 17 Jan 2026 18:52:50 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=89=80=E6=9C=89?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/service/content/gm_api/gm_api.test.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/app/service/content/gm_api/gm_api.test.ts b/src/app/service/content/gm_api/gm_api.test.ts index 77c0a2b38..b6e90af4b 100644 --- a/src/app/service/content/gm_api/gm_api.test.ts +++ b/src/app/service/content/gm_api/gm_api.test.ts @@ -494,7 +494,9 @@ values2.abc.arr.push(2); values2.abc.obj.b = 2; values2.abc.str = "456"; -return { value1, value2, value3, values1,values2 }; +const allValues = GM_getValues(); + +return { value1, value2, value3, values1,values2, allValues }; `; const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 }); const mockMessage = { @@ -551,6 +553,15 @@ return { value1, value2, value3, values1,values2 }; str: "456", }, }, + allValues: { + abc: { + arr: [1], + obj: { + a: "1", + }, + str: "123", + }, + }, }); }); From 0e2c37fe6a5f86d47df18ac8b56538f222436baa Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sun, 18 Jan 2026 08:50:57 +0900 Subject: [PATCH 6/7] unit test --- src/app/service/content/gm_api/gm_api.test.ts | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/app/service/content/gm_api/gm_api.test.ts b/src/app/service/content/gm_api/gm_api.test.ts index b6e90af4b..adfa8ce78 100644 --- a/src/app/service/content/gm_api/gm_api.test.ts +++ b/src/app/service/content/gm_api/gm_api.test.ts @@ -474,6 +474,14 @@ const value1 = { } GM_setValue("abc", value1); +const allValues1 = GM_getValues(); + +allValues1.abc.arr.push(8); +allValues1.n1 = 5; +allValues1.n2 = {c: 8}; +delete allValues1.abc.obj.a; +allValues1.abc.str = "0"; + const value2 = GM_getValue("abc"); value2.arr.push(2); @@ -486,17 +494,17 @@ value1.str = "789"; const value3 = GM_getValue("abc"); -const values1 = GM_getValues(["abc"]); +const values1 = GM_getValues(["abc", "n3"]); -const values2 = GM_getValues({"abc":{}}); +const values2 = GM_getValues({"abc":{}, "n4":{}, "n5":"hi"}); values2.abc.arr.push(2); values2.abc.obj.b = 2; values2.abc.str = "456"; -const allValues = GM_getValues(); +const allValues2 = GM_getValues(); -return { value1, value2, value3, values1,values2, allValues }; +return { value1, value2, value3, values1,values2, allValues1, allValues2 }; `; const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 }); const mockMessage = { @@ -552,8 +560,19 @@ return { value1, value2, value3, values1,values2, allValues }; }, str: "456", }, + n4: {}, + n5: "hi", + }, + allValues1: { + abc: { + arr: [1, 8], + obj: {}, + str: "0", + }, + n1: 5, + n2: { c: 8 }, }, - allValues: { + allValues2: { abc: { arr: [1], obj: { From d741071acf397aa17e4ef57b642af9bab47179c5 Mon Sep 17 00:00:00 2001 From: cyfung1031 <44498510+cyfung1031@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:43:48 +0900 Subject: [PATCH 7/7] unit test --- src/app/service/content/gm_api/gm_api.test.ts | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/app/service/content/gm_api/gm_api.test.ts b/src/app/service/content/gm_api/gm_api.test.ts index adfa8ce78..fd737de4a 100644 --- a/src/app/service/content/gm_api/gm_api.test.ts +++ b/src/app/service/content/gm_api/gm_api.test.ts @@ -503,8 +503,16 @@ values2.abc.obj.b = 2; values2.abc.str = "456"; const allValues2 = GM_getValues(); + + +const value4 = GM_getValue("abc"); +const value5 = GM_getValue("abc"); +value5.arr[0] = 9; +GM_setValue("abc", value5); + +const value6 = GM_getValue("abc"); -return { value1, value2, value3, values1,values2, allValues1, allValues2 }; +return { value1, value2, value3, values1,values2, allValues1, allValues2, value4, value5, value6 }; `; const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 }); const mockMessage = { @@ -516,7 +524,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; const ret = await exec.exec(); expect(mockSendMessage).toHaveBeenCalled(); - expect(mockSendMessage).toHaveBeenCalledTimes(1); + expect(mockSendMessage).toHaveBeenCalledTimes(2); expect(ret).toEqual({ value1: { @@ -581,6 +589,27 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; str: "123", }, }, + value4: { + arr: [1], + obj: { + a: "1", + }, + str: "123", + }, + value5: { + arr: [9], + obj: { + a: "1", + }, + str: "123", + }, + value6: { + arr: [9], + obj: { + a: "1", + }, + str: "123", + }, }); }); @@ -616,7 +645,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; api: "GM_setValues", params: [ // event id - expect.stringMatching(/^.+::\d$/), + expect.stringMatching(/^.+::\d+$/), // the object payload expect.objectContaining({ k: expect.stringMatching(/^##[\d.]+##$/), @@ -642,7 +671,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; api: "GM_setValues", params: [ // event id - expect.stringMatching(/^.+::\d$/), + expect.stringMatching(/^.+::\d+$/), // the object payload expect.objectContaining({ k: expect.stringMatching(/^##[\d.]+##$/), @@ -693,7 +722,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; api: "GM_setValues", params: [ // event id - expect.stringMatching(/^.+::\d$/), + expect.stringMatching(/^.+::\d+$/), // the object payload expect.objectContaining({ k: expect.stringMatching(/^##[\d.]+##$/), @@ -719,7 +748,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; api: "GM_setValue", params: [ // event id - expect.stringMatching(/^.+::\d$/), + expect.stringMatching(/^.+::\d+$/), // the string payload "b", ], @@ -764,7 +793,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; api: "GM_setValues", params: [ // event id - expect.stringMatching(/^.+::\d$/), + expect.stringMatching(/^.+::\d+$/), // the object payload expect.objectContaining({ k: expect.stringMatching(/^##[\d.]+##$/), @@ -790,7 +819,7 @@ return { value1, value2, value3, values1,values2, allValues1, allValues2 }; api: "GM_setValues", params: [ // event id - expect.stringMatching(/^.+::\d$/), + expect.stringMatching(/^.+::\d+$/), // the string payload expect.objectContaining({ k: expect.stringMatching(/^##[\d.]+##$/),