Merge
authorsundar
Fri, 23 Aug 2013 16:44:02 +0530
changeset 19628 6d484513c9fc
parent 19474 70c91fc38cb4 (current diff)
parent 19627 90d910ec15a3 (diff)
child 19629 2b74fcdca60e
Merge
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Fri Aug 23 16:44:02 2013 +0530
@@ -55,6 +55,7 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptException;
+import javax.script.SimpleBindings;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.GlobalObject;
@@ -74,6 +75,12 @@
  */
 
 public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
+    /**
+     * Key used to associate Nashorn global object mirror with arbitrary Bindings instance.
+     */
+    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));
@@ -83,16 +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;
@@ -100,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);
@@ -108,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);
     }
@@ -134,20 +173,13 @@
             }
         }, CREATE_CONTEXT_ACC_CTXT);
 
-        // create new global object
-        this.global = createNashornGlobal();
-        // set the default engine scope for the default context
-        context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
+        // cache this option that is used often
+        this._global_per_engine = nashornContext.getEnv()._global_per_engine;
 
-        // evaluate engine initial script
-        try {
-            evalEngineScript();
-        } catch (final ScriptException e) {
-            if (Context.DEBUG) {
-                e.printStackTrace();
-            }
-            throw new RuntimeException(e);
-        }
+        // create new global object
+        this.global = createNashornGlobal(context);
+        // set the default ENGINE_SCOPE object for the default context
+        context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
     }
 
     @Override
@@ -176,8 +208,13 @@
 
     @Override
     public Bindings createBindings() {
-        final ScriptObject newGlobal = createNashornGlobal();
-        return new ScriptObjectMirror(newGlobal, newGlobal);
+        if (_global_per_engine) {
+            // just create normal SimpleBindings.
+            // We use same 'global' for all Bindings.
+            return new SimpleBindings();
+        } else {
+            return createGlobalMirror(null);
+        }
     }
 
     // Compilable methods
@@ -213,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"));
@@ -280,58 +359,56 @@
         }
     }
 
-    @Override
-    public <T> T getInterface(final Class<T> clazz) {
-        return getInterfaceInner(null, clazz);
-    }
+    // Retrieve nashorn Global object for a given ScriptContext object
+    private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
+        if (_global_per_engine) {
+            // shared single global object for all ENGINE_SCOPE Bindings
+            return global;
+        }
 
-    @Override
-    public <T> T getInterface(final Object thiz, final Class<T> clazz) {
-        if (thiz == null) {
-            throw new IllegalArgumentException(getMessage("thiz.cannot.be.null"));
+        final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
+        // is this Nashorn's own Bindings implementation?
+        if (bindings instanceof ScriptObjectMirror) {
+            final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)bindings);
+            if (sobj != null) {
+                return sobj;
+            }
         }
-        return getInterfaceInner(thiz, clazz);
+
+        // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
+        Object scope = bindings.get(NASHORN_GLOBAL);
+        if (scope instanceof ScriptObjectMirror) {
+            final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)scope);
+            if (sobj != null) {
+                return sobj;
+            }
+        }
+
+        // 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 = createGlobalMirror(ctxt);
+        bindings.put(NASHORN_GLOBAL, mirror);
+        return mirror.getScriptObject();
     }
 
-    // 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);
+    // 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)) {
+            return sobj;
         }
 
-        if (self == UNDEFINED) {
-            // scope access and so throw ReferenceError
-            throw referenceError(ctxtGlobal, "not.defined", name);
-        }
-
-        return UNDEFINED;
+        return null;
     }
 
-    private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
-        final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
-        if (bindings instanceof ScriptObjectMirror) {
-             ScriptObject sobj = ((ScriptObjectMirror)bindings).getScriptObject();
-             if (sobj instanceof GlobalObject) {
-                 return sobj;
-             }
-        }
-
-        // didn't find global object from context given - return the engine-wide global
-        return global;
+    // 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);
     }
 
-    private ScriptObject createNashornGlobal() {
+    // Create a new Nashorn Global object
+    private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
         final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
             @Override
             public ScriptObject run() {
@@ -352,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
@@ -362,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);
@@ -402,8 +458,10 @@
             args = ScriptRuntime.EMPTY_ARRAY;
         }
         // if no arguments passed, expose it
-        args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
-        ctxtGlobal.set("arguments", args, false);
+        if (! (args instanceof ScriptObject)) {
+            args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
+            ctxtGlobal.set("arguments", args, false);
+        }
     }
 
     private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
@@ -456,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);
@@ -517,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/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Fri Aug 23 16:44:02 2013 +0530
@@ -99,12 +99,14 @@
             }
 
             final Object val = functionName == null? sobj : sobj.get(functionName);
-            if (! (val instanceof ScriptFunction)) {
-                throw new NoSuchMethodException("No such function " + ((functionName != null)? functionName : ""));
+            if (val instanceof ScriptFunction) {
+                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
+                return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
+            } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) {
+                return ((ScriptObjectMirror)val).call(null, args);
             }
 
-            final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-            return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
+            throw new NoSuchMethodException("No such function " + ((functionName != null)? functionName : ""));
         } catch (final RuntimeException | Error e) {
             throw e;
         } catch (final Throwable t) {
@@ -127,12 +129,14 @@
             }
 
             final Object val = functionName == null? sobj : sobj.get(functionName);
-            if (! (val instanceof ScriptFunction)) {
-                throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : ""));
+            if (val instanceof ScriptFunction) {
+                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
+                return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global);
+            } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) {
+                return ((ScriptObjectMirror)val).newObject(null, args);
             }
 
-            final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-            return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global);
+            throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : ""));
         } catch (final RuntimeException | Error e) {
             throw e;
         } catch (final Throwable t) {
@@ -374,6 +378,19 @@
     }
 
     /**
+     * Set the __proto__ of this object.
+     * @param proto new proto for this object
+     */
+    public void setProto(final Object proto) {
+        inGlobal(new Callable<Void>() {
+            @Override public Void call() {
+                sobj.setProtoCheck(unwrap(proto, global));
+                return null;
+            }
+        });
+    }
+
+    /**
      * ECMA 8.12.1 [[GetOwnProperty]] (P)
      *
      * @param key property key
--- a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js	Fri Aug 23 16:44:02 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);
     }
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Fri Aug 23 16:44:02 2013 +0530
@@ -543,8 +543,6 @@
     public Node leaveIdentNode(final IdentNode identNode) {
         final String name = identNode.getName();
 
-        start(identNode);
-
         if (identNode.isPropertyName()) {
             // assign a pseudo symbol to property name
             final Symbol pseudoSymbol = pseudoSymbol(name);
@@ -1850,9 +1848,10 @@
                 append("] ").
                 append(printNode ? node.toString() : "").
                 append(" in '").
-                append(lc.getCurrentFunction().getName());
+                append(lc.getCurrentFunction().getName()).
+                append('\'');
 
-            if(node instanceof Expression) {
+            if (node instanceof Expression) {
                 final Symbol symbol = ((Expression)node).getSymbol();
                 if (symbol == null) {
                     sb.append(" <NO SYMBOL>");
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Fri Aug 23 16:44:02 2013 +0530
@@ -32,7 +32,6 @@
 import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
-
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.internal.objects.annotations.Attribute;
@@ -44,6 +43,7 @@
 import jdk.nashorn.internal.runtime.ListAdapter;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
 
 /**
@@ -539,4 +539,25 @@
         }
         return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides);
     }
+
+    /**
+     * When given an object created using {@code Java.extend()} or equivalent mechanism (that is, any JavaScript-to-Java
+     * adapter), returns an object that can be used to invoke superclass methods on that object. E.g.:
+     * <pre>
+     * var cw = new FilterWriterAdapter(sw) {
+     *     write: function(s, off, len) {
+     *         s = capitalize(s, off, len)
+     *         cw_super.write(s, 0, s.length())
+     *     }
+     * }
+     * var cw_super = Java.super(cw)
+     * </pre>
+     * @param self the {@code Java} object itself - not used.
+     * @param adapter the original Java adapter instance for which the super adapter is created.
+     * @return a super adapter for the original adapter
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR, name="super")
+    public static Object _super(final Object self, final Object adapter) {
+        return Bootstrap.createSuperAdapter(adapter);
+    }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Fri Aug 23 16:44:02 2013 +0530
@@ -125,6 +125,28 @@
     }
 
     /**
+     * Nashorn extension: Object.setPrototypeOf ( O, proto )
+     * Also found in ES6 draft specification.
+     *
+     * @param  self self reference
+     * @param  obj object to set prototype for
+     * @param  proto prototype object to be used
+     * @return object whose prototype is set
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) {
+        if (obj instanceof ScriptObject) {
+            ((ScriptObject)obj).setProtoCheck(proto);
+            return obj;
+        } else if (obj instanceof ScriptObjectMirror) {
+            ((ScriptObjectMirror)obj).setProto(proto);
+            return obj;
+        }
+
+        throw notAnObject(obj);
+    }
+
+    /**
      * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
      *
      * @param self  self reference
@@ -184,7 +206,7 @@
         // FIXME: should we create a proper object with correct number of
         // properties?
         final ScriptObject newObj = Global.newEmptyInstance();
-        newObj.setProtoCheck(proto);
+        newObj.setProto((ScriptObject)proto);
         if (props != UNDEFINED) {
             NativeObject.defineProperties(self, newObj, props);
         }
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Fri Aug 23 16:44:02 2013 +0530
@@ -91,6 +91,11 @@
      */
     public static final String NASHORN_JAVA_REFLECTION = "nashorn.JavaReflection";
 
