changeset 517:d82ac93aa55c

8023631: engine.js init script should be loaded into every global instance created by engines Reviewed-by: attila, hannesw
author sundar
date Fri, 23 Aug 2013 16:10:37 +0530
parents 5a1e07b9a3cd
children 4dcd5a22fdd3
files src/jdk/nashorn/api/scripting/NashornScriptEngine.java src/jdk/nashorn/api/scripting/resources/engine.js test/src/jdk/nashorn/api/scripting/InvocableTest.java test/src/jdk/nashorn/api/scripting/ScopeTest.java test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
diffstat 6 files changed, 1121 insertions(+), 916 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Aug 22 22:32:16 2013 +0530
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Fri Aug 23 16:10:37 2013 +0530
@@ -80,6 +80,7 @@
      */
     public static final String NASHORN_GLOBAL = "nashorn.global";
 
+    // commonly used access control context objects
     private static AccessControlContext createPermAccCtxt(final String permName) {
         final Permissions perms = new Permissions();
         perms.add(new RuntimePermission(permName));
@@ -89,18 +90,23 @@
     private static final AccessControlContext CREATE_CONTEXT_ACC_CTXT = createPermAccCtxt(Context.NASHORN_CREATE_CONTEXT);
     private static final AccessControlContext CREATE_GLOBAL_ACC_CTXT  = createPermAccCtxt(Context.NASHORN_CREATE_GLOBAL);
 
+    // the factory that created this engine
     private final ScriptEngineFactory factory;
+    // underlying nashorn Context - 1:1 with engine instance
     private final Context             nashornContext;
     // do we want to share single Nashorn global instance across ENGINE_SCOPEs?
     private final boolean             _global_per_engine;
+    // This is the initial default Nashorn global object.
+    // This is used as "shared" global if above option is true.
     private final ScriptObject        global;
-    // initialized bit late to be made 'final'. Property object for "context"
-    // property of global object
-    private Property                  contextProperty;
+    // initialized bit late to be made 'final'.
+    // Property object for "context" property of global object.
+    private volatile Property         contextProperty;
 
     // default options passed to Nashorn Options object
     private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-doe" };
 
+    // Nashorn script engine error message management
     private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages";
 
     private static final ResourceBundle MESSAGES_BUNDLE;
@@ -108,6 +114,7 @@
         MESSAGES_BUNDLE = ResourceBundle.getBundle(MESSAGES_RESOURCE, Locale.getDefault());
     }
 
+    // helper to get Nashorn script engine error message
     private static String getMessage(final String msgId, final String... args) {
         try {
             return new MessageFormat(MESSAGES_BUNDLE.getString(msgId)).format(args);
@@ -116,6 +123,30 @@
         }
     }
 
+    // load engine.js and return content as a char[]
+    private static char[] loadEngineJSSource() {
+        final String script = "resources/engine.js";
+        try {
+            final InputStream is = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<InputStream>() {
+                        @Override
+                        public InputStream run() throws Exception {
+                            final URL url = NashornScriptEngine.class.getResource(script);
+                            return url.openStream();
+                        }
+                    });
+            return Source.readFully(new InputStreamReader(is));
+        } catch (final PrivilegedActionException | IOException e) {
+            if (Context.DEBUG) {
+                e.printStackTrace();
+            }
+            throw new RuntimeException(e);
+        }
+    }
+
+    // Source object for engine.js
+    private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource());
+
     NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
         this(factory, DEFAULT_OPTIONS, appLoader);
     }
@@ -146,19 +177,9 @@
         this._global_per_engine = nashornContext.getEnv()._global_per_engine;
 
         // create new global object
-        this.global = createNashornGlobal();
-        // set the default engine scope for the default context
+        this.global = createNashornGlobal(context);
+        // set the default ENGINE_SCOPE object for the default context
         context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
-
-        // evaluate engine initial script
-        try {
-            evalEngineScript();
-        } catch (final ScriptException e) {
-            if (Context.DEBUG) {
-                e.printStackTrace();
-            }
-            throw new RuntimeException(e);
-        }
     }
 
     @Override
@@ -192,8 +213,7 @@
             // We use same 'global' for all Bindings.
             return new SimpleBindings();
         } else {
-            final ScriptObject newGlobal = createNashornGlobal();
-            return new ScriptObjectMirror(newGlobal, newGlobal);
+            return createGlobalMirror(null);
         }
     }
 
@@ -230,6 +250,48 @@
         return invokeImpl(thiz, name, args);
     }
 
+    @Override
+    public <T> T getInterface(final Class<T> clazz) {
+        return getInterfaceInner(null, clazz);
+    }
+
+    @Override
+    public <T> T getInterface(final Object thiz, final Class<T> clazz) {
+        if (thiz == null) {
+            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
+        }
+        return getInterfaceInner(thiz, clazz);
+    }
+
+    // These are called from the "engine.js" script
+
+    /**
+     * This hook is used to search js global variables exposed from Java code.
+     *
+     * @param self 'this' passed from the script
+     * @param ctxt current ScriptContext in which name is searched
+     * @param name name of the variable searched
+     * @return the value of the named variable
+     */
+    public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
+        if (ctxt != null) {
+            final int scope = ctxt.getAttributesScope(name);
+            final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
+            if (scope != -1) {
+                return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
+            }
+
+            if (self == UNDEFINED) {
+                // scope access and so throw ReferenceError
+                throw referenceError(ctxtGlobal, "not.defined", name);
+            }
+        }
+
+        return UNDEFINED;
+    }
+
+    // Implementation only below this point
+
     private <T> T getInterfaceInner(final Object thiz, final Class<T> clazz) {
         if (clazz == null || !clazz.isInterface()) {
             throw new IllegalArgumentException(getMessage("interface.class.expected"));
@@ -297,47 +359,10 @@
         }
     }
 
-    @Override
-    public <T> T getInterface(final Class<T> clazz) {
-        return getInterfaceInner(null, clazz);
-    }
-
-    @Override
-    public <T> T getInterface(final Object thiz, final Class<T> clazz) {
-        if (thiz == null) {
-            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
-        }
-        return getInterfaceInner(thiz, clazz);
-    }
-
-    // These are called from the "engine.js" script
-
-    /**
-     * This hook is used to search js global variables exposed from Java code.
-     *
-     * @param self 'this' passed from the script
-     * @param ctxt current ScriptContext in which name is searched
-     * @param name name of the variable searched
-     * @return the value of the named variable
-     */
-    public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
-        final int scope = ctxt.getAttributesScope(name);
-        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
-        if (scope != -1) {
-            return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
-        }
-
-        if (self == UNDEFINED) {
-            // scope access and so throw ReferenceError
-            throw referenceError(ctxtGlobal, "not.defined", name);
-        }
-
-        return UNDEFINED;
-    }
-
+    // Retrieve nashorn Global object for a given ScriptContext object
     private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
         if (_global_per_engine) {
-            // shared single global for all ENGINE_SCOPE Bindings
+            // shared single global object for all ENGINE_SCOPE Bindings
             return global;
         }
 
@@ -361,11 +386,12 @@
 
         // We didn't find associated nashorn global mirror in the Bindings given!
         // Create new global instance mirror and associate with the Bindings.
-        final ScriptObjectMirror mirror = (ScriptObjectMirror)createBindings();
+        final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
         bindings.put(NASHORN_GLOBAL, mirror);
         return mirror.getScriptObject();
     }
 
