| 11 | |
| 12 | // 执行脚本,控制脚本执行与停止 |
| 13 | export default class ExecScript { |
| 14 | scriptRes: TScriptInfo; |
| 15 | |
| 16 | scriptFunc: ScriptFunc; |
| 17 | |
| 18 | logger: Logger; |
| 19 | |
| 20 | // proxyContext: typeof globalThis; |
| 21 | |
| 22 | sandboxContext?: IGM_Base & { [key: string]: any }; |
| 23 | |
| 24 | named?: { [key: string]: any }; |
| 25 | |
| 26 | constructor( |
| 27 | scriptRes: TScriptInfo, |
| 28 | options: { |
| 29 | envPrefix: string; |
| 30 | message: Message; |
| 31 | contentMsg: Message; |
| 32 | code: string | ScriptFunc; |
| 33 | envInfo: GMInfoEnv; |
| 34 | globalInjection?: { [key: string]: any }; // 主要是全域API. @grant none 时无效 |
| 35 | } |
| 36 | ) { |
| 37 | const { envPrefix, message, contentMsg, code, envInfo, globalInjection } = options; |
| 38 | this.scriptRes = scriptRes; |
| 39 | this.logger = LoggerCore.getInstance().logger({ |
| 40 | component: "exec", |
| 41 | uuid: scriptRes.uuid, |
| 42 | name: scriptRes.name, |
| 43 | }); |
| 44 | const GM_info = evaluateGMInfo(envInfo, scriptRes); |
| 45 | // 构建脚本资源 |
| 46 | if (typeof code === "string") { |
| 47 | this.scriptFunc = compileScript(code); |
| 48 | } else { |
| 49 | this.scriptFunc = code; |
| 50 | } |
| 51 | const grantSet = new Set(scriptRes.metadata.grant || []); |
| 52 | if (isContextMenuScript(scriptRes.metadata)) { |
| 53 | grantSet.add("GM_registerMenuCommand"); |
| 54 | grantSet.delete("none"); |
| 55 | } |
| 56 | if (grantSet.has("none")) { |
| 57 | // 不注入任何GM api |
| 58 | // ScriptCat行为:GM.info 和 GM_info 同时注入 |
| 59 | // 在不改变 Context 的情况下,以 named 传入多个全域变量 |
| 60 | const GM = Object.create(null); |
| 61 | GM.info = GM_info; |
| 62 | this.named = { GM, GM_info }; |
| 63 | } else { |
| 64 | // 构建脚本GM上下文 |
| 65 | this.sandboxContext = createContext(scriptRes, GM_info, envPrefix, message, contentMsg, grantSet); |
| 66 | if (globalInjection) { |
| 67 | Object.assign(this.sandboxContext, globalInjection); |
| 68 | } |
| 69 | } |
| 70 | } |
nothing calls this directly
no test coverage detected