diff -Nru rhino-1.7.7.2/debian/changelog rhino-1.7.7.2/debian/changelog --- rhino-1.7.7.2/debian/changelog 2020-09-03 11:59:51.000000000 +0000 +++ rhino-1.7.7.2/debian/changelog 2021-02-08 10:39:29.000000000 +0000 @@ -1,3 +1,20 @@ +rhino (1.7.7.2-3) unstable; urgency=medium + + * Team upload. + * Backported the JSR 223 script engine to use Rhino as a replacement + for Nashorn with OpenJDK 17 + * Standards-Version updated to 4.5.1 + * Switch to debhelper level 13 + + -- Emmanuel Bourg Mon, 08 Feb 2021 11:39:29 +0100 + +rhino (1.7.7.2-2) UNRELEASED; urgency=medium + + * Team upload. + * Add patch to install JAR as 1.7.7.2 (not 1.7.7.1) + + -- tony mancill Wed, 25 Nov 2020 12:02:51 -0800 + rhino (1.7.7.2-1) unstable; urgency=medium * Team upload. diff -Nru rhino-1.7.7.2/debian/compat rhino-1.7.7.2/debian/compat --- rhino-1.7.7.2/debian/compat 2020-09-03 11:36:47.000000000 +0000 +++ rhino-1.7.7.2/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -10 diff -Nru rhino-1.7.7.2/debian/control rhino-1.7.7.2/debian/control --- rhino-1.7.7.2/debian/control 2020-09-03 11:36:47.000000000 +0000 +++ rhino-1.7.7.2/debian/control 2021-02-08 10:39:26.000000000 +0000 @@ -7,11 +7,11 @@ Jakub Adam Build-Depends: ant, - debhelper (>= 10), + debhelper-compat (= 13), default-jdk, javahelper, maven-repo-helper -Standards-Version: 4.5.0 +Standards-Version: 4.5.1 Vcs-Git: https://salsa.debian.org/java-team/rhino.git Vcs-Browser: https://salsa.debian.org/java-team/rhino Homepage: http://www.mozilla.org/rhino/ diff -Nru rhino-1.7.7.2/debian/patches/08_fix-jar-version-number.patch rhino-1.7.7.2/debian/patches/08_fix-jar-version-number.patch --- rhino-1.7.7.2/debian/patches/08_fix-jar-version-number.patch 1970-01-01 00:00:00.000000000 +0000 +++ rhino-1.7.7.2/debian/patches/08_fix-jar-version-number.patch 2020-12-16 15:45:16.000000000 +0000 @@ -0,0 +1,14 @@ +Description: update POM to match upstream version +Author: tony mancill + +--- a/maven/maven-pom.xml ++++ b/maven/maven-pom.xml +@@ -12,7 +12,7 @@ + org.mozilla + rhino + Mozilla Rhino +- 1.7.7.1 ++ 1.7.7.2 + + jar + diff -Nru rhino-1.7.7.2/debian/patches/script-engine.patch rhino-1.7.7.2/debian/patches/script-engine.patch --- rhino-1.7.7.2/debian/patches/script-engine.patch 1970-01-01 00:00:00.000000000 +0000 +++ rhino-1.7.7.2/debian/patches/script-engine.patch 2021-02-08 10:03:36.000000000 +0000 @@ -0,0 +1,1303 @@ +From f195514ffee1b759ba088883732e77b026b3a694 Mon Sep 17 00:00:00 2001 +From: Gregory Brail +Date: Fri, 5 Jun 2020 14:38:28 -0700 +Subject: [PATCH] Implement standard Java ScriptEngine + +This is not based on the now-removed JDK code but instead does a +few things in a more modern way. See the comments for supported +parameters (you can set language and optimization level via +properties) and built-in functions (only print is supported right now.) + +This is built into a separate JAR called "rhino-engine" because +otherwise, including it in any Java 8 JDK would break scripts that +are expecting to see Nashorn instead. +--- + .circleci/config.yml | 2 +- + build.gradle | 86 ++++- + .../services/javax.script.ScriptEngineFactory | 1 + + .../javascript/engine/BindingsObject.java | 60 +++ + .../mozilla/javascript/engine/Builtins.java | 59 +++ + .../engine/RhinoCompiledScript.java | 33 ++ + .../engine/RhinoInvocationHandler.java | 25 ++ + .../javascript/engine/RhinoScriptEngine.java | 363 ++++++++++++++++++ + .../engine/RhinoScriptEngineFactory.java | 140 +++++++ + .../tests/scriptengine/BuiltinsTest.java | 54 +++ + .../tests/scriptengine/FactoryTest.java | 56 +++ + .../tests/scriptengine/InvocableTest.java | 158 ++++++++ + .../tests/scriptengine/ScriptEngineTest.java | 276 +++++++++++++ + 13 files changed, 1305 insertions(+), 8 deletions(-) + create mode 100644 src/META-INF/services/javax.script.ScriptEngineFactory + create mode 100644 src/org/mozilla/javascript/engine/BindingsObject.java + create mode 100644 src/org/mozilla/javascript/engine/Builtins.java + create mode 100644 src/org/mozilla/javascript/engine/RhinoCompiledScript.java + create mode 100644 src/org/mozilla/javascript/engine/RhinoInvocationHandler.java + create mode 100644 src/org/mozilla/javascript/engine/RhinoScriptEngine.java + create mode 100644 src/org/mozilla/javascript/engine/RhinoScriptEngineFactory.java + create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/BuiltinsTest.java + create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/FactoryTest.java + create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/InvocableTest.java + create mode 100644 testsrc/org/mozilla/javascript/tests/scriptengine/ScriptEngineTest.java + +--- /dev/null ++++ b/src/META-INF/services/javax.script.ScriptEngineFactory +@@ -0,0 +1 @@ ++org.mozilla.javascript.engine.RhinoScriptEngineFactory +--- /dev/null ++++ b/src/org/mozilla/javascript/engine/BindingsObject.java +@@ -0,0 +1,60 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++package org.mozilla.javascript.engine; ++ ++import org.mozilla.javascript.Context; ++import org.mozilla.javascript.Scriptable; ++import org.mozilla.javascript.ScriptableObject; ++import javax.script.Bindings; ++ ++/** ++ * This class makes the Bindings object into a Scriptable. That way, we can query and modify ++ * the contents of the Bindings on demand. ++ */ ++public class BindingsObject ++ extends ScriptableObject { ++ private final Bindings bindings; ++ ++ BindingsObject(Bindings bindings) { ++ if (bindings == null) { ++ throw new IllegalArgumentException("Bindings must not be null"); ++ } ++ this.bindings = bindings; ++ } ++ ++ @Override ++ public String getClassName() { ++ return "BindingsObject"; ++ } ++ ++ @Override ++ public Object get(String name, Scriptable start) { ++ Object ret = bindings.get(name); ++ if (ret == null) { ++ return Scriptable.NOT_FOUND; ++ } ++ return Context.jsToJava(ret, Object.class); ++ } ++ ++ @Override ++ public void put(String name, Scriptable start, Object value) { ++ bindings.put(name, Context.javaToJS(value, start)); ++ } ++ ++ @Override ++ public void delete(String name) { ++ bindings.remove(name); ++ } ++ ++ @Override ++ public boolean has(String name, Scriptable start) { ++ return bindings.containsKey(name); ++ } ++ ++ @Override ++ public Object[] getIds() { ++ return bindings.keySet().toArray(); ++ } ++} +--- /dev/null ++++ b/src/org/mozilla/javascript/engine/Builtins.java +@@ -0,0 +1,59 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++package org.mozilla.javascript.engine; ++ ++import java.io.IOException; ++import java.io.OutputStreamWriter; ++import java.io.Writer; ++import javax.script.ScriptContext; ++import org.mozilla.javascript.Context; ++import org.mozilla.javascript.Function; ++import org.mozilla.javascript.ScriptRuntime; ++import org.mozilla.javascript.Scriptable; ++import org.mozilla.javascript.ScriptableObject; ++ ++/** ++ *