+    // Retrieve nashorn Global object from a given ScriptObjectMirror
     private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) {
         ScriptObject sobj = mirror.getScriptObject();
         if (sobj instanceof GlobalObject && sobj.isOfContext(nashornContext)) {
@@ -375,7 +401,14 @@
         return null;
     }
 
-    private ScriptObject createNashornGlobal() {
+    // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
+    private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
+        final ScriptObject newGlobal = createNashornGlobal(ctxt);
+        return new ScriptObjectMirror(newGlobal, newGlobal);
+    }
+
+    // Create a new Nashorn Global object
+    private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
         final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
             @Override
             public ScriptObject run() {
@@ -396,7 +429,7 @@
         // current ScriptContext exposed as "context"
         // "context" is non-writable from script - but script engine still
         // needs to set it and so save the context Property object
-        contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, UNDEFINED);
+        contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, null);
         // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as
         // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property
         // in the Global of a Context we just created - both the Context and the Global were just created and can not be
@@ -406,38 +439,17 @@
         newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED);
         // file name default is null
         newGlobal.addOwnProperty(ScriptEngine.FILENAME, Property.NOT_ENUMERABLE, null);
+        // evaluate engine.js initialization script this new global object
+        try {
+            evalImpl(compileImpl(ENGINE_SCRIPT_SRC, newGlobal), ctxt, newGlobal);
+        } catch (final ScriptException exp) {
+            throw new RuntimeException(exp);
+        }
         return newGlobal;
     }
 
