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
4 changes: 3 additions & 1 deletion src/app/repo/scripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,12 @@ export interface ScriptSite {

export type ScriptAndCode = Script & ScriptCode;

export type ValueStore = { [key: string]: any };

// 脚本运行时的资源,包含已经编译好的脚本与脚本需要的资源
export interface ScriptRunResource extends Script {
code: string; // 原始代码
value: { [key: string]: any };
value: ValueStore;
flag: string;
resource: { [key: string]: { base64?: string } & Omit<Resource, "base64"> }; // 资源列表,包含脚本需要的资源
metadata: SCMetadata; // 经自定义覆盖的 Metadata
Expand Down
2 changes: 1 addition & 1 deletion src/app/service/content/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default class ContentRuntime {
let parentNode: EventTarget | undefined;
// 判断是不是content脚本发过来的
let msg: CustomEventMessage;
if (this.contentScriptSet.has(data.uuid) || this.scriptExecutor.execMap.has(data.uuid)) {
if (this.contentScriptSet.has(data.uuid) || this.scriptExecutor.execScriptMap.has(data.uuid)) {
msg = this.scriptExecutorMsg;
} else {
msg = this.senderToInject;
Expand Down
21 changes: 18 additions & 3 deletions src/app/service/content/exec_script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import type { Message } from "@Packages/message/types";
import type { ValueUpdateDataEncoded } from "./types";
import { evaluateGMInfo } from "./gm_api/gm_info";
import type { IGM_Base } from "./gm_api/gm_api";
import type { TScriptInfo } from "@App/app/repo/scripts";
import type { ScriptRunResource, TScriptInfo } from "@App/app/repo/scripts";
import { getStorageName } from "@App/pkg/utils/utils";

// 执行脚本,控制脚本执行与停止
export default class ExecScript {
Expand Down Expand Up @@ -64,8 +65,22 @@ export default class ExecScript {
this.sandboxContext?.emitEvent(event, eventId, data);
}

valueUpdate(data: ValueUpdateDataEncoded) {
this.sandboxContext?.valueUpdate(data);
valueUpdate(storageName: string, uuid: string, responses: ValueUpdateDataEncoded[]) {
const scriptRes = this.scriptRes;
if (scriptRes.uuid === uuid || getStorageName(scriptRes) === storageName) {
const context = this.sandboxContext;
if (context) {
const contextScriptRes = context.scriptRes as ScriptRunResource | null | undefined;
if (contextScriptRes) {
if (uuid === contextScriptRes.uuid || storageName === getStorageName(contextScriptRes)) {
contextScriptRes.value = context.extValueStoreCopy || contextScriptRes.value;
const valueStore = contextScriptRes.value;
context.valueStoreUpdate(valueStore, responses);
context.extValueStoreCopy = { ...valueStore };
}
Comment on lines +75 to +80
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valueUpdate 方法中,对 scriptRescontextScriptRes 进行了重复的 uuid 和 storageName 检查。由于外层已经检查了 scriptRes.uuid === uuid || getStorageName(scriptRes) === storageName,而 contextScriptRes 通常是 scriptRes 的引用或相同对象,内层的检查(第 75 行)是冗余的。建议移除内层重复检查,简化逻辑。

Suggested change
if (uuid === contextScriptRes.uuid || storageName === getStorageName(contextScriptRes)) {
contextScriptRes.value = context.extValueStoreCopy || contextScriptRes.value;
const valueStore = contextScriptRes.value;
context.valueStoreUpdate(valueStore, responses);
context.extValueStoreCopy = { ...valueStore };
}
contextScriptRes.value = context.extValueStoreCopy || contextScriptRes.value;
const valueStore = contextScriptRes.value;
context.valueStoreUpdate(valueStore, responses);
context.extValueStoreCopy = { ...valueStore };

Copilot uses AI. Check for mistakes.
}
}
}
}

execContext: any;
Expand Down
131 changes: 81 additions & 50 deletions src/app/service/content/gm_api/gm_api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { compileScript, compileScriptCode } from "../utils";
import type { Message } from "@Packages/message/types";
import { encodeRValue } from "@App/pkg/utils/message_value";
import { v4 as uuidv4 } from "uuid";
import { getStorageName } from "@App/pkg/utils/utils";
const nilFn: ScriptFunc = () => {};

const scriptRes = {
Expand Down Expand Up @@ -123,10 +124,14 @@ describe.concurrent("GM Api", () => {
script.value = { test: "ok" };
script.metadata.grant = ["GM.getValue"];
script.code = `return GM.getValue("test").then(v=>v+"!");`;
// @ts-ignore
const exec = new ExecScript(script, undefined, undefined, nilFn, envInfo);
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
const mockMessage = {
sendMessage: mockSendMessage,
} as unknown as Message;
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
exec.scriptFunc = compileScript(compileScriptCode(script));
const ret = await exec.exec();
const retPromise = exec.exec();
const ret = await retPromise;
expect(ret).toEqual("ok!");
});

Expand All @@ -135,10 +140,14 @@ describe.concurrent("GM Api", () => {
script.value = { test1: "23", test2: "45", test3: "67" };
script.metadata.grant = ["GM_listValues"];
script.code = `return GM_listValues().join("-");`;
// @ts-ignore
const exec = new ExecScript(script, undefined, undefined, nilFn, envInfo);
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
const mockMessage = {
sendMessage: mockSendMessage,
} as unknown as Message;
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
exec.scriptFunc = compileScript(compileScriptCode(script));
const ret = await exec.exec();
const retPromise = exec.exec();
const ret = await retPromise;
expect(ret).toEqual("test1-test2-test3");
});

Expand All @@ -151,22 +160,30 @@ describe.concurrent("GM Api", () => {
script.value.test1 = "40";
script.metadata.grant = ["GM_listValues"];
script.code = `return GM_listValues().join("-");`;
// @ts-ignore
const exec = new ExecScript(script, undefined, undefined, nilFn, envInfo);
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
const mockMessage = {
sendMessage: mockSendMessage,
} as unknown as Message;
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
exec.scriptFunc = compileScript(compileScriptCode(script));
const ret = await exec.exec();
expect(ret).toEqual("test5-test2-test3-test1"); // TM也沒有sort
const retPromise = exec.exec();
const ret = await retPromise;
expect(ret).toEqual("test5-test2-test3-test1"); // TM也没有sort
});

it.concurrent("GM.listValues", async () => {
const script = Object.assign({}, scriptRes) as ScriptLoadInfo;
script.value = { test1: "23", test2: "45", test3: "67" };
script.metadata.grant = ["GM.listValues"];
script.code = `return GM.listValues().then(v=>v.join("-"));`;
// @ts-ignore
const exec = new ExecScript(script, undefined, undefined, nilFn, envInfo);
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
const mockMessage = {
sendMessage: mockSendMessage,
} as unknown as Message;
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
exec.scriptFunc = compileScript(compileScriptCode(script));
const ret = await exec.exec();
const retPromise = exec.exec();
const ret = await retPromise;
expect(ret).toEqual("test1-test2-test3");
});

Expand All @@ -179,11 +196,15 @@ describe.concurrent("GM Api", () => {
script.value.test1 = "40";
script.metadata.grant = ["GM.listValues"];
script.code = `return GM.listValues().then(v=>v.join("-"));`;
// @ts-ignore
const exec = new ExecScript(script, undefined, undefined, nilFn, envInfo);
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
const mockMessage = {
sendMessage: mockSendMessage,
} as unknown as Message;
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
exec.scriptFunc = compileScript(compileScriptCode(script));
const ret = await exec.exec();
expect(ret).toEqual("test5-test2-test3-test1"); // TM也沒有sort
const retPromise = exec.exec();
const ret = await retPromise;
expect(ret).toEqual("test5-test2-test3-test1"); // TM也没有sort
});

it.concurrent("GM_getValues", async () => {
Expand Down Expand Up @@ -212,10 +233,14 @@ describe.concurrent("GM Api", () => {
script.value = { test1: "23", test2: 45, test3: "67" };
script.metadata.grant = ["GM.getValues"];
script.code = `return GM.getValues(["test2", "test3", "test1"]).then(v=>v);`;
// @ts-ignore
const exec = new ExecScript(script, undefined, undefined, nilFn, envInfo);
const mockSendMessage = vi.fn().mockResolvedValue({ code: 0 });
const mockMessage = {
sendMessage: mockSendMessage,
} as unknown as Message;
const exec = new ExecScript(script, "content", mockMessage, nilFn, envInfo);
exec.scriptFunc = compileScript(compileScriptCode(script));
const ret = await exec.exec();
const retPromise = exec.exec();
const ret = await retPromise;
expect(ret.test1).toEqual("23");
expect(ret.test2).toEqual(45);
expect(ret.test3).toEqual("67");
Expand Down Expand Up @@ -499,7 +524,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
keyValuePairs1,
],
Expand All @@ -523,7 +548,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
keyValuePairs2,
],
Expand Down Expand Up @@ -573,7 +598,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
keyValuePairs1,
],
Expand All @@ -592,7 +617,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 @@ -643,7 +668,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the object payload
keyValuePairs1,
],
Expand All @@ -667,7 +692,7 @@ describe.concurrent("GM_value", () => {
api: "GM_setValues",
params: [
// event id
expect.stringMatching(/^.+::\d$/),
expect.stringMatching(/^.+::\d+$/),
// the string payload
keyValuePairs2,
],
Expand Down Expand Up @@ -702,14 +727,16 @@ describe.concurrent("GM_value", () => {
const retPromise = exec.exec();
expect(mockSendMessage).toHaveBeenCalledTimes(1);
// 模拟值变化
exec.valueUpdate({
id: "id-1",
entries: [["param1", encodeRValue(123), encodeRValue(undefined)]],
uuid: script.uuid,
storageName: script.uuid,
sender: { runFlag: exec.sandboxContext!.runFlag, tabId: -2 },
valueUpdated: true,
});
exec.valueUpdate(getStorageName(script), script.uuid, [
{
id: "id-1",
valueChanges: [["param1", encodeRValue(123), encodeRValue(undefined)]],
uuid: script.uuid,
storageName: script.uuid,
sender: { runFlag: exec.sandboxContext!.runFlag, tabId: -2 },
updatetime: Date.now(),
},
]);
const ret = await retPromise;
expect(ret).toEqual({ name: "param1", oldValue: undefined, newValue: 123, remote: false });
});
Expand Down Expand Up @@ -737,14 +764,16 @@ describe.concurrent("GM_value", () => {
const retPromise = exec.exec();
expect(mockSendMessage).toHaveBeenCalledTimes(1);
// 模拟值变化
exec.valueUpdate({
id: "id-2",
entries: [["param2", encodeRValue(456), encodeRValue(undefined)]],
uuid: script.uuid,
storageName: "testStorage",
sender: { runFlag: "user", tabId: -2 },
valueUpdated: true,
});
exec.valueUpdate(getStorageName(script), script.uuid, [
{
id: "id-2",
valueChanges: [["param2", encodeRValue(456), encodeRValue(undefined)]],
uuid: script.uuid,
storageName: "testStorage",
sender: { runFlag: "user", tabId: -2 },
updatetime: Date.now(),
},
]);
const ret2 = await retPromise;
expect(ret2).toEqual({ name: "param2", oldValue: undefined, newValue: 456, remote: true });
});
Expand Down Expand Up @@ -772,14 +801,16 @@ describe.concurrent("GM_value", () => {
expect(id).toBeTypeOf("string");
expect(id.length).greaterThan(0);
// 触发valueUpdate
exec.valueUpdate({
id: id,
entries: [["a", encodeRValue(123), encodeRValue(undefined)]],
uuid: script.uuid,
storageName: script.uuid,
sender: { runFlag: exec.sandboxContext!.runFlag, tabId: -2 },
valueUpdated: true,
});
exec.valueUpdate(getStorageName(script), script.uuid, [
{
id: id,
valueChanges: [["a", encodeRValue(123), encodeRValue(undefined)]],
uuid: script.uuid,
storageName: script.uuid,
sender: { runFlag: exec.sandboxContext!.runFlag, tabId: -2 },
updatetime: Date.now(),
},
]);

const ret = await retPromise;
expect(ret).toEqual(123);
Expand Down
Loading
Loading