vite-uni-dev-tool
Version:
vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试
171 lines (146 loc) • 3.92 kB
text/typescript
import type { DevConsole } from '../devConsole';
type SandboxOptions = {
console: DevConsole;
};
export class DevRunJS {
private context: Record<string, any> = {};
private isDestroyed = false;
constructor(options: SandboxOptions) {
this.createContext(options.console);
}
/**
* 创建context
*
* @private
* @param {DevConsole} [console]
* @memberof DevRunJs
*/
createContext(console?: DevConsole): void {
// 基础全局对象
this.context.Math = Math;
this.context.Date = Date;
this.context.Array = Array;
this.context.Object = Object;
this.context.String = String;
this.context.Number = Number;
this.context.Boolean = Boolean;
// 这里是为了给运行环境添加调用入口
this.context.console = console;
}
// 估算对象大小(简化版)
estimateObjectSize(obj: any): number {
if (obj === null) return 0;
const seen = new Set();
let bytes = 0;
const sizeOf = (o: any): number => {
if (seen.has(o)) return 0;
seen.add(o);
if (typeof o === 'boolean') return 4;
if (typeof o === 'number') return 8;
if (typeof o === 'string') return o.length * 2;
if (typeof o === 'function') return 0; // 函数大小不计
if (Array.isArray(o)) {
return o.reduce((sum, item) => sum + sizeOf(item), 0);
}
if (typeof o === 'object') {
return Object.keys(o).reduce((sum, key) => sum + sizeOf(o[key]), 0);
}
return 0;
};
return sizeOf(obj) / (1024 * 1024); // 转换为 MB
}
/**
* 注入外部变量,方法
*
* @param {string} name
* @param {*} value
* @return {*} {this}
* @memberof DevRunJs
*/
setVariable(name: string, value: any): this {
if (this.isDestroyed) {
throw new Error('[DevTool] DevRunJS 已经被销毁');
}
this.context[name] = value;
return this;
}
/**
* 批量注入
*
* @param {Record<string, any>} variables
* @return {*} {this}
* @memberof DevRunJs
*/
setVariables(variables: Record<string, any>): this {
if (this.isDestroyed) {
throw new Error('[DevTool] DevRunJS 已经被销毁');
}
Object.assign(this.context, variables);
return this;
}
/**
*
* TODO
* code 中存在 var, let, const, function 等关键字定义的变量或方法时,应该存入 context 中,允许下一次运行 js 调用
* 局部定义的不加入 context
*
* @memberof DevRunJs
*/
matchingGlobalVarAndFunc(code: string) {}
/**
* TODO
* 清空客户端注入的context
*/
clearGlobalVarAndFunc() {}
/**
* 执行 code
*
* @param {string} code
* @return {*} {Promise<any>}
* @memberof DevRunJs
*/
execute(code: string): Promise<any> {
if (this.isDestroyed) {
return Promise.reject(new Error('[DevTool] DevRunJS 已经被销毁'));
}
try {
// 创建执行环境
const wrapper = new Function(
'context',
`
// 'use strict';
with (context) {
return (function() {
try {
${code}
} catch (e) {
return e;
}
})();
}
`,
);
return Promise.resolve(wrapper(this.context));
} catch (error) {
return Promise.reject(
new Error(`[DevTool] DevRunJS 执行错误: ${(error as Error).message}`),
);
}
}
/**
* 销毁
*
* @return {*} {void}
* @memberof DevRunJs
*/
destroy(): void {
if (this.isDestroyed) return;
// 清除上下文
for (const key in this.context) {
delete this.context[key];
}
// 释放资源
this.context = {};
this.isDestroyed = true;
}
}