+    /* Force DebuggerSupport to be loaded. */
+    static {
+        DebuggerSupport.FORCELOAD = true;
+    }
+
     /**
      * ContextCodeInstaller that has the privilege of installing classes in the Context.
      * Can only be instantiated from inside the context and is opaque to other classes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,310 @@
+/*
+ * 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  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  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  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.internal.runtime;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class provides support for external debuggers.  Its primary purpose is
+ * is to simplify the debugger tasks and provide better performance.
+ */
+final class DebuggerSupport {
+    /**
+     * Hook to force the loading of the DebuggerSupport class so that it is
+     * available to external debuggers.
+     */
+    static boolean FORCELOAD = true;
+
+    static {
+        /**
+         * Hook to force the loading of the DebuggerValueDesc class so that it is
+         * available to external debuggers.
+         */
+        DebuggerValueDesc forceLoad = new DebuggerValueDesc(null, false, null, null);
+    }
+
+    /** This class is used to send a bulk description of a value. */
+    static class DebuggerValueDesc {
+        /** Property key (or index) or field name. */
+        final String key;
+
+        /** If the value is expandable. */
+        final boolean expandable;
+
+        /** Property or field value as object. */
+        final Object valueAsObject;
+
+        /** Property or field value as string. */
+        final String valueAsString;
+
+        DebuggerValueDesc(final String key, final boolean expandable, final Object valueAsObject, final String valueAsString) {
+            this.key           = key;
+            this.expandable    = expandable;
+            this.valueAsObject = valueAsObject;
+            this.valueAsString = valueAsString;
+        }
+    }
+
+    /**
+     * Return the current context global.
+     * @return context global.
+     */
+    static Object getGlobal() {
+        return Context.getGlobalTrusted();
+    }
+
+    /**
+     * This method returns a bulk description of an object's properties.
+     * @param object Script object to be displayed by the debugger.
+     * @param all    true if to include non-enumerable values.
+     * @return An array of DebuggerValueDesc.
+     */
+    static DebuggerValueDesc[] valueInfos(final Object object, final boolean all) {
+        assert object instanceof ScriptObject;
+        return getDebuggerValueDescs((ScriptObject)object, all, new HashSet<>());
+    }
+
+    /**
+     * This method returns a debugger description of the value.
+     * @param name  Name of value (property name).
+     * @param value Data value.
+     * @param all   true if to include non-enumerable values.
+     * @return A DebuggerValueDesc.
+     */
+    static DebuggerValueDesc valueInfo(final String name, final Object value, final boolean all) {
+        return valueInfo(name, value, all, new HashSet<>());
+    }
+
+   /**
+     * This method returns a debugger description of the value.
+     * @param name       Name of value (property name).
+     * @param value      Data value.
+     * @param all        true if to include non-enumerable values.
+     * @param duplicates Duplication set to avoid cycles.
+     * @return A DebuggerValueDesc.
+     */
+    private static DebuggerValueDesc valueInfo(final String name, final Object value, final boolean all, final Set<Object> duplicates) {
+        if (value instanceof ScriptObject && !(value instanceof ScriptFunction)) {
+            final ScriptObject object = (ScriptObject)value;
+            return new DebuggerValueDesc(name, !object.isEmpty(), value, objectAsString(object, all, duplicates));
+        } else {
+            return new DebuggerValueDesc(name, false, value, valueAsString(value));
+        }
+    }
+
+    /**
+     * Generate the descriptions for an object's properties.
+     * @param object     Object to introspect.
+     * @param all        true if to include non-enumerable values.
+     * @param duplicates Duplication set to avoid cycles.
+     * @return An array of DebuggerValueDesc.
+     */
+    private static DebuggerValueDesc[] getDebuggerValueDescs(final ScriptObject object, final boolean all, final Set<Object> duplicates) {
+        if (duplicates.contains(object)) {
+            return null;
+        }
+
+        duplicates.add(object);
+
+        final String[] keys = object.getOwnKeys(all);
+        final DebuggerValueDesc[] descs = new DebuggerValueDesc[keys.length];
+
+        for (int i = 0; i < keys.length; i++) {
+            final String key = keys[i];
+            descs[i] = valueInfo(key, object.get(key), true, duplicates);
+        }
+
+        duplicates.remove(object);
+
+        return descs;
+    }
+
+    /**
+     * Generate a string representation of a Script object.
+     * @param object     Script object to represent.
+     * @param all        true if to include non-enumerable values.
+     * @param duplicates Duplication set to avoid cycles.
+     * @return String representation.
+     */
+    private static String objectAsString(final ScriptObject object, final boolean all, final Set<Object> duplicates) {
+        final StringBuilder sb = new StringBuilder();
+
+        if (ScriptObject.isArray(object)) {
+            sb.append('[');
+            final long length = object.getLong("length");
+
+            for (long i = 0; i < length; i++) {
+                if (object.has(i)) {
+                    final Object valueAsObject = object.get(i);
+                    final boolean isUndefined = JSType.of(valueAsObject) == JSType.UNDEFINED;
+
+                    if (isUndefined) {
+                        if (i != 0) {
+                            sb.append(",");
+                        }
+                    } else {
+                        if (i != 0) {
+                            sb.append(", ");
+                        }
+
+                        if (valueAsObject instanceof ScriptObject && !(valueAsObject instanceof ScriptFunction)) {
+                            final String objectString = objectAsString((ScriptObject)valueAsObject, true, duplicates);
+                            sb.append(objectString != null ? objectString : "{...}");
+                        } else {
+                            sb.append(valueAsString(valueAsObject));
+                        }
+                    }
+                } else {
+                    if (i != 0) {
+                        sb.append(',');
+                    }
+                }
+            }
+
+            sb.append(']');
+        } else {
+            sb.append('{');
+            final DebuggerValueDesc[] descs = getDebuggerValueDescs(object, all, duplicates);
+
+            if (descs != null) {
+                for (int i = 0; i < descs.length; i++) {
+                    if (i != 0) {
+                        sb.append(", ");
+                    }
+
+                    final String valueAsString = descs[i].valueAsString;
+                    sb.append(descs[i].key);
+                    sb.append(": ");
+                    sb.append(descs[i].valueAsString);
+                }
+            }
+
+            sb.append('}');
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * This method returns a string representation of a value.
+     * @param value Arbitrary value to be displayed by the debugger.
+     * @return A string representation of the value or an array of DebuggerValueDesc.
+     */
+    private static String valueAsString(final Object value) {
+        final JSType type = JSType.of(value);
+
+        switch (type) {
+        case BOOLEAN:
+            return value.toString();
+
+        case STRING:
+            return escape((String)value);
+
+        case NUMBER:
+            return JSType.toString(((Number)value).doubleValue());
+
+        case NULL:
+            return "null";
+
+        case UNDEFINED:
+            return "undefined";
+
+        case OBJECT:
+            return ScriptRuntime.safeToString(value);
+
+        case FUNCTION:
+            if (value instanceof ScriptFunction) {
+                return ((ScriptFunction)value).toSource();
+            } else {
+                return value.toString();
+            }
+
+        default:
+            return value.toString();
+        }
+    }
+
+    /**
+     * Escape a string into a form that can be parsed by JavaScript.
+     * @param value String to be escaped.
+     * @return Escaped string.
+     */
+    private static String escape(final String value) {
+        final StringBuilder sb = new StringBuilder();
+
+        sb.append("\"");
+
+        for (final char ch : value.toCharArray()) {
+            switch (ch) {
+            case '\\':
+                sb.append("\\\\");
+                break;
+            case '"':
+                sb.append("\\\"");
+                break;
+            case '\'':
+                sb.append("\\\'");
+                break;
+            case '\b':
+                sb.append("\\b");
+                break;
+            case '\f':
+                sb.append("\\f");
+                break;
+            case '\n':
+                sb.append("\\n");
+                break;
+            case '\r':
+                sb.append("\\r");
+                break;
+            case '\t':
+                sb.append("\\t");
+                break;
+            default:
+                if (ch < ' ' || ch >= 0xFF) {
+                    sb.append("\\u");
+
+                    final String hex = Integer.toHexString(ch);
+                    for (int i = hex.length(); i < 4; i++) {
+                        sb.append('0');
+                    }
+                    sb.append(hex);
+                } else {
+                    sb.append(ch);
+                }
+
+                break;
+            }
+        }
+
+        sb.append("\"");
+
+        return sb.toString();
+    }
+}
+
+
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java	Fri Aug 23 16:44:02 2013 +0530
@@ -30,11 +30,10 @@
 
 import java.lang.invoke.MethodHandles;
 import java.util.Locale;
-import jdk.internal.dynalink.beans.BeansLinker;
 import jdk.internal.dynalink.beans.StaticClass;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.parser.Lexer;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
 /**
  * Representation for ECMAScript types - this maps directly to the ECMA script standard
@@ -148,22 +147,10 @@
             return JSType.STRING;
         }
 
-        if (obj instanceof ScriptObject) {
-            return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT;
-        }
-
-        if (obj instanceof StaticClass) {
+        if (Bootstrap.isCallable(obj)) {
             return JSType.FUNCTION;
         }
 
-        if (BeansLinker.isDynamicMethod(obj)) {
-            return JSType.FUNCTION;
-        }
-
-        if (obj instanceof ScriptObjectMirror) {
-            return ((ScriptObjectMirror)obj).isFunction()? JSType.FUNCTION : JSType.OBJECT;
-        }
-
         return JSType.OBJECT;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java	Fri Aug 23 16:44:02 2013 +0530
@@ -54,4 +54,13 @@
      *
      */
     public void propertyModified(ScriptObject object, Property oldProp, Property newProp);
+
+    /**
+     * Given object's __proto__ has changed.
+     *
+     * @param object object whose __proto__ has changed.
+     * @param oldProto old __proto__
+     * @param newProto new __proto__
+     */
+    public void protoChanged(ScriptObject object, ScriptObject oldProto, ScriptObject newProto);
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java	Fri Aug 23 16:44:02 2013 +0530
@@ -140,6 +140,21 @@
         }
     }
 
