From 3f9a0ef92bc0222926ba8074c98f8faf841015a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=87=91?= Date: Tue, 27 Aug 2024 19:06:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81js=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/dy_js_exec_test.ts | 17 +++++++ src/utils/dynamic_script_executor.ts | 95 ++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 src/utils/dy_js_exec_test.ts create mode 100644 src/utils/dynamic_script_executor.ts diff --git a/src/utils/dy_js_exec_test.ts b/src/utils/dy_js_exec_test.ts new file mode 100644 index 0000000..764a9c7 --- /dev/null +++ b/src/utils/dy_js_exec_test.ts @@ -0,0 +1,17 @@ +// 示例使用 +import { DynamicScriptExecutor } from '@/utils/dynamic_script_executor.ts' + +const executor = new DynamicScriptExecutor({ + user: { name: 'Alice', age: 30 }, + sayHello: (name: string) => `Hello, ${name}!` +}) + + +// 代码块中有可能抛出异常的代码 +const result = executor.execute(` + console.log(user); + throw new Error('测试错误'); // 故意抛出一个错误 + return sayHello(user.name); +`) + +result.then(console.log).catch(console.error) diff --git a/src/utils/dynamic_script_executor.ts b/src/utils/dynamic_script_executor.ts new file mode 100644 index 0000000..0b91a0d --- /dev/null +++ b/src/utils/dynamic_script_executor.ts @@ -0,0 +1,95 @@ +type Context = Record; + +/** + * 动态执行 JavaScript 脚本的工具类 + */ +export class DynamicScriptExecutor { + private context: Context + + constructor(context: Context = {}) { + this.context = context + } + + setContext(context: Context) { + this.context = context + } + + // 检测JS代码的语法是否正确 + checkSyntax(script: string) { + const contextKeys = Object.keys(this.context).join(',') + + try { + // 尝试创建一个新的函数,如果代码有语法错误,这里会抛出异常 + new Function(contextKeys, `return (async () => { ${script} })();`) + return null // 语法正确 + } catch (error) { + // console.error('代码语法错误:', error) + return error // 语法错误 + } + } + + async execute(script: string): Promise { + const contextKeys = Object.keys(this.context).join(',') + const contextValues = Object.values(this.context) + + // 先检测代码语法 + const err = this.checkSyntax(script) + if (err !== null) { + console.error('检测到代码语法错误,未执行代码。') + throw err + } + + // 使用 Function 构造函数创建一个新的异步函数,并在其中执行代码 + const func = new Function(contextKeys, `return (async () => { ${script} })();`) + + try { + // 调用函数并传入上下文对象的值 + return await func(...contextValues) + } catch (error) { + this.handleError(error) + throw error + } + } + + private handleError(error: any) { + // 在这里处理错误,例如显示错误提示、日志记录、发送错误报告等 + //alert(`执行代码时发生错误: ${error.message}`) + console.error(`执行代码时发生错误: ${error.message}`) + } +} + +// 创建一个默认的执行器实例 +export const defaultExecutor = new DynamicScriptExecutor({ + + // 系统内置的一些全局对象 + + // 全局对象 + console, + setTimeout, + setInterval, + clearTimeout, + clearInterval, + fetch, + location, + // document, + FormData, + URLSearchParams, + Headers, + Request, + Response, + Blob, + FileReader, + WebSocket, + EventSource, + localStorage, + sessionStorage, + indexedDB, + crypto, + performance, + navigator, + history, + screen, + alert, + confirm, + prompt, +}) \ No newline at end of file