From 9268ce9fee650e63c3491bf889507a4db7324d91 Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Wed, 1 Jun 2022 17:52:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MiaoWoo --- pom.xml | 14 +- .../pw/yumc/MiaoScript/MiaoScriptBukkit.java | 3 +- .../pw/yumc/MiaoScript/MiaoScriptBungee.java | 3 +- .../pw/yumc/MiaoScript/MiaoScriptNukkit.java | 3 +- .../pw/yumc/MiaoScript/MiaoScriptSponge.java | 10 +- .../pw/yumc/MiaoScript/MiaoScriptSpring.java | 3 +- .../java/pw/yumc/MiaoScript/api/Base.java | 18 +- .../pw/yumc/MiaoScript/api/MiaoScriptAPI.java | 19 ++ .../pw/yumc/MiaoScript/api/ScriptEngine.java | 4 +- .../yumc/MiaoScript/api/loader/JarLoader.java | 27 ++- .../api/loader/MavenDependLoader.java | 16 +- .../MiaoScript/engine/MiaoScriptEngine.java | 192 ++++++++++-------- src/main/resources/core/require.js | 67 +++--- 13 files changed, 247 insertions(+), 132 deletions(-) diff --git a/pom.xml b/pom.xml index 122daf6..7033b0e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 pw.yumc MiaoScript - 0.22.0 + 0.22.3 502647092 @@ -50,6 +50,7 @@ DEV + §622-05-25 §afeat: 兼容 1.7.10-1.18.2 版本; §622-05-21 §afeat: 优化 框架加载逻辑; §622-05-20 §afeat: 调整 require 主包逻辑; §622-04-09 §afeat: 优化 引擎初始化逻辑; @@ -196,7 +197,8 @@ org.projectlombok lombok - 1.18.22 + 1.18.24 + compile org.kamranzafar @@ -219,6 +221,7 @@ net.md-5 bungeecord-api 1.16-R0.4 + compile cn.nukkit @@ -229,7 +232,7 @@ org.springframework spring-websocket - 5.3.18 + 5.3.19 compile @@ -238,10 +241,5 @@ 9.0.35 compile - - com.zaxxer - HikariCP - 4.0.3 - \ No newline at end of file diff --git a/src/main/java/pw/yumc/MiaoScript/MiaoScriptBukkit.java b/src/main/java/pw/yumc/MiaoScript/MiaoScriptBukkit.java index 7138be8..f6f0a20 100644 --- a/src/main/java/pw/yumc/MiaoScript/MiaoScriptBukkit.java +++ b/src/main/java/pw/yumc/MiaoScript/MiaoScriptBukkit.java @@ -2,6 +2,7 @@ package pw.yumc.MiaoScript; import lombok.SneakyThrows; import org.bukkit.plugin.java.JavaPlugin; +import pw.yumc.MiaoScript.api.MiaoScriptAPI; import pw.yumc.MiaoScript.api.ScriptEngine; /** @@ -17,7 +18,7 @@ public class MiaoScriptBukkit extends JavaPlugin { public MiaoScriptBukkit() { ClassLoader origin = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(getClassLoader()); - engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger(), this); + engine = MiaoScriptAPI.createEngine(getDataFolder().getCanonicalPath(), getLogger(), this); Thread.currentThread().setContextClassLoader(origin); engine.loadEngine(); } diff --git a/src/main/java/pw/yumc/MiaoScript/MiaoScriptBungee.java b/src/main/java/pw/yumc/MiaoScript/MiaoScriptBungee.java index 84579c3..15a9ed0 100644 --- a/src/main/java/pw/yumc/MiaoScript/MiaoScriptBungee.java +++ b/src/main/java/pw/yumc/MiaoScript/MiaoScriptBungee.java @@ -2,6 +2,7 @@ package pw.yumc.MiaoScript; import lombok.SneakyThrows; import net.md_5.bungee.api.plugin.Plugin; +import pw.yumc.MiaoScript.api.MiaoScriptAPI; import pw.yumc.MiaoScript.api.ScriptEngine; /** @@ -16,7 +17,7 @@ public class MiaoScriptBungee extends Plugin { @SneakyThrows public MiaoScriptBungee() { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); - engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger(), this); + engine = MiaoScriptAPI.createEngine(getDataFolder().getCanonicalPath(), getLogger(), this); engine.loadEngine(); } diff --git a/src/main/java/pw/yumc/MiaoScript/MiaoScriptNukkit.java b/src/main/java/pw/yumc/MiaoScript/MiaoScriptNukkit.java index 6aa658c..97273f6 100644 --- a/src/main/java/pw/yumc/MiaoScript/MiaoScriptNukkit.java +++ b/src/main/java/pw/yumc/MiaoScript/MiaoScriptNukkit.java @@ -2,6 +2,7 @@ package pw.yumc.MiaoScript; import cn.nukkit.plugin.PluginBase; import lombok.SneakyThrows; +import pw.yumc.MiaoScript.api.MiaoScriptAPI; import pw.yumc.MiaoScript.api.ScriptEngine; /** @@ -13,7 +14,7 @@ public class MiaoScriptNukkit extends PluginBase { @SneakyThrows public MiaoScriptNukkit() { Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); - engine = new ScriptEngine(getDataFolder().getCanonicalPath(), super.getLogger(), this); + engine = MiaoScriptAPI.createEngine(getDataFolder().getCanonicalPath(), super.getLogger(), this); engine.loadEngine(); } diff --git a/src/main/java/pw/yumc/MiaoScript/MiaoScriptSponge.java b/src/main/java/pw/yumc/MiaoScript/MiaoScriptSponge.java index 1ba2ae4..7808d2a 100644 --- a/src/main/java/pw/yumc/MiaoScript/MiaoScriptSponge.java +++ b/src/main/java/pw/yumc/MiaoScript/MiaoScriptSponge.java @@ -6,8 +6,8 @@ import org.slf4j.Logger; import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.game.GameReloadEvent; +import org.spongepowered.api.event.game.state.GamePreInitializationEvent; import org.spongepowered.api.event.game.state.GameStartedServerEvent; -import org.spongepowered.api.event.game.state.GameStartingServerEvent; import org.spongepowered.api.event.game.state.GameStoppingServerEvent; import org.spongepowered.api.plugin.Plugin; import pw.yumc.MiaoScript.api.MiaoScriptAPI; @@ -33,14 +33,14 @@ public class MiaoScriptSponge { @Listener @SneakyThrows - public void onStarting(GameStartingServerEvent event) { - engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger, this); + public void onPreInitialization(GamePreInitializationEvent event) { + engine = MiaoScriptAPI.createEngine(pluginConfigDir.getCanonicalPath(), logger, this); engine.loadEngine(); } @Listener @SneakyThrows - public void onStart(GameStartedServerEvent event) { + public void onStarted(GameStartedServerEvent event) { engine.enableEngine(); } @@ -55,7 +55,7 @@ public class MiaoScriptSponge { @SneakyThrows public void reload(GameReloadEvent event) { engine.disableEngine(); - engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger, this); + System.gc(); engine.loadEngine(); engine.enableEngine(); } diff --git a/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java b/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java index 4f9abf3..64eb4ed 100644 --- a/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java +++ b/src/main/java/pw/yumc/MiaoScript/MiaoScriptSpring.java @@ -6,6 +6,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import org.springframework.web.socket.server.standard.ServerEndpointExporter; +import pw.yumc.MiaoScript.api.MiaoScriptAPI; import pw.yumc.MiaoScript.api.ScriptEngine; import java.io.File; @@ -16,7 +17,7 @@ public class MiaoScriptSpring { @Bean @SneakyThrows public ScriptEngine buildScriptEngine(ApplicationContext applicationContext) { - return new ScriptEngine(new File("MiaoScript").getCanonicalPath(), log, applicationContext); + return MiaoScriptAPI.createEngine(new File("MiaoScript").getCanonicalPath(), log, applicationContext); } @Bean diff --git a/src/main/java/pw/yumc/MiaoScript/api/Base.java b/src/main/java/pw/yumc/MiaoScript/api/Base.java index 3e78676..23c5f29 100644 --- a/src/main/java/pw/yumc/MiaoScript/api/Base.java +++ b/src/main/java/pw/yumc/MiaoScript/api/Base.java @@ -25,7 +25,15 @@ public class Base { } public Class getClass(String name) throws ClassNotFoundException { - return Class.forName(name); + try { + return Class.forName(name); + } catch (Throwable ignored) { + } + try { + return Class.forName(name, true, instance.getClass().getClassLoader()); + } catch (Throwable ex) { + return Class.forName(name, true, instance.getClass().getClassLoader().getParent()); + } } public Object getInstance() { @@ -44,6 +52,14 @@ public class Base { return MiaoScriptAPI.loadMavenDepend(groupId, artifactId, version); } + public File[] loadMavenDepend(String groupId, String artifactId, String version, ClassLoader classLoader) { + return MiaoScriptAPI.loadMavenDepend(groupId, artifactId, version, classLoader); + } + + public File[] parentLoadMavenDepend(String groupId, String artifactId, String version) { + return MiaoScriptAPI.parentLoadMavenDepend(groupId, artifactId, version); + } + public String read(String path) throws IOException { return read(Paths.get(path)); } diff --git a/src/main/java/pw/yumc/MiaoScript/api/MiaoScriptAPI.java b/src/main/java/pw/yumc/MiaoScript/api/MiaoScriptAPI.java index 3bd0936..2eb3ccf 100644 --- a/src/main/java/pw/yumc/MiaoScript/api/MiaoScriptAPI.java +++ b/src/main/java/pw/yumc/MiaoScript/api/MiaoScriptAPI.java @@ -14,6 +14,11 @@ public class MiaoScriptAPI { private static ScriptEngine scriptEngine; private static PluginManager pluginManager; + public static ScriptEngine createEngine(String root, Object logger, Object instance) { + MiaoScriptAPI.scriptEngine = new ScriptEngine(root, logger, instance); + return MiaoScriptAPI.scriptEngine; + } + public static String getRoot() { return root; } @@ -45,4 +50,18 @@ public class MiaoScriptAPI { } return MavenDependLoader.load(MiaoScriptAPI.libPath, groupId, artifactId, version); } + + public static File[] loadMavenDepend(String groupId, String artifactId, String version, ClassLoader classLoader) { + if (root == null || scriptEngine == null) { + throw new IllegalStateException("root can't be null before loadMavenDepend."); + } + return MavenDependLoader.load(MiaoScriptAPI.libPath, groupId, artifactId, version, classLoader); + } + + public static File[] parentLoadMavenDepend(String groupId, String artifactId, String version) { + if (root == null || scriptEngine == null) { + throw new IllegalStateException("root can't be null before loadMavenDepend."); + } + return MavenDependLoader.parentLoad(MiaoScriptAPI.libPath, groupId, artifactId, version); + } } diff --git a/src/main/java/pw/yumc/MiaoScript/api/ScriptEngine.java b/src/main/java/pw/yumc/MiaoScript/api/ScriptEngine.java index f296156..7107877 100644 --- a/src/main/java/pw/yumc/MiaoScript/api/ScriptEngine.java +++ b/src/main/java/pw/yumc/MiaoScript/api/ScriptEngine.java @@ -20,7 +20,7 @@ public class ScriptEngine { private MiaoScriptEngine engine; private Object future; - public ScriptEngine(String root, Object logger, Object instance) { + ScriptEngine(String root, Object logger, Object instance) { this.loader = Thread.currentThread().getContextClassLoader(); this.root = root; this.logger = logger; @@ -32,7 +32,7 @@ public class ScriptEngine { public void createEngine() { synchronized (logger) { if (this.engine == null) { - this.engine = new MiaoScriptEngine("nashorn", root); + this.engine = new MiaoScriptEngine(root); this.engine.put("base", this.base); this.engine.put("ScriptEngineContextHolder", this); } diff --git a/src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java b/src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java index 7e68346..6c054ed 100644 --- a/src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java +++ b/src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java @@ -10,6 +10,9 @@ import java.lang.reflect.Method; import java.net.URL; public class JarLoader { + private static sun.misc.Unsafe unsafe; + private static long offset; + private static Object parentUcp; private static Object ucp; private static MethodHandle addURLMethodHandle; @@ -23,12 +26,26 @@ public class JarLoader { return file; } + @SneakyThrows + public static File parentLoad(File file) { + if (parentUcp == null) + throw new IllegalStateException("parentUcp is null."); + addURLMethodHandle.invoke(parentUcp, file.toURI().toURL()); + return file; + } + + @SneakyThrows + public static File load(File file, ClassLoader loader) { + addURLMethodHandle.invoke(unsafe.getObject(loader, offset), file.toURI().toURL()); + return file; + } + private static void initReflect() { try { - ClassLoader loader = ClassLoader.getSystemClassLoader(); + ClassLoader loader = JarLoader.class.getClassLoader(); Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); - sun.misc.Unsafe unsafe = (sun.misc.Unsafe) theUnsafe.get(null); + unsafe = (sun.misc.Unsafe) theUnsafe.get(null); Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP"); MethodHandles.Lookup lookup = (MethodHandles.Lookup) unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field)); Field ucpField; @@ -37,11 +54,13 @@ public class JarLoader { } catch (NoSuchFieldException e) { ucpField = loader.getClass().getSuperclass().getDeclaredField("ucp"); } - long offset = unsafe.objectFieldOffset(ucpField); + offset = unsafe.objectFieldOffset(ucpField); ucp = unsafe.getObject(loader, offset); Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class); addURLMethodHandle = lookup.unreflect(method); - } catch (Exception e) { + if (loader.getParent() != null) + parentUcp = unsafe.getObject(loader.getParent(), offset); + } catch (Throwable e) { throw new RuntimeException(e); } } diff --git a/src/main/java/pw/yumc/MiaoScript/api/loader/MavenDependLoader.java b/src/main/java/pw/yumc/MiaoScript/api/loader/MavenDependLoader.java index f4fcce8..5215564 100644 --- a/src/main/java/pw/yumc/MiaoScript/api/loader/MavenDependLoader.java +++ b/src/main/java/pw/yumc/MiaoScript/api/loader/MavenDependLoader.java @@ -14,7 +14,7 @@ import java.nio.file.StandardCopyOption; import java.security.MessageDigest; public class MavenDependLoader { - private static final String MavenRepo = "https://maven.aliyun.com/repository/public"; + public static final String MavenRepo = "https://maven.aliyun.com/repository/public"; public static File[] load(String libPath, String groupId, String artifactId, String version) { return new File[]{ @@ -23,6 +23,20 @@ public class MavenDependLoader { }; } + public static File[] parentLoad(String libPath, String groupId, String artifactId, String version) { + return new File[]{ + downloadAndCheckSha1(libPath, groupId, artifactId, version, "pom"), + JarLoader.parentLoad(downloadAndCheckSha1(libPath, groupId, artifactId, version, "jar")) + }; + } + + public static File[] load(String libPath, String groupId, String artifactId, String version, ClassLoader loader) { + return new File[]{ + downloadAndCheckSha1(libPath, groupId, artifactId, version, "pom"), + JarLoader.load(downloadAndCheckSha1(libPath, groupId, artifactId, version, "jar"), loader) + }; + } + @SneakyThrows public static File downloadAndCheckSha1(String libPath, String groupId, String artifactId, String version, String ext) { File sha1 = getMavenFile(libPath, groupId, artifactId, version, ext + ".sha1"); diff --git a/src/main/java/pw/yumc/MiaoScript/engine/MiaoScriptEngine.java b/src/main/java/pw/yumc/MiaoScript/engine/MiaoScriptEngine.java index 8193f7d..65a7c6c 100644 --- a/src/main/java/pw/yumc/MiaoScript/engine/MiaoScriptEngine.java +++ b/src/main/java/pw/yumc/MiaoScript/engine/MiaoScriptEngine.java @@ -5,12 +5,12 @@ import lombok.val; import pw.yumc.MiaoScript.api.loader.JarLoader; import pw.yumc.MiaoScript.api.loader.MavenDependLoader; -import javax.script.ScriptEngine; import javax.script.*; import java.io.File; import java.io.Reader; import java.lang.reflect.Method; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; /** * 喵式脚本引擎 @@ -19,111 +19,143 @@ import java.util.HashMap; * @since 2016年8月29日 上午7:51:43 */ public class MiaoScriptEngine implements ScriptEngine, Invocable { - private static MiaoScriptEngine DEFAULT; - private static final ScriptEngineManager manager; - private ScriptEngine engine; - static { - manager = new ScriptEngineManager(ClassLoader.getSystemClassLoader()); - } - - public static void setBindings(Bindings bindings) { - manager.setBindings(bindings); - } - - public static Bindings getBindings() { - return manager.getBindings(); - } - - public MiaoScriptEngine() { - this("js"); - } - - public MiaoScriptEngine(final String engineType) { - this(manager, engineType, null); - } - - public MiaoScriptEngine(ScriptEngineManager engineManager) { - this(engineManager, "js", null); - } - - public MiaoScriptEngine(final String engineType, String engineRoot) { - this(manager, engineType, engineRoot); - } - - public MiaoScriptEngine(ScriptEngineManager engineManager, final String engineType, String engineRoot) { - // JDK11 Polyfill 存在类效验问题 直接用OpenJDK的Nashorn - if (System.getProperty("java.version").startsWith("11.") && engineRoot != null) { - this.loadNetworkNashorn(engineRoot); - if (engine == null) - throw new UnsupportedOperationException("当前环境 JDK11 不支持 Nashorn 脚本类型!"); - return; + public MiaoScriptEngine(String engineRoot) { + if (new File(engineRoot, "debug").exists()) { + System.setProperty("nashorn.debug", "true"); } - try { - engine = engineManager.getEngineByName(engineType); - } catch (final NullPointerException ignored) { - } - if (engine == null) { - val extDirs = System.getProperty("java.ext.dirs"); - if (extDirs != null) { - this.loadLocalNashorn(extDirs, engineType); - } else if (engineRoot != null) { - this.loadNetworkNashorn(engineRoot); - } + if (getJavaVersion() > 15) { + this.loadGraalJS(engineRoot); + } else { + this.loadNashorn(engineRoot); } if (engine == null) - throw new UnsupportedOperationException("当前环境不支持 " + engineType + " 脚本类型!"); + throw new UnsupportedOperationException("当前环境不支持 Nashorn 或 GraalJS 脚本引擎."); } - private void loadLocalNashorn(String extDirs, String engineType) { + private void loadGraalJS(String engineRoot) { + this.engine = this.parentLoadNetworkNashorn(engineRoot); + if (this.engine == null) { + this.engine = this.loadNetworkGraalJS(engineRoot); + } + } + + private void loadNashorn(String engineRoot) { + try { + this.createEngineByName(); + } catch (final Throwable ex) { + ex.printStackTrace(); + } + try { + val extDirs = System.getProperty("java.ext.dirs"); + if (this.engine == null && extDirs != null) { + this.engine = this.loadLocalNashorn(extDirs); + } + } catch (final Throwable ex) { + ex.printStackTrace(); + } + try { + if (this.engine == null && engineRoot != null) { + this.engine = this.loadNetworkNashorn(engineRoot); + } + } catch (final Throwable ex) { + ex.printStackTrace(); + } + if (this.engine == null) + throw new UnsupportedOperationException("当前环境不支持 Nashorn 脚本引擎."); + } + + private int getJavaVersion() { + String version = System.getProperty("java.version"); + if (version.startsWith("1.")) { + version = version.substring(2, 3); + } else { + int dot = version.indexOf("."); + if (dot != -1) { + version = version.substring(0, dot); + } + } + return Integer.parseInt(version); + } + + private ScriptEngine loadLocalNashorn(String extDirs) { val dirs = extDirs.split(File.pathSeparator); for (String dir : dirs) { File nashorn = new File(dir, "nashorn.jar"); if (nashorn.exists()) { JarLoader.load(nashorn); - this.createEngineByName(engineType); + return this.createEngineByName(); } } + return null; } @SneakyThrows - private void loadNetworkNashorn(String engineRoot) { + private ScriptEngine loadNetworkNashorn(String engineRoot) { File libRootFile = new File(engineRoot, "libs"); libRootFile.mkdirs(); String libRoot = libRootFile.getCanonicalPath(); - MavenDependLoader.load(libRoot, "org.openjdk.nashorn", "nashorn-core", "15.3"); - MavenDependLoader.load(libRoot, "org.ow2.asm", "asm", "9.2"); - MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-commons", "9.2"); - MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-tree", "9.2"); - MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-util", "9.2"); - Class NashornScriptEngineFactory = Class.forName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory"); - Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine"); - Object factory = NashornScriptEngineFactory.newInstance(); - engine = (ScriptEngine) getScriptEngine.invoke(factory); + MavenDependLoader.load(libRoot, "org.openjdk.nashorn", "nashorn-core", "15.4"); + MavenDependLoader.load(libRoot, "org.ow2.asm", "asm", "9.3"); + MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-commons", "9.3"); + MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-tree", "9.3"); + MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-util", "9.3"); + return createEngineByFactoryClassName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory", false); } - private void createEngineByName(String engineType) { - try { - engine = new ScriptEngineManager(Thread.currentThread().getContextClassLoader()).getEngineByName(engineType); - } catch (NullPointerException ignored) { + @SneakyThrows + private ScriptEngine parentLoadNetworkNashorn(String engineRoot) { + File libRootFile = new File(engineRoot, "libs"); + libRootFile.mkdirs(); + String libRoot = libRootFile.getCanonicalPath(); + MavenDependLoader.parentLoad(libRoot, "org.openjdk.nashorn", "nashorn-core", "15.4"); + MavenDependLoader.parentLoad(libRoot, "org.ow2.asm", "asm", "9.3"); + MavenDependLoader.parentLoad(libRoot, "org.ow2.asm", "asm-commons", "9.3"); + MavenDependLoader.parentLoad(libRoot, "org.ow2.asm", "asm-tree", "9.3"); + MavenDependLoader.parentLoad(libRoot, "org.ow2.asm", "asm-util", "9.3"); + return createEngineByFactoryClassName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory", false); + } + + @SneakyThrows + private ScriptEngine loadNetworkGraalJS(String engineRoot) { + File libRootFile = new File(engineRoot, "libs"); + libRootFile.mkdirs(); + String libRoot = libRootFile.getCanonicalPath(); + MavenDependLoader.load(libRoot, "org.graalvm.js", "js", "22.1.0.1"); + MavenDependLoader.load(libRoot, "org.graalvm.js", "js-scriptengine", "22.1.0.1"); + MavenDependLoader.load(libRoot, "org.graalvm.regex", "regex", "22.1.0.1"); + MavenDependLoader.load(libRoot, "org.graalvm.sdk", "graal-sdk", "22.1.0.1"); + MavenDependLoader.load(libRoot, "org.graalvm.truffle", "truffle-api", "22.1.0.1"); + return createEngineByFactoryClassName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory", false); + } + + @SneakyThrows + private ScriptEngine createEngineByName() { + return createEngineByFactoryClassName("jdk.nashorn.api.scripting.NashornScriptEngineFactory", true); + } + + @SneakyThrows + private ScriptEngine createEngineByFactoryClassName(String factoryClassName, boolean jdk) { + Class NashornScriptEngineFactory = Class.forName(factoryClassName); + Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine", String[].class); + Object factory = NashornScriptEngineFactory.newInstance(); + List engineArgs = new ArrayList<>(); + engineArgs.add("--language=es5"); + engineArgs.add("--optimistic-types=false"); + if (getJavaVersion() >= 11 && jdk) { + engineArgs.add("--no-deprecation-warning"); } + return (ScriptEngine) getScriptEngine.invoke(factory, (Object) engineArgs.toArray(new String[]{})); } public ScriptEngine getEngine() { return this.engine; } - public static MiaoScriptEngine getDefault() { - if (DEFAULT == null) { - DEFAULT = new MiaoScriptEngine(); - } - return DEFAULT; - } - @Override public Bindings createBindings() { - return new SimpleBindings(new HashMap<>(engine.getBindings(ScriptContext.GLOBAL_SCOPE))); + return engine.createBindings(); } @Override @@ -177,13 +209,13 @@ public class MiaoScriptEngine implements ScriptEngine, Invocable { } @Override - public T getInterface(final Class clasz) { - return ((Invocable) engine).getInterface(clasz); + public T getInterface(final Class cls) { + return ((Invocable) engine).getInterface(cls); } @Override - public T getInterface(final Object thiz, final Class clasz) { - return ((Invocable) engine).getInterface(thiz, clasz); + public T getInterface(final Object thiz, final Class cls) { + return ((Invocable) engine).getInterface(thiz, cls); } @Override diff --git a/src/main/resources/core/require.js b/src/main/resources/core/require.js index 75a3b2b..08004c6 100644 --- a/src/main/resources/core/require.js +++ b/src/main/resources/core/require.js @@ -28,9 +28,9 @@ // @ts-check ( /** - * @param {string} parent + * @param {string} root */ - function (parent) { + function (root) { 'use strict' var System = Java.type('java.lang.System') @@ -181,7 +181,7 @@ try { var json = JSON.parse(base.read(_package)) if (json.main) { - return resolveAsFile(json.main, dir) + return resolveAsFile(json.main, dir) || resolveAsFile('index.js', new File(dir, json.main)) } } catch (error) { throw __error('resolveAsDirectory ' + dir + ' package.json error ' + error) @@ -239,18 +239,26 @@ if (!loader) { throw __error('Unsupported module ' + filename + '. require loader not found.') } - console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(optional)) + /** + * @type any + */ var module = { id: id, name: name, ext: ext, + parent: optional.parent, exports: {}, loaded: false, loader: loader, - require: getRequire(file.parentFile, id), - __dirname: file.parentFile, - __filename: file + path: _absolute(file.parentFile), + filename: _absolute(file), + children: [] } + module.require = getRequire(module) + if (module.parent && module.parent.children) { + module.parent.children.push(module) + } + console.trace('Loading module', name + '(' + id + ')', 'Optional', JSON.stringify(__assign(optional, { parent: undefined }))) cacheModules[id] = module return loader(module, file, __assign(optional, { id: id })) } @@ -288,7 +296,7 @@ name: optional.id }) compiledWrapper.apply(module.exports, [ - module, module.exports, module.require, module.__dirname, module.__filename + module, module.exports, module.require, module.path, module.filename ]) module.loaded = true if (optional.afterCompile) { @@ -467,7 +475,7 @@ * 检查缓存模块 */ function checkCacheModule(optional) { - return optional.local ? cacheModuleIds[optional.parentId] && cacheModuleIds[optional.parentId][optional.path] : cacheModuleIds[optional.path] + return optional.local ? cacheModuleIds[optional.parent.id] && cacheModuleIds[optional.parent.id][optional.path] : cacheModuleIds[optional.path] } /** @@ -511,11 +519,11 @@ */ function setCacheModule(file, optional) { if (optional.local) { - var parent = cacheModuleIds[optional.parentId] + var parent = cacheModuleIds[optional.parent.id] if (!parent) { - cacheModuleIds[optional.parentId] = {} + cacheModuleIds[optional.parent.id] = {} } - return cacheModuleIds[optional.parentId][optional.path] = _canonical(file) + return cacheModuleIds[optional.parent.id][optional.path] = _canonical(file) } return cacheModuleIds[optional.path] = _canonical(file) } @@ -527,11 +535,10 @@ /** * 闭包方法 - * @param {string} parent 父目录 - * @param {string} parentId + * @param {any} parent 父模块 * @returns {Function} */ - function exports(parent, parentId) { + function exports(parent) { /** * @param {string} path * @param {any} optional @@ -540,13 +547,13 @@ if (!path) { throw __error('require path can\'t be undefined or empty!') } - return _require(path, parent, __assign({ + var optional = __assign({ cache: true, - parentId: parentId, parent: parent, path: path, local: path.startsWith('.') || path.startsWith('/') - }, optional)).exports + }, optional) + return _require(path, parent.path, optional).exports } } @@ -555,9 +562,8 @@ * @param {any} optional 附加选项 */ function __DynamicResolve__(path, optional) { - return _canonical(new File(resolve(path, parent, __assign({ + return _canonical(new File(resolve(path, root, __assign({ cache: true, - parent: parent, local: path.startsWith('.') || path.startsWith('/') }, optional)))) } @@ -592,14 +598,13 @@ } /** - * @param {string} parent - * @param {string} parentId + * @param {any} parent */ - function getRequire(parent, parentId) { + function getRequire(parent) { /** * @type {any} require */ - var require = exports(parent, parentId) + var require = exports(parent) require.resolve = __DynamicResolve__ require.clear = __DynamicClear__ require.disable = __DynamicDisable__ @@ -643,8 +648,9 @@ function printRequireInfo() { console.info('Initialization require module.') - console.info('ParentDir:', _canonical(parent)) + console.info('ParentDir:', root) console.info('Require module env list:') + console.info('- JAVA_VERSION: ', System.getProperty("java.version")) 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('- MS_FALLBACK_NODE_REGISTRY:', MS_FALLBACK_NODE_REGISTRY) @@ -676,7 +682,11 @@ console.warn("无法获取到最新的版本锁定信息 使用默认配置.") console.warn("InitVersionLock Error:", error) console.debug(error) - ModulesVersionLock = { "@babel/standalone": "7.12.18", "crypto-js": "3.3.0" } + ModulesVersionLock = { + "@babel/standalone": "7.12.18", + "crypto-js": "3.3.0", + "core-js": "3.19.3" + } } console.info('Lock module version List:') for (var key in ModulesVersionLock) { @@ -731,5 +741,8 @@ initCacheModuleIds() initVersionLock() - return initRequireLoader(getRequire(parent, "")) + return initRequireLoader(getRequire({ + id: 'main', + path: root + })) })