+    /**
+     * This method can be called to notify __proto__ modification to this object's listeners.
+     *
+     * @param object The ScriptObject whose __proto__ was changed.
+     * @param oldProto old __proto__
+     * @param newProto new __proto__
+     */
+    protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
+        if (listeners != null) {
+            for (PropertyListener listener : listeners.keySet()) {
+                listener.protoChanged(object, oldProto, newProto);
+            }
+        }
+    }
+
     // PropertyListener methods
 
     @Override
@@ -156,4 +171,9 @@
     public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
         notifyPropertyModified(object, oldProp, newProp);
     }
+
+    @Override
+    public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
+        notifyProtoChanged(object, oldProto, newProto);
+    }
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java	Fri Aug 23 16:44:02 2013 +0530
@@ -230,7 +230,7 @@
     }
 
     /**
-     * Indicate that a prototype property hash changed.
+     * Indicate that a prototype property has changed.
      *
      * @param property {@link Property} to invalidate.
      */
@@ -251,6 +251,18 @@
     }
 
     /**
+     * Indicate that proto itself has changed in hierachy somewhere.
+     */
+    private void invalidateAllProtoGetSwitchPoints() {
+        assert !isShared() : "proto invalidation on a shared PropertyMap";
+
+        if (protoGetSwitches != null) {
+            final Collection<SwitchPoint> sws = protoGetSwitches.values();
+            SwitchPoint.invalidateAll(sws.toArray(new SwitchPoint[sws.size()]));
+        }
+    }
+
+    /**
      * Add a property to the map, re-binding its getters and setters,
      * if available, to a given receiver. This is typically the global scope. See
      * {@link ScriptObject#addBoundProperties(ScriptObject)}
@@ -878,6 +890,15 @@
         invalidateProtoGetSwitchPoint(oldProp);
     }
 
+    @Override
+    public void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
+        // We may walk and invalidate SwitchPoints for properties inherited
+        // from 'object' or it's old proto chain. But, it may not be worth it.
+        // For example, a new proto may have a user defined getter/setter for
+        // a data property down the chain. So, invalidating all is better.
+        invalidateAllProtoGetSwitchPoints();
+    }
+
     /*
      * Debugging and statistics.
      */
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Fri Aug 23 16:44:02 2013 +0530
@@ -86,6 +86,9 @@
     /** Launch using as fx application */
     public final boolean _fx;
 
+    /** Use single Global instance per jsr223 engine instance. */
+    public final boolean _global_per_engine;
+
     /**
      * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
      * (function declarations are source elements, but not statements).
@@ -128,9 +131,6 @@
     /** Do not support typed arrays. */
     public final boolean _no_typed_arrays;
 
-    /** Package to which generated class files are added */
-    public final String  _package;
-
     /** Only parse the source code, do not compile */
     public final boolean _parse_only;
 
@@ -211,12 +211,12 @@
             _function_statement = FunctionStatementBehavior.ACCEPT;
         }
         _fx                   = options.getBoolean("fx");
+        _global_per_engine    = options.getBoolean("global.per.engine");
         _lazy_compilation     = options.getBoolean("lazy.compilation");
         _loader_per_compile   = options.getBoolean("loader.per.compile");
         _no_java              = options.getBoolean("no.java");
         _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
         _no_typed_arrays      = options.getBoolean("no.typed.arrays");
-        _package              = options.getString("package");
         _parse_only           = options.getBoolean("parse.only");
         _print_ast            = options.getBoolean("print.ast");
         _print_lower_ast      = options.getBoolean("print.lower.ast");
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Aug 23 16:44:02 2013 +0530
@@ -1008,10 +1008,6 @@
         return getMap().findProperty(key);
     }
 
-    static String convertKey(final Object key) {
-        return (key instanceof String) ? (String)key : JSType.toString(key);
-    }
-
     /**
      * Overridden by {@link jdk.nashorn.internal.objects.NativeArguments} class (internal use.)
      * Used for argument access in a vararg function using parameter name.
@@ -1129,6 +1125,9 @@
         proto = newProto;
 
         if (isPrototype()) {
+            // tell listeners that my __proto__ has been changed
+            notifyProtoChanged(this, oldProto, newProto);
+
             if (oldProto != null) {
                 oldProto.removePropertyListener(this);
             }
@@ -1144,7 +1143,19 @@
      * @param newProto Prototype to set.
      */
     public final void setProtoCheck(final Object newProto) {
+        if (!isExtensible()) {
+            throw typeError("__proto__.set.non.extensible", ScriptRuntime.safeToString(this));
+        }
+
         if (newProto == null || newProto instanceof ScriptObject) {
+            // check for circularity
+            ScriptObject proto = (ScriptObject)newProto;
+            while (proto != null) {
+                if (proto == this) {
+                    throw typeError("circular.__proto__.set", ScriptRuntime.safeToString(this));
+                }
+                proto = proto.getProto();
+            }
             setProto((ScriptObject)newProto);
         } else {
             final ScriptObject global = Context.getGlobalTrusted();
@@ -2359,7 +2370,7 @@
             return array.getInt(index);
         }
 
-        return getInt(index, convertKey(key));
+        return getInt(index, JSType.toString(key));
     }
 
     @Override
@@ -2371,7 +2382,7 @@
             return array.getInt(index);
         }
 
-        return getInt(index, convertKey(key));
+        return getInt(index, JSType.toString(key));
     }
 
     @Override
@@ -2383,7 +2394,7 @@
             return array.getInt(index);
         }
 
-        return getInt(index, convertKey(key));
+        return getInt(index, JSType.toString(key));
     }
 
     @Override
@@ -2394,7 +2405,7 @@
             return array.getInt(key);
         }
 
-        return getInt(key, convertKey(key));
+        return getInt(key, JSType.toString(key));
     }
 
     private long getLong(final int index, final String key) {
@@ -2436,7 +2447,7 @@
             return array.getLong(index);
         }
 
-        return getLong(index, convertKey(key));
+        return getLong(index, JSType.toString(key));
     }
 
     @Override
@@ -2448,7 +2459,7 @@
             return array.getLong(index);
         }
 
-        return getLong(index, convertKey(key));
+        return getLong(index, JSType.toString(key));
     }
 
     @Override
@@ -2460,7 +2471,7 @@
             return array.getLong(index);
         }
 
