feat: add ts defiend

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2020-02-01 02:41:24 +08:00
parent 46925f9b52
commit 2a891c1117

View File

@ -24,291 +24,360 @@
* 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行 * 3. 如果 xx/index.json 存在 则使用 `xx/index.json` 解析为对象加载 并停止执行
* 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行 * 暂不支持 4. 如果 xx/index.msm 是一个文件 则使用MScript解析器解析 并停止执行
*/ */
(function(parent) { // @ts-check
'use strict'; /// <reference types="@ms/nashorn" />
var File = Java.type('java.io.File'); (
var Paths = Java.type('java.nio.file.Paths'); /**
var Files = Java.type('java.nio.file.Files'); * @param {any} parent
var StandardCopyOption = Java.type('java.nio.file.StandardCopyOption'); */
var FileNotFoundException = Java.type('java.io.FileNotFoundException'); function(parent) {
'use strict';
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');
var FileNotFoundException = Java.type('java.io.FileNotFoundException');
var TarInputStream = Java.type('org.kamranzafar.jtar.TarInputStream'); var TarInputStream = Java.type('org.kamranzafar.jtar.TarInputStream');
var GZIPInputStream = Java.type('java.util.zip.GZIPInputStream'); var GZIPInputStream = Java.type('java.util.zip.GZIPInputStream');
var BufferedInputStream = Java.type('java.io.BufferedInputStream'); var BufferedInputStream = Java.type('java.io.BufferedInputStream');
var URL = Java.type('java.net.URL') var URL = Java.type('java.net.URL')
var separatorChar = File.separatorChar; var JavaString = Java.type('java.lang.String')
var separatorChar = File.separatorChar;
var CoreModules = ['assert', 'async_hooks', 'child_process', 'cluster', 'crypto', 'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https', 'inspector', 'net', 'os', 'path', 'vm', 'url', 'util', 'zlib', 'worker_threads'] var CoreModules = ['assert', 'async_hooks', 'child_process', 'cluster', 'crypto', 'dns', 'domain', 'events', 'fs', 'http', 'http2', 'https', 'inspector', 'net', 'os', 'path', 'vm', 'url', 'util', 'zlib', 'worker_threads']
function __assign(t) { /**
for (var s, i = 1, n = arguments.length; i < n; i++) { * @param {...object} t
s = arguments[i]; */
if (s === undefined) { continue; }; function __assign(t) {
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) for (var s, i = 1, n = arguments.length; i < n; i++) {
t[p] = s[p]; s = arguments[i];
if (s === undefined) { continue; };
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
/**
* 判断是否为一个文件
* @param {any} file
* @returns {*}
*/
function _isFile(file) {
return file.isFile && file.isFile();
} }
return t;
};
/** /**
* 判断是否为一个文件 * 获得文件规范路径
* @param file * @param {any} file
* @returns {*} * @returns {*}
*/ */
function _isFile(file) { function _canonical(file) {
return file.isFile && file.isFile(); return file.canonicalPath;
}
/**
* 获得文件规范路径
* @param file
* @returns {*}
*/
function _canonical(file) {
return file.canonicalPath;
}
/**
* 获得文件绝对路径
* @param file
* @returns {*}
*/
function _absolute(file) {
return file.absolutePath;
}
/**
* 解析模块名称为文件
* 按照下列顺序查找
* 当前目录 ./
* 父目录 ../
* 模块目录 /node_modules
* @param name 模块名称
* @param parent 父目录
*/
function resolve(name, parent) {
name = _canonical(name) || name;
// 解析本地目录
if (name.startsWith('./') || name.startsWith('../')) {
return resolveAsFile(name, parent) || resolveAsDirectory(name, parent) || undefined;
} else {
// 解析Node目录
var dir = [parent, 'node_modules'].join(separatorChar);
if (cacheModuleIds[name]) return cacheModuleIds[name]
cacheModuleIds[name] = resolveAsFile(name, dir) || resolveAsDirectory(name, dir) ||
(parent && parent.toString().startsWith(root) ? resolve(name, new File(parent).getParent()) : undefined);
return cacheModuleIds[name];
} }
}
/** /**
* 解析文件 * 获得文件绝对路径
* @param file 文件 * @param {any} file
* @param dir 目录 * @returns {*}
* @returns {*} */
*/ function _absolute(file) {
function resolveAsFile(file, dir) { return file.absolutePath;
file = dir != undefined ? new File(dir, file) : new File(file);
// 直接文件
if (file.isFile()) {
return file;
} }
// JS文件
var js = new File(normalizeName(_absolute(file), '.js'));
if (js.isFile()) {
return js;
}
// JSON文件
var json = new File(normalizeName(_absolute(file), '.json'));
if (json.isFile()) {
return json;
}
}
/** /**
* 解析目录 * 解析模块名称为文件
* @param file 文件 * 按照下列顺序查找
* @param dir 目录 * 当前目录 ./
* @returns {*} * 父目录 ../
*/ * 模块目录 /node_modules
function resolveAsDirectory(file, dir) { * @param {string} name 模块名称
dir = dir != undefined ? new File(dir, file) : new File(file); * @param {string} parent 父目录
var _package = new File(dir, 'package.json'); */
if (_package.exists()) { function resolve(name, parent) {
var json = JSON.parse(base.read(_package)); name = _canonical(name) || name;
if (json.main) { // 解析本地目录
return resolveAsFile(json.main, dir); if (name.startsWith('./') || name.startsWith('../')) {
return resolveAsFile(name, parent) || resolveAsDirectory(name, parent) || undefined;
} else {
// 解析Node目录
var dir = [parent, 'node_modules'].join(separatorChar);
if (cacheModuleIds[name]) return cacheModuleIds[name]
cacheModuleIds[name] = resolveAsFile(name, dir) || resolveAsDirectory(name, dir) ||
// @ts-ignore
(parent && parent.toString().startsWith(root) ? resolve(name, new File(parent).getParent()) : undefined);
return cacheModuleIds[name];
} }
} }
// if no package or package.main exists, look for index.js
return resolveAsFile('index.js', dir);
}
/** /**
* 后缀检测和添加 * 解析文件
* @param fileName 文件名称 * @param {string} file 文件
* @param ext 后缀 * @param {string | undefined} dir 目录
* @returns {*} * @returns {*}
*/ */
function normalizeName(fileName, ext) { function resolveAsFile(file, dir) {
var extension = ext || '.js'; file = dir != undefined ? new File(dir, file) : new File(file);
if (fileName.endsWith(extension)) { // 直接文件
return fileName; // @ts-ignore
if (file.isFile()) {
return file;
}
// JS文件
var js = new File(normalizeName(_absolute(file), '.js'));
if (js.isFile()) {
return js;
}
// JSON文件
var json = new File(normalizeName(_absolute(file), '.json'));
if (json.isFile()) {
return json;
}
} }
return fileName + extension;
}
/** /**
* 编译模块 * 解析目录
* @param id 模块ID * @param {string} file 文件
* @param name 模块名称 * @param {string | undefined} dir 目录
* @param file 模块文件 * @returns {*}
* @param optional 附加选项 */
* @returns {Object} function resolveAsDirectory(file, dir) {
*/ dir = dir != undefined ? new File(dir, file) : new File(file);
function getCacheModule(id, name, file, optional) { var _package = new File(dir, 'package.json');
var module = cacheModules[id]; if (_package.exists()) {
if (optional.cache && module) { // @ts-ignore
var json = JSON.parse(base.read(_package));
if (json.main) {
return resolveAsFile(json.main, dir);
}
}
// if no package or package.main exists, look for index.js
return resolveAsFile('index.js', dir);
}
/**
* 后缀检测和添加
* @param {string} fileName 文件名称
* @param {string} ext 后缀
* @returns {*}
*/
function normalizeName(fileName, ext) {
var extension = ext || '.js';
if (fileName.endsWith(extension)) {
return fileName;
}
return fileName + extension;
}
/**
* 检查模块缓存
* @param {string} id 模块ID
* @param {string} name 模块名称
* @param {any} file 模块文件
* @param {any} optional 附加选项
* @returns {Object}
*/
function getCacheModule(id, name, file, optional) {
var module = cacheModules[id];
if (optional.cache && module) {
return module;
}
return createModule(id, name, file, optional)
}
/**
* 编译模块
* @param {string} id 模块ID
* @param {string} name 模块名称
* @param {any} file 模块文件
* @param {any} optional 附加选项
* @returns {Object}
*/
function createModule(id, name, file, optional) {
console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(optional));
var module = {
id: id,
exports: {},
loaded: false,
require: getRequire(file.parentFile, id)
};
cacheModules[id] = module;
var cfile = _canonical(file);
if (cfile.endsWith('.js')) {
compileJs(module, file, optional);
} else if (cfile.endsWith('.json')) {
compileJson(module, file);
} else if (cfile.endsWith('.msm')) {
throw Error('Unsupported MiaoScript module!');
} else {
throw Error('Unknown file type ' + cfile);
}
return module; return module;
} }
console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(optional));
module = { /**
id: id, * 预编译JS
exports: {}, * @param {any} module JS模块
loaded: false, * @param {any} file JS文件
require: getRequire(file.parentFile) * @param {any} optional 附加选项
}; * @returns {void}
cacheModules[id] = module; */
var cfile = _canonical(file); function compileJs(module, file, optional) {
if (cfile.endsWith('.js')) { // @ts-ignore
compileJs(module, file, optional); var origin = base.read(file);
} else if (cfile.endsWith('.json')) { if (optional.hook) {
compileJson(module, file); origin = optional.hook(origin);
} else if (cfile.endsWith('.msm')) { }
throw Error('Unsupported MiaoScript module!'); // 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
} else { // @ts-ignore
throw Error('Unknown file type ' + cfile); var compiledWrapper = engineLoad({ script: '(function $(module, exports, require, __dirname, __filename) {' + origin + '});', name: file });
compiledWrapper.apply(module.exports, [
module, module.exports, module.require, file.parentFile, file
]);
module.loaded = true;
} }
return module;
}
/** /**
* 预编译JS * 预编译Json
* @param module JS模块 * @param {{ id?: string | null; exports?: {}; loaded: any; require?: any; }} module Json模块
* @param file JS文件 * @param {any} file Json 文件
* @param optional 附加选项 * @returns {void}
* @returns {Object} */
*/ function compileJson(module, file) {
function compileJs(module, file, optional) { // @ts-ignore
var origin = base.read(file); module.exports = JSON.parse(base.read(file));
if (optional.hook) { module.loaded = true;
origin = optional.hook(origin);
} }
// 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
var compiledWrapper = engineLoad({ script: '(function $(module, exports, require, __dirname, __filename) {' + origin + '});', name: file });
compiledWrapper.apply(module.exports, [
module, module.exports, module.require, file.parentFile, file
]);
module.loaded = true;
}
/** /**
* 预编译Json * 尝试从网络下载依赖包
* @param module Json模块 * @param {string} name 包名称
* @param file Json 文件 */
* @returns {Object} function download(name) {
*/ // handle name es6-map/implement => es6-map @ms/common/dist/reflect => @ms/common
function compileJson(module, file) { var name_arr = name.split('/');
module.exports = JSON.parse(base.read(file)); var module_name = name.startsWith('@') ? name_arr[0] + '/' + name_arr[1] : name_arr[0];
module.loaded = true; // at windows need replace file name java.lang.IllegalArgumentException: Invalid prefix or suffix
} var tempFile = Files.createTempFile(module_name.replace('/', '_'), '.json');
Files.copy(new URL('https://repo.yumc.pw/repository/npm/' + module_name).openStream(), tempFile, StandardCopyOption.REPLACE_EXISTING);
/** var info = JSON.parse(new JavaString(Files.readAllBytes(tempFile), 'UTF-8')); tempFile.toFile().deleteOnExit();
* 尝试从网络下载依赖包 var url = info.versions[info['dist-tags']['latest']].dist.tarball;
* @param name 包名称 console.log('node_module ' + module_name + ' not found at local but exist at internet ' + url + ' downloading...')
*/ var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new URL(url).openStream())));
function download(name) { // @ts-ignore
// handle name es6-map/implement => es6-map @ms/common/dist/reflect => @ms/common var entry; var target = root + separatorChar + 'node_modules' + separatorChar + module_name;
var name_arr = name.split('/'); while ((entry = tis.getNextEntry()) != null) {
var module_name = name.startsWith('@') ? name_arr[0] + '/' + name_arr[1] : name_arr[0]; var targetPath = Paths.get(target + separatorChar + entry.getName().substring('package/'.length));
// at windows need replace file name java.lang.IllegalArgumentException: Invalid prefix or suffix targetPath.toFile().getParentFile().mkdirs();
var tempFile = Files.createTempFile(module_name.replace('/', '_'), '.json'); Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING);
Files.copy(new URL('https://repo.yumc.pw/repository/npm/' + module_name).openStream(), tempFile, StandardCopyOption.REPLACE_EXISTING); }
var info = JSON.parse(new java.lang.String(Files.readAllBytes(tempFile), 'UTF-8')); tempFile.toFile().deleteOnExit(); return name;
var url = info.versions[info['dist-tags']['latest']].dist.tarball;
console.log('node_module ' + module_name + ' not found at local but exist at internet ' + url + ' downloading...')
var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new URL(url).openStream())));
var entry; var target = root + separatorChar + 'node_modules' + separatorChar + module_name;
while ((entry = tis.getNextEntry()) != null) {
var targetPath = Paths.get(target + separatorChar + entry.getName().substring('package/'.length));
targetPath.toFile().getParentFile().mkdirs();
Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING);
} }
return name;
}
function checkCoreModule(name) { /**
if (CoreModules.indexOf(name) != -1) { * 检查核心模块
throw new Error("Can't load nodejs core module " + name + " . maybe later will auto replace to @ms/" + name + ' to compatible...') * @param {string} name
} */
} function checkCoreModule(name) {
if (CoreModules.indexOf(name) != -1) {
/** throw new Error("Can't load nodejs core module " + name + " . maybe later will auto replace to @ms/" + name + ' to compatible...')
* 加载模块
* @param name 模块名称
* @param path 路径
* @param optional 附加选项
* @returns {*}
*/
function _require(name, path, optional) {
checkCoreModule(name);
var file = new File(name);
file = _isFile(file) ? file : resolve(name, path);
optional = __assign({ cache: true }, optional);
if (file === undefined) {
try {
// excloud local dir, prevent too many recursive call and cache not found module
if (name.startsWith('.') || name.startsWith('/') || optional.recursive || notFoundModules[name]) {
console.log(name, path, optional, notFoundModules[name])
throw new Error("Can't found module " + name + ' at local or network!')
}
optional.recursive = true;
return _require(download(name), path, optional);
} catch (ex) {
notFoundModules[name] = true;
throw new FileNotFoundException("Can't found module " + name + ' in directory ' + path + ' ERROR: ' + ex)
} }
} }
// 重定向文件名称和类型
return getCacheModule(_canonical(file), file.name.split('.')[0], file, optional);
}
/** /**
* 闭包方法 * 加载模块
* @param parent 父目录 * @param {string} name 模块名称
* @returns {Function} * @param {string} path 路径
*/ * @param {any} optional 附加选项
function exports(parent) { * @returns {*}
return function __DynamicRequire__(path, optional) { */
return _require(path, parent, optional).exports; function _require(name, path, optional) {
}; checkCoreModule(name);
} var file = new File(name);
file = _isFile(file) ? file : resolve(name, path);
function getRequire(parent) { optional = __assign({ cache: true }, optional);
var require = exports(parent) if (file === undefined) {
require.resolve = function __DynamicResolve__(name) { try {
return _canonical(new File(resolve(name, parent))) // excloud local dir, prevent too many recursive call and cache not found module
if (name.startsWith('.') || name.startsWith('/') || optional.recursive || notFoundModules[name]) {
console.log(name, path, optional, notFoundModules[name])
throw new Error("Can't found module " + name + '(' + JSON.stringify(optional) + ') at local ' + path + ' or network!')
}
optional.recursive = true;
return _require(download(name), path, optional);
} catch (ex) {
notFoundModules[name] = true;
throw new FileNotFoundException("Can't found module " + name + ' in directory ' + path + ' ERROR: ' + ex)
}
}
// 重定向文件名称和类型
return getCacheModule(_canonical(file), file.name.split('.')[0], file, optional);
} }
return require;
}
if (typeof parent === 'string') { /**
parent = new File(parent); * 闭包方法
} * @param {string} parent 父目录
var cacheModules = []; * @param {string} parentId
var cacheModuleIds = []; * @returns {Function}
var notFoundModules = []; */
console.info('Initialization require module... ParentDir:', _canonical(parent)); function exports(parent, parentId) {
return getRequire(parent); var __DynamicRequire__ =
}); /**
* @param {string} path
* @param {any} optional
*/
function __DynamicRequire__(path, optional) {
return _require(path, parent, __assign({ parentId: parentId }, optional)).exports;
}
return __DynamicRequire__
}
/**
* @param {string} parent
* @param {string} parentId
*/
function getRequire(parent, parentId) {
/**
* @type {any} require
*/
var require = exports(parent, parentId)
require.resolve =
/**
* @param {string} name
*/
function __DynamicResolve__(name) {
return _canonical(new File(resolve(name, parent)))
}
require.clear =
/**
* @param {string} name
*/
function __DynamicClear__(name) {
var moduleId = require.resolve(name)
console.trace('Clear module ' + name + '(' + moduleId + ') ...')
return delete cacheModules[moduleId]
}
return require;
}
if (typeof parent === 'string') {
parent = new File(parent);
}
/**
* @type {{[key:string]:any}} cacheModules
*/
var cacheModules = {};
/**
* @type {{[key:string]:string}} cacheModules
*/
var cacheModuleIds = {};
/**
* @type {{[key:string]:boolean}} cacheModules
*/
var notFoundModules = {};
console.info('Initialization require module. ParentDir:', _canonical(parent));
return getRequire(parent, "null");
});