You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

134 lines
3.1 KiB

import React from 'react'
type Context = Record<string, any>;
/**
* 动态执行 JavaScript 脚本的工具类
*/
export class DynamicScriptExecutor {
private context: Context
private startDelimiter: string
private endDelimiter: string
constructor(context: Context = {}, startDelimiter: string = '{{', endDelimiter: string = '}}') {
this.context = context
this.startDelimiter = startDelimiter
this.endDelimiter = endDelimiter
}
setDelimiters(startDelimiter: string, endDelimiter: string) {
this.startDelimiter = startDelimiter
this.endDelimiter = endDelimiter
}
setContext(context: Context) {
this.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 // 语法错误
}
}
// 自动识别并提取动态JS执行块
extractDynamicJSBlocks(input: string): string[] {
const regex = new RegExp(
`${this.escapeRegExp(this.startDelimiter)}(.*?)${this.escapeRegExp(this.endDelimiter)}`,
'gs'
)
const matches: string[] = []
let match
while ((match = regex.exec(input)) !== null) {
matches.push(match[1].trim())
}
return matches
}
// 执行所有提取的动态JS块
async execute(input: string): Promise<any[]> {
const dynamicBlocks = this.extractDynamicJSBlocks(input)
const results: any[] = []
for (const script of dynamicBlocks) {
const contextKeys = Object.keys(this.context).join(',')
const contextValues = Object.values(this.context)
const error = this.checkSyntax(script)
if (error !== null) {
throw error // 抛出异常以便在调用方捕获
}
const func = new Function(contextKeys, `return (async () => { ${script} })();`)
try {
results.push(await func(...contextValues))
} catch (error) {
this.handleError(error)
throw error
}
}
return results
}
private handleError(error: any) {
console.log(`执行代码时发生错误: ${error.message}`)
}
// 转义正则表达式中的特殊字符
private escapeRegExp(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}
}
// 创建一个默认的执行器实例
export const defaultExecutor = new DynamicScriptExecutor({
// 系统内置的一些全局对象
// 全局对象
console,
setTimeout,
setInterval,
clearTimeout,
clearInterval,
fetch,
location,
React,
// document,
FormData,
URLSearchParams,
Headers,
Request,
Response,
Blob,
FileReader,
WebSocket,
EventSource,
localStorage,
sessionStorage,
indexedDB,
crypto,
performance,
navigator,
history,
screen,
alert,
confirm,
prompt,
})