-        return getLong(index, convertKey(key));
+        return getLong(index, JSType.toString(key));
     }
 
     @Override
@@ -2471,7 +2482,7 @@
             return array.getLong(key);
         }
 
-        return getLong(key, convertKey(key));
+        return getLong(key, JSType.toString(key));
     }
 
     private double getDouble(final int index, final String key) {
@@ -2513,7 +2524,7 @@
             return array.getDouble(index);
         }
 
-        return getDouble(index, convertKey(key));
+        return getDouble(index, JSType.toString(key));
     }
 
     @Override
@@ -2525,7 +2536,7 @@
             return array.getDouble(index);
         }
 
-        return getDouble(index, convertKey(key));
+        return getDouble(index, JSType.toString(key));
     }
 
     @Override
@@ -2537,7 +2548,7 @@
             return array.getDouble(index);
         }
 
-        return getDouble(index, convertKey(key));
+        return getDouble(index, JSType.toString(key));
     }
 
     @Override
@@ -2548,7 +2559,7 @@
             return array.getDouble(key);
         }
 
-        return getDouble(key, convertKey(key));
+        return getDouble(key, JSType.toString(key));
     }
 
     private Object get(final int index, final String key) {
@@ -2590,7 +2601,7 @@
             return array.getObject(index);
         }
 
-        return get(index, convertKey(key));
+        return get(index, JSType.toString(key));
     }
 
     @Override
@@ -2602,7 +2613,7 @@
             return array.getObject(index);
         }
 
-        return get(index, convertKey(key));
+        return get(index, JSType.toString(key));
     }
 
     @Override
@@ -2614,7 +2625,7 @@
             return array.getObject(index);
         }
 
-        return get(index, convertKey(key));
+        return get(index, JSType.toString(key));
     }
 
     @Override
@@ -2625,7 +2636,7 @@
             return array.getObject(key);
         }
 
-        return get(key, convertKey(key));
+        return get(key, JSType.toString(key));
     }
 
     /**
@@ -2640,7 +2651,7 @@
         final long longIndex = index & JSType.MAX_UINT;
 
         if (!getArray().has(index)) {
-            final String key = convertKey(longIndex);
+            final String key = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
 
             if (find != null) {
@@ -2786,7 +2797,7 @@
             return;
         }
 
-        final String       propName = convertKey(key);
+        final String       propName = JSType.toString(key);
         final FindProperty find     = findProperty(propName, true);
 
         setObject(find, strict, propName, value);
@@ -3008,7 +3019,7 @@
             }
         }
 
-        final FindProperty find = findProperty(convertKey(key), true);
+        final FindProperty find = findProperty(JSType.toString(key), true);
 
         return find != null;
     }
@@ -3025,7 +3036,7 @@
             }
         }
 
-        final FindProperty find = findProperty(convertKey(key), true);
+        final FindProperty find = findProperty(JSType.toString(key), true);
 
         return find != null;
     }
@@ -3042,7 +3053,7 @@
             }
         }
 
-        final FindProperty find = findProperty(convertKey(key), true);
+        final FindProperty find = findProperty(JSType.toString(key), true);
 
         return find != null;
     }
@@ -3059,7 +3070,7 @@
             }
         }
 
-        final FindProperty find = findProperty(convertKey(key), true);
+        final FindProperty find = findProperty(JSType.toString(key), true);
 
         return find != null;
     }
@@ -3072,7 +3083,7 @@
             return true;
         }
 
-        final FindProperty find = findProperty(convertKey(key), false);
+        final FindProperty find = findProperty(JSType.toString(key), false);
 
         return find != null;
     }
@@ -3085,7 +3096,7 @@
             return true;
         }
 
-        final FindProperty find = findProperty(convertKey(key), false);
+        final FindProperty find = findProperty(JSType.toString(key), false);
 
         return find != null;
     }
@@ -3098,7 +3109,7 @@
             return true;
         }
 
-        final FindProperty find = findProperty(convertKey(key), false);
+        final FindProperty find = findProperty(JSType.toString(key), false);
 
         return find != null;
     }
@@ -3111,7 +3122,7 @@
             return true;
         }
 
-        final FindProperty find = findProperty(convertKey(key), false);
+        final FindProperty find = findProperty(JSType.toString(key), false);
 
         return find != null;
     }
@@ -3181,7 +3192,7 @@
     }
 
     private boolean deleteObject(final Object key, final boolean strict) {
-        final String propName = convertKey(key);
+        final String propName = JSType.toString(key);
         final FindProperty find = findProperty(propName, false);
 
         if (find == null) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Fri Aug 23 16:44:02 2013 +0530
@@ -37,7 +37,9 @@
 import java.lang.reflect.Array;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import jdk.internal.dynalink.beans.StaticClass;
@@ -221,49 +223,71 @@
     }
 
     /**
-     * Used to determine property iterator used in for in.
-     * @param obj Object to iterate on.
-     * @return Iterator.
+     * Returns an iterator over property identifiers used in the {@code for...in} statement. Note that the ECMAScript
+     * 5.1 specification, chapter 12.6.4. uses the terminology "property names", which seems to imply that the property
+     * identifiers are expected to be strings, but this is not actually spelled out anywhere, and Nashorn will in some
+     * cases deviate from this. Namely, we guarantee to always return an iterator over {@link String} values for any
+     * built-in JavaScript object. We will however return an iterator over {@link Integer} objects for native Java
+     * arrays and {@link List} objects, as well as arbitrary objects representing keys of a {@link Map}. Therefore, the
+     * expression {@code typeof i} within a {@code for(i in obj)} statement can return something other than
+     * {@code string} when iterating over native Java arrays, {@code List}, and {@code Map} objects.
+     * @param obj object to iterate on.
+     * @return iterator over the object's property names.
      */