-    private void evalEngineScript() throws ScriptException {
-        final String script = "resources/engine.js";
-        final String name   = NashornException.ENGINE_SCRIPT_SOURCE_NAME;
-        try {
-            final InputStream is = AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<InputStream>() {
-                        @Override
-                        public InputStream run() throws Exception {
-                            final URL url = NashornScriptEngine.class.getResource(script);
-                            return url.openStream();
-                        }
-                    });
-            put(ScriptEngine.FILENAME, name);
-            try (final InputStreamReader isr = new InputStreamReader(is)) {
-                eval(isr);
-            }
-        } catch (final PrivilegedActionException | IOException e) {
-            if (Context.DEBUG) {
-                e.printStackTrace();
-            }
-            throw new ScriptException(e);
-        } finally {
-            put(ScriptEngine.FILENAME, null);
-        }
-    }
-
-    // scripts should see "context" and "engine" as variables
-    private void setContextVariables(final ScriptContext ctxt) {
-        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
+    // scripts should see "context" and "engine" as variables in the given global object
+    private void setContextVariables(final ScriptObject ctxtGlobal, final ScriptContext ctxt) {
         // set "context" global variable via contextProperty - because this
         // property is non-writable
         contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
@@ -502,18 +514,24 @@
     }
 
     private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException {
+        return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
+    }
+
+    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final ScriptObject ctxtGlobal) throws ScriptException {
         if (script == null) {
             return null;
         }
         final ScriptObject oldGlobal = Context.getGlobal();
-        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
         final boolean globalChanged = (oldGlobal != ctxtGlobal);
         try {
             if (globalChanged) {
                 Context.setGlobal(ctxtGlobal);
             }
 
-            setContextVariables(ctxt);
+            // set ScriptContext variables if ctxt is non-null
+            if (ctxt != null) {
+                setContextVariables(ctxtGlobal, ctxt);
+            }
             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
         } catch (final Exception e) {
             throwAsScriptException(e);
@@ -563,15 +581,18 @@
     }
 
     private ScriptFunction compileImpl(final Source source, final ScriptContext ctxt) throws ScriptException {
+        return compileImpl(source, getNashornGlobalFrom(ctxt));
+    }
+
+    private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
         final ScriptObject oldGlobal = Context.getGlobal();
-        final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
-        final boolean globalChanged = (oldGlobal != ctxtGlobal);
+        final boolean globalChanged = (oldGlobal != newGlobal);
         try {
             if (globalChanged) {
-                Context.setGlobal(ctxtGlobal);
+                Context.setGlobal(newGlobal);
             }
 
-            return nashornContext.compileScript(source, ctxtGlobal);
+            return nashornContext.compileScript(source, newGlobal);
         } catch (final Exception e) {
             throwAsScriptException(e);
             throw new AssertionError("should not reach here");
--- a/src/jdk/nashorn/api/scripting/resources/engine.js	Thu Aug 22 22:32:16 2013 +0530
+++ b/src/jdk/nashorn/api/scripting/resources/engine.js	Fri Aug 23 16:10:37 2013 +0530
@@ -23,10 +23,9 @@
 
 /**
  * This script file is executed by script engine at the construction
- * of the engine. The functions here assume global variables "context"
- * of type javax.script.ScriptContext and "engine" of the type
+ * of the every new Global object. The functions here assume global variables
+ * "context" of type javax.script.ScriptContext and "engine" of the type
  * jdk.nashorn.api.scripting.NashornScriptEngine.
- *
  **/
 
 Object.defineProperty(this, "__noSuchProperty__", {
@@ -40,7 +39,7 @@
 });
 
 function print() {
-    var writer = context.getWriter();
+    var writer = context != null? context.writer : engine.context.writer;
     if (! (writer instanceof java.io.PrintWriter)) {
         writer = new java.io.PrintWriter(writer);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java	Fri Aug 23 16:10:37 2013 +0530
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.scripting;
+
+import java.util.Objects;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+import org.testng.Assert;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for javax.script.Invocable implementation of nashorn.
+ */
+public class InvocableTest {
+
+    private void log(String msg) {
+        org.testng.Reporter.log(msg, true);
+    }
+
+    @Test
+    public void invokeMethodTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            e.eval("var Example = function() { this.hello = function() { return 'Hello World!'; };}; myExample = new Example();");
+            final Object obj = e.get("myExample");
+            final Object res = ((Invocable) e).invokeMethod(obj, "hello");
+            assertEquals(res, "Hello World!");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+    }
+
+    @Test
+    /**
+     * Check that we can call invokeMethod on an object that we got by
+     * evaluating script with different Context set.
+     */
+    public void invokeMethodDifferentContextTest() {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            // define an object with method on it
+            Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
+
+            final ScriptContext ctxt = new SimpleScriptContext();
+            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
+            e.setContext(ctxt);
+
+            // invoke 'func' on obj - but with current script context changed
+            final Object res = ((Invocable) e).invokeMethod(obj, "hello");
+            assertEquals(res, "Hello World!");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+    }
+
+    @Test
+    /**
+     * Check that invokeMethod throws NPE on null method name.
+     */
+    public void invokeMethodNullNameTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            final Object obj = e.eval("({})");
+            final Object res = ((Invocable) e).invokeMethod(obj, null);
+            fail("should have thrown NPE");
+        } catch (final Exception exp) {
+            if (!(exp instanceof NullPointerException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that invokeMethod throws NoSuchMethodException on missing method.
+     */
+    public void invokeMethodMissingTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            final Object obj = e.eval("({})");
+            final Object res = ((Invocable) e).invokeMethod(obj, "nonExistentMethod");
+            fail("should have thrown NoSuchMethodException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof NoSuchMethodException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that calling method on non-script object 'thiz' results in
+     * IllegalArgumentException.
+     */
+    public void invokeMethodNonScriptObjectThizTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            ((Invocable) e).invokeMethod(new Object(), "toString");
+            fail("should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that calling method on null 'thiz' results in
+     * IllegalArgumentException.
+     */
+    public void invokeMethodNullThizTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            ((Invocable) e).invokeMethod(null, "toString");
+            fail("should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that calling method on mirror created by another engine results in
+     * IllegalArgumentException.
+     */
+    public void invokeMethodMixEnginesTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine engine1 = m.getEngineByName("nashorn");
+        final ScriptEngine engine2 = m.getEngineByName("nashorn");
+
+        try {
+            Object obj = engine1.eval("({ run: function() {} })");
+            // pass object from engine1 to engine2 as 'thiz' for invokeMethod
+            ((Invocable) engine2).invokeMethod(obj, "run");
+            fail("should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public void getInterfaceTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Invocable inv = (Invocable) e;
+
+        // try to get interface from global functions
+        try {
+            e.eval("function run() { print('run'); };");
+            final Runnable runnable = inv.getInterface(Runnable.class);
+            runnable.run();
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+
+        // try interface on specific script object
+        try {
+            e.eval("var obj = { run: function() { print('run from obj'); } };");
+            Object obj = e.get("obj");
+            final Runnable runnable = inv.getInterface(obj, Runnable.class);
+            runnable.run();
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+    }
+
+    public interface Foo {
+
+        public void bar();
+    }
+
+    public interface Foo2 extends Foo {
+
+        public void bar2();
+    }
+
+    @Test
+    public void getInterfaceMissingTest() {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine engine = manager.getEngineByName("nashorn");
+
+        // don't define any function.
+        try {
+            engine.eval("");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+
+        Runnable runnable = ((Invocable) engine).getInterface(Runnable.class);
+        if (runnable != null) {
+            fail("runnable is not null!");
+        }
+
+        // now define "run"
+        try {
+            engine.eval("function run() { print('this is run function'); }");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+        runnable = ((Invocable) engine).getInterface(Runnable.class);
+        // should not return null now!
+        runnable.run();
+
+        // define only one method of "Foo2"
+        try {
+            engine.eval("function bar() { print('bar function'); }");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+
+        Foo2 foo2 = ((Invocable) engine).getInterface(Foo2.class);
+        if (foo2 != null) {
+            throw new RuntimeException("foo2 is not null!");
+        }
+
+        // now define other method of "Foo2"
+        try {
+            engine.eval("function bar2() { print('bar2 function'); }");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+        foo2 = ((Invocable) engine).getInterface(Foo2.class);
+        foo2.bar();
+        foo2.bar2();
+    }
+
+    @Test
+    /**
+     * Try passing non-interface Class object for interface implementation.
+     */
+    public void getNonInterfaceGetInterfaceTest() {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine engine = manager.getEngineByName("nashorn");
+        try {
+            log(Objects.toString(((Invocable) engine).getInterface(Object.class)));
+            fail("Should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                fail("IllegalArgumentException expected, got " + exp);
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that we can get interface out of a script object even after
+     * switching to use different ScriptContext.
+     */
+    public void getInterfaceDifferentContext() {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+        try {
+            Object obj = e.eval("({ run: function() { } })");
+
+            // change script context
+            ScriptContext ctxt = new SimpleScriptContext();
+            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
+            e.setContext(ctxt);
+
+            Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
+            r.run();
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+    }
+
+    @Test
+    /**
+     * Check that getInterface on non-script object 'thiz' results in
+     * IllegalArgumentException.
+     */
+    public void getInterfaceNonScriptObjectThizTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            ((Invocable) e).getInterface(new Object(), Runnable.class);
+            fail("should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that getInterface on null 'thiz' results in
+     * IllegalArgumentException.
+     */
+    public void getInterfaceNullThizTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            ((Invocable) e).getInterface(null, Runnable.class);
+            fail("should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that calling getInterface on mirror created by another engine
+     * results in IllegalArgumentException.
+     */
+    public void getInterfaceMixEnginesTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine engine1 = m.getEngineByName("nashorn");
+        final ScriptEngine engine2 = m.getEngineByName("nashorn");
+
+        try {
+            Object obj = engine1.eval("({ run: function() {} })");
+            // pass object from engine1 to engine2 as 'thiz' for getInterface
+            ((Invocable) engine2).getInterface(obj, Runnable.class);
+            fail("should have thrown IllegalArgumentException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof IllegalArgumentException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * check that null function name results in NPE.
+     */
+    public void invokeFunctionNullNameTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            final Object res = ((Invocable) e).invokeFunction(null);
+            fail("should have thrown NPE");
+        } catch (final Exception exp) {
+            if (!(exp instanceof NullPointerException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that attempt to call missing function results in
+     * NoSuchMethodException.
+     */
+    public void invokeFunctionMissingTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            final Object res = ((Invocable) e).invokeFunction("NonExistentFunc");
+            fail("should have thrown NoSuchMethodException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof NoSuchMethodException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    /**
+     * Check that invokeFunction calls functions only from current context's
+     * Bindings.
+     */
+    public void invokeFunctionDifferentContextTest() {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+
+        try {
+            // define an object with method on it
+            Object obj = e.eval("function hello() { return 'Hello World!'; }");
+            final ScriptContext ctxt = new SimpleScriptContext();
+            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
+            // change engine's current context
+            e.setContext(ctxt);
+
+            ((Invocable) e).invokeFunction("hello"); // no 'hello' in new context!
+            fail("should have thrown NoSuchMethodException");
+        } catch (final Exception exp) {
+            if (!(exp instanceof NoSuchMethodException)) {
+                exp.printStackTrace();
+                fail(exp.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public void invokeFunctionExceptionTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        try {
+            e.eval("function func() { throw new TypeError(); }");
+        } catch (final Throwable t) {
+            t.printStackTrace();
+            fail(t.getMessage());
+        }
+
+        try {
+            ((Invocable) e).invokeFunction("func");
+            fail("should have thrown exception");
+        } catch (final ScriptException se) {
+            // ECMA TypeError property wrapped as a ScriptException
+            log("got " + se + " as expected");
+        } catch (final Throwable t) {
+            t.printStackTrace();
+            fail(t.getMessage());
+        }
+    }
+
+    @Test
+    public void invokeMethodExceptionTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        try {
+            e.eval("var sobj = {}; sobj.foo = function func() { throw new TypeError(); }");
+        } catch (final Throwable t) {
+            t.printStackTrace();
+            fail(t.getMessage());
+        }
+
+        try {
+            final Object sobj = e.get("sobj");
+            ((Invocable) e).invokeMethod(sobj, "foo");
+            fail("should have thrown exception");
+        } catch (final ScriptException se) {
+            // ECMA TypeError property wrapped as a ScriptException
+            log("got " + se + " as expected");
+        } catch (final Throwable t) {
+            t.printStackTrace();
+            fail(t.getMessage());
+        }
+    }
+
+    @Test
+    /**
+     * Tests whether invocation of a JavaScript method through a variable arity
+     * Java method will pass the vararg array. Both non-vararg and vararg
+     * JavaScript methods are tested.
+     *
+     * @throws ScriptException
+     */
+    public void variableArityInterfaceTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        e.eval(
+                "function test1(i, strings) {"
+                + "    return 'i == ' + i + ', strings instanceof java.lang.String[] == ' + (strings instanceof Java.type('java.lang.String[]')) + ', strings == ' + java.util.Arrays.toString(strings)"
+                + "}"
+                + "function test2() {"
+                + "    return 'arguments[0] == ' + arguments[0] + ', arguments[1] instanceof java.lang.String[] == ' + (arguments[1] instanceof Java.type('java.lang.String[]')) + ', arguments[1] == ' + java.util.Arrays.toString(arguments[1])"
+                + "}");
+        final VariableArityTestInterface itf = ((Invocable) e).getInterface(VariableArityTestInterface.class);
+        Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
+        Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Fri Aug 23 16:10:37 2013 +0530
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.scripting;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
+import org.testng.Assert;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for jsr223 Bindings "scope" (engine, global scopes)
+ */
+public class ScopeTest {
+
+    @Test
+    public void createBindingsTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        Bindings b = e.createBindings();
+        b.put("foo", 42.0);
+        Object res = null;
+        try {
+            res = e.eval("foo == 42.0", b);
+        } catch (final ScriptException | NullPointerException se) {
+            se.printStackTrace();
+            fail(se.getMessage());
+        }
+
+        assertEquals(res, Boolean.TRUE);
+    }
+
+    @Test
+    public void engineScopeTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
+
+        // check few ECMA standard built-in global properties
+        assertNotNull(engineScope.get("Object"));
+        assertNotNull(engineScope.get("TypeError"));
+        assertNotNull(engineScope.get("eval"));
+
+        // can access via ScriptEngine.get as well
+        assertNotNull(e.get("Object"));
+        assertNotNull(e.get("TypeError"));
+        assertNotNull(e.get("eval"));
+
+        // Access by either way should return same object
+        assertEquals(engineScope.get("Array"), e.get("Array"));
+        assertEquals(engineScope.get("EvalError"), e.get("EvalError"));
+        assertEquals(engineScope.get("undefined"), e.get("undefined"));
+
+        // try exposing a new variable from scope
+        engineScope.put("myVar", "foo");
+        try {
+            assertEquals(e.eval("myVar"), "foo");
+        } catch (final ScriptException se) {
+            se.printStackTrace();
+            fail(se.getMessage());
+        }
+
+        // update "myVar" in script an check the value from scope
+        try {
+            e.eval("myVar = 'nashorn';");
+        } catch (final ScriptException se) {
+            se.printStackTrace();
+            fail(se.getMessage());
+        }
+
+        // now check modified value from scope and engine
+        assertEquals(engineScope.get("myVar"), "nashorn");
+        assertEquals(e.get("myVar"), "nashorn");
+    }
+
+    @Test
+    public void multiGlobalTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final Bindings b = e.createBindings();
+        final ScriptContext newCtxt = new SimpleScriptContext();
+        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+        try {
+            Object obj1 = e.eval("Object");
+            Object obj2 = e.eval("Object", newCtxt);
+            Assert.assertNotEquals(obj1, obj2);
+            Assert.assertNotNull(obj1);
+            Assert.assertNotNull(obj2);
+            Assert.assertEquals(obj1.toString(), obj2.toString());
+
+            e.eval("x = 'hello'");
+            e.eval("x = 'world'", newCtxt);
+            Object x1 = e.getContext().getAttribute("x");
+            Object x2 = newCtxt.getAttribute("x");
+            Assert.assertNotEquals(x1, x2);
+            Assert.assertEquals(x1, "hello");
+            Assert.assertEquals(x2, "world");
+
+            x1 = e.eval("x");
+            x2 = e.eval("x", newCtxt);
+            Assert.assertNotEquals(x1, x2);
+            Assert.assertEquals(x1, "hello");
+            Assert.assertEquals(x2, "world");
+
+            final ScriptContext origCtxt = e.getContext();
+            e.setContext(newCtxt);
+            e.eval("y = new Object()");
+            e.eval("y = new Object()", origCtxt);
+
+            Object y1 = origCtxt.getAttribute("y");
+            Object y2 = newCtxt.getAttribute("y");
+            Assert.assertNotEquals(y1, y2);
+            Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
+            Assert.assertEquals("[object Object]", y1.toString());
+            Assert.assertEquals("[object Object]", y2.toString());
+        } catch (final ScriptException se) {
+            se.printStackTrace();
+            fail(se.getMessage());
+        }
+    }
+
+    @Test
+    public void userEngineScopeBindingsTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        e.eval("function func() {}");
+
+        final ScriptContext newContext = new SimpleScriptContext();
+        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
+        // we are using a new bindings - so it should have 'func' defined
+        Object value = e.eval("typeof func", newContext);
+        assertTrue(value.equals("undefined"));
+    }
+
+    @Test
+    public void userEngineScopeBindingsNoLeakTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptContext newContext = new SimpleScriptContext();
+        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
+        e.eval("function foo() {}", newContext);
+
+        // in the default context's ENGINE_SCOPE, 'foo' shouldn't exist
+        assertTrue(e.eval("typeof foo").equals("undefined"));
+    }
+
+    @Test
+    public void userEngineScopeBindingsRetentionTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptContext newContext = new SimpleScriptContext();
+        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
+        e.eval("function foo() {}", newContext);
+
+        // definition retained with user's ENGINE_SCOPE Binding
+        assertTrue(e.eval("typeof foo", newContext).equals("function"));
+
+        final Bindings oldBindings = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
+        // but not in another ENGINE_SCOPE binding
+        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
+        assertTrue(e.eval("typeof foo", newContext).equals("undefined"));
+
+        // restore ENGINE_SCOPE and check again
+        newContext.setBindings(oldBindings, ScriptContext.ENGINE_SCOPE);
+        assertTrue(e.eval("typeof foo", newContext).equals("function"));
+    }
+
+    @Test
+    // check that engine.js definitions are visible in all new global instances
+    public void checkBuiltinsInNewBindingsTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        // check default global instance has engine.js definitions
+        final Bindings g = (Bindings) e.eval("this");
+        Object value = g.get("__noSuchProperty__");
+        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
+        value = g.get("print");
+        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
+
+        // check new global instance created has engine.js definitions
+        Bindings b = e.createBindings();
+        value = b.get("__noSuchProperty__");
+        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
+        value = b.get("print");
+        assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
+
+        // put a mapping into GLOBAL_SCOPE
+        final Bindings globalScope = e.getContext().getBindings(ScriptContext.GLOBAL_SCOPE);
+        globalScope.put("x", "hello");
+
+        // GLOBAL_SCOPE mapping should be visible from default ScriptContext eval
+        assertTrue(e.eval("x").equals("hello"));
+
+        final ScriptContext ctx = new SimpleScriptContext();
+        ctx.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+        ctx.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+        // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval
+        assertTrue(e.eval("x", ctx).equals("hello"));
+
+        // try some arbitray Bindings for ENGINE_SCOPE
+        Bindings sb = new SimpleBindings();
+        ctx.setBindings(sb, ScriptContext.ENGINE_SCOPE);
+
+        // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval
+        assertTrue(e.eval("x", ctx).equals("hello"));
+
+        // engine.js builtins are still defined even with arbitrary Bindings
+        assertTrue(e.eval("typeof print", ctx).equals("function"));
+        assertTrue(e.eval("typeof __noSuchProperty__", ctx).equals("function"));
+
+        // ENGINE_SCOPE definition should 'hide' GLOBAL_SCOPE definition
+        sb.put("x", "newX");
+        assertTrue(e.eval("x", ctx).equals("newX"));
+    }
+}
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Thu Aug 22 22:32:16 2013 +0530
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Fri Aug 23 16:10:37 2013 +0530
@@ -26,7 +26,6 @@
 package jdk.nashorn.api.scripting;
 
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
@@ -34,22 +33,13 @@
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
 import java.util.concurrent.Callable;
-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.ScriptEngineManager;
 import javax.script.ScriptException;
-import javax.script.SimpleBindings;
-import javax.script.SimpleScriptContext;
-import org.testng.Assert;
 import org.testng.annotations.Test;
 
 /**
@@ -240,214 +230,6 @@
     }
 
     @Test
-    public void createBindingsTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        Bindings b = e.createBindings();
-        b.put("foo", 42.0);
-        Object res = null;
-        try {
-            res = e.eval("foo == 42.0", b);
-        } catch (final ScriptException | NullPointerException se) {
-            se.printStackTrace();
-            fail(se.getMessage());
-        }
-
-        assertEquals(res, Boolean.TRUE);
-    }
-
-    @Test
-    public void getInterfaceTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        final Invocable inv = (Invocable)e;
-
-        // try to get interface from global functions
-        try {
-            e.eval("function run() { print('run'); };");
-            final Runnable runnable = inv.getInterface(Runnable.class);
-            runnable.run();
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-
-        // try interface on specific script object
-        try {
-            e.eval("var obj = { run: function() { print('run from obj'); } };");
-            Object obj = e.get("obj");
-            final Runnable runnable = inv.getInterface(obj, Runnable.class);
-            runnable.run();
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-    }
-
-    public interface Foo {
-        public void bar();
-    }
-
-    public interface Foo2 extends Foo {
-        public void bar2();
-    }
-
-    @Test
-    public void getInterfaceMissingTest() {
-        final ScriptEngineManager manager = new ScriptEngineManager();
-        final ScriptEngine engine = manager.getEngineByName("nashorn");
-
-        // don't define any function.
-        try {
-            engine.eval("");
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-
-        Runnable runnable = ((Invocable)engine).getInterface(Runnable.class);
-        if (runnable != null) {
-            fail("runnable is not null!");
-        }
-
-        // now define "run"
-        try {
-            engine.eval("function run() { print('this is run function'); }");
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-        runnable = ((Invocable)engine).getInterface(Runnable.class);
-        // should not return null now!
-        runnable.run();
-
-        // define only one method of "Foo2"
-        try {
-            engine.eval("function bar() { print('bar function'); }");
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-
-        Foo2 foo2 = ((Invocable)engine).getInterface(Foo2.class);
-        if (foo2 != null) {
-            throw new RuntimeException("foo2 is not null!");
-        }
-
-        // now define other method of "Foo2"
-        try {
-            engine.eval("function bar2() { print('bar2 function'); }");
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-        foo2 = ((Invocable)engine).getInterface(Foo2.class);
-        foo2.bar();
-        foo2.bar2();
-    }
-
-    @Test
-    /**
-     * Try passing non-interface Class object for interface implementation.
-     */
-    public void getNonInterfaceGetInterfaceTest() {
-        final ScriptEngineManager manager = new ScriptEngineManager();
-        final ScriptEngine engine = manager.getEngineByName("nashorn");
-        try {
-            log(Objects.toString(((Invocable)engine).getInterface(Object.class)));
-            fail("Should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                fail("IllegalArgumentException expected, got " + exp);
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that we can get interface out of a script object even after
-     * switching to use different ScriptContext.
-     */
-    public void getInterfaceDifferentContext() {
-       ScriptEngineManager m = new ScriptEngineManager();
-       ScriptEngine e = m.getEngineByName("nashorn");
-       try {
-           Object obj = e.eval("({ run: function() { } })");
-
-           // change script context
-           ScriptContext ctxt = new SimpleScriptContext();
-           ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
-           e.setContext(ctxt);
-
-           Runnable r = ((Invocable)e).getInterface(obj, Runnable.class);
-           r.run();
-       }catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-       }
-    }
-
-    @Test
-    /**
-     * Check that getInterface on non-script object 'thiz' results in IllegalArgumentException.
-     */
-    public void getInterfaceNonScriptObjectThizTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            ((Invocable)e).getInterface(new Object(), Runnable.class);
-            fail("should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that getInterface on null 'thiz' results in IllegalArgumentException.
-     */
-    public void getInterfaceNullThizTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            ((Invocable)e).getInterface(null, Runnable.class);
-            fail("should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that calling getInterface on mirror created by another engine results in IllegalArgumentException.
-     */
-    public void getInterfaceMixEnginesTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine engine1 = m.getEngineByName("nashorn");
-        final ScriptEngine engine2 = m.getEngineByName("nashorn");
-
-        try {
-            Object obj = engine1.eval("({ run: function() {} })");
-            // pass object from engine1 to engine2 as 'thiz' for getInterface
-            ((Invocable)engine2).getInterface(obj, Runnable.class);
-            fail("should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
     public void accessGlobalTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
@@ -622,88 +404,6 @@
         assertEquals(sw.toString().replaceAll("\r", ""), "hello world\n");
     }
 
-    @SuppressWarnings("unchecked")
-    @Test
-    public void reflectionTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        e.eval("var obj = { x: 344, y: 'nashorn' }");
-
-        int count = 0;
-        Map<Object, Object> map = (Map<Object, Object>)e.get("obj");
-        assertFalse(map.isEmpty());
-        assertTrue(map.keySet().contains("x"));
-        assertTrue(map.containsKey("x"));
-        assertTrue(map.values().contains("nashorn"));
-        assertTrue(map.containsValue("nashorn"));
-        for (final Map.Entry<?, ?> ex : map.entrySet()) {
-            final Object key = ex.getKey();
-            if (key.equals("x")) {
-                assertTrue(344 == ((Number)ex.getValue()).doubleValue());
-                count++;
-            } else if (key.equals("y")) {
-                assertEquals(ex.getValue(), "nashorn");
-                count++;
-            }
-        }
-        assertEquals(2, count);
-        assertEquals(2, map.size());
-
-        // add property
-        map.put("z", "hello");
-        assertEquals(e.eval("obj.z"), "hello");
-        assertEquals(map.get("z"), "hello");
-        assertTrue(map.keySet().contains("z"));
-        assertTrue(map.containsKey("z"));
-        assertTrue(map.values().contains("hello"));
-        assertTrue(map.containsValue("hello"));
-        assertEquals(map.size(), 3);
-
-        final Map<Object, Object> newMap = new HashMap<>();
-        newMap.put("foo", 23.0);
-        newMap.put("bar", true);
-        map.putAll(newMap);
-
-        assertEquals(e.eval("obj.foo"), 23.0);
-        assertEquals(e.eval("obj.bar"), true);
-
-        // remove using map method
-        map.remove("foo");
-        assertEquals(e.eval("typeof obj.foo"), "undefined");
-
-        count = 0;
-        e.eval("var arr = [ true, 'hello' ]");
-        map = (Map<Object, Object>)e.get("arr");
-        assertFalse(map.isEmpty());
-        assertTrue(map.containsKey("length"));
-        assertTrue(map.containsValue("hello"));
-        for (final Map.Entry<?, ?> ex : map.entrySet()) {
-            final Object key = ex.getKey();
-            if (key.equals("0")) {
-                assertEquals(ex.getValue(), Boolean.TRUE);
-                count++;
-            } else if (key.equals("1")) {
-                assertEquals(ex.getValue(), "hello");
-                count++;
-            }
-        }
-        assertEquals(count, 2);
-        assertEquals(map.size(), 2);
-
-        // add element
-        map.put("2", "world");
-        assertEquals(map.get("2"), "world");
-        assertEquals(map.size(), 3);
-
-        // remove all
-        map.clear();
-        assertTrue(map.isEmpty());
-        assertEquals(e.eval("typeof arr[0]"), "undefined");
-        assertEquals(e.eval("typeof arr[1]"), "undefined");
-        assertEquals(e.eval("typeof arr[2]"), "undefined");
-    }
-
     @Test
     public void redefineEchoTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
@@ -716,150 +416,6 @@
             fail(exp.getMessage());
         }
     }
-
-    @Test
-    public void invokeMethodTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            e.eval("var Example = function() { this.hello = function() { return 'Hello World!'; };}; myExample = new Example();");
-            final Object obj = e.get("myExample");
-            final Object res = ((Invocable)e).invokeMethod(obj, "hello");
-            assertEquals(res, "Hello World!");
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-    }
-
-    @Test
-    /**
-     * Check that we can call invokeMethod on an object that we got by evaluating
-     * script with different Context set.
-     */
-    public void invokeMethodDifferentContextTest() {
-       ScriptEngineManager m = new ScriptEngineManager();
-       ScriptEngine e = m.getEngineByName("nashorn");
-
-       try {
-           // define an object with method on it
-           Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
-
-           final ScriptContext ctxt = new SimpleScriptContext();
-           ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
-           e.setContext(ctxt);
-
-           // invoke 'func' on obj - but with current script context changed
-           final Object res = ((Invocable)e).invokeMethod(obj, "hello");
-           assertEquals(res, "Hello World!");
-       } catch (final Exception exp) {
-           exp.printStackTrace();
-           fail(exp.getMessage());
-       }
-    }
-
-    @Test
-    /**
-     * Check that invokeMethod throws NPE on null method name.
-     */
-    public void invokeMethodNullNameTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            final Object obj = e.eval("({})");
-            final Object res = ((Invocable)e).invokeMethod(obj, null);
-            fail("should have thrown NPE");
-        } catch (final Exception exp) {
-            if (! (exp instanceof NullPointerException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that invokeMethod throws NoSuchMethodException on missing method.
-     */
-    public void invokeMethodMissingTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            final Object obj = e.eval("({})");
-            final Object res = ((Invocable)e).invokeMethod(obj, "nonExistentMethod");
-            fail("should have thrown NoSuchMethodException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof NoSuchMethodException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that calling method on non-script object 'thiz' results in IllegalArgumentException.
-     */
-    public void invokeMethodNonScriptObjectThizTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            ((Invocable)e).invokeMethod(new Object(), "toString");
-            fail("should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that calling method on null 'thiz' results in IllegalArgumentException.
-     */
-    public void invokeMethodNullThizTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            ((Invocable)e).invokeMethod(null, "toString");
-            fail("should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-
-    @Test
-    /**
-     * Check that calling method on mirror created by another engine results in IllegalArgumentException.
-     */
-    public void invokeMethodMixEnginesTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine engine1 = m.getEngineByName("nashorn");
-        final ScriptEngine engine2 = m.getEngineByName("nashorn");
-
-        try {
-            Object obj = engine1.eval("({ run: function() {} })");
-            // pass object from engine1 to engine2 as 'thiz' for invokeMethod
-            ((Invocable)engine2).invokeMethod(obj, "run");
-            fail("should have thrown IllegalArgumentException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof IllegalArgumentException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
     @Test
     public void noEnumerablePropertiesTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
@@ -921,308 +477,6 @@
     }
 
     @Test
-    public void jsobjectTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        try {
-            e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
-            JSObject obj = (JSObject) e.get("obj");
-
-            // try basic get on existing properties
-            if (! obj.getMember("bar").equals("hello")) {
-                fail("obj.bar != 'hello'");
-            }
-
-            if (! obj.getSlot(1).equals("world")) {
-                fail("obj[1] != 'world'");
-            }
-
-            if (! obj.call("func", new Object[0]).equals("hello")) {
-                fail("obj.call('func') != 'hello'");
-            }
-
-            // try setting properties
-            obj.setMember("bar", "new-bar");
-            obj.setSlot(1, "new-element-1");
-            if (! obj.getMember("bar").equals("new-bar")) {
-                fail("obj.bar != 'new-bar'");
-            }
-
-            if (! obj.getSlot(1).equals("new-element-1")) {
-                fail("obj[1] != 'new-element-1'");
-            }
-
-            // try adding properties
-            obj.setMember("prop", "prop-value");
-            obj.setSlot(12, "element-12");
-            if (! obj.getMember("prop").equals("prop-value")) {
-                fail("obj.prop != 'prop-value'");
-            }
-
-            if (! obj.getSlot(12).equals("element-12")) {
-                fail("obj[12] != 'element-12'");
-            }
-
-            // delete properties
-            obj.removeMember("prop");
-            if ("prop-value".equals(obj.getMember("prop"))) {
-                fail("obj.prop is not deleted!");
-            }
-
-            // Simple eval tests
-            assertEquals(obj.eval("typeof Object"), "function");
-            assertEquals(obj.eval("'nashorn'.substring(3)"), "horn");
-        } catch (final Exception exp) {
-            exp.printStackTrace();
-            fail(exp.getMessage());
-        }
-    }
-
-    @Test
-    /**
-     * check that null function name results in NPE.
-     */
-    public void invokeFunctionNullNameTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            final Object res = ((Invocable)e).invokeFunction(null);
-            fail("should have thrown NPE");
-        } catch (final Exception exp) {
-            if (! (exp instanceof NullPointerException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that attempt to call missing function results in NoSuchMethodException.
-     */
-    public void invokeFunctionMissingTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            final Object res = ((Invocable)e).invokeFunction("NonExistentFunc");
-            fail("should have thrown NoSuchMethodException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof NoSuchMethodException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    /**
-     * Check that invokeFunction calls functions only from current context's Bindings.
-     */
-    public void invokeFunctionDifferentContextTest() {
-        ScriptEngineManager m = new ScriptEngineManager();
-        ScriptEngine e = m.getEngineByName("nashorn");
-
-        try {
-            // define an object with method on it
-            Object obj = e.eval("function hello() { return 'Hello World!'; }");
-            final ScriptContext ctxt = new SimpleScriptContext();
-            ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
-            // change engine's current context
-            e.setContext(ctxt);
-
-            ((Invocable)e).invokeFunction("hello"); // no 'hello' in new context!
-            fail("should have thrown NoSuchMethodException");
-        } catch (final Exception exp) {
-            if (! (exp instanceof NoSuchMethodException)) {
-                exp.printStackTrace();
-                fail(exp.getMessage());
-            }
-        }
-    }
-
-    @Test
-    public void invokeFunctionExceptionTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        try {
-            e.eval("function func() { throw new TypeError(); }");
-        } catch (final Throwable t) {
-            t.printStackTrace();
-            fail(t.getMessage());
-        }
-
-        try {
-            ((Invocable)e).invokeFunction("func");
-            fail("should have thrown exception");
-        } catch (final ScriptException se) {
-            // ECMA TypeError property wrapped as a ScriptException
-            log("got " + se + " as expected");
-        } catch (final Throwable t) {
-            t.printStackTrace();
-            fail(t.getMessage());
-        }
-    }
-
-    @Test
-    public void invokeMethodExceptionTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        try {
-            e.eval("var sobj = {}; sobj.foo = function func() { throw new TypeError(); }");
-        } catch (final Throwable t) {
-            t.printStackTrace();
-            fail(t.getMessage());
-        }
-
-        try {
-            final Object sobj = e.get("sobj");
-            ((Invocable)e).invokeMethod(sobj, "foo");
-            fail("should have thrown exception");
-        } catch (final ScriptException se) {
-            // ECMA TypeError property wrapped as a ScriptException
-            log("got " + se + " as expected");
-        } catch (final Throwable t) {
-            t.printStackTrace();
-            fail(t.getMessage());
-        }
-    }
-
-    @Test
-    public void scriptObjectMirrorToStringTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        try {
-            Object obj = e.eval("new TypeError('wrong type')");
-            assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
-        } catch (final Throwable t) {
-            t.printStackTrace();
-            fail(t.getMessage());
-        }
-
-        try {
-            Object obj = e.eval("function func() { print('hello'); }");
-            assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
-        } catch (final Throwable t) {
-            t.printStackTrace();
-            fail(t.getMessage());
-        }
-    }
-
-    @Test
-    public void engineScopeTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
-
-        // check few ECMA standard built-in global properties
-        assertNotNull(engineScope.get("Object"));
-        assertNotNull(engineScope.get("TypeError"));
-        assertNotNull(engineScope.get("eval"));
-
-        // can access via ScriptEngine.get as well
-        assertNotNull(e.get("Object"));
-        assertNotNull(e.get("TypeError"));
-        assertNotNull(e.get("eval"));
-
-        // Access by either way should return same object
-        assertEquals(engineScope.get("Array"), e.get("Array"));
-        assertEquals(engineScope.get("EvalError"), e.get("EvalError"));
-        assertEquals(engineScope.get("undefined"), e.get("undefined"));
-
-        // try exposing a new variable from scope
-        engineScope.put("myVar", "foo");
-        try {
-            assertEquals(e.eval("myVar"), "foo");
-        } catch (final ScriptException se) {
-            se.printStackTrace();
-            fail(se.getMessage());
-        }
-
-        // update "myVar" in script an check the value from scope
-        try {
-            e.eval("myVar = 'nashorn';");
-        } catch (final ScriptException se) {
-            se.printStackTrace();
-            fail(se.getMessage());
-        }
-
-        // now check modified value from scope and engine
-        assertEquals(engineScope.get("myVar"), "nashorn");
-        assertEquals(e.get("myVar"), "nashorn");
-    }
-
-    @Test
-    public void multiGlobalTest() {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        final Bindings b = e.createBindings();
-        final ScriptContext newCtxt = new SimpleScriptContext();
-        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
-
-        try {
-            Object obj1 = e.eval("Object");
-            Object obj2 = e.eval("Object", newCtxt);
-            Assert.assertNotEquals(obj1, obj2);
-            Assert.assertNotNull(obj1);
-            Assert.assertNotNull(obj2);
-            Assert.assertEquals(obj1.toString(), obj2.toString());
-
-            e.eval("x = 'hello'");
-            e.eval("x = 'world'", newCtxt);
-            Object x1 = e.getContext().getAttribute("x");
-            Object x2 = newCtxt.getAttribute("x");
-            Assert.assertNotEquals(x1, x2);
-            Assert.assertEquals(x1, "hello");
-            Assert.assertEquals(x2, "world");
-
-            x1 = e.eval("x");
-            x2 = e.eval("x", newCtxt);
-            Assert.assertNotEquals(x1, x2);
-            Assert.assertEquals(x1, "hello");
-            Assert.assertEquals(x2, "world");
-
-            final ScriptContext origCtxt = e.getContext();
-            e.setContext(newCtxt);
-            e.eval("y = new Object()");
-            e.eval("y = new Object()", origCtxt);
-
-            Object y1 = origCtxt.getAttribute("y");
-            Object y2 = newCtxt.getAttribute("y");
-            Assert.assertNotEquals(y1, y2);
-            Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
-            Assert.assertEquals("[object Object]", y1.toString());
-            Assert.assertEquals("[object Object]", y2.toString());
-        } catch (final ScriptException se) {
-            se.printStackTrace();
-            fail(se.getMessage());
-        }
-    }
-
-    @Test
-    /**
-     * Tests whether invocation of a JavaScript method through a variable arity Java method will pass the vararg array.
-     * Both non-vararg and vararg JavaScript methods are tested.
-     * @throws ScriptException
-     */
-    public void variableArityInterfaceTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        e.eval(
-            "function test1(i, strings) {" +
-            "    return 'i == ' + i + ', strings instanceof java.lang.String[] == ' + (strings instanceof Java.type('java.lang.String[]')) + ', strings == ' + java.util.Arrays.toString(strings)" +
-            "}" +
-            "function test2() {" +
-            "    return 'arguments[0] == ' + arguments[0] + ', arguments[1] instanceof java.lang.String[] == ' + (arguments[1] instanceof Java.type('java.lang.String[]')) + ', arguments[1] == ' + java.util.Arrays.toString(arguments[1])" +
-            "}"
-        );
-        final VariableArityTestInterface itf = ((Invocable)e).getInterface(VariableArityTestInterface.class);
-        Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
-        Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
-    }
-
-    @Test
     // check that print function prints arg followed by newline char
     public void printTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
@@ -1257,76 +511,4 @@
         // dos2unix - fix line endings if running on windows
         assertEquals(sw.toString().replaceAll("\r", ""), "34 true hello\n");
     }
-
-    @Test
-    public void mirrorNewObjectGlobalFunctionTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        final ScriptEngine e2 = m.getEngineByName("nashorn");
-
-        e.eval("function func() {}");
-        e2.put("foo", e.get("func"));
-        final Object e2global = e2.eval("this");
-        final Object newObj = ((ScriptObjectMirror)e2global).newObject("foo");
-        assertTrue(newObj instanceof ScriptObjectMirror);
-    }
-
-    @Test
-    public void mirrorNewObjectInstanceFunctionTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        final ScriptEngine e2 = m.getEngineByName("nashorn");
-
-        e.eval("function func() {}");
-        e2.put("func", e.get("func"));
-        final Object e2obj = e2.eval("({ foo: func })");
-        final Object newObj = ((ScriptObjectMirror)e2obj).newObject("foo");
-        assertTrue(newObj instanceof ScriptObjectMirror);
-    }
-
-    @Test
-    public void userEngineScopeBindingsTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        e.eval("function func() {}");
-
-        final ScriptContext newContext = new SimpleScriptContext();
-        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
-        // we are using a new bindings - so it should have 'func' defined
-        Object value = e.eval("typeof func", newContext);
-        assertTrue(value.equals("undefined"));
-    }
-
-    @Test
-    public void userEngineScopeBindingsNoLeakTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        final ScriptContext newContext = new SimpleScriptContext();
-        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
-        e.eval("function foo() {}", newContext);
-
-        // in the default context's ENGINE_SCOPE, 'foo' shouldn't exist
-        assertTrue(e.eval("typeof foo").equals("undefined"));
-    }
-
-    @Test
-    public void userEngineScopeBindingsRetentionTest() throws ScriptException {
-        final ScriptEngineManager m = new ScriptEngineManager();
-        final ScriptEngine e = m.getEngineByName("nashorn");
-        final ScriptContext newContext = new SimpleScriptContext();
-        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
-        e.eval("function foo() {}", newContext);
-
-        // definition retained with user's ENGINE_SCOPE Binding
-        assertTrue(e.eval("typeof foo", newContext).equals("function"));
-
-        final Bindings oldBindings = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
-        // but not in another ENGINE_SCOPE binding
-        newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
-        assertTrue(e.eval("typeof foo", newContext).equals("undefined"));
-
-        // restore ENGINE_SCOPE and check again
-        newContext.setBindings(oldBindings, ScriptContext.ENGINE_SCOPE);
-        assertTrue(e.eval("typeof foo", newContext).equals("function"));
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java	Fri Aug 23 16:10:37 2013 +0530
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.scripting;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import org.testng.annotations.Test;
+
+/**
+ * Tests to check jdk.nashorn.api.scripting.ScriptObjectMirror API.
+ */
+public class ScriptObjectMirrorTest {
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void reflectionTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        e.eval("var obj = { x: 344, y: 'nashorn' }");
+
+        int count = 0;
+        Map<Object, Object> map = (Map<Object, Object>) e.get("obj");
+        assertFalse(map.isEmpty());
+        assertTrue(map.keySet().contains("x"));
+        assertTrue(map.containsKey("x"));
+        assertTrue(map.values().contains("nashorn"));
+        assertTrue(map.containsValue("nashorn"));
+        for (final Map.Entry<?, ?> ex : map.entrySet()) {
+            final Object key = ex.getKey();
+            if (key.equals("x")) {
+                assertTrue(344 == ((Number) ex.getValue()).doubleValue());
+                count++;
+            } else if (key.equals("y")) {
+                assertEquals(ex.getValue(), "nashorn");
+                count++;
+            }
+        }
+        assertEquals(2, count);
+        assertEquals(2, map.size());
+
+        // add property
+        map.put("z", "hello");
+        assertEquals(e.eval("obj.z"), "hello");
+        assertEquals(map.get("z"), "hello");
+        assertTrue(map.keySet().contains("z"));
+        assertTrue(map.containsKey("z"));
+        assertTrue(map.values().contains("hello"));
+        assertTrue(map.containsValue("hello"));
+        assertEquals(map.size(), 3);
+
+        final Map<Object, Object> newMap = new HashMap<>();
+        newMap.put("foo", 23.0);
+        newMap.put("bar", true);
+        map.putAll(newMap);
+
+        assertEquals(e.eval("obj.foo"), 23.0);
+        assertEquals(e.eval("obj.bar"), true);
+
+        // remove using map method
+        map.remove("foo");
+        assertEquals(e.eval("typeof obj.foo"), "undefined");
+
+        count = 0;
+        e.eval("var arr = [ true, 'hello' ]");
+        map = (Map<Object, Object>) e.get("arr");
+        assertFalse(map.isEmpty());
+        assertTrue(map.containsKey("length"));
+        assertTrue(map.containsValue("hello"));
+        for (final Map.Entry<?, ?> ex : map.entrySet()) {
+            final Object key = ex.getKey();
+            if (key.equals("0")) {
+                assertEquals(ex.getValue(), Boolean.TRUE);
+                count++;
+            } else if (key.equals("1")) {
+                assertEquals(ex.getValue(), "hello");
+                count++;
+            }
+        }
+        assertEquals(count, 2);
+        assertEquals(map.size(), 2);
+
+        // add element
+        map.put("2", "world");
+        assertEquals(map.get("2"), "world");
+        assertEquals(map.size(), 3);
+
+        // remove all
+        map.clear();
+        assertTrue(map.isEmpty());
+        assertEquals(e.eval("typeof arr[0]"), "undefined");
+        assertEquals(e.eval("typeof arr[1]"), "undefined");
+        assertEquals(e.eval("typeof arr[2]"), "undefined");
+    }
+
+    @Test
+    public void jsobjectTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        try {
+            e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
+            JSObject obj = (JSObject) e.get("obj");
+
+            // try basic get on existing properties
+            if (!obj.getMember("bar").equals("hello")) {
+                fail("obj.bar != 'hello'");
+            }
+
+            if (!obj.getSlot(1).equals("world")) {
+                fail("obj[1] != 'world'");
+            }
+
+            if (!obj.call("func", new Object[0]).equals("hello")) {
+                fail("obj.call('func') != 'hello'");
+            }
+
+            // try setting properties
+            obj.setMember("bar", "new-bar");
+            obj.setSlot(1, "new-element-1");
+            if (!obj.getMember("bar").equals("new-bar")) {
+                fail("obj.bar != 'new-bar'");
+            }
+
+            if (!obj.getSlot(1).equals("new-element-1")) {
+                fail("obj[1] != 'new-element-1'");
+            }
+
+            // try adding properties
+            obj.setMember("prop", "prop-value");
+            obj.setSlot(12, "element-12");
+            if (!obj.getMember("prop").equals("prop-value")) {
+                fail("obj.prop != 'prop-value'");
+            }
+
+            if (!obj.getSlot(12).equals("element-12")) {
+                fail("obj[12] != 'element-12'");
+            }
+
+            // delete properties
+            obj.removeMember("prop");
+            if ("prop-value".equals(obj.getMember("prop"))) {
+                fail("obj.prop is not deleted!");
+            }
+
+            // Simple eval tests
+            assertEquals(obj.eval("typeof Object"), "function");
+            assertEquals(obj.eval("'nashorn'.substring(3)"), "horn");
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+    }
+
+    @Test
+    public void scriptObjectMirrorToStringTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        try {
+            Object obj = e.eval("new TypeError('wrong type')");
+            assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
+        } catch (final Throwable t) {
+            t.printStackTrace();
+            fail(t.getMessage());
+        }
+
+        try {
+            Object obj = e.eval("function func() { print('hello'); }");
+            assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
+        } catch (final Throwable t) {
+            t.printStackTrace();
+            fail(t.getMessage());
+        }
+    }
+
+    @Test
+    public void mirrorNewObjectGlobalFunctionTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptEngine e2 = m.getEngineByName("nashorn");
+
+        e.eval("function func() {}");
+        e2.put("foo", e.get("func"));
+        final Object e2global = e2.eval("this");
+        final Object newObj = ((ScriptObjectMirror) e2global).newObject("foo");
+        assertTrue(newObj instanceof ScriptObjectMirror);
+    }
+
+    @Test
+    public void mirrorNewObjectInstanceFunctionTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptEngine e2 = m.getEngineByName("nashorn");
+
+        e.eval("function func() {}");
+        e2.put("func", e.get("func"));
+        final Object e2obj = e2.eval("({ foo: func })");
+        final Object newObj = ((ScriptObjectMirror) e2obj).newObject("foo");
+        assertTrue(newObj instanceof ScriptObjectMirror);
+    }
+}