feat: add node-shim & move plugin interface
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
		@@ -26,7 +26,8 @@ export namespace plugin {
 | 
				
			|||||||
        enable(...args: any[]): void;
 | 
					        enable(...args: any[]): void;
 | 
				
			||||||
        disable(...args: any[]): void;
 | 
					        disable(...args: any[]): void;
 | 
				
			||||||
        reload(...args: any[]): void;
 | 
					        reload(...args: any[]): void;
 | 
				
			||||||
        getPlugins(): Map<string, any>;
 | 
					        getPlugin(name: string): plugin.Plugin;
 | 
				
			||||||
 | 
					        getPlugins(): Map<string, plugin.Plugin>;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    export interface Plugin {
 | 
					    export interface Plugin {
 | 
				
			||||||
        description: PluginMetadata;
 | 
					        description: PluginMetadata;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,196 +1,204 @@
 | 
				
			|||||||
 | 
					/// <reference types="@ccms/types/dist/typings/jdk" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 反射工具类
 | 
					 * 反射工具类
 | 
				
			||||||
 * Created by MiaoWoo on 2017/2/9 0009.
 | 
					 * Created by MiaoWoo on 2017/2/9 0009.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const JavaClass = Java.type('java.lang.Class');
 | 
					const JavaClass = Java.type('java.lang.Class')
 | 
				
			||||||
const JavaObject = Java.type('java.lang.Object')
 | 
					const JavaObject = Java.type('java.lang.Object')
 | 
				
			||||||
const NoSuchFieldException = Java.type('java.lang.NoSuchFieldException');
 | 
					const NoSuchFieldException = Java.type('java.lang.NoSuchFieldException')
 | 
				
			||||||
const methodCache = [];
 | 
					const methodCache = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Reflect {
 | 
					class Reflect {
 | 
				
			||||||
    private obj: any;
 | 
					    private obj: java.lang.Object
 | 
				
			||||||
    private class: any
 | 
					    private class: java.lang.Class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(obj: any) {
 | 
					    constructor(obj: any) {
 | 
				
			||||||
        // if (obj === undefined || obj === null) { throw Error(`reflect object can't be ${obj}!`) }
 | 
					        // if (obj === undefined || obj === null) { throw Error(`reflect object can't be ${obj}!`) }
 | 
				
			||||||
        if (obj instanceof JavaClass) {
 | 
					        if (obj instanceof JavaClass) {
 | 
				
			||||||
            this.obj = null;
 | 
					            this.obj = null
 | 
				
			||||||
            this.class = obj;
 | 
					            this.class = obj
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this.obj = obj;
 | 
					            this.obj = obj
 | 
				
			||||||
            if (obj !== null && obj !== undefined && obj.class) {
 | 
					            if (obj !== null && obj !== undefined && obj.class) {
 | 
				
			||||||
                this.class = obj.class;
 | 
					                this.class = obj.class
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    method(...args: any[]) {
 | 
					    method(name: string, ...args: any[]) {
 | 
				
			||||||
        return declaredMethod(this.class, args[0], types(args.slice(1)));
 | 
					        return declaredMethod(this.class, name, args)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    methods() {
 | 
					    methods() {
 | 
				
			||||||
        return Java.from(declaredMethods(this.class));
 | 
					        return Java.from(declaredMethods(this.class))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    field(name): Reflect {
 | 
					    field(name: string | java.lang.String): Reflect {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            // Try getting a public field
 | 
					            // Try getting a public field
 | 
				
			||||||
            let field = this.class.field(name);
 | 
					            let field = this.class.getField(name)
 | 
				
			||||||
            return on(field.get(this.obj));
 | 
					            return on(field.get(this.obj))
 | 
				
			||||||
        } catch (ex) {
 | 
					        } catch (ex) {
 | 
				
			||||||
            // Try again, getting a non-public field
 | 
					            // Try again, getting a non-public field
 | 
				
			||||||
            return on(accessible(declaredField(this.class, name)).get(this.obj));
 | 
					            return on(accessible(declaredField(this.class, name)).get(this.obj))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fields(declared = false) {
 | 
					    fields(declared = false): java.lang.reflect.Field[] {
 | 
				
			||||||
        return Java.from(declared ? this.class.declaredFields : this.class.fields);
 | 
					        return Java.from(declared ? this.class.getDeclaredFields() : this.class.getFields())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    values(declared = false) {
 | 
					    values(declared = false) {
 | 
				
			||||||
        let cache = {};
 | 
					        return this.fields(declared).reduce((cache, field) => { return cache[field.getName()] = this.field(field.getName()).get() }, {}) as any
 | 
				
			||||||
        this.fields(declared).forEach(fed => cache[fed.name] = this.field(fed.name).get())
 | 
					 | 
				
			||||||
        return cache;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    call(...args): Reflect {
 | 
					    call(...args: any[]): Reflect {
 | 
				
			||||||
        let params = args.slice(1);
 | 
					        let params = args.slice(1)
 | 
				
			||||||
        let method = accessible(declaredMethod(this.class, args[0], types(params)));
 | 
					        let method = accessible(declaredMethod(this.class, args[0], ...types(params)))
 | 
				
			||||||
        let result = method.invoke(this.get(), params);
 | 
					        let result = method.invoke(this.get(), params)
 | 
				
			||||||
        return result && on(result);
 | 
					        return result && on(result)
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get(...args): Reflect | any {
 | 
					    get(): any
 | 
				
			||||||
        return args.length === 1 ? this.field(args[0]) : this.obj;
 | 
					    get(index: number, declared?: boolean): Reflect
 | 
				
			||||||
    };
 | 
					    get(prop: string): Reflect
 | 
				
			||||||
 | 
					    get(param?: string | number, declared: boolean = true): Reflect | any {
 | 
				
			||||||
 | 
					        if (param == undefined || param == null) return this.obj
 | 
				
			||||||
 | 
					        if (typeof param == "number") {
 | 
				
			||||||
 | 
					            return on(accessible(this.fields(declared)[param]).get(this.obj))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (typeof param == "string") {
 | 
				
			||||||
 | 
					            return this.field(param)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // noinspection JSUnusedGlobalSymbols
 | 
					    set(name: any, value: any): Reflect {
 | 
				
			||||||
    set(name, value): Reflect {
 | 
					        accessible(declaredField(this.class, name)).set(this.obj, value)
 | 
				
			||||||
        accessible(declaredField(this.class, name)).set(this.obj, value);
 | 
					        return this
 | 
				
			||||||
        return this;
 | 
					    }
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    create(...args): Reflect {
 | 
					    create(...args): Reflect {
 | 
				
			||||||
        return on(declaredConstructor(this.class, args).newInstance(args));
 | 
					        return on(declaredConstructor(this.class, args).newInstance(args))
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Get an array of types for an array of objects
 | 
					 * Get an array of types for an array of objects
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function types(values, def?) {
 | 
					function types(values: any[], def?: any) {
 | 
				
			||||||
    if (values === null) {
 | 
					    if (values === null) {
 | 
				
			||||||
        return [];
 | 
					        return []
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    let result: any[] = [];
 | 
					    let result: java.lang.Class[] = []
 | 
				
			||||||
    values.forEach(t => result.push((t || def) ? JavaObject.class : t instanceof JavaClass ? t : t.class));
 | 
					    values.forEach(t => result.push((t || def) ? JavaObject.class : t instanceof JavaClass ? t : t.class))
 | 
				
			||||||
    return result;
 | 
					    return result
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function accessible(accessible) {
 | 
					function accessible<T extends java.lang.reflect.AccessibleObject>(accessible: T): T {
 | 
				
			||||||
    if (accessible === null) {
 | 
					    if (accessible === null) {
 | 
				
			||||||
        return null;
 | 
					        return null
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!accessible.isAccessible()) {
 | 
					    if (!accessible.isAccessible()) {
 | 
				
			||||||
        accessible.setAccessible(true);
 | 
					        accessible.setAccessible(true)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return accessible;
 | 
					    return accessible
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function declaredConstructor(clazz, param) {
 | 
					function declaredConstructor(clazz, param) {
 | 
				
			||||||
    let constructor;
 | 
					    let constructor
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        constructor = clazz.getDeclaredConstructor(types(param));
 | 
					        constructor = clazz.getDeclaredConstructor(types(param))
 | 
				
			||||||
    } catch (ex) {
 | 
					    } catch (ex) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            constructor = clazz.getDeclaredConstructor(types(param, true));
 | 
					            constructor = clazz.getDeclaredConstructor(types(param, true))
 | 
				
			||||||
        } catch (ex) {
 | 
					        } catch (ex) {
 | 
				
			||||||
            constructor = clazz.getDeclaredConstructors()[0];
 | 
					            constructor = clazz.getDeclaredConstructors()[0]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return accessible(constructor);
 | 
					    return accessible(constructor)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function declaredField(clazz, name) {
 | 
					function declaredField(clazz: java.lang.Class, name: string | java.lang.String) {
 | 
				
			||||||
    if (!clazz) { throw Error(`target class can't be ${clazz}!`) }
 | 
					    if (!clazz) { throw Error(`target class can't be ${clazz}!`) }
 | 
				
			||||||
    let target = clazz;
 | 
					    let target = clazz
 | 
				
			||||||
    let field = null;
 | 
					    let field = null
 | 
				
			||||||
    // noinspection JSUnresolvedVariable
 | 
					    // noinspection JSUnresolvedVariable
 | 
				
			||||||
    while (target !== JavaObject.class) {
 | 
					    while (target !== JavaObject.class) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            field = target.getDeclaredField(name);
 | 
					            field = target.getDeclaredField(name)
 | 
				
			||||||
            if (field !== null) { break; }
 | 
					            if (field !== null) { break }
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
            if (target === undefined) { break; }
 | 
					            if (target === undefined) { break }
 | 
				
			||||||
            target = target.getSuperclass();
 | 
					            target = target.getSuperclass()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (field === null) {
 | 
					    if (field === null) {
 | 
				
			||||||
        throw new NoSuchFieldException(name + " is not found in " + clazz.name);
 | 
					        throw new NoSuchFieldException(name + " is not found in " + clazz.getName())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return field;
 | 
					    return field
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function declaredMethod(clazz, name, clazzs) {
 | 
					function declaredMethod(clazz: java.lang.Class, name: string, ...clazzs: any[]): java.lang.reflect.Method {
 | 
				
			||||||
    let key = clazz.name + '.' + name + ':' + (clazzs || []).join(':');
 | 
					    let key = clazz.getName() + '.' + name + ':' + (clazzs || []).join(':')
 | 
				
			||||||
    if (!methodCache[key]) {
 | 
					    if (!methodCache[key]) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            methodCache[key] = clazz.getMethod(name, clazzs);
 | 
					            methodCache[key] = clazz.getMethod(name, clazzs as any)
 | 
				
			||||||
        } catch (ex) {
 | 
					        } catch (ex) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                methodCache[key] = clazz.getDeclaredMethod(name, clazzs);
 | 
					                methodCache[key] = clazz.getDeclaredMethod(name, clazzs as any)
 | 
				
			||||||
            } catch (ex) {
 | 
					            } catch (ex) {
 | 
				
			||||||
                for (const m of Java.from(declaredMethods(clazz))) {
 | 
					                for (const m of Java.from(declaredMethods(clazz))) {
 | 
				
			||||||
                    if (m.name == name) {
 | 
					                    if (m.name == name) {
 | 
				
			||||||
                        methodCache[key] = m;
 | 
					                        methodCache[key] = m
 | 
				
			||||||
                        break;
 | 
					                        break
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return methodCache[key];
 | 
					    return methodCache[key]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function declaredMethods(clazz) {
 | 
					function declaredMethods(clazz) {
 | 
				
			||||||
    return clazz.declaredMethods;
 | 
					    return clazz.declaredMethods
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let classMethodsCache: any[] = [];
 | 
					let classMethodsCache: any[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function mapToObject(javaObj) {
 | 
					function mapToObject(javaObj) {
 | 
				
			||||||
    if (!javaObj || !javaObj.class) { throw new TypeError(`参数 ${javaObj} 不是一个Java对象!`) }
 | 
					    if (!javaObj || !javaObj.class) { throw new TypeError(`参数 ${javaObj} 不是一个Java对象!`) }
 | 
				
			||||||
    let target = {};
 | 
					    let target = {}
 | 
				
			||||||
    getJavaObjectMethods(javaObj).forEach(t => mapMethod(target, javaObj, t));
 | 
					    getJavaObjectMethods(javaObj).forEach(t => mapMethod(target, javaObj, t))
 | 
				
			||||||
    return target;
 | 
					    return target
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getJavaObjectMethods(javaObj) {
 | 
					function getJavaObjectMethods(javaObj) {
 | 
				
			||||||
    let className = javaObj.class.name;
 | 
					    let className = javaObj.class.name
 | 
				
			||||||
    if (!classMethodsCache[className]) {
 | 
					    if (!classMethodsCache[className]) {
 | 
				
			||||||
        let names: any[] = [];
 | 
					        let names: any[] = []
 | 
				
			||||||
        let methods = javaObj.class.methods;
 | 
					        let methods = javaObj.class.methods
 | 
				
			||||||
        for (let i in methods) {
 | 
					        for (let i in methods) {
 | 
				
			||||||
            names.push(methods[i].name);
 | 
					            names.push(methods[i].name)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        classMethodsCache[className] = names;
 | 
					        classMethodsCache[className] = names
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return classMethodsCache[className];
 | 
					    return classMethodsCache[className]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function mapMethod(target, source, name) {
 | 
					function mapMethod(target, source, name) {
 | 
				
			||||||
    target[name] = function __SimpleDynamicMethod__(...args) {
 | 
					    target[name] = function __SimpleDynamicMethod__(...args) {
 | 
				
			||||||
        if (args.length > 0) {
 | 
					        if (args.length > 0) {
 | 
				
			||||||
            return source[name](args);
 | 
					            return source[name](args)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return source[name]();
 | 
					            return source[name]()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function on(obj) {
 | 
					function on(obj) {
 | 
				
			||||||
    // if (!obj || !obj.class) { throw new TypeError(`参数 ${obj} 不是一个Java对象!`) }
 | 
					    // if (!obj || !obj.class) { throw new TypeError(`参数 ${obj} 不是一个Java对象!`) }
 | 
				
			||||||
    return new Reflect(obj);
 | 
					    return new Reflect(obj)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export = {
 | 
					export = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,7 @@ class MiaoScriptCore {
 | 
				
			|||||||
        console.i18n("ms.core.engine.disable")
 | 
					        console.i18n("ms.core.engine.disable")
 | 
				
			||||||
        this.pluginManager.disable(this.pluginManager.getPlugins())
 | 
					        this.pluginManager.disable(this.pluginManager.getPlugins())
 | 
				
			||||||
        this.taskManager.disable()
 | 
					        this.taskManager.disable()
 | 
				
			||||||
 | 
					        process.exit(0)
 | 
				
			||||||
        //@ts-ignore
 | 
					        //@ts-ignore
 | 
				
			||||||
        require.disable()
 | 
					        require.disable()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,13 @@
 | 
				
			|||||||
/// <reference types="@ccms/nashorn" />
 | 
					/// <reference types="@ccms/nashorn" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import i18n from '@ccms/i18n'
 | 
					import i18n from '@ccms/i18n'
 | 
				
			||||||
let ployfillStartTime = new Date().getTime();
 | 
					let ployfillStartTime = new Date().getTime()
 | 
				
			||||||
i18n.initialize();
 | 
					i18n.initialize()
 | 
				
			||||||
console.i18n("ms.ployfill.initialize");
 | 
					console.i18n("ms.ployfill.initialize")
 | 
				
			||||||
require('./es5-ext');
 | 
					require('./es5-ext')
 | 
				
			||||||
require('core-js');
 | 
					require('./node-shim')
 | 
				
			||||||
require('./node-shim');
 | 
					require('core-js')
 | 
				
			||||||
global.setGlobal('Proxy', require('./proxy').Proxy)
 | 
					global.setGlobal('Proxy', require('./proxy').Proxy)
 | 
				
			||||||
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
 | 
					global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
 | 
				
			||||||
global.setGlobal('Blob', require('blob-polyfill').Blob)
 | 
					global.setGlobal('Blob', require('blob-polyfill').Blob)
 | 
				
			||||||
console.i18n("ms.ployfill.completed", { time: (new Date().getTime() - ployfillStartTime) / 1000 });
 | 
					console.i18n("ms.ployfill.completed", { time: (new Date().getTime() - ployfillStartTime) / 1000 })
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,36 @@
 | 
				
			|||||||
global.setGlobal('process', {
 | 
					import { EventEmitter } from 'events'
 | 
				
			||||||
    env: {
 | 
					
 | 
				
			||||||
 | 
					const Thread = Java.type('java.lang.Thread')
 | 
				
			||||||
 | 
					const ThreadGroup = Java.type("java.lang.ThreadGroup")
 | 
				
			||||||
 | 
					const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
 | 
				
			||||||
 | 
					const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor')
 | 
				
			||||||
 | 
					const LinkedBlockingQueue = Java.type("java.util.concurrent.LinkedBlockingQueue")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const threadCount = new AtomicInteger(0)
 | 
				
			||||||
 | 
					const threadGroup = new ThreadGroup("@ccms/ployfill-micro-task")
 | 
				
			||||||
 | 
					const microTaskPool = new ThreadPoolExecutor(
 | 
				
			||||||
 | 
					    10, 100, 60, Packages.java.util.concurrent.TimeUnit.SECONDS,
 | 
				
			||||||
 | 
					    new LinkedBlockingQueue(500),
 | 
				
			||||||
 | 
					    (run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()),
 | 
				
			||||||
 | 
					    new ThreadPoolExecutor.CallerRunsPolicy()
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Process extends EventEmitter {
 | 
				
			||||||
 | 
					    env = {
 | 
				
			||||||
        __noSuchProperty__: (prop) => {
 | 
					        __noSuchProperty__: (prop) => {
 | 
				
			||||||
            return Packages.java.lang.System.getenv(prop)
 | 
					            return Packages.java.lang.System.getenv(prop)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    }
 | 
				
			||||||
    platform: Packages.java.lang.System.getProperty("os.name")
 | 
					    platform = Packages.java.lang.System.getProperty("os.name")
 | 
				
			||||||
}, {})
 | 
					    nextTick(func: Function) {
 | 
				
			||||||
 | 
					        microTaskPool.execute(func)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    queueMicrotask(func: Function) {
 | 
				
			||||||
 | 
					        microTaskPool.execute(func)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    exit() {
 | 
				
			||||||
 | 
					        microTaskPool.shutdown();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					global.setGlobal('process', new Process(), {})
 | 
				
			||||||
 | 
					global.setGlobal('queueMicrotask', (func: any) => microTaskPool.execute(func), {})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
import { server, MiaoScriptConsole, event } from "@ccms/api";
 | 
					import { server, MiaoScriptConsole, event, plugin } from "@ccms/api";
 | 
				
			||||||
import { injectable, inject, postConstruct } from "@ccms/container";
 | 
					import { injectable, inject, postConstruct } from "@ccms/container";
 | 
				
			||||||
import { getPluginMetadata } from "./utils";
 | 
					import { getPluginMetadata } from "./utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export namespace interfaces {
 | 
					export namespace interfaces {
 | 
				
			||||||
    @injectable()
 | 
					    @injectable()
 | 
				
			||||||
    export abstract class Plugin {
 | 
					    export abstract class Plugin implements plugin.Plugin {
 | 
				
			||||||
        public description: PluginMetadata;
 | 
					        public description: PluginMetadata;
 | 
				
			||||||
        public logger: Console;
 | 
					        public logger: Console;
 | 
				
			||||||
        @inject(server.Console)
 | 
					        @inject(server.Console)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,8 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private initialized: boolean = false
 | 
					    private initialized: boolean = false
 | 
				
			||||||
    private pluginRequireMap: Map<string, any>
 | 
					    private pluginRequireMap: Map<string, any>
 | 
				
			||||||
    private pluginInstanceMap: Map<string, interfaces.Plugin>
 | 
					    private pluginInstanceMap: Map<string, plugin.Plugin>
 | 
				
			||||||
    private pluginMetadataMap: Map<string, interfaces.PluginMetadata>
 | 
					    private pluginMetadataMap: Map<string, plugin.PluginMetadata>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initialize() {
 | 
					    initialize() {
 | 
				
			||||||
        if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
 | 
					        if (this.pluginInstance === undefined) { throw new Error("Can't found Plugin Instance!") }
 | 
				
			||||||
@@ -52,23 +52,27 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        this.buildPlugins()
 | 
					        this.buildPlugins()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private logStage(plugin: interfaces.Plugin, stage: string) {
 | 
					    private logStage(plugin: plugin.Plugin, stage: string) {
 | 
				
			||||||
        console.i18n("ms.plugin.manager.stage", { stage, plugin: plugin.description.name, version: plugin.description.version, author: plugin.description.author })
 | 
					        console.i18n("ms.plugin.manager.stage", { stage, plugin: plugin.description.name, version: plugin.description.version, author: plugin.description.author })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private runPluginStage(plugin: interfaces.Plugin, stage: string, ext: Function) {
 | 
					    private runPluginStage(plugin: plugin.Plugin, stage: string, ext: Function) {
 | 
				
			||||||
        this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
 | 
					        try {
 | 
				
			||||||
        ext()
 | 
					            this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
 | 
				
			||||||
        this.runCatch(plugin, stage)
 | 
					            ext()
 | 
				
			||||||
        this.runCatch(plugin, `${this.serverType}${stage}`)
 | 
					            this.runCatch(plugin, stage)
 | 
				
			||||||
        this.execPluginStage(plugin, stage)
 | 
					            this.runCatch(plugin, `${this.serverType}${stage}`)
 | 
				
			||||||
 | 
					            this.execPluginStage(plugin, stage)
 | 
				
			||||||
 | 
					        } catch (ex) {
 | 
				
			||||||
 | 
					            console.i18n("ms.plugin.manager.stage.exec.error", { plugin: plugin.description.name, executor: stage, error: ex })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 从文件加载插件
 | 
					     * 从文件加载插件
 | 
				
			||||||
     * @param file java.io.File
 | 
					     * @param file java.io.File
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    loadFromFile(file: string): interfaces.Plugin {
 | 
					    loadFromFile(file: string): plugin.Plugin {
 | 
				
			||||||
        let metadata = this.loadPlugin(file)
 | 
					        let metadata = this.loadPlugin(file)
 | 
				
			||||||
        let plugin = this.buildPlugin(metadata && metadata.description ? metadata.description : this.pluginMetadataMap.get(file.toString()))
 | 
					        let plugin = this.buildPlugin(metadata && metadata.description ? metadata.description : this.pluginMetadataMap.get(file.toString()))
 | 
				
			||||||
        this.load(plugin)
 | 
					        this.load(plugin)
 | 
				
			||||||
@@ -77,7 +81,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    load(...args: any[]): void {
 | 
					    load(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => {
 | 
				
			||||||
            this.runPluginStage(plugin, 'load', () => {
 | 
					            this.runPluginStage(plugin, 'load', () => {
 | 
				
			||||||
                this.loadConfig(plugin)
 | 
					                this.loadConfig(plugin)
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
@@ -85,7 +89,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enable(...args: any[]): void {
 | 
					    enable(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => {
 | 
				
			||||||
            this.runPluginStage(plugin, 'enable', () => {
 | 
					            this.runPluginStage(plugin, 'enable', () => {
 | 
				
			||||||
                this.registryCommand(plugin)
 | 
					                this.registryCommand(plugin)
 | 
				
			||||||
                this.registryListener(plugin)
 | 
					                this.registryListener(plugin)
 | 
				
			||||||
@@ -94,7 +98,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    disable(...args: any[]): void {
 | 
					    disable(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((plugin: plugin.Plugin) => {
 | 
				
			||||||
            this.runPluginStage(plugin, 'disable', () => {
 | 
					            this.runPluginStage(plugin, 'disable', () => {
 | 
				
			||||||
                this.saveConfig(plugin)
 | 
					                this.saveConfig(plugin)
 | 
				
			||||||
                this.unregistryCommand(plugin)
 | 
					                this.unregistryCommand(plugin)
 | 
				
			||||||
@@ -104,12 +108,16 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reload(...args: any[]): void {
 | 
					    reload(...args: any[]): void {
 | 
				
			||||||
        this.checkAndGet(args[0]).forEach((pl: interfaces.Plugin) => {
 | 
					        this.checkAndGet(args[0]).forEach((pl: plugin.Plugin) => {
 | 
				
			||||||
            this.disable(pl)
 | 
					            this.disable(pl)
 | 
				
			||||||
            this.loadFromFile(pl.description.source)
 | 
					            this.loadFromFile(pl.description.source)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getPlugin(name: string) {
 | 
				
			||||||
 | 
					        return this.pluginInstanceMap.get(name)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getPlugins() {
 | 
					    getPlugins() {
 | 
				
			||||||
        return this.pluginInstanceMap
 | 
					        return this.pluginInstanceMap
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -123,11 +131,11 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private checkAndGet(name: string | interfaces.Plugin | undefined | any): Map<string, interfaces.Plugin> | interfaces.Plugin[] {
 | 
					    private checkAndGet(name: string | plugin.Plugin | undefined | any): Map<string, plugin.Plugin> | plugin.Plugin[] {
 | 
				
			||||||
        if (name == this.pluginInstanceMap) { return this.pluginInstanceMap }
 | 
					        if (name == this.pluginInstanceMap) { return this.pluginInstanceMap }
 | 
				
			||||||
        if (typeof name == 'string' && this.pluginInstanceMap.has(name)) { return [this.pluginInstanceMap.get(name)] }
 | 
					        if (typeof name == 'string' && this.pluginInstanceMap.has(name)) { return [this.pluginInstanceMap.get(name)] }
 | 
				
			||||||
        if (name instanceof interfaces.Plugin) { return [name as interfaces.Plugin] }
 | 
					        if (name instanceof interfaces.Plugin) { return [name as plugin.Plugin] }
 | 
				
			||||||
        if (name.description || name.description.name) { return [name as interfaces.Plugin] }
 | 
					        if (name.description || name.description.name) { return [name as plugin.Plugin] }
 | 
				
			||||||
        throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
 | 
					        throw new Error(`Plugin ${JSON.stringify(name)} not exist!`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -214,12 +222,12 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private buildPlugin(metadata: interfaces.PluginMetadata) {
 | 
					    private buildPlugin(metadata: interfaces.PluginMetadata) {
 | 
				
			||||||
        let pluginInstance: interfaces.Plugin
 | 
					        let pluginInstance: plugin.Plugin
 | 
				
			||||||
        switch (metadata.type) {
 | 
					        switch (metadata.type) {
 | 
				
			||||||
            case "ioc":
 | 
					            case "ioc":
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    this.bindPlugin(metadata)
 | 
					                    this.bindPlugin(metadata)
 | 
				
			||||||
                    pluginInstance = this.container.getNamed<interfaces.Plugin>(plugin.Plugin, metadata.name)
 | 
					                    pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
 | 
				
			||||||
                    if (!(pluginInstance instanceof interfaces.Plugin)) {
 | 
					                    if (!(pluginInstance instanceof interfaces.Plugin)) {
 | 
				
			||||||
                        console.i18n('ms.plugin.manager.build.not.extends', { source: metadata.source })
 | 
					                        console.i18n('ms.plugin.manager.build.not.extends', { source: metadata.source })
 | 
				
			||||||
                        return
 | 
					                        return
 | 
				
			||||||
@@ -235,13 +243,13 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
            default:
 | 
					            default:
 | 
				
			||||||
                throw new Error('§4不支持的插件类型 请检查加载器是否正常启用!')
 | 
					                throw new Error('§4不支持的插件类型 请检查加载器是否正常启用!')
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.pluginInstanceMap.set(metadata.name, pluginInstance)
 | 
					        pluginInstance && this.pluginInstanceMap.set(metadata.name, pluginInstance)
 | 
				
			||||||
        return pluginInstance
 | 
					        return pluginInstance
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private bindPlugin(metadata: interfaces.PluginMetadata) {
 | 
					    private bindPlugin(metadata: interfaces.PluginMetadata) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            let pluginInstance = this.container.getNamed<interfaces.Plugin>(plugin.Plugin, metadata.name)
 | 
					            let pluginInstance = this.container.getNamed<plugin.Plugin>(plugin.Plugin, metadata.name)
 | 
				
			||||||
            if (pluginInstance.description.source + '' !== metadata.source + '') {
 | 
					            if (pluginInstance.description.source + '' !== metadata.source + '') {
 | 
				
			||||||
                console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
 | 
					                console.i18n('ms.plugin.manager.build.duplicate', { exists: pluginInstance.description.source, source: metadata.source })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -251,7 +259,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private loadConfig(plugin: interfaces.Plugin) {
 | 
					    private loadConfig(plugin: plugin.Plugin) {
 | 
				
			||||||
        let configs = getPluginConfigMetadata(plugin)
 | 
					        let configs = getPluginConfigMetadata(plugin)
 | 
				
			||||||
        for (let [_, config] of configs) {
 | 
					        for (let [_, config] of configs) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
@@ -276,7 +284,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private saveConfig(plugin: interfaces.Plugin) {
 | 
					    private saveConfig(plugin: plugin.Plugin) {
 | 
				
			||||||
        let configs = getPluginConfigMetadata(plugin)
 | 
					        let configs = getPluginConfigMetadata(plugin)
 | 
				
			||||||
        for (let [_, config] of configs) {
 | 
					        for (let [_, config] of configs) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
@@ -290,7 +298,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private registryCommand(pluginInstance: interfaces.Plugin) {
 | 
					    private registryCommand(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
					        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
				
			||||||
        let tabs = getPluginTabCompleterMetadata(pluginInstance)
 | 
					        let tabs = getPluginTabCompleterMetadata(pluginInstance)
 | 
				
			||||||
        for (const [_, cmd] of cmds) {
 | 
					        for (const [_, cmd] of cmds) {
 | 
				
			||||||
@@ -303,7 +311,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private registryListener(pluginInstance: interfaces.Plugin) {
 | 
					    private registryListener(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
        let events = getPluginListenerMetadata(pluginInstance)
 | 
					        let events = getPluginListenerMetadata(pluginInstance)
 | 
				
			||||||
        for (const event of events) {
 | 
					        for (const event of events) {
 | 
				
			||||||
            // ignore space listener
 | 
					            // ignore space listener
 | 
				
			||||||
@@ -313,18 +321,18 @@ export class PluginManagerImpl implements plugin.PluginManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private unregistryCommand(pluginInstance: interfaces.Plugin) {
 | 
					    private unregistryCommand(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
					        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
				
			||||||
        cmds.forEach(cmd => {
 | 
					        cmds.forEach(cmd => {
 | 
				
			||||||
            this.CommandManager.off(pluginInstance, cmd.name)
 | 
					            this.CommandManager.off(pluginInstance, cmd.name)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private unregistryListener(pluginInstance: interfaces.Plugin) {
 | 
					    private unregistryListener(pluginInstance: plugin.Plugin) {
 | 
				
			||||||
        this.EventManager.disable(pluginInstance)
 | 
					        this.EventManager.disable(pluginInstance)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private execPluginStage(pluginInstance: interfaces.Plugin, stageName: string) {
 | 
					    private execPluginStage(pluginInstance: plugin.Plugin, stageName: string) {
 | 
				
			||||||
        let stages = getPluginStageMetadata(pluginInstance, stageName)
 | 
					        let stages = getPluginStageMetadata(pluginInstance, stageName)
 | 
				
			||||||
        for (const stage of stages) {
 | 
					        for (const stage of stages) {
 | 
				
			||||||
            if (!this.allowProcess(stage.servers)) { continue }
 | 
					            if (!this.allowProcess(stage.servers)) { continue }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user