2017-09-23 09:42:16 +00:00
|
|
|
/**
|
2017-10-30 12:47:10 +00:00
|
|
|
* 符合 CommonJS 规范的 类似 Node 的模块化加载
|
|
|
|
* 一. 注: MiaoScript 中 require.main 不存在
|
|
|
|
* 二. 加载 require 流程 例如 在 dir 目录下 调用 require('xx');
|
|
|
|
* a) 加载流程
|
|
|
|
* 1. 如果xx模块是一个內建模块
|
|
|
|
* a. 编译并返回该模块
|
|
|
|
* b. 停止执行
|
|
|
|
* 2. 如果模块以 `./` `../` 开头
|
|
|
|
* a. 尝试使用 resolveAsFile(dir/xx) 加载文件
|
|
|
|
* b. 尝试使用 resolveAsDirectory(dir/xx) 加载目录
|
2019-04-24 01:33:00 +00:00
|
|
|
* 3. 尝试去 root root/node_modules => xx 加载模块
|
2017-11-30 05:22:44 +00:00
|
|
|
* a. 尝试使用 resolveAsFile(xx/xx) 加载文件
|
|
|
|
* b. 尝试使用 resolveAsDirectory(xx/xx) 加载目录
|
2017-10-30 12:47:10 +00:00
|
|
|
* 4. 抛出 not found 异常
|
|
|
|
* b) resolveAsFile 解析流程
|
|
|
|
* 1. 如果 xx 是一个文件 则作为 `javascript` 文本加载 并停止执行
|
|
|
|
* 2. 如果 xx.js 是一个文件 则作为 `javascript` 文本加载 并停止执行
|
2017-11-30 05:22:44 +00:00
|
|
|
* 3. 如果 xx.json 是一个文件 则使用 `JSON.parse(xx.json)` 解析为对象加载 并停止执行
|
|
|
|
* 暂不支持 4. 如果 xx.msm 是一个文件 则使用MScript解析器解析 并停止执行
|
2017-10-30 12:47:10 +00:00
|
|
|
* c) resolveAsDirectory 解析流程
|
|
|
|
* 1. 如果 xx/package.json 存在 则使用 `JSON.parse(xx/package.json)` 解析并取得 main 字段使用 resolveAsFile(main) 加载
|
|
|
|
* 2. 如果 xx/index.js 存在 则使用 resolveAsFile(xx/index.js) 加载
|
2017-11-30 05:22:44 +00:00
|
|
|
* 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行
|
|
|
|
* 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行
|
2017-09-23 09:42:16 +00:00
|
|
|
*/
|
2022-04-19 09:20:43 +00:00
|
|
|
/// <reference path="./index.d.ts" />
|
2020-01-31 18:41:24 +00:00
|
|
|
// @ts-check
|
|
|
|
(
|
|
|
|
/**
|
2020-06-23 05:39:00 +00:00
|
|
|
* @param {string} parent
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
2020-05-02 16:31:59 +00:00
|
|
|
function (parent) {
|
2020-11-11 09:27:43 +00:00
|
|
|
'use strict'
|
2022-04-19 09:20:43 +00:00
|
|
|
var System = Java.type('java.lang.System')
|
|
|
|
|
2020-11-11 09:27:43 +00:00
|
|
|
var File = Java.type('java.io.File')
|
|
|
|
var Paths = Java.type('java.nio.file.Paths')
|
|
|
|
var Files = Java.type('java.nio.file.Files')
|
|
|
|
var StandardCopyOption = Java.type('java.nio.file.StandardCopyOption')
|
2019-09-23 10:46:32 +00:00
|
|
|
|
2020-11-11 09:27:43 +00:00
|
|
|
var TarInputStream = Java.type('org.kamranzafar.jtar.TarInputStream')
|
|
|
|
var GZIPInputStream = Java.type('java.util.zip.GZIPInputStream')
|
|
|
|
var BufferedInputStream = Java.type('java.io.BufferedInputStream')
|
2017-09-23 09:42:16 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
var URL = Java.type('java.net.URL')
|
2021-07-10 10:29:44 +00:00
|
|
|
var ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream")
|
|
|
|
var ByteArray = Java.type("byte[]")
|
2021-03-26 10:51:54 +00:00
|
|
|
var Thread = Java.type('java.lang.Thread')
|
2021-07-10 10:29:44 +00:00
|
|
|
var Callable = Java.type('java.util.concurrent.Callable')
|
|
|
|
var Executors = Java.type('java.util.concurrent.Executors')
|
2022-04-19 09:20:43 +00:00
|
|
|
var TimeUnit = Java.type('java.util.concurrent.TimeUnit')
|
2020-11-11 09:27:43 +00:00
|
|
|
var separatorChar = File.separatorChar
|
2020-01-17 10:39:23 +00:00
|
|
|
|
2022-04-19 09:20:43 +00:00
|
|
|
var MS_NODE_PATH = System.getenv("MS_NODE_PATH") || root + separatorChar + 'node_modules'
|
|
|
|
var MS_NODE_REGISTRY = System.getenv("MS_NODE_REGISTRY") || 'https://registry.npmmirror.com'
|
|
|
|
var FALLBACK_NODE_REGISTRY = System.getenv("FALLBACK_NODE_REGISTRY") || 'https://repo.yumc.pw/repository/npm'
|
2020-05-14 11:12:03 +00:00
|
|
|
var CoreModules = [
|
|
|
|
"assert", "async_hooks", "Buffer", "child_process", "cluster", "crypto",
|
|
|
|
"dgram", "dns", "domain", "events", "fs", "http", "http2", "https",
|
|
|
|
"inspector", "net", "os", "path", "perf_hooks", "process", "punycode",
|
|
|
|
"querystring", "readline", "repl", "stream", "string_decoder",
|
|
|
|
"timer", "tls", "trace_events", "tty", "url", "util",
|
|
|
|
"v8", "vm", "wasi", "worker_threads", "zlib"
|
|
|
|
]
|
2019-09-05 07:58:24 +00:00
|
|
|
|
2020-11-11 09:27:43 +00:00
|
|
|
var ModulesVersionLock = {}
|
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* @param {...object} t
|
|
|
|
*/
|
|
|
|
function __assign(t) {
|
|
|
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
2020-11-11 09:27:43 +00:00
|
|
|
s = arguments[i]
|
2020-06-23 05:39:00 +00:00
|
|
|
if (s === undefined) {
|
2020-11-11 09:27:43 +00:00
|
|
|
continue
|
2020-06-23 05:39:00 +00:00
|
|
|
}
|
2020-01-31 18:41:24 +00:00
|
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
2020-11-11 09:27:43 +00:00
|
|
|
t[p] = s[p]
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
return t
|
2020-06-23 05:39:00 +00:00
|
|
|
}
|
2017-11-30 05:22:44 +00:00
|
|
|
|
2020-06-23 05:39:00 +00:00
|
|
|
// noinspection JSValidateJSDoc
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 判断是否为一个文件
|
|
|
|
* @param {any} file
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function _isFile(file) {
|
2020-12-17 10:34:57 +00:00
|
|
|
return file && file.isFile && file.isFile()
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2017-11-30 05:22:44 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 获得文件规范路径
|
|
|
|
* @param {any} file
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function _canonical(file) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return file.canonicalPath
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2019-09-01 15:58:07 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 获得文件绝对路径
|
|
|
|
* @param {any} file
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function _absolute(file) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return file.absolutePath
|
2017-10-11 17:39:51 +00:00
|
|
|
}
|
2017-10-10 13:01:43 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 解析模块名称为文件
|
|
|
|
* 按照下列顺序查找
|
|
|
|
* 当前目录 ./
|
|
|
|
* 父目录 ../
|
2020-06-23 05:39:00 +00:00
|
|
|
* 递归模块目录 ../node_modules 到root
|
|
|
|
* 寻找 ${NODE_PATH}
|
2020-01-31 18:41:24 +00:00
|
|
|
* @param {string} name 模块名称
|
|
|
|
* @param {string} parent 父目录
|
2020-12-17 08:17:16 +00:00
|
|
|
* @param {any} optional 附加参数
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
2020-12-17 08:17:16 +00:00
|
|
|
function resolve(name, parent, optional) {
|
2020-11-11 09:27:43 +00:00
|
|
|
name = _canonical(name) || name
|
2020-01-31 18:41:24 +00:00
|
|
|
// 解析本地目录
|
2020-12-17 08:17:16 +00:00
|
|
|
if (optional.local) {
|
|
|
|
return resolveAsFile(name, parent) || resolveAsDirectory(name, parent) || undefined
|
2020-01-31 18:41:24 +00:00
|
|
|
} else {
|
|
|
|
// 解析Node目录
|
2020-11-11 09:27:43 +00:00
|
|
|
var dir = [parent, 'node_modules'].join(separatorChar)
|
2020-12-17 08:17:16 +00:00
|
|
|
return resolveAsFile(name, dir) || resolveAsDirectory(name, dir) ||
|
2020-06-23 05:39:00 +00:00
|
|
|
(parent && parent.toString().startsWith(root) ?
|
2022-04-19 09:20:43 +00:00
|
|
|
resolve(name, new File(parent).getParent(), optional) : resolveAsDirectory(name, MS_NODE_PATH) || undefined)
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2017-09-23 09:42:16 +00:00
|
|
|
}
|
2020-01-31 18:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 解析文件
|
2022-04-19 09:20:43 +00:00
|
|
|
* @param {any} file 文件
|
2020-01-31 18:41:24 +00:00
|
|
|
* @param {string | undefined} dir 目录
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function resolveAsFile(file, dir) {
|
2020-11-11 09:27:43 +00:00
|
|
|
file = dir !== undefined ? new File(dir, file) : new File(file)
|
2020-01-31 18:41:24 +00:00
|
|
|
// 直接文件
|
|
|
|
if (file.isFile()) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return file
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
|
|
|
// JS文件
|
2020-11-11 09:27:43 +00:00
|
|
|
var js = new File(normalizeName(_absolute(file), '.js'))
|
2020-01-31 18:41:24 +00:00
|
|
|
if (js.isFile()) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return js
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
|
|
|
// JSON文件
|
2020-11-11 09:27:43 +00:00
|
|
|
var json = new File(normalizeName(_absolute(file), '.json'))
|
2020-01-31 18:41:24 +00:00
|
|
|
if (json.isFile()) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return json
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2017-11-30 05:22:44 +00:00
|
|
|
}
|
2020-01-31 18:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 解析目录
|
|
|
|
* @param {string} file 文件
|
|
|
|
* @param {string | undefined} dir 目录
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function resolveAsDirectory(file, dir) {
|
2020-11-11 09:27:43 +00:00
|
|
|
dir = dir !== undefined ? new File(dir, file) : new File(file)
|
|
|
|
var _package = new File(dir, 'package.json')
|
2020-01-31 18:41:24 +00:00
|
|
|
if (_package.exists()) {
|
2020-11-11 09:27:43 +00:00
|
|
|
var json = JSON.parse(base.read(_package))
|
2020-01-31 18:41:24 +00:00
|
|
|
if (json.main) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return resolveAsFile(json.main, dir)
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// if no package or package.main exists, look for index.js
|
2020-11-11 09:27:43 +00:00
|
|
|
return resolveAsFile('index.js', dir)
|
2017-10-11 17:39:51 +00:00
|
|
|
}
|
2017-10-26 13:01:24 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 后缀检测和添加
|
|
|
|
* @param {string} fileName 文件名称
|
|
|
|
* @param {string} ext 后缀
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function normalizeName(fileName, ext) {
|
2020-11-11 09:27:43 +00:00
|
|
|
var extension = ext || '.js'
|
2020-01-31 18:41:24 +00:00
|
|
|
if (fileName.endsWith(extension)) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return fileName
|
2017-10-11 17:39:51 +00:00
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
return fileName + extension
|
2017-10-11 17:39:51 +00:00
|
|
|
}
|
2017-10-10 13:01:43 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 检查模块缓存
|
|
|
|
* @param {string} id 模块ID
|
|
|
|
* @param {any} file 模块文件
|
|
|
|
* @param {any} optional 附加选项
|
|
|
|
* @returns {Object}
|
|
|
|
*/
|
2022-04-19 09:20:43 +00:00
|
|
|
function getCacheModule(id, file, optional) {
|
2020-11-11 09:27:43 +00:00
|
|
|
var module = cacheModules[id]
|
2020-01-31 18:41:24 +00:00
|
|
|
if (optional.cache && module) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return module
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2022-04-19 09:20:43 +00:00
|
|
|
return createModule(id, file, optional)
|
2017-09-23 09:42:16 +00:00
|
|
|
}
|
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 编译模块
|
|
|
|
* @param {string} id 模块ID
|
|
|
|
* @param {any} file 模块文件
|
|
|
|
* @param {any} optional 附加选项
|
|
|
|
* @returns {Object}
|
|
|
|
*/
|
2022-04-19 09:20:43 +00:00
|
|
|
function createModule(id, file, optional) {
|
|
|
|
var filename = file.name
|
|
|
|
var lastDotIndexOf = filename.lastIndexOf('.')
|
|
|
|
if (lastDotIndexOf == -1) {
|
|
|
|
throw Error('require module must include file ext.')
|
|
|
|
}
|
|
|
|
var name = filename.substring(0, lastDotIndexOf)
|
|
|
|
var ext = filename.substring(lastDotIndexOf + 1)
|
|
|
|
var loader = requireLoaders[ext]
|
|
|
|
if (!loader) {
|
|
|
|
throw Error('Unsupported module ' + filename + '. require loader not found.')
|
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(optional))
|
2020-01-31 18:41:24 +00:00
|
|
|
var module = {
|
|
|
|
id: id,
|
2022-04-19 09:20:43 +00:00
|
|
|
name: name,
|
|
|
|
ext: ext,
|
2020-01-31 18:41:24 +00:00
|
|
|
exports: {},
|
|
|
|
loaded: false,
|
2022-04-19 09:20:43 +00:00
|
|
|
loader: loader,
|
|
|
|
require: getRequire(file.parentFile, id),
|
|
|
|
__dirname: file.parentFile,
|
|
|
|
__filename: file
|
2020-11-11 09:27:43 +00:00
|
|
|
}
|
|
|
|
cacheModules[id] = module
|
2022-04-19 09:20:43 +00:00
|
|
|
return loader(module, file, __assign(optional, { id: id }))
|
2017-11-30 05:22:44 +00:00
|
|
|
}
|
2017-10-10 13:01:43 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 预编译JS
|
|
|
|
* @param {any} module JS模块
|
|
|
|
* @param {any} file JS文件
|
|
|
|
* @param {any} optional 附加选项
|
2022-04-19 09:20:43 +00:00
|
|
|
* @returns {any}
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
2022-04-19 09:20:43 +00:00
|
|
|
function compileJsFile(module, file, optional) {
|
|
|
|
return compileJs(module, base.read(file), optional)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 预编译JS
|
|
|
|
* @param {any} module JS模块
|
|
|
|
* @param {any} script JS脚本
|
|
|
|
* @param {any} optional 附加选项
|
|
|
|
* @returns {any}
|
|
|
|
*/
|
|
|
|
function compileJs(module, script, optional) {
|
2020-01-31 18:41:24 +00:00
|
|
|
if (optional.hook) {
|
2022-04-19 09:20:43 +00:00
|
|
|
script = optional.hook(script)
|
|
|
|
}
|
|
|
|
if (optional.beforeCompile) {
|
|
|
|
script = optional.beforeCompile(script)
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
|
|
|
// 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
|
2020-02-16 06:48:54 +00:00
|
|
|
// 2020-02-16 结尾新增换行 防止有注释导致加载失败
|
2020-06-23 05:39:00 +00:00
|
|
|
var compiledWrapper = engineLoad({
|
2022-04-19 09:20:43 +00:00
|
|
|
script: '(function (module, exports, require, __dirname, __filename) {' + script + '\n});',
|
2020-06-23 05:39:00 +00:00
|
|
|
name: optional.id
|
2020-11-11 09:27:43 +00:00
|
|
|
})
|
2020-01-31 18:41:24 +00:00
|
|
|
compiledWrapper.apply(module.exports, [
|
2022-04-19 09:20:43 +00:00
|
|
|
module, module.exports, module.require, module.__dirname, module.__filename
|
2020-11-11 09:27:43 +00:00
|
|
|
])
|
|
|
|
module.loaded = true
|
2022-04-19 09:20:43 +00:00
|
|
|
if (optional.afterCompile) {
|
|
|
|
module = optional.afterCompile(module) || module
|
|
|
|
}
|
|
|
|
return module
|
2017-11-30 05:22:44 +00:00
|
|
|
}
|
2017-09-23 09:42:16 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 预编译Json
|
|
|
|
* @param {{ id?: string | null; exports?: {}; loaded: any; require?: any; }} module Json模块
|
|
|
|
* @param {any} file Json 文件
|
2022-04-19 09:20:43 +00:00
|
|
|
* @returns {any}
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
|
|
|
function compileJson(module, file) {
|
2020-11-11 09:27:43 +00:00
|
|
|
module.exports = JSON.parse(base.read(file))
|
|
|
|
module.loaded = true
|
2022-04-19 09:20:43 +00:00
|
|
|
return module
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2017-09-27 12:40:57 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 尝试从网络下载依赖包
|
|
|
|
* @param {string} name 包名称
|
|
|
|
*/
|
|
|
|
function download(name) {
|
2022-04-19 09:20:43 +00:00
|
|
|
// process package name
|
|
|
|
// es6-map/implement => es6-map
|
|
|
|
// @ccms/common/dist/reflect => @ccms/common
|
2020-11-11 09:27:43 +00:00
|
|
|
var name_arr = name.split('/')
|
|
|
|
var module_name = name.startsWith('@') ? name_arr[0] + '/' + name_arr[1] : name_arr[0]
|
2022-04-19 09:20:43 +00:00
|
|
|
var target = MS_NODE_PATH + separatorChar + module_name
|
2020-11-11 09:27:43 +00:00
|
|
|
var _package = new File(target, 'package.json')
|
2021-06-22 07:05:27 +00:00
|
|
|
if (_package.exists()) {
|
|
|
|
return
|
|
|
|
}
|
2020-01-31 18:41:24 +00:00
|
|
|
// at windows need replace file name java.lang.IllegalArgumentException: Invalid prefix or suffix
|
2020-11-11 09:27:43 +00:00
|
|
|
var info = fetchPackageInfo(module_name)
|
|
|
|
var url = info.versions[ModulesVersionLock[module_name] || info['dist-tags']['latest']].dist.tarball
|
2020-03-02 16:57:19 +00:00
|
|
|
console.log('fetch node_module ' + module_name + ' from ' + url + ' waiting...')
|
2021-07-10 10:29:44 +00:00
|
|
|
return executor.submit(new Callable(function () {
|
2021-03-26 10:40:57 +00:00
|
|
|
var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new URL(url).openStream())))
|
|
|
|
var entry
|
|
|
|
while ((entry = tis.getNextEntry()) != null) {
|
|
|
|
var targetPath = Paths.get(target + separatorChar + entry.getName().substring(8))
|
|
|
|
targetPath.toFile().getParentFile().mkdirs()
|
|
|
|
Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING)
|
|
|
|
}
|
|
|
|
return name
|
2022-04-19 09:20:43 +00:00
|
|
|
}))
|
|
|
|
// default wait 45 seconds
|
|
|
|
.get(45, TimeUnit.SECONDS)
|
2019-09-23 10:46:32 +00:00
|
|
|
}
|
|
|
|
|
2020-05-02 16:31:59 +00:00
|
|
|
/**
|
|
|
|
* @param {string} module_name
|
|
|
|
*/
|
2020-03-31 08:55:18 +00:00
|
|
|
function fetchPackageInfo(module_name) {
|
2020-11-11 09:27:43 +00:00
|
|
|
var content = ''
|
2020-03-02 16:57:19 +00:00
|
|
|
try {
|
2021-07-10 10:29:44 +00:00
|
|
|
content = fetchContent(MS_NODE_REGISTRY + '/' + module_name)
|
2022-04-19 09:20:43 +00:00
|
|
|
} catch (ex) {
|
|
|
|
console.warn('can\'t fetch package ' + module_name + ' from ' + MS_NODE_REGISTRY + ' registry. try fetch from ' + FALLBACK_NODE_REGISTRY + ' registry...')
|
|
|
|
content = fetchContent(FALLBACK_NODE_REGISTRY + '/' + module_name)
|
2020-03-02 16:57:19 +00:00
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
return JSON.parse(content)
|
|
|
|
}
|
|
|
|
|
2022-04-19 09:20:43 +00:00
|
|
|
function fetchContent(url, timeout) {
|
|
|
|
timeout = timeout || 10
|
|
|
|
return executor.submit(new Callable(function fetchContent() {
|
2021-07-10 10:29:44 +00:00
|
|
|
var input = new URL(url).openStream()
|
|
|
|
var output = new ByteArrayOutputStream()
|
|
|
|
var buffer = new ByteArray(1024)
|
|
|
|
try {
|
|
|
|
var n
|
|
|
|
while ((n = input.read(buffer)) !== -1) {
|
|
|
|
output.write(buffer, 0, n)
|
|
|
|
}
|
|
|
|
return output.toString("UTF-8")
|
|
|
|
} finally {
|
2022-04-19 09:20:43 +00:00
|
|
|
input.close()
|
2021-07-10 10:29:44 +00:00
|
|
|
output.close()
|
|
|
|
}
|
2022-04-19 09:20:43 +00:00
|
|
|
})).get(timeout, TimeUnit.SECONDS)
|
2020-03-02 16:57:19 +00:00
|
|
|
}
|
|
|
|
|
2020-05-02 16:31:59 +00:00
|
|
|
var lastModule = ''
|
2021-06-22 07:05:27 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 检查核心模块
|
|
|
|
* @param {string} name
|
2020-05-14 11:12:03 +00:00
|
|
|
* @param {string} path
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
2020-12-17 08:17:16 +00:00
|
|
|
function checkCoreModule(name, path, optional) {
|
2020-05-02 16:31:59 +00:00
|
|
|
if (name.startsWith('@ms') && lastModule.endsWith('.js')) {
|
2020-05-14 11:12:03 +00:00
|
|
|
console.warn(lastModule + ' load deprecated module ' + name + ' auto replace to ' + (name = name.replace('@ms', global.scope)) + '...')
|
2020-11-11 09:27:43 +00:00
|
|
|
return name
|
2020-05-02 16:31:59 +00:00
|
|
|
} else {
|
|
|
|
lastModule = name
|
|
|
|
}
|
2020-06-23 05:39:00 +00:00
|
|
|
if (CoreModules.indexOf(name) !== -1) {
|
2020-05-14 11:12:03 +00:00
|
|
|
var newName = global.scope + '/nodejs/dist/' + name
|
2020-12-17 08:17:16 +00:00
|
|
|
if (resolve(newName, path, optional) !== undefined) {
|
2020-11-11 09:27:43 +00:00
|
|
|
return newName
|
2020-03-31 08:55:18 +00:00
|
|
|
}
|
2020-05-14 11:12:03 +00:00
|
|
|
throw new Error("Can't load nodejs core module " + name + " . maybe later will auto replace to " + global.scope + "/nodejs/" + name + ' to compatible...')
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
return name
|
2020-01-17 10:39:23 +00:00
|
|
|
}
|
2021-06-22 07:05:27 +00:00
|
|
|
|
2020-12-17 08:17:16 +00:00
|
|
|
/**
|
|
|
|
* 检查缓存模块
|
|
|
|
*/
|
|
|
|
function checkCacheModule(optional) {
|
2020-12-17 10:34:57 +00:00
|
|
|
return optional.local ? cacheModuleIds[optional.parentId] && cacheModuleIds[optional.parentId][optional.path] : cacheModuleIds[optional.path]
|
2020-12-17 08:17:16 +00:00
|
|
|
}
|
2021-06-22 07:05:27 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 加载模块
|
|
|
|
* @param {string} name 模块名称
|
|
|
|
* @param {string} path 路径
|
|
|
|
* @param {any} optional 附加选项
|
|
|
|
* @returns {*}
|
|
|
|
*/
|
|
|
|
function _require(name, path, optional) {
|
2020-12-17 10:34:57 +00:00
|
|
|
// require direct file
|
|
|
|
var file = _isFile(name) ? name : new File(name)
|
2021-06-22 07:05:27 +00:00
|
|
|
if (_isFile(file)) {
|
|
|
|
return _requireFile(file, optional)
|
|
|
|
}
|
2020-12-17 10:34:57 +00:00
|
|
|
// require cache module
|
2020-12-17 08:17:16 +00:00
|
|
|
var cachePath = checkCacheModule(optional)
|
2020-12-17 10:34:57 +00:00
|
|
|
var cacheFile = new File(cachePath)
|
2021-06-22 07:05:27 +00:00
|
|
|
if (cachePath && cacheFile.exists()) {
|
|
|
|
return _requireFile(cacheFile, optional)
|
|
|
|
}
|
2022-04-19 09:20:43 +00:00
|
|
|
// check core module
|
2020-12-17 08:17:16 +00:00
|
|
|
name = checkCoreModule(name, path, optional)
|
2022-04-19 09:20:43 +00:00
|
|
|
// search module
|
2020-12-17 10:34:57 +00:00
|
|
|
if ((file = resolve(name, path, optional)) === undefined) {
|
2020-12-17 08:17:16 +00:00
|
|
|
// excloud local dir, prevent too many recursive call and cache not found module
|
|
|
|
if (optional.local || optional.recursive || notFoundModules[name]) {
|
|
|
|
throw new Error("Can't found module " + name + '(' + JSON.stringify(optional) + ') at local ' + path + ' or network!')
|
|
|
|
}
|
2020-01-31 18:41:24 +00:00
|
|
|
try {
|
2020-11-11 09:27:43 +00:00
|
|
|
optional.recursive = true
|
|
|
|
return _require(download(name), path, optional)
|
2020-01-31 18:41:24 +00:00
|
|
|
} catch (ex) {
|
2020-11-11 09:27:43 +00:00
|
|
|
notFoundModules[name] = true
|
2021-06-22 06:03:16 +00:00
|
|
|
throw new Error("Can't found module " + name + ' in directory ' + path + ' ERROR: ' + ex)
|
2019-09-23 16:19:39 +00:00
|
|
|
}
|
2019-09-23 10:46:32 +00:00
|
|
|
}
|
2020-12-17 10:34:57 +00:00
|
|
|
setCacheModule(file, optional)
|
2020-12-17 08:17:16 +00:00
|
|
|
return _requireFile(file, optional)
|
|
|
|
}
|
|
|
|
|
2020-12-17 10:34:57 +00:00
|
|
|
/**
|
|
|
|
* 设置模块缓存
|
2021-06-22 07:05:27 +00:00
|
|
|
* @param {any} file
|
|
|
|
* @param {any} optional
|
2020-12-17 10:34:57 +00:00
|
|
|
*/
|
|
|
|
function setCacheModule(file, optional) {
|
|
|
|
if (optional.local) {
|
|
|
|
var parent = cacheModuleIds[optional.parentId]
|
2021-06-22 07:05:27 +00:00
|
|
|
if (!parent) {
|
|
|
|
cacheModuleIds[optional.parentId] = {}
|
|
|
|
}
|
2020-12-17 10:34:57 +00:00
|
|
|
return cacheModuleIds[optional.parentId][optional.path] = _canonical(file)
|
|
|
|
}
|
|
|
|
return cacheModuleIds[optional.path] = _canonical(file)
|
|
|
|
}
|
|
|
|
|
2020-12-17 08:17:16 +00:00
|
|
|
function _requireFile(file, optional) {
|
2020-01-31 18:41:24 +00:00
|
|
|
// 重定向文件名称和类型
|
2022-04-19 09:20:43 +00:00
|
|
|
return getCacheModule(_canonical(file), file, optional)
|
2017-10-10 13:01:43 +00:00
|
|
|
}
|
2017-09-23 09:42:16 +00:00
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* 闭包方法
|
|
|
|
* @param {string} parent 父目录
|
|
|
|
* @param {string} parentId
|
|
|
|
* @returns {Function}
|
|
|
|
*/
|
|
|
|
function exports(parent, parentId) {
|
2020-06-23 05:39:00 +00:00
|
|
|
/**
|
|
|
|
* @param {string} path
|
|
|
|
* @param {any} optional
|
|
|
|
*/
|
|
|
|
return function __DynamicRequire__(path, optional) {
|
2021-06-22 07:05:27 +00:00
|
|
|
if (!path) {
|
|
|
|
throw new Error('require path can\'t be undefined or empty!')
|
|
|
|
}
|
|
|
|
return _require(path, parent, __assign({
|
|
|
|
cache: true,
|
|
|
|
parentId: parentId,
|
|
|
|
parent: parent,
|
|
|
|
path: path,
|
|
|
|
local: path.startsWith('.') || path.startsWith('/')
|
|
|
|
}, optional)).exports
|
2020-06-23 05:39:00 +00:00
|
|
|
}
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2020-06-23 05:39:00 +00:00
|
|
|
|
2020-05-14 11:12:03 +00:00
|
|
|
/**
|
2021-03-26 07:54:26 +00:00
|
|
|
* @param {string} path
|
2020-12-17 08:17:16 +00:00
|
|
|
* @param {any} optional 附加选项
|
2020-05-14 11:12:03 +00:00
|
|
|
*/
|
2021-03-26 07:54:26 +00:00
|
|
|
function __DynamicResolve__(path, optional) {
|
2021-06-22 07:05:27 +00:00
|
|
|
return _canonical(new File(resolve(path, parent, __assign({
|
|
|
|
cache: true,
|
|
|
|
parent: parent,
|
|
|
|
local: path.startsWith('.') || path.startsWith('/')
|
|
|
|
}, optional))))
|
2020-05-14 11:12:03 +00:00
|
|
|
}
|
2020-06-23 05:39:00 +00:00
|
|
|
|
2020-05-14 11:12:03 +00:00
|
|
|
/**
|
|
|
|
* @param {string} name
|
|
|
|
*/
|
|
|
|
function __DynamicClear__(name) {
|
|
|
|
for (var cacheModule in cacheModules) {
|
2020-06-23 05:39:00 +00:00
|
|
|
if (cacheModule.indexOf(name) !== -1) {
|
2020-05-14 11:12:03 +00:00
|
|
|
console.trace('Clear module ' + cacheModule + ' ...')
|
|
|
|
delete cacheModules[cacheModule]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-23 05:39:00 +00:00
|
|
|
|
2020-05-14 11:12:03 +00:00
|
|
|
function __DynamicDisable__() {
|
2020-12-17 10:34:57 +00:00
|
|
|
base.save(cacheModuleIdsFile, JSON.stringify(upgradeMode ? {} : cacheModuleIds))
|
2020-05-14 11:12:03 +00:00
|
|
|
for (var cacheModule in cacheModules) {
|
|
|
|
delete cacheModules[cacheModule]
|
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
cacheModules = undefined
|
2020-06-23 05:39:00 +00:00
|
|
|
for (var cacheModuleId in cacheModuleIds) {
|
|
|
|
delete cacheModuleIds[cacheModuleId]
|
2020-05-14 11:12:03 +00:00
|
|
|
}
|
2020-11-11 09:27:43 +00:00
|
|
|
cacheModuleIds = undefined
|
|
|
|
notFoundModules = undefined
|
2020-05-14 11:12:03 +00:00
|
|
|
}
|
2020-06-23 05:39:00 +00:00
|
|
|
|
2020-12-17 10:34:57 +00:00
|
|
|
function __setUpgradeMode__(status) {
|
|
|
|
upgradeMode = status
|
|
|
|
}
|
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* @param {string} parent
|
|
|
|
* @param {string} parentId
|
|
|
|
*/
|
|
|
|
function getRequire(parent, parentId) {
|
|
|
|
/**
|
|
|
|
* @type {any} require
|
|
|
|
*/
|
|
|
|
var require = exports(parent, parentId)
|
2020-05-14 11:12:03 +00:00
|
|
|
require.resolve = __DynamicResolve__
|
|
|
|
require.clear = __DynamicClear__
|
|
|
|
require.disable = __DynamicDisable__
|
2020-12-17 10:34:57 +00:00
|
|
|
require.setUpgradeMode = __setUpgradeMode__
|
2022-04-19 09:20:43 +00:00
|
|
|
require.loader = {
|
|
|
|
register: registerLoader,
|
|
|
|
get: getLoader,
|
|
|
|
unregister: unregisterLoader,
|
|
|
|
}
|
2022-02-16 06:36:22 +00:00
|
|
|
require.internal = {
|
|
|
|
coreModules: CoreModules,
|
|
|
|
cacheModules: cacheModules,
|
|
|
|
cacheModuleIds: cacheModuleIds,
|
|
|
|
notFoundModules: notFoundModules,
|
2022-04-19 09:20:43 +00:00
|
|
|
requireLoaders: requireLoaders
|
|
|
|
}
|
|
|
|
return require
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} ext
|
|
|
|
* @param {any} loader
|
|
|
|
*/
|
|
|
|
function registerLoader(ext, loader) {
|
|
|
|
requireLoaders[ext] = loader
|
|
|
|
console.info('Register Require Loader ' + ext + ' => ' + (loader.name || '<anonymous>') + '.')
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @param {*} ext
|
|
|
|
*/
|
|
|
|
function getLoader(ext) {
|
|
|
|
return requireLoaders[ext]
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @param {*} ext
|
|
|
|
*/
|
|
|
|
function unregisterLoader(ext) {
|
|
|
|
delete requireLoaders[ext]
|
|
|
|
console.info('unregister Require Loader ' + ext + '.')
|
|
|
|
}
|
|
|
|
|
|
|
|
function printRequireInfo() {
|
|
|
|
console.info('Initialization require module.')
|
|
|
|
console.info('ParentDir:', _canonical(parent))
|
|
|
|
console.info('Require module env list:')
|
|
|
|
console.info('- MS_NODE_PATH:', MS_NODE_PATH.startsWith(root) ? MS_NODE_PATH.split(root)[1] : MS_NODE_PATH)
|
|
|
|
console.info('- MS_NODE_REGISTRY:', MS_NODE_REGISTRY)
|
|
|
|
console.info('- FALLBACK_NODE_REGISTRY:', FALLBACK_NODE_REGISTRY)
|
|
|
|
}
|
|
|
|
|
|
|
|
function initCacheModuleIds() {
|
|
|
|
try {
|
|
|
|
cacheModuleIds = JSON.parse(base.read(cacheModuleIdsFile))
|
|
|
|
if (cacheModuleIds['@ccms-cache-module-root'] != MS_NODE_PATH) {
|
|
|
|
throw new Error('canonicalRoot Change ' + cacheModuleIds['@ccms-cache-module-root'] + ' to ' + MS_NODE_PATH + ' Clear Cache!')
|
|
|
|
}
|
|
|
|
console.log('Read cacheModuleIds from file', cacheModuleIdsFile.startsWith(root) ? cacheModuleIdsFile.split(root)[1] : cacheModuleIdsFile)
|
|
|
|
} catch (error) {
|
|
|
|
cacheModuleIds = {}
|
|
|
|
cacheModuleIds['@ccms-cache-module-root'] = MS_NODE_PATH
|
|
|
|
console.log('Initialization new cacheModuleIds: ' + error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function initVersionLock() {
|
|
|
|
try {
|
|
|
|
ModulesVersionLock = JSON.parse(fetchContent('https://ms.yumc.pw/api/plugin/download/name/version_lock', 5))
|
|
|
|
try {
|
|
|
|
ModulesVersionLock = __assign(ModulesVersionLock, JSON.parse(base.read(localVersionLockFile)))
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.warn("无法获取到最新的版本锁定信息 使用默认配置.")
|
|
|
|
console.warn("InitVersionLock Error:", error)
|
|
|
|
console.debug(error)
|
|
|
|
ModulesVersionLock = { "@babel/standalone": "7.12.18", "crypto-js": "3.3.0" }
|
|
|
|
}
|
|
|
|
console.info('Lock module version List:')
|
|
|
|
for (var key in ModulesVersionLock) {
|
|
|
|
console.info('- ' + key + ': ' + ModulesVersionLock[key])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function initRequireLoader(require) {
|
|
|
|
registerLoader('js', compileJsFile)
|
|
|
|
registerLoader('json', compileJson)
|
|
|
|
try {
|
|
|
|
engineLoad({
|
|
|
|
script: fetchContent('https://ms.yumc.pw/api/plugin/download/name/require_loader', 5),
|
|
|
|
name: 'core/require_loader.js'
|
|
|
|
})(require)
|
|
|
|
} catch (error) {
|
|
|
|
console.warn("无法获取到最新的加载器信息 使用默认配置.")
|
|
|
|
console.warn("InitRequireLoader Error:", error)
|
|
|
|
console.debug(error)
|
|
|
|
registerLoader('ms', compileJsFile)
|
2022-02-16 06:36:22 +00:00
|
|
|
}
|
2020-05-14 11:12:03 +00:00
|
|
|
return require
|
2020-01-17 10:39:23 +00:00
|
|
|
}
|
|
|
|
|
2020-01-31 18:41:24 +00:00
|
|
|
if (typeof parent === 'string') {
|
2020-11-11 09:27:43 +00:00
|
|
|
parent = new File(parent)
|
2020-01-31 18:41:24 +00:00
|
|
|
}
|
2022-04-19 09:20:43 +00:00
|
|
|
/**
|
|
|
|
* @type {{[key:string]:(module:any, file:string, optional?:any)=>any}} requireLoader
|
|
|
|
*/
|
|
|
|
var requireLoaders = {}
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
|
|
|
* @type {{[key:string]:any}} cacheModules
|
|
|
|
*/
|
2020-11-11 09:27:43 +00:00
|
|
|
var cacheModules = {}
|
2022-04-19 09:20:43 +00:00
|
|
|
var cacheModuleIdsFile = _canonical(new File(MS_NODE_PATH, 'cacheModuleIds.json'))
|
|
|
|
var localVersionLockFile = _canonical(new File(MS_NODE_PATH, 'moduleVersionLock.json'))
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
2022-02-16 06:36:22 +00:00
|
|
|
* @type {{[key:string]:{[key:string]:string}|string}} cacheModuleIds
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
2020-11-11 09:27:43 +00:00
|
|
|
var cacheModuleIds = {}
|
2020-01-31 18:41:24 +00:00
|
|
|
/**
|
2020-03-31 08:55:18 +00:00
|
|
|
* @type {{[key:string]:boolean}} notFoundModules
|
2020-01-31 18:41:24 +00:00
|
|
|
*/
|
2020-11-11 09:27:43 +00:00
|
|
|
var notFoundModules = {}
|
2020-12-17 10:34:57 +00:00
|
|
|
var upgradeMode = false
|
2021-07-10 10:29:44 +00:00
|
|
|
var executor = Executors.newSingleThreadExecutor(function (r) {
|
|
|
|
return new Thread(r, "MiaoScript require thread")
|
|
|
|
})
|
2022-04-19 09:20:43 +00:00
|
|
|
|
|
|
|
printRequireInfo()
|
|
|
|
initCacheModuleIds()
|
|
|
|
initVersionLock()
|
|
|
|
|
|
|
|
return initRequireLoader(getRequire(parent, ""))
|
2020-11-11 09:27:43 +00:00
|
|
|
})
|