2 changed files with 112 additions and 0 deletions
			
			
		@ -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) | 
			
		||||
@ -0,0 +1,95 @@ | 
			
		|||||
 | 
				type Context = Record<string, any>; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * 动态执行 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<any> { | 
			
		||||
 | 
				    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, | 
			
		||||
 | 
				}) | 
			
		||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue