diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java index 3e4bee75d..af3cbac00 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/RhinoCraftScriptEngine.java @@ -19,10 +19,7 @@ package com.sk89q.worldedit.scripting; -import com.google.common.io.CharStreams; import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.scripting.compat.BabelScriptTranspiler; -import com.sk89q.worldedit.scripting.compat.ScriptTranspiler; import org.mozilla.javascript.Context; import org.mozilla.javascript.ImporterTopLevel; import org.mozilla.javascript.JavaScriptException; @@ -31,13 +28,10 @@ import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.WrappedException; -import java.io.StringReader; import java.util.Map; import javax.script.ScriptException; public class RhinoCraftScriptEngine implements CraftScriptEngine { - - private static final ScriptTranspiler TRANSPILER = new BabelScriptTranspiler(); private int timeLimit; @Override @@ -53,7 +47,6 @@ public class RhinoCraftScriptEngine implements CraftScriptEngine { @Override public Object evaluate(String script, String filename, Map args) throws ScriptException, Throwable { - String transpiled = CharStreams.toString(TRANSPILER.transpile(new StringReader(script))); RhinoContextFactory factory = new RhinoContextFactory(timeLimit); Context cx = factory.enterContext(); cx.setClassShutter(new MinecraftHidingClassShutter()); @@ -65,7 +58,7 @@ public class RhinoCraftScriptEngine implements CraftScriptEngine { Context.javaToJS(entry.getValue(), scope)); } try { - return cx.evaluateString(scope, transpiled, filename, 1, null); + return cx.evaluateString(scope, script, filename, 1, null); } catch (Error e) { throw new ScriptException(e.getMessage()); } catch (RhinoException e) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/compat/BabelScriptTranspiler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/compat/BabelScriptTranspiler.java deleted file mode 100644 index 2ca0fd9c1..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/compat/BabelScriptTranspiler.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.scripting.compat; - -import com.google.common.io.CharStreams; -import org.mozilla.javascript.Context; -import org.mozilla.javascript.ContextFactory; -import org.mozilla.javascript.Function; -import org.mozilla.javascript.Scriptable; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.util.concurrent.TimeUnit; - -public class BabelScriptTranspiler implements ScriptTranspiler { - - private static final RemoteScript BABEL = new RemoteScript( - "https://unpkg.com/@babel/standalone@7.9/babel.min.js", - "babel.min.js", - new RemoteScript( - "https://unpkg.com/core-js-bundle@3.6.5/index.js", - "core-js-bundle.js" - ), - new RemoteScript( - "https://unpkg.com/regenerator-runtime@0.13.5/runtime.js", - "regenerator-runtime.js" - ) - ); - - private final ContextFactory contextFactory = new ContextFactory() { - @Override - protected Context makeContext() { - Context context = super.makeContext(); - context.setLanguageVersion(Context.VERSION_ES6); - return context; - } - }; - private final Function executeBabel; - - public BabelScriptTranspiler() { - Scriptable babel = BABEL.getScope(); - executeBabel = contextFactory.call(ctx -> { - ctx.setOptimizationLevel(9); - String execBabelSource = "function(source) {\n" + - "return Babel.transform(source, { presets: ['env'] }).code;\n" + - "}\n"; - return ctx.compileFunction( - babel, execBabelSource, "", 1, null - ); - }); - } - - @Override - public Reader transpile(Reader script) throws IOException { - long startTranspile = System.nanoTime(); - Scriptable babel = BABEL.getScope(); - String source = CharStreams.toString(script); - String result = (String) contextFactory.call(ctx -> - executeBabel.call(ctx, babel, null, new Object[] { source }) - ); - System.err.println(result); - System.err.println("Took " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTranspile)); - return new StringReader(result); - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/compat/RemoteScript.java b/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/compat/RemoteScript.java deleted file mode 100644 index ee59db817..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/scripting/compat/RemoteScript.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.sk89q.worldedit.scripting.compat; - -import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.util.net.HttpRequest; -import org.mozilla.javascript.Context; -import org.mozilla.javascript.ContextFactory; -import org.mozilla.javascript.Scriptable; -import org.mozilla.javascript.ScriptableObject; -import org.mozilla.javascript.TopLevel; - -import java.io.IOException; -import java.io.Reader; -import java.io.UncheckedIOException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; - -import static com.google.common.base.Preconditions.checkState; - -public class RemoteScript { - - private static final int MAX_REDIRECTS = 100; - - - private final ContextFactory contextFactory = new ContextFactory() { - @Override - protected boolean hasFeature(Context cx, int featureIndex) { - if (featureIndex == Context.FEATURE_OLD_UNDEF_NULL_THIS) { - return true; - } - return super.hasFeature(cx, featureIndex); - } - - @Override - protected Context makeContext() { - Context context = super.makeContext(); - context.setLanguageVersion(Context.VERSION_ES6); - return context; - } - }; - private final Path cacheDir = WorldEdit.getInstance() - .getWorkingDirectoryFile("craftscripts/.cache").toPath(); - private final URL source; - private final String cacheFileName; - private final Path cachePath; - private final List dependencies; - - private volatile Scriptable cachedScope; - - public RemoteScript(String source, String cacheFileName, RemoteScript... dependencies) { - this.source = HttpRequest.url(source); - this.cacheFileName = cacheFileName; - this.cachePath = cacheDir.resolve(cacheFileName); - this.dependencies = ImmutableList.copyOf(dependencies); - } - - private synchronized void ensureCached() throws IOException { - if (!Files.exists(cacheDir)) { - Files.createDirectories(cacheDir); - } - if (!Files.exists(cachePath)) { - boolean downloadedBabel = false; - int redirects = 0; - URL url = source; - while (redirects < MAX_REDIRECTS && !downloadedBabel) { - try (HttpRequest request = HttpRequest.get(url)) { - request.execute(); - request.expectResponseCode(200, 301, 302); - if (request.getResponseCode() > 300) { - redirects++; - url = HttpRequest.url(request.getSingleHeaderValue("Location")); - continue; - } - request.saveContent(cachePath.toFile()); - downloadedBabel = true; - } - } - checkState(downloadedBabel, "Too many redirects following: %s", url); - checkState(Files.exists(cachePath), "Failed to actually download %s", cacheFileName); - } - } - - protected synchronized void loadIntoScope(Context ctx, Scriptable scope) { - try { - ensureCached(); - try (Reader reader = Files.newBufferedReader(cachePath)) { - ctx.evaluateReader(scope, reader, cacheFileName, 1, null); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - /** - * Get a scope that the script has been evaluated in. - * - * @return the scope - */ - public synchronized Scriptable getScope() { - if (cachedScope != null) { - return cachedScope; - } - - // parse + execute standalone script to load it into the scope - cachedScope = contextFactory.call(ctx -> { - ScriptableObject scriptable = new TopLevel(); - Scriptable newScope = ctx.initStandardObjects(scriptable); - ctx.setOptimizationLevel(9); - for (RemoteScript dependency : dependencies) { - dependency.loadIntoScope(ctx, newScope); - } - loadIntoScope(ctx, newScope); - return newScope; - }); - - return cachedScope; - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java index fa689bab2..5cb0adbb9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/net/HttpRequest.java @@ -45,6 +45,8 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; +import static com.google.common.base.Preconditions.checkState; + public class HttpRequest implements Closeable { private static final int CONNECT_TIMEOUT = 1000 * 5; @@ -215,6 +217,13 @@ public class HttpRequest implements Closeable { return conn.getResponseCode(); } + public String getSingleHeaderValue(String header) { + checkState(conn != null, "No connection has been made"); + + // maybe we should check for multi-header? + return conn.getHeaderField(header); + } + /** * Get the input stream. *