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