Skip to content

Commit 0892fcd

Browse files
CodFrmCopilotcyfung1031
authored
🐛 处理value引用问题 #1141 (#1147)
* 处理value引用问题 #1141 * Update src/app/service/content/gm_api/gm_api.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update gm_api.ts * Update gm_api.ts * 获取所有的单元测试 * unit test * unit test --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: cyfung1031 <44498510+cyfung1031@users.noreply.github.com>
1 parent 5d70786 commit 0892fcd

2 files changed

Lines changed: 176 additions & 16 deletions

File tree

src/app/service/content/gm_api/gm_api.test.ts

Lines changed: 158 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,158 @@ describe.concurrent("GM_value", () => {
461461
expect(ret).toEqual({ ret1: 123, ret2: 456 });
462462
});
463463

464+
it.concurrent("value引用问题 #1141", async () => {
465+
const script = Object.assign({}, scriptRes) as ScriptLoadInfo;
466+
script.metadata.grant = ["GM_getValue", "GM_setValue", "GM_getValues"];
467+
script.code = `
468+
const value1 = {
469+
arr: [1],
470+
obj: {
471+
a: "1"
472+
},
473+
str: "123",
474+
}
475+
GM_setValue("abc", value1);
476+
477+
const allValues1 = GM_getValues();
478+
479+
allValues1.abc.arr.push(8);
480+
allValues1.n1 = 5;
481+
allValues1.n2 = {c: 8};
482+
delete allValues1.abc.obj.a;
483+
allValues1.abc.str = "0";
484+
485+
const value2 = GM_getValue("abc");
486+
487+
value2.arr.push(2);
488+
value2.obj.b = 2;
489+
value2.str = "456";
490+
491+
value1.arr.push(3);
492+
value1.obj.b = 3;
493+
value1.str = "789";
494+
495+
const value3 = GM_getValue("abc");
496+
497+
const values1 = GM_getValues(["abc", "n3"]);
498+
499+
const values2 = GM_getValues({"abc":{}, "n4":{}, "n5":"hi"});
500+
501+
values2.abc.arr.push(2);
502+
values2.abc.obj.b = 2;
503+
values2.abc.str = "456";
504+
505+
const allValues2 = GM_getValues();
506+
507+
508+
const value4 = GM_getValue("abc");
509+
const value5 = GM_getValue("abc");
510+
value5.arr[0] = 9;
511+
GM_setValue("abc", value5);
512+
513+
const value6 = GM_getValue("abc");
514+
515+
return { value1, value2, value3, values1,values2, allValues1, allValues2, value4, value5, value6 };
516+
`;
517+
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
518+
const mockMessage = {
519+
sendMessage: mockSendMessage,
520+
} as unknown as Message;
521+
// @ts-ignore
522+
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
523+
exec.scriptFunc = compileScript(compileScriptCode(script));
524+
const ret = await exec.exec();
525+
526+
expect(mockSendMessage).toHaveBeenCalled();
527+
expect(mockSendMessage).toHaveBeenCalledTimes(2);
528+
529+
expect(ret).toEqual({
530+
value1: {
531+
arr: [1, 3],
532+
obj: {
533+
a: "1",
534+
b: 3,
535+
},
536+
str: "789",
537+
},
538+
value2: {
539+
arr: [1, 2],
540+
obj: {
541+
a: "1",
542+
b: 2,
543+
},
544+
str: "456",
545+
},
546+
value3: {
547+
arr: [1],
548+
obj: {
549+
a: "1",
550+
},
551+
str: "123",
552+
},
553+
values1: {
554+
abc: {
555+
arr: [1],
556+
obj: {
557+
a: "1",
558+
},
559+
str: "123",
560+
},
561+
},
562+
values2: {
563+
abc: {
564+
arr: [1, 2],
565+
obj: {
566+
a: "1",
567+
b: 2,
568+
},
569+
str: "456",
570+
},
571+
n4: {},
572+
n5: "hi",
573+
},
574+
allValues1: {
575+
abc: {
576+
arr: [1, 8],
577+
obj: {},
578+
str: "0",
579+
},
580+
n1: 5,
581+
n2: { c: 8 },
582+
},
583+
allValues2: {
584+
abc: {
585+
arr: [1],
586+
obj: {
587+
a: "1",
588+
},
589+
str: "123",
590+
},
591+
},
592+
value4: {
593+
arr: [1],
594+
obj: {
595+
a: "1",
596+
},
597+
str: "123",
598+
},
599+
value5: {
600+
arr: [9],
601+
obj: {
602+
a: "1",
603+
},
604+
str: "123",
605+
},
606+
value6: {
607+
arr: [9],
608+
obj: {
609+
a: "1",
610+
},
611+
str: "123",
612+
},
613+
});
614+
});
615+
464616
it.concurrent("GM_setValues", async () => {
465617
const script = Object.assign({}, scriptRes) as ScriptLoadInfo;
466618
script.metadata.grant = ["GM_getValues", "GM_setValues"];
@@ -493,7 +645,7 @@ describe.concurrent("GM_value", () => {
493645
api: "GM_setValues",
494646
params: [
495647
// event id
496-
expect.stringMatching(/^.+::\d$/),
648+
expect.stringMatching(/^.+::\d+$/),
497649
// the object payload
498650
expect.objectContaining({
499651
k: expect.stringMatching(/^##[\d.]+##$/),
@@ -519,7 +671,7 @@ describe.concurrent("GM_value", () => {
519671
api: "GM_setValues",
520672
params: [
521673
// event id
522-
expect.stringMatching(/^.+::\d$/),
674+
expect.stringMatching(/^.+::\d+$/),
523675
// the object payload
524676
expect.objectContaining({
525677
k: expect.stringMatching(/^##[\d.]+##$/),
@@ -570,7 +722,7 @@ describe.concurrent("GM_value", () => {
570722
api: "GM_setValues",
571723
params: [
572724
// event id
573-
expect.stringMatching(/^.+::\d$/),
725+
expect.stringMatching(/^.+::\d+$/),
574726
// the object payload
575727
expect.objectContaining({
576728
k: expect.stringMatching(/^##[\d.]+##$/),
@@ -596,7 +748,7 @@ describe.concurrent("GM_value", () => {
596748
api: "GM_setValue",
597749
params: [
598750
// event id
599-
expect.stringMatching(/^.+::\d$/),
751+
expect.stringMatching(/^.+::\d+$/),
600752
// the string payload
601753
"b",
602754
],
@@ -641,7 +793,7 @@ describe.concurrent("GM_value", () => {
641793
api: "GM_setValues",
642794
params: [
643795
// event id
644-
expect.stringMatching(/^.+::\d$/),
796+
expect.stringMatching(/^.+::\d+$/),
645797
// the object payload
646798
expect.objectContaining({
647799
k: expect.stringMatching(/^##[\d.]+##$/),
@@ -667,7 +819,7 @@ describe.concurrent("GM_value", () => {
667819
api: "GM_setValues",
668820
params: [
669821
// event id
670-
expect.stringMatching(/^.+::\d$/),
822+
expect.stringMatching(/^.+::\d+$/),
671823
// the string payload
672824
expect.objectContaining({
673825
k: expect.stringMatching(/^##[\d.]+##$/),

src/app/service/content/gm_api/gm_api.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ export default class GMApi extends GM_Base {
235235
if (!a.scriptRes) return undefined;
236236
const ret = a.scriptRes.value[key];
237237
if (ret !== undefined) {
238+
if (ret && typeof ret === "object") {
239+
return structuredClone(ret);
240+
}
238241
return ret;
239242
}
240243
return defaultValue;
@@ -266,14 +269,14 @@ export default class GMApi extends GM_Base {
266269
if (promise) {
267270
valueChangePromiseMap.set(id, promise);
268271
}
269-
// 对object的value进行一次转化
270-
if (value && typeof value === "object") {
271-
value = JSON.parse(JSON.stringify(value));
272-
}
273272
if (value === undefined) {
274273
delete a.scriptRes.value[key];
275274
a.sendMessage("GM_setValue", [id, key]);
276275
} else {
276+
// 对object的value进行一次转化
277+
if (value && typeof value === "object") {
278+
value = structuredClone(value);
279+
}
277280
a.scriptRes.value[key] = value;
278281
a.sendMessage("GM_setValue", [id, key, value]);
279282
}
@@ -294,13 +297,13 @@ export default class GMApi extends GM_Base {
294297
const valueStore = a.scriptRes.value;
295298
for (const [key, value] of Object.entries(values)) {
296299
let value_ = value;
297-
// 对object的value进行一次转化
298-
if (value_ && typeof value_ === "object") {
299-
value_ = JSON.parse(JSON.stringify(value_));
300-
}
301300
if (value_ === undefined) {
302301
if (valueStore[key]) delete valueStore[key];
303302
} else {
303+
// 对object的value进行一次转化
304+
if (value_ && typeof value_ === "object") {
305+
value_ = structuredClone(value_);
306+
}
304307
valueStore[key] = value_;
305308
}
306309
}
@@ -366,7 +369,7 @@ export default class GMApi extends GM_Base {
366369
if (!this.scriptRes) return {};
367370
if (!keysOrDefaults) {
368371
// Returns all values
369-
return this.scriptRes.value;
372+
return structuredClone(this.scriptRes.value);
370373
}
371374
const result: TGMKeyValue = {};
372375
if (Array.isArray(keysOrDefaults)) {
@@ -375,7 +378,12 @@ export default class GMApi extends GM_Base {
375378
for (let index = 0; index < keysOrDefaults.length; index++) {
376379
const key = keysOrDefaults[index];
377380
if (key in this.scriptRes.value) {
378-
result[key] = this.scriptRes.value[key];
381+
// 对object的value进行一次转化
382+
let value = this.scriptRes.value[key];
383+
if (value && typeof value === "object") {
384+
value = structuredClone(value);
385+
}
386+
result[key] = value;
379387
}
380388
}
381389
} else {

0 commit comments

Comments
 (0)