Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 158 additions & 6 deletions src/app/service/content/gm_api/gm_api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,158 @@ 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 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);
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", "n3"]);

const values2 = GM_getValues({"abc":{}, "n4":{}, "n5":"hi"});

values2.abc.arr.push(2);
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, value4, value5, value6 };
`;
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(2);

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",
},
n4: {},
n5: "hi",
},
allValues1: {
abc: {
arr: [1, 8],
obj: {},
str: "0",
},
n1: 5,
n2: { c: 8 },
},
allValues2: {
abc: {
arr: [1],
obj: {
a: "1",
},
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",
},
});
});

it.concurrent("GM_setValues", async () => {
const script = Object.assign({}, scriptRes) as ScriptLoadInfo;
script.metadata.grant = ["GM_getValues", "GM_setValues"];
Expand Down Expand Up @@ -493,7 +645,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
expect.objectContaining({
k: expect.stringMatching(/^##[\d.]+##$/),
Expand All @@ -519,7 +671,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
expect.objectContaining({
k: expect.stringMatching(/^##[\d.]+##$/),
Expand Down Expand Up @@ -570,7 +722,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
expect.objectContaining({
k: expect.stringMatching(/^##[\d.]+##$/),
Expand All @@ -596,7 +748,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValue",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the string payload
"b",
],
Expand Down Expand Up @@ -641,7 +793,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
expect.objectContaining({
k: expect.stringMatching(/^##[\d.]+##$/),
Expand All @@ -667,7 +819,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the string payload
expect.objectContaining({
k: expect.stringMatching(/^##[\d.]+##$/),
Expand Down
28 changes: 18 additions & 10 deletions src/app/service/content/gm_api/gm_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -266,14 +269,14 @@ export default class GMApi extends GM_Base {
if (promise) {
valueChangePromiseMap.set(id, promise);
}
// 对object的value进行一次转化
if (value && typeof value === "object") {
value = JSON.parse(JSON.stringify(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]);
}
Expand All @@ -294,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_;
}
}
Expand Down Expand Up @@ -366,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)) {
Expand All @@ -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 {
Expand Down
Loading