(resource: CompileScriptCodeResource)
| 130 | .replace("{{functionBody}}", () => code); |
| 131 | |
| 132 | export function compileScriptCodeByResource(resource: CompileScriptCodeResource): string { |
| 133 | const requireCode = resource.require.map((r) => r.content).join("\n;"); |
| 134 | const preCode = requireCode; // 不需要 async 封装 |
| 135 | let code = resource.code; // 需要 async 封装, 可top-level await |
| 136 | // context 和 name 以unnamed arguments方式导入。避免代码能直接以变量名存取 |
| 137 | // this = context: globalThis |
| 138 | // arguments = [named: Object, scriptName: string] |
| 139 | // 使用sandboxContext时,arguments[0]为undefined, this.$则为一次性Proxy变量,用于全域拦截context |
| 140 | // 非沙盒环境时,先读取 arguments[0],因此不会读取页面环境的 this.$ |
| 141 | // 在UserScripts API中,由于执行不是在物件导向里呼叫,使用arrow function的话会把this改变。须使用 .call(this) [ 或 .bind(this)() ] |
| 142 | |
| 143 | if (resource.isContextMenu) { |
| 144 | code = `GM_registerMenuCommand((${JSON.stringify(resource.name)}), ()=>{let GM_registerMenuCommand=window.GM_registerMenuCommand=GM.registerMenuCommand=undefined;\n${code}\n}, {nested:false});\n`; |
| 145 | } |
| 146 | |
| 147 | const joinedCode = [ |
| 148 | "with(arguments[0]||this.$){", |
| 149 | `${preCode}`, |
| 150 | "return(async function(){", |
| 151 | `${code}`, |
| 152 | "}).call(this);}", |
| 153 | ] |
| 154 | .filter(Boolean) |
| 155 | .join("\n"); |
| 156 | const codeBody = addTryCatch(joinedCode); |
| 157 | return `${codeBody}${sourceMapTo(`${resource.name}.user.js`)}\n`; |
| 158 | } |
| 159 | |
| 160 | // 通过脚本代码编译脚本函数 |
| 161 | export function compileScript(code: string): ScriptFunc { |
no test coverage detected