++ * This class defines the following built-in functions for the RhinoScriptEngine. ++ *

++ *
    ++ *
  • print(arg, arg, ...): Write each argument, concatenated to the ScriptEngine's ++ * "standard output" as a string.
  • ++ *
++ */ ++public class Builtins { ++ ++ static final Object BUILTIN_KEY = new Object(); ++ ++ private Writer stdout; ++ ++ void register(Context cx, ScriptableObject scope, ScriptContext sc) { ++ if (sc.getWriter() == null) { ++ stdout = new OutputStreamWriter(System.out); ++ } else { ++ stdout = sc.getWriter(); ++ } ++ ++ scope.defineFunctionProperties(new String[]{"print"}, ++ Builtins.class, ++ ScriptableObject.PERMANENT | ScriptableObject.DONTENUM); ++ } ++ ++ public static void print(Context cx, Scriptable thisObj, Object[] args, Function f) ++ throws IOException { ++ Builtins self = getSelf(thisObj); ++ for (Object arg : args) { ++ self.stdout.write(ScriptRuntime.toString(arg)); ++ } ++ self.stdout.write('\n'); ++ } ++ ++ private static Builtins getSelf(Scriptable scope) { ++ // Since this class is invoked as a set of anonymous functions, "this" ++ // in JavaScript does not point to "this" in Java. We set a key on the ++ // top-level scope to address this. ++ return (Builtins) ScriptableObject.getTopScopeValue(scope, BUILTIN_KEY); ++ } ++} +--- /dev/null ++++ b/src/org/mozilla/javascript/engine/RhinoCompiledScript.java +@@ -0,0 +1,33 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++package org.mozilla.javascript.engine; ++ ++import javax.script.CompiledScript; ++import javax.script.ScriptContext; ++import javax.script.ScriptEngine; ++import javax.script.ScriptException; ++import org.mozilla.javascript.Script; ++ ++public class RhinoCompiledScript ++ extends CompiledScript { ++ ++ private final RhinoScriptEngine engine; ++ private final Script script; ++ ++ RhinoCompiledScript(RhinoScriptEngine engine, Script script) { ++ this.engine = engine; ++ this.script = script; ++ } ++ ++ @Override ++ public Object eval(ScriptContext context) throws ScriptException { ++ return engine.eval(script, context); ++ } ++ ++ @Override ++ public ScriptEngine getEngine() { ++ return engine; ++ } ++} +--- /dev/null ++++ b/src/org/mozilla/javascript/engine/RhinoInvocationHandler.java +@@ -0,0 +1,25 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++package org.mozilla.javascript.engine; ++ ++import java.lang.reflect.InvocationHandler; ++import java.lang.reflect.Method; ++ ++public class RhinoInvocationHandler ++ implements InvocationHandler { ++ ++ private final Object thiz; ++ private final RhinoScriptEngine engine; ++ ++ RhinoInvocationHandler(RhinoScriptEngine engine, Object thiz) { ++ this.engine = engine; ++ this.thiz = thiz; ++ } ++ ++ @Override ++ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ++ return engine.invokeMethodRaw(thiz, method.getName(), method.getReturnType(), args); ++ } ++} +--- /dev/null ++++ b/src/org/mozilla/javascript/engine/RhinoScriptEngine.java +@@ -0,0 +1,355 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++package org.mozilla.javascript.engine; ++ ++import java.io.IOException; ++import java.io.Reader; ++import java.lang.reflect.Method; ++import java.lang.reflect.Proxy; ++import javax.script.AbstractScriptEngine; ++import javax.script.Bindings; ++import javax.script.Compilable; ++import javax.script.CompiledScript; ++import javax.script.Invocable; ++import javax.script.ScriptContext; ++import javax.script.ScriptEngine; ++import javax.script.ScriptEngineFactory; ++import javax.script.ScriptException; ++import javax.script.SimpleBindings; ++import org.mozilla.javascript.Callable; ++import org.mozilla.javascript.Context; ++import org.mozilla.javascript.ContextFactory; ++import org.mozilla.javascript.RhinoException; ++import org.mozilla.javascript.Script; ++import org.mozilla.javascript.Scriptable; ++import org.mozilla.javascript.ScriptableObject; ++ ++/** ++ *

++ * This is the implementation of the standard ScriptEngine interface for Rhino. ++ *

++ *

++ * An instance of the Rhino ScriptEngine is fully self-contained. Bindings at the GLOBAL_SCOPE may ++ * be set, but there is nothing special about them -- if both global and ENGINE_SCOPE bindings are ++ * set then the "engine" bindings override the global ones. ++ *

++ *

++ * The Rhino engine is not thread safe. Rhino does no synchronization of ScriptEngine instances and ++ * no synchronization of Bindings instances. It is up to the caller to ensure that the ScriptEngine ++ * and all its Bindings are used by a single thread at a time. ++ *

++ *

++ * The Rhino script engine includes some top-level built-in functions. See the Builtins class for ++ * more documentation. ++ *

++ *

++ * The engine supports a few configuration parameters that may be set at the "engine scope". Both ++ * are numbers that may be set to a String or Number object. ++ *

++ *
    ++ *
  • javax.script.language_version: The version of the JavaScript language supported, ++ * which is an integer defined in the Context class. The default is the latest "ES6" ++ * version, defined as 200.
  • ++ *
  • org.mozilla.javascript.optimization_level: The level of optimization Rhino performs ++ * on the generated bytecode. Default is 9, which is the most. Set to -1 to use interpreted ++ * mode.
  • ++ *
++ */ ++public class RhinoScriptEngine ++ extends AbstractScriptEngine ++ implements Compilable, Invocable { ++ ++ /** ++ * Reserved key for the Rhino optimization level. Default is "9," for optimized and compiled code. ++ * Set this to "-1" to run Rhino in interpreted mode -- this is much much slower but the only ++ * option on platforms like Android that don't support class files. ++ */ ++ public static final String OPTIMIZATION_LEVEL = "org.mozilla.javascript.optimization_level"; ++ ++ static final int DEFAULT_LANGUAGE_VERSION = Context.VERSION_ES6; ++ private static final int DEFAULT_OPT = 9; ++ private static final boolean DEFAULT_DEBUG = true; ++ private static final String DEFAULT_FILENAME = "eval"; ++ ++ private static final CtxFactory ctxFactory = new CtxFactory(); ++ ++ private final RhinoScriptEngineFactory factory; ++ private final Builtins builtins; ++ private ScriptableObject topLevelScope = null; ++ ++ RhinoScriptEngine(RhinoScriptEngineFactory factory) { ++ this.factory = factory; ++ this.builtins = new Builtins(); ++ } ++ ++ private Scriptable initScope(Context cx, ScriptContext sc) throws ScriptException { ++ configureContext(cx); ++ ++ if (topLevelScope == null) { ++ topLevelScope = cx.initStandardObjects(); ++ // We need to stash this away so that the built in functions can find ++ // this engine's specific stuff that they need to work. ++ topLevelScope.associateValue(Builtins.BUILTIN_KEY, builtins); ++ builtins.register(cx, topLevelScope, sc); ++ } ++ ++ Scriptable engineScope = new BindingsObject( ++ sc.getBindings(ScriptContext.ENGINE_SCOPE)); ++ engineScope.setParentScope(null); ++ engineScope.setPrototype(topLevelScope); ++ ++ if (sc.getBindings(ScriptContext.GLOBAL_SCOPE) != null) { ++ Scriptable globalScope = new BindingsObject( ++ sc.getBindings(ScriptContext.GLOBAL_SCOPE)); ++ globalScope.setParentScope(null); ++ globalScope.setPrototype(topLevelScope); ++ engineScope.setPrototype(globalScope); ++ } ++ ++ return engineScope; ++ } ++ ++ @Override ++ public Object eval(String script, ScriptContext context) throws ScriptException { ++ Context cx = ctxFactory.enterContext(); ++ try { ++ Scriptable scope = initScope(cx, context); ++ Object ret = cx.evaluateString(scope, script, getFilename(), 0, null); ++ return Context.jsToJava(ret, Object.class); ++ } catch (RhinoException re) { ++ throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(), ++ re.columnNumber()); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ @Override ++ public Object eval(Reader reader, ScriptContext context) throws ScriptException { ++ Context cx = ctxFactory.enterContext(); ++ try { ++ Scriptable scope = initScope(cx, context); ++ Object ret = cx.evaluateReader(scope, reader, getFilename(), 0, null); ++ return Context.jsToJava(ret, Object.class); ++ } catch (RhinoException re) { ++ throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(), ++ re.columnNumber()); ++ } catch (IOException ioe) { ++ throw new ScriptException(ioe); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ @Override ++ public CompiledScript compile(String script) throws ScriptException { ++ Context cx = ctxFactory.enterContext(); ++ try { ++ configureContext(cx); ++ Script s = ++ cx.compileString(script, getFilename(), 1, null); ++ return new RhinoCompiledScript(this, s); ++ } catch (RhinoException re) { ++ throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(), ++ re.columnNumber()); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ @Override ++ public CompiledScript compile(Reader script) throws ScriptException { ++ Context cx = ctxFactory.enterContext(); ++ try { ++ configureContext(cx); ++ Script s = ++ cx.compileReader(script, getFilename(), 1, null); ++ return new RhinoCompiledScript(this, s); ++ } catch (RhinoException re) { ++ throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(), ++ re.columnNumber()); ++ } catch (IOException ioe) { ++ throw new ScriptException(ioe); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ Object eval(Script script, ScriptContext sc) throws ScriptException { ++ Context cx = ctxFactory.enterContext(); ++ try { ++ Scriptable scope = initScope(cx, sc); ++ Object ret = script.exec(cx, scope); ++ return Context.jsToJava(ret, Object.class); ++ } catch (RhinoException re) { ++ throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(), ++ re.columnNumber()); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ @Override ++ public Object invokeFunction(String name, Object... args) ++ throws ScriptException, NoSuchMethodException { ++ return invokeMethod(null, name, args); ++ } ++ ++ @Override ++ public Object invokeMethod(Object thiz, String name, Object... args) ++ throws ScriptException, NoSuchMethodException { ++ return invokeMethodRaw(thiz, name, Object.class, args); ++ } ++ ++ Object invokeMethodRaw(Object thiz, String name, Class returnType, Object... args) ++ throws ScriptException, NoSuchMethodException { ++ Context cx = ctxFactory.enterContext(); ++ try { ++ Scriptable scope = initScope(cx, context); ++ ++ Scriptable localThis; ++ if (thiz == null) { ++ localThis = scope; ++ } else { ++ localThis = Context.toObject(thiz, scope); ++ } ++ ++ Object f = ScriptableObject.getProperty(localThis, name); ++ if (f == Scriptable.NOT_FOUND) { ++ throw new NoSuchMethodException(name); ++ } ++ if (!(f instanceof Callable)) { ++ throw new ScriptException("\"" + name + "\" is not a function"); ++ } ++ Callable func = (Callable) f; ++ ++ if (args != null) { ++ for (int i = 0; i < args.length; i++) { ++ args[i] = Context.javaToJS(args[i], scope); ++ } ++ } ++ ++ Object ret = func.call(cx, scope, localThis, args); ++ if (returnType == Void.TYPE) { ++ return null; ++ } ++ return Context.jsToJava(ret, returnType); ++ ++ } catch (RhinoException re) { ++ throw new ScriptException(re.getMessage(), re.sourceName(), re.lineNumber(), ++ re.columnNumber()); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ @Override ++ public T getInterface(Class clasz) { ++ if ((clasz == null) || !clasz.isInterface()) { ++ throw new IllegalArgumentException("Not an interface"); ++ } ++ Context cx = ctxFactory.enterContext(); ++ try { ++ Scriptable scope = initScope(cx, context); ++ if (methodsMissing(scope, clasz)) { ++ return null; ++ } ++ } catch (ScriptException se) { ++ return null; ++ } finally { ++ Context.exit(); ++ } ++ return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), ++ new Class[]{clasz}, new RhinoInvocationHandler(this, null)); ++ } ++ ++ @Override ++ public T getInterface(Object thiz, Class clasz) { ++ if ((clasz == null) || !clasz.isInterface()) { ++ throw new IllegalArgumentException("Not an interface"); ++ } ++ Context cx = ctxFactory.enterContext(); ++ try { ++ Scriptable scope = initScope(cx, context); ++ Scriptable thisObj = Context.toObject(thiz, scope); ++ if (methodsMissing(thisObj, clasz)) { ++ return null; ++ } ++ } catch (ScriptException se) { ++ return null; ++ } finally { ++ Context.exit(); ++ } ++ return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), ++ new Class[]{clasz}, new RhinoInvocationHandler(this, thiz)); ++ } ++ ++ @Override ++ public Bindings createBindings() { ++ return new SimpleBindings(); ++ } ++ ++ @Override ++ public ScriptEngineFactory getFactory() { ++ return factory; ++ } ++ ++ private void configureContext(Context cx) throws ScriptException { ++ Object lv = get(ScriptEngine.LANGUAGE_VERSION); ++ if (lv != null) { ++ cx.setLanguageVersion(parseInteger(lv)); ++ } ++ Object ol = get(OPTIMIZATION_LEVEL); ++ if (ol != null) { ++ cx.setOptimizationLevel(parseInteger(ol)); ++ } ++ } ++ ++ private int parseInteger(Object v) throws ScriptException { ++ if (v instanceof String) { ++ try { ++ return Integer.parseInt((String) v); ++ } catch (NumberFormatException nfe) { ++ throw new ScriptException("Invalid number " + v); ++ } ++ } else if (v instanceof Integer) { ++ return (Integer) v; ++ } else { ++ throw new ScriptException("Value must be a string or number"); ++ } ++ } ++ ++ private String getFilename() { ++ Object fn = get(ScriptEngine.FILENAME); ++ if (fn instanceof String) { ++ return (String) fn; ++ } ++ return DEFAULT_FILENAME; ++ } ++ ++ private boolean methodsMissing(Scriptable scope, Class clasz) { ++ for (Method m : clasz.getMethods()) { ++ if (m.getDeclaringClass() == Object.class) { ++ continue; ++ } ++ Object methodObj = ScriptableObject.getProperty(scope, m.getName()); ++ if (!(methodObj instanceof Callable)) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ private static final class CtxFactory ++ extends ContextFactory { ++ ++ @Override ++ protected void onContextCreated(Context cx) { ++ cx.setLanguageVersion(Context.VERSION_ES6); ++ cx.setOptimizationLevel(DEFAULT_OPT); ++ cx.setGeneratingDebug(DEFAULT_DEBUG); ++ } ++ } ++} +--- /dev/null ++++ b/src/org/mozilla/javascript/engine/RhinoScriptEngineFactory.java +@@ -0,0 +1,140 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++package org.mozilla.javascript.engine; ++ ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++import javax.script.ScriptEngine; ++import javax.script.ScriptEngineFactory; ++import org.mozilla.javascript.Context; ++ ++/** ++ *

++ * This is an implementation of the standard Java "ScriptEngine" for Rhino. If the Rhino engine ++ * (typically in the form of the "rhino-engine" JAR) is in the classpath, then this script ++ * engine will be activated. ++ *

++ *

++ * See the list of constants in this class for the list of language names, file extensions, and ++ * MIME types that this engine supports. This list is essentially the same as the list supported ++ * in the Nashorn script engine that was included in Java 8. ++ *

++ *

++ * Since this engine and Nashorn support the same language and file extensions, then unless ++ * you are sure you are running in an environment that has Nashorn, the best way to get this ++ * engine is to call ScriptEngine.getEngineByName("rhino") to ask for Rhino directly. ++ *

++ */ ++public class RhinoScriptEngineFactory ++ implements ScriptEngineFactory { ++ ++ public static final String NAME = "rhino"; ++ public static final String LANGUAGE = "javascript"; ++ public static final List NAMES = ++ Arrays.asList("rhino", "Rhino", "javascript", "JavaScript"); ++ public static final List EXTENSIONS = ++ Collections.singletonList("js"); ++ public static final List MIME_TYPES = ++ Arrays.asList("application/javascript", "application/ecmascript", ++ "text/javascript", "text/ecmascript"); ++ public static final String LANGUAGE_VERSION = ++ String.valueOf(RhinoScriptEngine.DEFAULT_LANGUAGE_VERSION); ++ ++ @Override ++ public String getEngineName() { ++ return NAME; ++ } ++ ++ @Override ++ public String getEngineVersion() { ++ Context cx = Context.enter(); ++ try { ++ String v = cx.getImplementationVersion(); ++ return (v == null ? "unknown" : v); ++ } finally { ++ Context.exit(); ++ } ++ } ++ ++ @Override ++ public List getExtensions() { ++ return EXTENSIONS; ++ } ++ ++ @Override ++ public List getMimeTypes() { ++ return MIME_TYPES; ++ } ++ ++ @Override ++ public List getNames() { ++ return NAMES; ++ } ++ ++ @Override ++ public String getLanguageName() { ++ return LANGUAGE; ++ } ++ ++ @Override ++ public String getLanguageVersion() { ++ return LANGUAGE_VERSION; ++ } ++ ++ @Override ++ public Object getParameter(String key) { ++ switch (key) { ++ case ScriptEngine.ENGINE: ++ return getEngineName(); ++ case ScriptEngine.ENGINE_VERSION: ++ return getEngineVersion(); ++ case ScriptEngine.LANGUAGE: ++ return getLanguageName(); ++ case ScriptEngine.LANGUAGE_VERSION: ++ return getLanguageVersion(); ++ case ScriptEngine.NAME: ++ return NAME; ++ case "THREADING": ++ // Engines are explicitly not thread-safe ++ return null; ++ default: ++ return null; ++ } ++ } ++ ++ @Override ++ public String getMethodCallSyntax(String obj, String m, String... args) { ++ StringBuilder sb = new StringBuilder(); ++ sb.append(obj).append('.').append(m).append('('); ++ for (int i = 0; i < args.length; i++) { ++ if (i > 0) { ++ sb.append(','); ++ } ++ sb.append(args[i]); ++ } ++ sb.append(");"); ++ return sb.toString(); ++ } ++ ++ @Override ++ public String getOutputStatement(String toDisplay) { ++ return "print('" + toDisplay + "');"; ++ } ++ ++ @Override ++ public String getProgram(String... statements) { ++ StringBuilder sb = new StringBuilder(); ++ for (String stmt : statements) { ++ sb.append(stmt).append(";\n"); ++ } ++ return sb.toString(); ++ } ++ ++ @Override ++ public ScriptEngine getScriptEngine() { ++ return new RhinoScriptEngine(this); ++ } ++} +--- /dev/null ++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/BuiltinsTest.java +@@ -0,0 +1,54 @@ ++package org.mozilla.javascript.tests.scriptengine; ++ ++import java.io.StringWriter; ++import javax.script.ScriptContext; ++import javax.script.ScriptEngine; ++import javax.script.ScriptEngineManager; ++import javax.script.ScriptException; ++import javax.script.SimpleScriptContext; ++import org.junit.Before; ++import org.junit.BeforeClass; ++import org.junit.Test; ++import org.mozilla.javascript.engine.RhinoScriptEngineFactory; ++ ++import static org.junit.Assert.*; ++ ++public class BuiltinsTest { ++ ++ private static ScriptEngineManager manager; ++ ++ private ScriptEngine engine; ++ ++ @BeforeClass ++ public static void init() { ++ manager = new ScriptEngineManager(); ++ manager.registerEngineName("rhino", new RhinoScriptEngineFactory()); ++ } ++ ++ @Before ++ public void setup() { ++ engine = manager.getEngineByName("rhino"); ++ } ++ ++ @Test ++ public void testPrintStdout() throws ScriptException { ++ engine.eval("print('Hello, World!');"); ++ } ++ ++ @Test ++ public void testPrintWriter() throws ScriptException { ++ StringWriter sw = new StringWriter(); ++ ScriptContext sc = new SimpleScriptContext(); ++ sc.setWriter(sw); ++ engine.eval("print('one', 2, true);", sc); ++ assertEquals(sw.toString(), "one2true\n"); ++ } ++ ++ @Test ++ public void testPrintWriterGeneric() throws ScriptException { ++ StringWriter sw = new StringWriter(); ++ engine.getContext().setWriter(sw); ++ engine.eval(engine.getFactory().getOutputStatement("Display This!")); ++ assertEquals(sw.toString(), "Display This!\n"); ++ } ++} +--- /dev/null ++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/FactoryTest.java +@@ -0,0 +1,56 @@ ++package org.mozilla.javascript.tests.scriptengine; ++ ++import javax.script.ScriptEngine; ++import javax.script.ScriptEngineFactory; ++import javax.script.ScriptEngineManager; ++import org.junit.Test; ++import org.mozilla.javascript.engine.RhinoScriptEngine; ++import org.mozilla.javascript.engine.RhinoScriptEngineFactory; ++ ++import static org.junit.Assert.*; ++ ++/* ++ * A series of tests that depend on us having our engine registered with the ++ * ScriptEngineManager by default. ++ */ ++public class FactoryTest { ++ ++ @Test ++ public void findRhinoFactory() { ++ ScriptEngineManager manager = new ScriptEngineManager(); ++ for (ScriptEngineFactory factory : manager.getEngineFactories()) { ++ if (factory instanceof RhinoScriptEngineFactory) { ++ assertEquals("rhino", factory.getEngineName()); ++ assertEquals("rhino", factory.getParameter(ScriptEngine.ENGINE)); ++ assertEquals("rhino", factory.getParameter(ScriptEngine.NAME)); ++ // This could be "unknown" if we're not running from a regular JAR ++ assertFalse(factory.getEngineVersion().isEmpty()); ++ assertEquals("javascript", factory.getLanguageName()); ++ assertEquals("javascript", factory.getParameter(ScriptEngine.LANGUAGE)); ++ assertEquals("200", factory.getLanguageVersion()); ++ assertEquals("200", factory.getParameter(ScriptEngine.LANGUAGE_VERSION)); ++ assertNull(factory.getParameter("THREADING")); ++ assertTrue(factory.getExtensions().contains("js")); ++ assertTrue(factory.getMimeTypes().contains("application/javascript")); ++ assertTrue(factory.getMimeTypes().contains("application/ecmascript")); ++ assertTrue(factory.getMimeTypes().contains("text/javascript")); ++ assertTrue(factory.getMimeTypes().contains("text/ecmascript")); ++ assertTrue(factory.getNames().contains("rhino")); ++ assertTrue(factory.getNames().contains("Rhino")); ++ assertTrue(factory.getNames().contains("javascript")); ++ assertTrue(factory.getNames().contains("JavaScript")); ++ return; ++ } ++ } ++ fail("Expected to find Rhino script engine"); ++ } ++ ++ @Test ++ public void testRhinoFactory() { ++ // This will always uniquely return our engine. ++ // In Java 8, other ways to find it may return Nashorn. ++ ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino"); ++ assertTrue(engine instanceof RhinoScriptEngine); ++ ++ } ++} +--- /dev/null ++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/InvocableTest.java +@@ -0,0 +1,158 @@ ++package org.mozilla.javascript.tests.scriptengine; ++ ++import java.io.FileNotFoundException; ++import java.io.FileReader; ++import javax.script.Invocable; ++import javax.script.ScriptEngine; ++import javax.script.ScriptEngineManager; ++import javax.script.ScriptException; ++import org.junit.Before; ++import org.junit.BeforeClass; ++import org.junit.Test; ++import org.mozilla.javascript.engine.RhinoScriptEngineFactory; ++ ++import static org.junit.Assert.*; ++ ++public class InvocableTest { ++ ++ private static ScriptEngineManager manager; ++ ++ private ScriptEngine engine; ++ private Invocable iEngine; ++ ++ @BeforeClass ++ public static void init() { ++ manager = new ScriptEngineManager(); ++ manager.registerEngineName("rhino", new RhinoScriptEngineFactory()); ++ } ++ ++ @Before ++ public void setup() { ++ engine = manager.getEngineByName("rhino"); ++ iEngine = (Invocable) engine; ++ } ++ ++ @Test ++ public void invokeFunctionTest() throws ScriptException, NoSuchMethodException { ++ engine.eval("function foo(a, b) { return a + b; }"); ++ Object result = iEngine.invokeFunction("foo", 2, 2); ++ assertEquals(result, 4L); ++ } ++ ++ @Test ++ public void invokeScriptFunctionTest() throws ScriptException, NoSuchMethodException { ++ Object scriptObj = engine.eval("let o = {};\n" ++ + "o.test = function(x) { return x + 2; }\n" ++ + "o;"); ++ assertEquals(4L, iEngine.invokeMethod(scriptObj, "test", 2)); ++ } ++ ++ @Test ++ public void invokeGenericFunctionTest() throws ScriptException, NoSuchMethodException { ++ engine.eval("let o = {};\n" ++ + "o.test = function(x) { return x + 2; }\n"); ++ Object result = engine.eval(engine.getFactory().getMethodCallSyntax("o", "test", "1")); ++ assertEquals(3L, result); ++ } ++ ++ @Test ++ public void invokeGenericFunctionTest2() throws ScriptException, NoSuchMethodException { ++ engine.eval("let o = {};\n" ++ + "o.test = function(x, y) { return x + y; }\n"); ++ Object result = engine.eval(engine.getFactory().getMethodCallSyntax("o", "test", "1", "7")); ++ assertEquals(8L, result); ++ } ++ ++ @Test ++ public void invokeMethodTest() ++ throws ScriptException, NoSuchMethodException, FileNotFoundException { ++ engine.eval(new FileReader("testsrc/assert.js")); ++ engine.eval("function FooObj() { this.x = 0; }\n" ++ + "FooObj.prototype.set = function(a, b) { this.x = a + b; }"); ++ engine.eval("let f = new FooObj();\n" ++ + "assertEquals(f.x, 0);\n" ++ + "f.set(2, 2);\n" ++ + "assertEquals(f.x, 4);"); ++ ++ Object fooObj = engine.eval("let y = new FooObj(); y"); ++ assertNotNull(fooObj); ++ iEngine.invokeMethod(fooObj, "set", 3, 3); ++ Object result = engine.eval("y.x"); ++ assertEquals(result, 6L); ++ } ++ ++ @Test ++ public void interfaceFunctionTest() ++ throws ScriptException, FileNotFoundException { ++ engine.eval(new FileReader("testsrc/assert.js")); ++ engine.eval("var foo = 'initialized';\n" ++ + "function setFoo(v) { foo = v; }\n" ++ + "function getFoo() { return foo; }\n" ++ + "function addItUp(a, b) { return a + b; }"); ++ I tester = iEngine.getInterface(I.class); ++ assertEquals(tester.getFoo(), "initialized"); ++ tester.setFoo("tested"); ++ assertEquals(tester.getFoo(), "tested"); ++ assertEquals(tester.addItUp(100, 1), 101); ++ } ++ ++ @Test ++ public void interfaceMethodTest() ++ throws ScriptException, FileNotFoundException { ++ engine.eval(new FileReader("testsrc/assert.js")); ++ Object foo = engine.eval("function Foo() { this.foo = 'initialized' }\n" ++ + "Foo.prototype.setFoo = function(v) { this.foo = v; };\n" ++ + "Foo.prototype.getFoo = function() { return this.foo; };\n" ++ + "Foo.prototype.addItUp = function(a, b) { return a + b; };\n" ++ + "new Foo();"); ++ I tester = iEngine.getInterface(foo, I.class); ++ assertEquals(tester.getFoo(), "initialized"); ++ tester.setFoo("tested"); ++ assertEquals(tester.getFoo(), "tested"); ++ assertEquals(tester.addItUp(100, 1), 101); ++ } ++ ++ @Test ++ public void interfaceFunctionMissingTest() { ++ I tester = iEngine.getInterface(I.class); ++ assertNull(tester); ++ } ++ ++ @Test ++ public void interfaceMethodMissingTest() ++ throws ScriptException { ++ // Functions defined, but not on the right object ++ Object foo = engine.eval("var foo = 'initialized';\n" ++ + "function setFoo(v) { foo = v; }\n" ++ + "function getFoo() { return foo; }\n" ++ + "function addItUp(a, b) { return a + b; }\n" ++ + "function Foo() {}\n" ++ + "new Foo();"); ++ I tester = iEngine.getInterface(foo, I.class); ++ assertNull(tester); ++ } ++ ++ @Test ++ public void invokeNotFoundTest() { ++ assertThrows(NoSuchMethodException.class, () -> { ++ iEngine.invokeFunction("foo", 2, 2); ++ }); ++ } ++ ++ @Test ++ public void invokeNotFunctionTest() { ++ assertThrows(ScriptException.class, () -> { ++ engine.eval("foo = 'bar';"); ++ iEngine.invokeFunction("foo", 2, 2); ++ }); ++ } ++ ++ interface I { ++ ++ void setFoo(String v); ++ ++ String getFoo(); ++ ++ int addItUp(int a, int b); ++ } ++} +--- /dev/null ++++ b/testsrc/org/mozilla/javascript/tests/scriptengine/ScriptEngineTest.java +@@ -0,0 +1,276 @@ ++package org.mozilla.javascript.tests.scriptengine; ++ ++import java.io.File; ++import java.io.FileReader; ++import java.io.IOException; ++import java.io.StringReader; ++import javax.script.Bindings; ++import javax.script.Compilable; ++import javax.script.CompiledScript; ++import javax.script.ScriptContext; ++import javax.script.ScriptEngine; ++import javax.script.ScriptEngineFactory; ++import javax.script.ScriptEngineManager; ++import javax.script.ScriptException; ++import javax.script.SimpleBindings; ++import javax.script.SimpleScriptContext; ++import org.junit.Before; ++import org.junit.BeforeClass; ++import org.junit.Test; ++import org.mozilla.javascript.engine.RhinoScriptEngine; ++import org.mozilla.javascript.engine.RhinoScriptEngineFactory; ++ ++import static org.junit.Assert.*; ++ ++public class ScriptEngineTest { ++ ++ private static ScriptEngineManager manager; ++ private ScriptEngine engine; ++ private Compilable cEngine; ++ ++ @BeforeClass ++ public static void initManager() { ++ manager = new ScriptEngineManager(); ++ manager.registerEngineName("rhino", new RhinoScriptEngineFactory()); ++ } ++ ++ @Before ++ public void init() { ++ engine = manager.getEngineByName("rhino"); ++ cEngine = (Compilable) engine; ++ } ++ ++ @Test ++ public void testHello() throws ScriptException { ++ Object result = engine.eval("'Hello, World!';"); ++ assertEquals(result, "Hello, World!"); ++ } ++ ++ @Test ++ public void testHelloInterpreted() throws ScriptException { ++ engine.put(RhinoScriptEngine.OPTIMIZATION_LEVEL, -1); ++ Object result = engine.eval("'Hello, World!';"); ++ assertEquals(result, "Hello, World!"); ++ } ++ ++ ++ @Test ++ public void testHelloReader() throws ScriptException { ++ String src = "1 + 1;"; ++ StringReader sr = new StringReader(src); ++ Object result = engine.eval(sr); ++ assertEquals(result, 2L); ++ } ++ ++ @Test ++ public void testGenericStatements() throws ScriptException { ++ Object result = engine.eval(engine.getFactory().getProgram( ++ "let x = 1;", ++ "let y = 2", ++ "x + y" ++ )); ++ assertEquals(3L, result); ++ } ++ ++ @Test ++ public void testThrows() { ++ assertThrows(ScriptException.class, () -> { ++ engine.eval("throw 'This is an error'"); ++ }); ++ } ++ ++ @Test ++ public void testEngineBindings() throws IOException, ScriptException { ++ engine.put("string", "Hello"); ++ engine.put("integer", 123); ++ engine.put("a", "a"); ++ engine.put("b", "b"); ++ engine.put("c", "c"); ++ ++ // Ensure that stuff we just stuck in bindings made it to a global ++ engine.eval(new FileReader("testsrc/assert.js")); ++ engine.eval("assertEquals(string, 'Hello');\n" ++ + "assertEquals(integer, 123);\n" ++ + "string = 'Goodbye';\n" ++ + "assertEquals(string, 'Goodbye');"); ++ assertEquals(engine.get("string"), "Goodbye"); ++ ++ // Make sure we can delete ++ engine.getBindings(ScriptContext.ENGINE_SCOPE).remove("string"); ++ // This will throw because string is undefined ++ assertThrows(ScriptException.class, () -> { ++ engine.eval("let failing = string + '123';"); ++ }); ++ } ++ ++ @Test ++ public void testEngineScope() throws IOException, ScriptException { ++ engine.put("string", "Hello"); ++ engine.put("integer", 123); ++ engine.eval(new FileReader("testsrc/assert.js")); ++ engine.eval("assertEquals(string, 'Hello');" ++ + "assertEquals(integer, 123);"); ++ ++ // Additional things added to the context but old stuff still there ++ engine.put("second", true); ++ engine.put("integer", 99); ++ engine.eval("assertEquals(string, 'Hello');" ++ + "assertEquals(integer, 99);" ++ + "assertTrue(second);"); ++ } ++ ++ @Test ++ public void testScopedBindings() throws IOException, ScriptException { ++ ScriptContext sc = new SimpleScriptContext(); ++ ++ // We treat engine and global scope the same -- if the user actually ++ // uses both, then engine scope overrides global scope. ++ Bindings eb = new SimpleBindings(); ++ sc.setBindings(eb, ScriptContext.ENGINE_SCOPE); ++ eb.put("engine", Boolean.TRUE); ++ eb.put("level", 2); ++ ++ Bindings gb = new SimpleBindings(); ++ sc.setBindings(gb, ScriptContext.GLOBAL_SCOPE); ++ gb.put("global", Boolean.TRUE); ++ gb.put("level", 0); ++ ++ engine.eval(new FileReader("testsrc/assert.js"), sc); ++ engine.eval("assertTrue(engine);" ++ + "assertTrue(global);" ++ + "assertEquals(level, 2);", sc); ++ } ++ ++ @Test ++ public void testReservedBindings() throws ScriptException { ++ engine.put(ScriptEngine.ENGINE, "engine"); ++ engine.put(ScriptEngine.ENGINE_VERSION, "123"); ++ engine.put(ScriptEngine.LANGUAGE, "foo"); ++ engine.put(ScriptEngine.NAME, "nothing"); ++ ++ // Can't actually test for those invalid property names -- but ++ // at least they didn't break the script. ++ assertEquals(engine.eval("'success'"), "success"); ++ } ++ ++ @Test ++ public void testCompiled() throws ScriptException, IOException { ++ CompiledScript asserts = ++ cEngine.compile(new FileReader("testsrc/assert.js")); ++ CompiledScript tests = ++ cEngine.compile("assertEquals(compiled, true);"); ++ ++ // Fails because asserts have not been loaded ++ assertThrows(ScriptException.class, tests::eval); ++ ++ asserts.eval(); ++ // Fails because value has not been set ++ assertThrows(ScriptException.class, tests::eval); ++ ++ engine.put("compiled", Boolean.TRUE); ++ tests.eval(); ++ } ++ ++ @Test ++ public void testCompiled2() throws ScriptException, IOException { ++ CompiledScript asserts = ++ cEngine.compile(new FileReader("testsrc/assert.js")); ++ CompiledScript init = ++ cEngine.compile("value = 0;"); ++ CompiledScript tests = ++ cEngine.compile("assertEquals(value, expectedValue);" ++ + "value += 1;"); ++ ++ asserts.eval(); ++ init.eval(); ++ for (int i = 0; i <= 10; i++) { ++ engine.put("expectedValue", i); ++ tests.eval(); ++ } ++ } ++ ++ @Test ++ public void testCompiledThrows() throws ScriptException { ++ engine.put(ScriptEngine.FILENAME, "throws1.js"); ++ CompiledScript throw1 = cEngine.compile("throw 'one';"); ++ engine.put(ScriptEngine.FILENAME, "throws2.js"); ++ CompiledScript throw2 = cEngine.compile("throw 'two';"); ++ ++ try { ++ throw1.eval(); ++ fail("Expected a throw"); ++ } catch (ScriptException se) { ++ assertTrue(se.getMessage().startsWith("one")); ++ assertEquals("throws1.js", se.getFileName()); ++ assertEquals(1, se.getLineNumber()); ++ } ++ ++ try { ++ throw2.eval(); ++ fail("Expected a throw"); ++ } catch (ScriptException se) { ++ assertTrue(se.getMessage().startsWith("two")); ++ assertEquals("throws2.js", se.getFileName()); ++ assertEquals(1, se.getLineNumber()); ++ } ++ } ++ ++ @Test ++ public void testCantCompile() { ++ assertThrows(ScriptException.class, () -> { ++ cEngine.compile("This is not JavaScript at all!"); ++ }); ++ } ++ ++ @Test ++ public void testLanguageVersion() throws ScriptException { ++ // Default language version is modernish ++ ScriptEngine newEngine = manager.getEngineByName("rhino"); ++ assertEquals(newEngine.eval("Symbol() == Symbol()"), Boolean.FALSE); ++ ++ // Older language versions ++ ScriptEngine oldEngine = manager.getEngineByName("rhino"); ++ oldEngine.put(ScriptEngine.LANGUAGE_VERSION, 120); ++ assertThrows(ScriptException.class, () -> { ++ oldEngine.eval("Symbol() == Symbol()"); ++ }); ++ ++ // The same with a string ++ ScriptEngine olderEngine = manager.getEngineByName("rhino"); ++ olderEngine.put(ScriptEngine.LANGUAGE_VERSION, "100"); ++ assertThrows(ScriptException.class, () -> { ++ olderEngine.eval("Symbol() == Symbol()"); ++ }); ++ } ++ ++ @Test ++ public void testBadLanguageVersion() { ++ assertThrows(ScriptException.class, () -> { ++ engine.put(ScriptEngine.LANGUAGE_VERSION, "Not a number"); ++ engine.eval("print('Hi!');"); ++ }); ++ assertThrows(ScriptException.class, () -> { ++ engine.put(ScriptEngine.LANGUAGE_VERSION, 3.14); ++ engine.eval("print('Hi!');"); ++ }); ++ } ++ ++ @Test ++ public void testFilename() { ++ engine.put(ScriptEngine.FILENAME, "test.js"); ++ try { ++ engine.eval("throw 'This is an exception';"); ++ } catch (ScriptException se) { ++ assertEquals(se.getFileName(), "test.js"); ++ } ++ } ++ ++ @Test ++ public void testJavaObject() throws ScriptException { ++ File f = new File("testsrc/assert.js"); ++ String absVal = f.getAbsolutePath(); ++ engine.put("file", f); ++ Object result = engine.eval("file.getAbsolutePath();"); ++ assertEquals(absVal, result); ++ } ++} +--- a/build.xml ++++ b/build.xml +@@ -87,7 +87,9 @@ + basedir="${classes}" + manifest="src/manifest" + compress="${jar-compression}" +- /> ++ > ++ ++ + + + diff -Nru rhino-1.7.7.2/debian/patches/series rhino-1.7.7.2/debian/patches/series --- rhino-1.7.7.2/debian/patches/series 2020-09-03 11:36:47.000000000 +0000 +++ rhino-1.7.7.2/debian/patches/series 2021-02-08 09:51:49.000000000 +0000 @@ -2,3 +2,6 @@ 05_modify-usage.patch 06_preserve-backward-compatibility.patch 07_fix-context-implementation-version.patch +08_fix-jar-version-number.patch +script-engine.patch + diff -Nru rhino-1.7.7.2/debian/rules rhino-1.7.7.2/debian/rules --- rhino-1.7.7.2/debian/rules 2020-09-03 11:36:47.000000000 +0000 +++ rhino-1.7.7.2/debian/rules 2021-02-08 10:39:26.000000000 +0000 @@ -7,7 +7,7 @@ dh $@ --with javahelper --with maven-repo-helper override_dh_auto_build: - dh_auto_build -- jar javadoc + dh_auto_build -- jar javadoc -Dsource-level=7 -Dtarget-jvm=7 override_dh_installchangelogs: dh_installchangelogs -- RELEASE-NOTES.md