-    public static Iterator<String> toPropertyIterator(final Object obj) {
+    public static Iterator<?> toPropertyIterator(final Object obj) {
         if (obj instanceof ScriptObject) {
             return ((ScriptObject)obj).propertyIterator();
         }
 
         if (obj != null && obj.getClass().isArray()) {
-            final int length = Array.getLength(obj);
-
-            return new Iterator<String>() {
-                private int index = 0;
-
-                @Override
-                public boolean hasNext() {
-                    return index < length;
-                }
-
-                @Override
-                public String next() {
-                    return "" + index++; //TODO numeric property iterator?
-                }
-
-                @Override
-                public void remove() {
-                    throw new UnsupportedOperationException();
-                }
-            };
+            return new RangeIterator(Array.getLength(obj));
         }
 
         if (obj instanceof ScriptObjectMirror) {
             return ((ScriptObjectMirror)obj).keySet().iterator();
         }
 
+        if (obj instanceof List) {
+            return new RangeIterator(((List<?>)obj).size());
+        }
+
+        if (obj instanceof Map) {
+            return ((Map<?,?>)obj).keySet().iterator();
+        }
+
         return Collections.emptyIterator();
     }
 
+    private static final class RangeIterator implements Iterator<Integer> {
+        private final int length;
+        private int index;
+
+        RangeIterator(int length) {
+            this.length = length;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return index < length;
+        }
+
+        @Override
+        public Integer next() {
+            return index++;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
     /**
-     * Used to determine property value iterator used in for each in.
-     * @param obj Object to iterate on.
-     * @return Iterator.
+     * Returns an iterator over property values used in the {@code for each...in} statement. Aside from built-in JS
+     * objects, it also operates on Java arrays, any {@link Iterable}, as well as on {@link Map} objects, iterating over
+     * map values.
+     * @param obj object to iterate on.
+     * @return iterator over the object's property values.
      */
     public static Iterator<?> toValueIterator(final Object obj) {
         if (obj instanceof ScriptObject) {
@@ -301,6 +325,10 @@
             return ((ScriptObjectMirror)obj).values().iterator();
         }
 
+        if (obj instanceof Map) {
+            return ((Map<?,?>)obj).values().iterator();
+        }
+
         if (obj instanceof Iterable) {
             return ((Iterable<?>)obj).iterator();
         }
--- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java	Fri Aug 23 16:44:02 2013 +0530
@@ -73,7 +73,7 @@
     public boolean delete(final Object key, final boolean strict) {
         if (expression instanceof ScriptObject) {
             final ScriptObject self = (ScriptObject)expression;
-            final String propName = ScriptObject.convertKey(key);
+            final String propName = JSType.toString(key);
 
             final FindProperty find = self.findProperty(propName, true);
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Fri Aug 23 16:44:02 2013 +0530
@@ -36,6 +36,7 @@
 import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.DynamicLinkerFactory;
 import jdk.internal.dynalink.beans.BeansLinker;
+import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
@@ -61,7 +62,7 @@
     static {
         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
         factory.setPrioritizedLinkers(new NashornLinker(), new NashornPrimitiveLinker(), new NashornStaticClassLinker(),
-                new BoundDynamicMethodLinker(), new JSObjectLinker(), new ReflectionCheckLinker());
+                new BoundDynamicMethodLinker(), new JavaSuperAdapterLinker(), new JSObjectLinker(), new ReflectionCheckLinker());
         factory.setFallbackLinkers(new BeansLinker(), new NashornBottomLinker());
         factory.setSyncOnRelink(true);
         final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1);
@@ -88,7 +89,8 @@
         return obj instanceof ScriptFunction ||
             ((obj instanceof ScriptObjectMirror) && ((ScriptObjectMirror)obj).isFunction()) ||
             isDynamicMethod(obj) ||
-            isFunctionalInterfaceObject(obj);
+            isFunctionalInterfaceObject(obj) ||
+            obj instanceof StaticClass;
     }
 
     /**
@@ -262,6 +264,16 @@
     }
 
     /**
+     * Creates a super-adapter for an adapter, that is, an adapter to the adapter that allows invocation of superclass
+     * methods on it.
+     * @param adapter the original adapter
+     * @return a new adapter that can be used to invoke super methods on the original adapter.
+     */
+    public static Object createSuperAdapter(final Object adapter) {
+        return new JavaSuperAdapter(adapter);
+    }
+
+    /**
      * If the given class is a reflection-specific class (anything in {@code java.lang.reflect} and
      * {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is
      * a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}.
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java	Fri Aug 23 16:44:02 2013 +0530
@@ -67,11 +67,12 @@
         // BeansLinker.
         final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
         final MethodType type = descriptor.getMethodType();
+        final Class<?> dynamicMethodClass = dynamicMethod.getClass();
         final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(
-                type.changeParameterType(0, dynamicMethod.getClass()).changeParameterType(1, boundThis.getClass()));
+                type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass()));
 
         // Delegate to BeansLinker
-        final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethod.getClass()).getGuardedInvocation(
+        final GuardedInvocation inv = BeansLinker.getLinkerForClass(dynamicMethodClass).getGuardedInvocation(
                 linkRequest.replaceArguments(newDescriptor, args), linkerServices);
         if(inv == null) {
             return null;
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Fri Aug 23 16:44:02 2013 +0530
@@ -173,6 +173,9 @@
     private static final String CLASS_INIT = "<clinit>";
     private static final String STATIC_GLOBAL_FIELD_NAME = "staticGlobal";
 
+    // Method name prefix for invoking super-methods
+    static final String SUPER_PREFIX = "super$";
+
     /**
      * Collection of methods we never override: Object.clone(), Object.finalize().
      */
@@ -240,6 +243,7 @@
         }
         generateConstructors();
         generateMethods();
+        generateSuperMethods();
         // }
         cw.visitEnd();
     }
@@ -507,6 +511,10 @@
 
     private static void endInitMethod(final InstructionAdapter mv) {
         mv.visitInsn(RETURN);
+        endMethod(mv);
+    }
+
+    private static void endMethod(final InstructionAdapter mv) {
         mv.visitMaxs(0, 0);
         mv.visitEnd();
     }
@@ -603,13 +611,8 @@
      */
     private void generateMethod(final MethodInfo mi) {
         final Method method = mi.method;
-        final int mod = method.getModifiers();
-        final int access = ACC_PUBLIC | (method.isVarArgs() ? ACC_VARARGS : 0);
         final Class<?>[] exceptions = method.getExceptionTypes();
-        final String[] exceptionNames = new String[exceptions.length];
-        for (int i = 0; i < exceptions.length; ++i) {
-            exceptionNames[i] = Type.getInternalName(exceptions[i]);
-        }
+        final String[] exceptionNames = getExceptionNames(exceptions);
         final MethodType type = mi.type;
         final String methodDesc = type.toMethodDescriptorString();
         final String name = mi.getName();
@@ -617,14 +620,8 @@
         final Type asmType = Type.getMethodType(methodDesc);
         final Type[] asmArgTypes = asmType.getArgumentTypes();
 
-        // Determine the first index for a local variable
-        int nextLocalVar = 1; // this
-        for(final Type t: asmArgTypes) {
-            nextLocalVar += t.getSize();
-        }
-
-        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(access, name, methodDesc, null,
-                exceptionNames));
+        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method), name,
+                methodDesc, null, exceptionNames));
         mv.visitCode();
 
         final Label instanceHandleDefined = new Label();
@@ -646,7 +643,7 @@
         }
 
         // No handle is available, fall back to default behavior
-        if(Modifier.isAbstract(mod)) {
+        if(Modifier.isAbstract(method.getModifiers())) {
             // If the super method is abstract, throw an exception
             mv.anew(UNSUPPORTED_OPERATION_TYPE);
             mv.dup();
@@ -654,14 +651,7 @@
             mv.athrow();
         } else {
             // If the super method is not abstract, delegate to it.
-            mv.visitVarInsn(ALOAD, 0);
-            int nextParam = 1;
-            for(final Type t: asmArgTypes) {
-                mv.load(nextParam, t);
-                nextParam += t.getSize();
-            }
-            mv.invokespecial(superClassName, name, methodDesc);
-            mv.areturn(asmReturnType);
+            emitSuperCall(mv, name, methodDesc);
         }
 
         final Label setupGlobal = new Label();
@@ -685,6 +675,12 @@
         // stack: [creatingGlobal, someHandle]
         mv.visitLabel(setupGlobal);
 
+        // Determine the first index for a local variable
+        int nextLocalVar = 1; // "this" is at 0
+        for(final Type t: asmArgTypes) {
+            nextLocalVar += t.getSize();
+        }
+        // Set our local variable indices
         final int currentGlobalVar  = nextLocalVar++;
         final int globalsDifferVar  = nextLocalVar++;
 
@@ -775,8 +771,7 @@
             }
             mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, throwableHandler, THROWABLE_TYPE_NAME);
         }
