-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy pathmoduleLoader.js
More file actions
117 lines (105 loc) · 3.71 KB
/
moduleLoader.js
File metadata and controls
117 lines (105 loc) · 3.71 KB
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
import {readFileSync, existsSync} from 'fs';
import path from "path";
import {createRequire} from 'module';
import {fileURLToPath} from "url";
import axios from 'axios';
import fetchSync from 'sync-fetch';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT_DIR = path.resolve(__dirname, '../');
const LIB_ROOT = path.join(ROOT_DIR, 'spider/js');
const customRequire = createRequire(import.meta.url);
// 导出 rootRequire
export const rootRequire = (modulePath) => {
if (modulePath.startsWith('./') || modulePath.startsWith('../')) {
const absolutePath = path.resolve(LIB_ROOT, modulePath);
return customRequire(absolutePath);
}
return customRequire(modulePath);
};
// 导出 initializeGlobalDollar 函数
export function initializeGlobalDollar() {
if (globalThis.$) return; // 避免重复初始化
let currentSandbox = null;
// 执行模块代码
function executeModule(js_code, sandbox) {
const script = `
(function () {
try {
${js_code}
} catch (err) {
throw new Error("Error executing module script: " + err.message);
}
})();
`;
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 loadLocalModule(jsm_path) {
const fullPath = path.join(__dirname, '../spider/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}. 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}`);
}
}
// 初始化 $ 对象
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");
const isURL = /^(https?:)?\/\//.test(jsm_path);
const js_code = isURL
? await loadRemoteModule(jsm_path)
: 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");
const isURL = /^(https?:)?\/\//.test(jsm_path);
const js_code = isURL
? fetchSync(jsm_path).text()
: loadLocalModule(jsm_path);
return executeModule(js_code, currentSandbox);
},
};
}