-
Notifications
You must be signed in to change notification settings - Fork 159
/
Copy pathmoduleLoader.js
122 lines (105 loc) · 3.45 KB
/
moduleLoader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {readFileSync, existsSync} from 'fs';
import path from "path";
import {fileURLToPath} from "url";
import axios from 'axios';
import fetchSync from 'sync-fetch';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// 公共函数:加载本地模块代码
function loadLocalModule(jsm_path) {
const fullPath = path.join(__dirname, '../js', jsm_path);
if (!existsSync(fullPath)) {
throw new Error(`Module not found: ${fullPath}`);
}
const baseName = path.basename(fullPath);
if (!baseName.startsWith('_lib')) {
throw new Error(`Invalid module name: ${baseName}. Module names must start with "_lib".`);
}
return readFileSync(fullPath, 'utf8');
}
// 公共函数:加载远程模块代码
async function loadRemoteModule(jsm_path) {
try {
const response = await axios.get(jsm_path, {
headers: {
'user-agent': 'Mozilla/5.0',
},
timeout: 5000,
});
return response.data;
} catch (error) {
throw new Error(`Failed to fetch remote module: ${error.message}`);
}
}
// 执行模块代码并导出
function executeModule(js_code, sandbox) {
const script = `
(function () {
try {
${js_code}
} catch (err) {
throw new Error("Error executing module script: " + err.message);
}
})();
`;
// 如果下面沙箱代码执行后无法让模块正确继承原型链方法,还是用eval吧
// eval(script);
const scriptRunner = new Function('sandbox', `
with (sandbox) {
${script}
}
`);
scriptRunner(sandbox);
if (!$.exports || Object.keys($.exports).length === 0) {
throw new Error(`Module did not export anything.`);
}
return $.exports;
}
// 全局 $ 对象
(function () {
let currentSandbox = null; // 存储当前沙箱上下文
globalThis.$ = {
/**
* 设置当前沙箱
* @param {Object} sandbox - 沙箱上下文
*/
setSandbox(sandbox) {
currentSandbox = sandbox;
},
/**
* 异步加载模块
* @param {string} jsm_path - 模块路径或网络地址
* @returns {Promise<any>} - 模块的导出内容
*/
async import(jsm_path) {
if (!currentSandbox) {
throw new Error("No sandbox context set. Use $.setSandbox before calling $.import.");
}
const isURL = /^(https?:)?\/\//.test(jsm_path);
let js_code;
if (isURL) {
js_code = await loadRemoteModule(jsm_path);
} else {
js_code = loadLocalModule(jsm_path);
}
return executeModule(js_code, currentSandbox);
},
/**
* 同步加载模块
* @param {string} jsm_path - 模块路径或网络地址
* @returns {any} - 模块的导出内容
*/
require(jsm_path) {
if (!currentSandbox) {
throw new Error("No sandbox context set. Use $.setSandbox before calling $.require.");
}
const isURL = /^(https?:)?\/\//.test(jsm_path);
let js_code;
if (isURL) {
js_code = fetchSync(jsm_path).text();
} else {
js_code = loadLocalModule(jsm_path);
}
return executeModule(js_code, currentSandbox);
},
};
})();