-        mv.visitMaxs(0, 0);
-        mv.visitEnd();
+        endMethod(mv);
     }
 
     /**
@@ -817,6 +812,53 @@
         return false;
     }
 
+    private void generateSuperMethods() {
+        for(final MethodInfo mi: methodInfos) {
+            if(!Modifier.isAbstract(mi.method.getModifiers())) {
+                generateSuperMethod(mi);
+            }
+        }
+    }
+
+    private void generateSuperMethod(MethodInfo mi) {
+        final Method method = mi.method;
+
+        final String methodDesc = mi.type.toMethodDescriptorString();
+        final String name = mi.getName();
+
+        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method),
+                SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
+        mv.visitCode();
+
+        emitSuperCall(mv, name, methodDesc);
+
+        endMethod(mv);
+    }
+
+    private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) {
+        mv.visitVarInsn(ALOAD, 0);
+        int nextParam = 1;
+        final Type methodType = Type.getMethodType(methodDesc);
+        for(final Type t: methodType.getArgumentTypes()) {
+            mv.load(nextParam, t);
+            nextParam += t.getSize();
+        }
+        mv.invokespecial(superClassName, name, methodDesc);
+        mv.areturn(methodType.getReturnType());
+    }
+
+    private static String[] getExceptionNames(final Class<?>[] exceptions) {
+        final String[] exceptionNames = new String[exceptions.length];
+        for (int i = 0; i < exceptions.length; ++i) {
+            exceptionNames[i] = Type.getInternalName(exceptions[i]);
+        }
+        return exceptionNames;
+    }
+
+    private static int getAccessModifiers(final Method method) {
+        return ACC_PUBLIC | (method.isVarArgs() ? ACC_VARARGS : 0);
+    }
+
     /**
      * Gathers methods that can be implemented or overridden from the specified type into this factory's
      * {@link #methodInfos} set. It will add all non-final, non-static methods that are either public or protected from
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Fri Aug 23 16:44:02 2013 +0530
@@ -34,7 +34,6 @@
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.security.SecureClassLoader;
-
 import jdk.internal.dynalink.beans.StaticClass;
 
 /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,44 @@
+/*
+ * 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.internal.runtime.linker;
+
+/**
+ * Represents a an adapter for invoking superclass methods on an adapter instance generated by
+ * {@link JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
+ * without any behavior. All the behavior is defined in the {@code JavaSuperAdapterLinker}.
+ */
+class JavaSuperAdapter {
+    private final Object adapter;
+
+    JavaSuperAdapter(final Object adapter) {
+        adapter.getClass(); // NPE check
+        this.adapter = adapter;
+    }
+
+    public Object getAdapter() {
+        return adapter;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,180 @@
+/*
+ * 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.internal.runtime.linker;
+
+import static jdk.nashorn.internal.lookup.Lookup.EMPTY_GETTER;
+import static jdk.nashorn.internal.runtime.linker.JavaAdapterBytecodeGenerator.SUPER_PREFIX;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.beans.BeansLinker;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.internal.dynalink.support.Lookup;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * A linker for instances of {@link JavaSuperAdapter}. Only links {@code getMethod} calls, by forwarding them to the
+ * bean linker for the adapter class and prepending {@code super$} to method names.
+ *
+ */
+final class JavaSuperAdapterLinker implements TypeBasedGuardingDynamicLinker {
+    private static final String GET_METHOD = "getMethod";
+    private static final String DYN_GET_METHOD = "dyn:" + GET_METHOD;
+    private static final String DYN_GET_METHOD_FIXED = DYN_GET_METHOD + ":" + SUPER_PREFIX;
+
+    private static final MethodHandle ADD_PREFIX_TO_METHOD_NAME;
+    private static final MethodHandle BIND_DYNAMIC_METHOD;
+    private static final MethodHandle GET_ADAPTER;
+    private static final MethodHandle IS_ADAPTER_OF_CLASS;
+
+    static {
+        final Lookup lookup = new Lookup(MethodHandles.lookup());
+        ADD_PREFIX_TO_METHOD_NAME = lookup.findOwnStatic("addPrefixToMethodName", Object.class, Object.class);
+        BIND_DYNAMIC_METHOD = lookup.findOwnStatic("bindDynamicMethod", Object.class, Object.class, Object.class);
+        GET_ADAPTER = lookup.findVirtual(JavaSuperAdapter.class, "getAdapter", MethodType.methodType(Object.class));
+        IS_ADAPTER_OF_CLASS = lookup.findOwnStatic("isAdapterOfClass", boolean.class, Class.class, Object.class);
+    }
+
+    @Override
+    public boolean canLinkType(final Class<?> type) {
+        return type == JavaSuperAdapter.class;
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
+            throws Exception {
+        final Object objSuperAdapter = linkRequest.getReceiver();
+        if(!(objSuperAdapter instanceof JavaSuperAdapter)) {
+            return null;
+        }
+
+        final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
+        if(!CallSiteDescriptorFactory.tokenizeOperators(descriptor).contains(GET_METHOD)) {
+            // We only handle getMethod
+            return null;
+        }
+
+        final Object adapter = ((JavaSuperAdapter)objSuperAdapter).getAdapter();
+
+        // Replace argument (javaSuperAdapter, ...) => (adapter, ...) when delegating to BeansLinker
+        final Object[] args = linkRequest.getArguments();
+        args[0] = adapter;
+
+        // Use R(T0, ...) => R(adapter.class, ...) call site type when delegating to BeansLinker.
+        final MethodType type = descriptor.getMethodType();
+        final Class<?> adapterClass = adapter.getClass();
+        final boolean hasFixedName = descriptor.getNameTokenCount() > 2;
+        final String opName = hasFixedName ? (DYN_GET_METHOD_FIXED + descriptor.getNameToken(
+                CallSiteDescriptor.NAME_OPERAND)) : DYN_GET_METHOD;
+
+        final CallSiteDescriptor newDescriptor = NashornCallSiteDescriptor.get(descriptor.getLookup(), opName,
+                type.changeParameterType(0, adapterClass), 0);
+
+        // Delegate to BeansLinker
+        final GuardedInvocation guardedInv = BeansLinker.getLinkerForClass(adapterClass).getGuardedInvocation(
+                linkRequest.replaceArguments(newDescriptor, args), linkerServices);
+
+        final MethodHandle guard = IS_ADAPTER_OF_CLASS.bindTo(adapterClass);
+        if(guardedInv == null) {
+            // Short circuit the lookup here for non-existent methods by linking an empty getter. If we just returned
+            // null instead, BeansLinker would find final methods on the JavaSuperAdapter instead: getClass() and
+            // wait().
+            return new GuardedInvocation(MethodHandles.dropArguments(EMPTY_GETTER, 1,type.parameterList().subList(1,
+                    type.parameterCount())), guard).asType(descriptor);
+        }
+
+        final MethodHandle invocation = guardedInv.getInvocation();
+        final MethodType invType = invocation.type();
+        // For invocation typed R(T0, ...) create a dynamic method binder of type R(R, T0)
+        final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(invType.returnType(),
+                invType.returnType(), invType.parameterType(0)));
+        // For invocation typed R(T0, T1, ...) create a dynamic method binder of type R(R, T0, T1, ...)
+        final MethodHandle droppingBinder = MethodHandles.dropArguments(typedBinder, 2,
+                invType.parameterList().subList(1, invType.parameterCount()));
+        // Finally, fold the invocation into the binder to produce a method handle that will bind every returned
+        // DynamicMethod object from dyn:getMethod calls to the actual receiver
+        // R(R(T0, T1, ...), T0, T1, ...)
+        final MethodHandle bindingInvocation = MethodHandles.foldArguments(droppingBinder, invocation);
+
+        final MethodHandle typedGetAdapter = asFilterType(GET_ADAPTER, 0, invType, type);
+        final MethodHandle adaptedInvocation;
+        if(hasFixedName) {
+            adaptedInvocation = MethodHandles.filterArguments(bindingInvocation, 0, typedGetAdapter);
+        } else {
+            // Add a filter that'll prepend "super$" to each name passed to the variable-name "dyn:getMethod".
+            final MethodHandle typedAddPrefix = asFilterType(ADD_PREFIX_TO_METHOD_NAME, 1, invType, type);
+            adaptedInvocation = MethodHandles.filterArguments(bindingInvocation, 0, typedGetAdapter, typedAddPrefix);
+        }
+
+        return guardedInv.replaceMethods(adaptedInvocation, guard).asType(descriptor);
+    }
+
+    /**
+     * Adapts the type of a method handle used as a filter in a position from a source method type to a target method type.
+     * @param filter the filter method handle
+     * @param pos the position in the argument list that it's filtering
+     * @param targetType the target method type for filtering
+     * @param sourceType the source method type for filtering
+     * @return a type adapted filter
+     */
+    private static MethodHandle asFilterType(final MethodHandle filter, int pos, MethodType targetType, MethodType sourceType) {
+        return filter.asType(MethodType.methodType(targetType.parameterType(pos), sourceType.parameterType(pos)));
+    }
+
+    @SuppressWarnings("unused")
+    private static Object addPrefixToMethodName(final Object name) {
+        return SUPER_PREFIX.concat(String.valueOf(name));
+    }
+
+    /**
+     * Used to transform the return value of getMethod; transform a {@code DynamicMethod} into a
+     * {@code BoundDynamicMethod} while also accounting for the possibility of a non-existent method.
+     * @param dynamicMethod the dynamic method to bind
+     * @param boundThis the adapter underlying a super adapter, to which the dynamic method is bound.
+     * @return a dynamic method bound to the adapter instance.
+     */
+    @SuppressWarnings("unused")
+    private static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
+        return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindDynamicMethod(dynamicMethod, boundThis);
+    }
+
+    /**
+     * Used as the guard of linkages, as the receiver is not guaranteed to be a JavaSuperAdapter.
+     * @param clazz the class the receiver's adapter is tested against.
+     * @param obj receiver
+     * @return true if the receiver is a super adapter, and its underlying adapter is of the specified class
+     */
+    @SuppressWarnings("unused")
+    private static boolean isAdapterOfClass(Class<?> clazz, Object obj) {
+        return obj instanceof JavaSuperAdapter && clazz == (((JavaSuperAdapter)obj).getAdapter()).getClass();
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java	Fri Aug 23 16:44:02 2013 +0530
@@ -60,7 +60,7 @@
      * @param flags the flags string
      */
     protected RegExp(final String source, final String flags) {
-        this.source = source;
+        this.source = source.length() == 0 ? "(?:)" : source;
         for (int i = 0; i < flags.length(); i++) {
             final char ch = flags.charAt(i);
             switch (ch) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Fri Aug 23 16:44:02 2013 +0530
@@ -94,6 +94,8 @@
 type.error.cant.redefine.property=Cannot redefine property "{0}" of {1}
 type.error.property.not.writable="{0}" is not a writable property of {1}
 type.error.object.non.extensible=Cannot add new property "{0}" to non-extensible {1}
+type.error.__proto__.set.non.extensible=Cannot set __proto__ of non-extensible {0}
+type.error.circular.__proto__.set=Cannot create__proto__ cycle for {0}
 
 # miscellaneous
 type.error.regex.cant.supply.flags=Cannot supply flags when constructing one RegExp from another
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Fri Aug 23 16:44:02 2013 +0530
@@ -157,6 +157,14 @@
     default=false                               \
 }
 
+nashorn.option.global.per.engine = {            \
+    name="--global-per-engine",                 \
+    desc="Use single Global instance per script engine instance.", \
+    is_undocumented=true,                                          \
+    type=Boolean,                               \
+    default=false                               \
+}
+
 nashorn.option.log = {                                                       \
     name="--log",                                                            \
     is_undocumented=true,                                                    \
@@ -216,15 +224,6 @@
     default=false                                  \
 }
 
-nashorn.option.package = {                                     \
-    name="--package",                                          \
-    is_undocumented=true,                                      \
-    desc="Package to which generated .class files are added.", \
-    params="<package>",                                        \
-    type=String,                                               \
-    default=""                                                 \
-}
-
 nashorn.option.parse.only = {       \
     name="--parse-only",            \
     is_undocumented=true,           \
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Fri Aug 23 16:44:02 2013 +0530
@@ -144,7 +144,7 @@
         return Object.getPrototypeOf(this);
     },
     set: function(x) {
-        throw new TypeError("__proto__ set not supported");
+        Object.setPrototypeOf(this, x);
     }
 });
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8022903.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8022903: Enhance for-in and for-each for Lists and Maps
+ *
+ * @test
+ * @run
+ */
+
+var colors = new java.util.ArrayList()
+colors.add("red")
+colors.add("purple")
+colors.add("pink")
+
+for(var index in colors) {
+    print("colors[" + index + "]=" + colors[index])
+}
+
+for each(var color in colors) {
+    print(color)
+}
+
+var capitals = new java.util.LinkedHashMap()
+capitals.Sweden = "Stockholm"
+capitals.Hungary = "Budapet"
+capitals.Croatia = "Zagreb"
+
+for(var key in capitals) {
+    print("capital of " + key + " is " + capitals[key])
+}
+
+for each(var capital in capitals) {
+    print(capital)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8022903.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,12 @@
+colors[0]=red
+colors[1]=purple
+colors[2]=pink
+red
+purple
+pink
+capital of Sweden is Stockholm
+capital of Hungary is Budapet
+capital of Croatia is Zagreb
+Stockholm
+Budapet
+Zagreb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023368.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8023368: Instance __proto__ property should exist and be writable.
+ *
+ * @test
+ * @run
+ */
+
+load("nashorn:mozilla_compat.js");
+
+// function to force same callsites
+function check(obj) {
+    print(obj.func());
+    print(obj.x);
+    print(obj.toString());
+}
+
+function Func() {
+}
+
+Func.prototype.func = function() {
+    return "Func.prototype.func";
+}
+
+Func.prototype.x = "hello";
+
+var obj = new Func();
+var obj2 = Object.create(obj);
+
+// check direct and indirect __proto__ change
+check(obj);
+check(obj2);
+obj.__proto__ = {
+   func: function() {
+        return "obj.__proto__.func @ " + __LINE__;
+   },
+   x: 344
+};
+
+check(obj);
+check(obj2);
+
+// check indirect (1 and 2 levels) __proto__ function change
+obj.__proto__.__proto__ = {
+    toString: function() {
+        return "new object.toString";
+    }
+};
+
+check(obj);
+check(obj2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023368.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,18 @@
+Func.prototype.func
+hello
+[object Object]
+Func.prototype.func
+hello
+[object Object]
+obj.__proto__.func @ 57
+344
+[object Object]
+obj.__proto__.func @ 57
+344
+[object Object]
+obj.__proto__.func @ 57
+344
+new object.toString
+obj.__proto__.func @ 57
+344
+new object.toString
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023368_2.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8023368: Instance __proto__ property should exist and be writable.
+ *
+ * @test
+ * @run
+ */
+
+// check Object.setPrototypeOf extension rather than using __proto__
+
+// function to force same callsites
+function check(obj) {
+    print(obj.func());
+    print(obj.x);
+    print(obj.toString());
+}
+
+function Func() {
+}
+
+Func.prototype.func = function() {
+    return "Func.prototype.func";
+}
+
+Func.prototype.x = "hello";
+
+var obj = new Func();
+var obj2 = Object.create(obj);
+
+// check direct and indirect __proto__ change
+check(obj);
+check(obj2);
+Object.setPrototypeOf(obj, {
+   func: function() {
+        return "obj.__proto__.func @ " + __LINE__;
+   },
+   x: 344
+});
+
+check(obj);
+check(obj2);
+
+// check indirect (1 and 2 levels) __proto__ function change
+Object.setPrototypeOf(Object.getPrototypeOf(obj), {
+    toString: function() {
+        return "new object.toString";
+    }
+});
+
+check(obj);
+check(obj2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023368_2.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,18 @@
+Func.prototype.func
+hello
+[object Object]
+Func.prototype.func
+hello
+[object Object]
+obj.__proto__.func @ 57
+344
+[object Object]
+obj.__proto__.func @ 57
+344
+[object Object]
+obj.__proto__.func @ 57
+344
+new object.toString
+obj.__proto__.func @ 57
+344
+new object.toString
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023373.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8023373: allow super invocation for adapters
+ *
+ * @test
+ * @run
+ */
+
+var CharArray = Java.type("char[]")
+var jString = Java.type("java.lang.String")
+var Character = Java.type("java.lang.Character")
+
+function capitalize(s) {
+    if(s instanceof CharArray) {
+        return new jString(s).toUpperCase()
+    }
+    if(s instanceof jString) {
+        return s.toUpperCase()
+    }
+    return Character.toUpperCase(s) // must be int
+}
+
+var sw = new (Java.type("java.io.StringWriter"))
+
+var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))
+
+var cw = new FilterWriterAdapter(sw) {
+    write: function(s, off, len) {
+        s = capitalize(s)
+        // Must handle overloads by arity
+        if(off === undefined) {	
+            cw.super$write(s, 0, s.length())
+        } else if (typeof s === "string") {
+            cw.super$write(s, off, len)
+        }
+    }
+}
+
+cw.write("abcd")
+cw.write("e".charAt(0))
+cw.write("fgh".toCharArray())
+cw.write("**ijk**", 2, 3)
+cw.write("***lmno**".toCharArray(), 3, 4)
+cw.flush()
+print(sw)
+
+// Can invoke super for Object methods
+print("cw has super hashCode(): " + (typeof cw.super$hashCode === "function"))
+print("cw has super equals(): " + (typeof cw.super$equals === "function"))
+// Can't invoke super for final methods
+print("cw has no super getClass(): " + (typeof cw.super$getClass === "undefined"))
+print("cw has no super wait(): " + (typeof cw.super$wait === "undefined"))
+
+var r = new (Java.type("java.lang.Runnable"))(function() {})
+// Can't invoke super for abstract methods
+print("r has no super run(): " + (typeof r.super$run === "undefined"))
+// Interfaces can also invoke super Object methods
+print("r has super hashCode(): " + (typeof r.super$hashCode === "function"))
+print("r has super equals(): " + (typeof r.super$equals === "function"))
+// But still can't invoke final methods
+print("r has no super getClass(): " + (typeof r.super$getClass === "undefined"))
+print("r has no super wait(): " + (typeof r.super$wait === "undefined"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023373.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,10 @@
+ABCDEFGHIJKLMNO
+cw has super hashCode(): true
+cw has super equals(): true
+cw has no super getClass(): true
+cw has no super wait(): true
+r has no super run(): true
+r has super hashCode(): true
+r has super equals(): true
+r has no super getClass(): true
+r has no super wait(): true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023531.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8023531: new RegExp('').toString() should return '/(?:)/'
+ *
+ * @test
+ * @run
+ */
+
+if (new RegExp("").toString() !== "/(?:)/") {
+    throw new Error();
+} else if (!(new RegExp("").test(""))) {
+    throw new Error();
+}
+
+if (new RegExp("", "g").toString() !== "/(?:)/g") {
+    throw new Error();
+} else if (!(new RegExp("", "g").test(""))) {
+    throw new Error();
+}
+
+if (new RegExp("", "i").toString() !== "/(?:)/i") {
+    throw new Error();
+} else if (!(new RegExp("", "i").test(""))) {
+    throw new Error();
+}
+
+if (new RegExp("", "m").toString() !== "/(?:)/m") {
+    throw new Error();
+} else if (!(new RegExp("", "m").test(""))) {
+    throw new Error();
+}
+
+if (RegExp("").toString() !== "/(?:)/") {
+    throw new Error();
+} else if (!RegExp("").test("")) {
+    throw new Error();
+}
+
+if (RegExp("", "g").toString() !== "/(?:)/g") {
+    throw new Error();
+} else if (!RegExp("", "g").test("")) {
+    throw new Error();
+}
+
+if (RegExp("", "i").toString() !== "/(?:)/i") {
+    throw new Error();
+} else if (!RegExp("", "i").test("")) {
+    throw new Error();
+}
+
+if (RegExp("", "m").toString() !== "/(?:)/m") {
+    throw new Error();
+} else if (!RegExp("", "m").test("")) {
+    throw new Error();
+}
+
+var re = /abc/;
+re.compile("");
+if (re.toString() !== "/(?:)/") {
+    throw new Error();
+} else if (!re.test("")) {
+    throw new Error();
+}
+
+re.compile("", "g");
+if (re.toString() !== "/(?:)/g") {
+    throw new Error();
+} else if (!re.test("")) {
+    throw new Error();
+}
+
+re.compile("", "i");
+if (re.toString() !== "/(?:)/i") {
+    throw new Error();
+} else if (!re.test("")) {
+    throw new Error();
+}
+
+re.compile("", "m");
+if (re.toString() !== "/(?:)/m") {
+    throw new Error();
+} else if (!re.test("")) {
+    throw new Error();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023551.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8023551: Mirror functions can not be invoked using invokeMethod, invokeFunction
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+
+function func(x) {
+   print("func: " + x);
+}
+
+e.put("func", func);
+e.invokeFunction("func", "hello");
+
+var obj = e.eval("({ foo: func })");
+e.invokeMethod(obj, "foo", "world");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023551.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,2 @@
+func: hello
+func: world
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023630.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8023630: Implement Java.super() as the preferred way to call super methods
+ *
+ * @test
+ * @run
+ */
+
+var CharArray = Java.type("char[]")
+var jString = Java.type("java.lang.String")
+var Character = Java.type("java.lang.Character")
+
+function capitalize(s) {
+    if(s instanceof CharArray) {
+        return new jString(s).toUpperCase()
+    }
+    if(s instanceof jString) {
+        return s.toUpperCase()
+    }
+    return Character.toUpperCase(s) // must be int
+}
+
+var sw = new (Java.type("java.io.StringWriter"))
+
+var FilterWriterAdapter = Java.extend(Java.type("java.io.FilterWriter"))
+
+var cw = new FilterWriterAdapter(sw) {
+    write: function(s, off, len) {
+        s = capitalize(s)
+        // Must handle overloads by arity
+        if(off === undefined) {	
+            cw_super.write(s, 0, s.length())
+        } else if (typeof s === "string") {
+            cw_super.write(s, off, len)
+        }
+    }
+}
+var cw_super = Java.super(cw)
+
+cw.write("abcd")
+cw.write("e".charAt(0))
+cw.write("fgh".toCharArray())
+cw.write("**ijk**", 2, 3)
+cw.write("***lmno**".toCharArray(), 3, 4)
+cw.flush()
+print(sw)
+
+// Can invoke super for Object methods
+print("cw_super has hashCode(): " + (typeof cw_super.hashCode === "function"))
+print("cw_super has super equals(): " + (typeof cw_super.equals === "function"))
+// Can't invoke super for final methods
+print("cw_super has no getClass(): " + (typeof cw_super.getClass === "undefined"))
+print("cw_super has no wait(): " + (typeof cw_super.wait === "undefined"))
+
+var r = new (Java.type("java.lang.Runnable"))(function() {})
+var r_super = Java.super(r)
+
+// Can't invoke super for abstract methods
+print("r_super has no run(): " + (typeof r_super.run === "undefined"))
+// Interfaces can also invoke super Object methods
+print("r_super has hashCode(): " + (typeof r_super.hashCode === "function"))
+print("r_super has equals(): " + (typeof r_super.equals === "function"))
+// But still can't invoke final methods
+print("r_super has no getClass(): " + (typeof r_super.getClass === "undefined"))
+print("r_super has no wait(): " + (typeof r_super.wait === "undefined"))
+
+var name = "write"
+print("cw_super can access write through [] getter: " + (typeof cw_super[name] === "function"))
+var name = "hashCode"
+print("cw_super can access hashCode through [] getter: " + (typeof cw_super[name] === "function"))
+var name = "getClass"
+print("cw_super can not access getClass through [] getter: " + (typeof cw_super[name] === "undefined"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8023630.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,13 @@
+ABCDEFGHIJKLMNO
+cw_super has hashCode(): true
+cw_super has super equals(): true
+cw_super has no getClass(): true
+cw_super has no wait(): true
+r_super has no run(): true
+r_super has hashCode(): true
+r_super has equals(): true
+r_super has no getClass(): true
+r_super has no wait(): true
+cw_super can access write through [] getter: true
+cw_super can access hashCode through [] getter: true
+cw_super can not access getClass through [] getter: true
--- a/nashorn/test/script/basic/NASHORN-397.js	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/test/script/basic/NASHORN-397.js	Fri Aug 23 16:44:02 2013 +0530
@@ -35,7 +35,10 @@
     fail("typeof(5).x is not 'number'");
 }
 
-if (typeof (java.lang.System.out) != 'object') {
+// It is function because PrintStream implements Closeable, which is
+// marked with @FunctionalInterface. Yes, this means calling a stream
+// like "stream()" closes it.
+if (typeof (java.lang.System.out) != 'function') {
     fail("typeof java.lang.System.out is not 'object'");
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/circular_proto.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8023368: Instance __proto__ property should exist and be writable.
+ *
+ * @test
+ * @run
+ */
+
+// check that we cannot create __proto__ cycle
+load("nashorn:mozilla_compat.js");
+
+var obj = {};
+var obj2 = Object.create(obj);
+
+// attempt to create __proto__ cycle
+try {
+    obj.__proto__ = obj2;
+    fail("Should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        fail("Expected TypeError, got " + e);
+    }
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/circular_proto.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,1 @@
+TypeError: Cannot create__proto__ cycle for [object Object]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/mirror_proto_assign.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8023368: Instance __proto__ property should exist and be writable.
+ *
+ * @test
+ * @run
+ */
+
+// check that Object.setPrototypeOf works for mirror objects as well.
+
+var global = loadWithNewGlobal({
+    name: "test",
+    script: "var obj = {}; this"
+});
+
+var proto = global.eval("({ foo: 323 })");
+
+Object.setPrototypeOf(global.obj, proto);
+
+function func(obj) {
+    // check proto inherited value
+    print("obj.foo = " + obj.foo);
+}
+
+func(global.obj);
+
+var newProto = global.eval("({ foo: 'hello' })");
+Object.setPrototypeOf(global.obj, newProto);
+
+func(global.obj);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/mirror_proto_assign.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,2 @@
+obj.foo = 323
+obj.foo = hello
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/nonextensible_proto_assign.js	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8023368: Instance __proto__ property should exist and be writable.
+ *
+ * @test
+ * @run
+ */
+
+load("nashorn:mozilla_compat.js")
+
+// check that we cannot assign to __proto__ of a non-extensible object
+try {
+    var obj = {}
+    Object.preventExtensions(obj);
+    obj.__proto__ = { };
+    fail("Should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        fail("Expected TypeError, got " + e);
+    }
+    print(e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/nonextensible_proto_assign.js.EXPECTED	Fri Aug 23 16:44:02 2013 +0530
@@ -0,0 +1,1 @@
+TypeError: Cannot set __proto__ of non-extensible [object Object]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java	Fri Aug 23 16:44:02 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/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java	Fri Aug 23 16:44:02 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/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Fri Aug 23 16:44:02 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,21 +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.SimpleScriptContext;
-import org.testng.Assert;
 import org.testng.annotations.Test;
 
 /**
@@ -239,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");
@@ -621,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();
@@ -715,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();
@@ -920,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();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java	Fri Aug 23 16:44:02 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);
+    }
+}
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Mon Aug 19 19:37:29 2013 +0530
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java	Fri Aug 23 16:44:02 2013 +0530
@@ -32,7 +32,10 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
+import javax.script.ScriptContext;
 import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import org.testng.annotations.Test;
 
@@ -196,4 +199,25 @@
         }
         fail("Cannot find nashorn factory!");
     }
+
+    @Test
+    public void globalPerEngineTest() throws ScriptException {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        final String[] options = new String[] { "--global-per-engine" };
+        final ScriptEngine e = fac.getScriptEngine(options);
+
+        e.eval("function foo() {}");
+
+        final ScriptContext newCtx = new SimpleScriptContext();
+        newCtx.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+        // all global definitions shared and so 'foo' should be
+        // visible in new Bindings as well.
+        assertTrue(e.eval("typeof foo", newCtx).equals("function"));
+
+        e.eval("function bar() {}", newCtx);
+
+        // bar should be visible in default context
+        assertTrue(e.eval("typeof bar").equals("function"));
+    }
 }