Merge
authorlana
Thu, 04 Jun 2015 18:49:16 -0700
changeset 30986 4b727de06e46
parent 30973 e6e0e1dd0dc7 (current diff)
parent 30985 2394ab6a64b2 (diff)
child 30987 17533ce1beb0
Merge
--- a/nashorn/README	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/README	Thu Jun 04 18:49:16 2015 -0700
@@ -72,14 +72,11 @@
 - Running tests
 
 Nashorn tests are TestNG based. Running tests requires downloading the
-TestNG library and placing its jar file into the lib subdirectory:
+TestNG library and placing its jar file into the test/lib subdirectory. This is
+done automatically when executing the "ant externals" command to get external
+test suites (see below).
 
-    # download and install TestNG
-    wget http://testng.org/testng-x.y.z.zip
-    unzip testng-x.y.z.zip
-    cp testng-x.y.z/testng-x.y.z.jar test/lib/testng.jar
-    
-After that, you can run the tests using:
+Once TestNG is properly installed, you can run the tests using:
     cd make
     ant clean test
     
--- a/nashorn/make/build.xml	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/make/build.xml	Thu Jun 04 18:49:16 2015 -0700
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
- Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2015, 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
@@ -396,7 +396,7 @@
   </target>
 
   <target name="check-testng" unless="testng.available">
-    <echo message="WARNING: TestNG not available, will not run tests. Please copy testng.jar under test/lib directory."/>
+    <echo message="WARNING: TestNG not available, will not run tests. Please copy testng.jar under ${test.lib} directory."/>
   </target>
 
   <!-- only to be invoked as dependency of "test" target -->
@@ -469,7 +469,7 @@
     </testng>
   </target>
 
-  <target name="test" depends="javadoc, test-pessimistic, test-optimistic"/>
+  <target name="test" depends="get-testng, javadoc, test-pessimistic, test-optimistic"/>
 
   <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <echo message="Running test suite in OPTIMISTIC mode..."/>
@@ -499,7 +499,7 @@
     <echo message="WARNING: Jemmy or JavaFX or TestNG not available, will not run tests. Please copy testng.jar, JemmyCore.jar, JemmyFX.jar, JemmyAWTInput.jar under test${file.separator}lib directory. And make sure you have jfxrt.jar in ${java.home}${file.separator}lib${file.separator}ext dir."/>
   </target>
 
-  <target name="testjfx" depends="jar, check-jemmy.jfx.testng, compile-test" if="jemmy.jfx.testng.available">
+  <target name="testjfx" depends="jar, get-testng, check-jemmy.jfx.testng, compile-test" if="jemmy.jfx.testng.available">
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
     </fileset>
@@ -527,7 +527,7 @@
     </testng>
   </target>
 
-  <target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="testmarkdown" depends="jar, get-testng, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
     </fileset>
@@ -546,7 +546,7 @@
     </testng>
   </target>
 
-  <target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="test262" depends="jar, get-testng, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
     </fileset>
@@ -570,7 +570,7 @@
 
   <target name="test262parallel" depends="test262-parallel"/>
 
-  <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="test262-parallel" depends="jar, get-testng, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <!-- use just build.test.classes.dir to avoid referring to TestNG -->
     <java classname="${parallel.test.runner}" dir="${basedir}" fork="true">
       <jvmarg line="${boot.class.path}"/>
@@ -589,7 +589,7 @@
 
   <target name="testparallel" depends="test-parallel"/>
 
-  <target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="test-parallel" depends="jar, get-testng, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
       <!-- use just build.test.classes.dir to avoid referring to TestNG -->
       <java classname="${parallel.test.runner}" dir="${basedir}"
         failonerror="true"
@@ -694,7 +694,7 @@
   </target>
 
   <!-- get all external test scripts -->
-  <target name="externals" depends="init, check-external-tests, get-test262, get-octane, get-sunspider">
+  <target name="externals" depends="init, check-external-tests, get-test262, get-octane, get-sunspider, get-testng">
     <!-- make external test dir -->
     <mkdir dir="${test.external.dir}"/>
 
@@ -719,8 +719,8 @@
 
     <!-- showdown -->
     <mkdir dir="${test.external.dir}/showdown"/>
-    <get src="https://raw.github.com/coreyti/showdown/master/src/showdown.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
-    <get src="https://raw.github.com/coreyti/showdown/master/src/extensions/table.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
+    <get src="https://raw.githubusercontent.com/showdownjs/showdown/0.5.4/src/showdown.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
+    <get src="https://raw.githubusercontent.com/showdownjs/showdown/0.5.4/src/extensions/table.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
 
   </target>
 
@@ -730,12 +730,20 @@
   <!-- run all perf tests -->
   <target name="perf" depends="externals, update-externals, sunspider, octane"/>
 
-  <!-- run all tests -->
-  <target name="exit-if-no-testng" depends="init, check-testng" unless="${testng.available}">
-     <fail message="Exiting.."/>
+  <!-- download and install testng.jar -->
+  <target name="get-testng" depends="prepare" unless="testng.available">
+    <get src="http://testng.org/testng-6.8.zip" dest="${test.lib}" skipexisting="true" ignoreerrors="true"/>
+    <unzip src="${test.lib}${file.separator}testng-6.8.zip" dest="${test.lib}">
+      <patternset>
+        <include name="testng-6.8/testng-6.8.jar"/>
+      </patternset>
+    </unzip>
+    <move file="${test.lib}${file.separator}testng-6.8${file.separator}testng-6.8.jar" tofile="${test.lib}${file.separator}testng.jar"/>
+    <delete dir="${test.lib}${file.separator}testng-6.8"/>
   </target>
 
-  <target name="alltests" depends="exit-if-no-testng, externals, update-externals, test, test262parallel, perf"/>
+  <!-- run all tests -->
+  <target name="alltests" depends="get-testng, externals, update-externals, test, test262parallel, testmarkdown, perf"/>
 
   <import file="build-benchmark.xml"/>
 
--- a/nashorn/make/project.properties	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/make/project.properties	Thu Jun 04 18:49:16 2015 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2015, 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
@@ -77,8 +77,11 @@
 # configuration for java flight recorder
 run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
 
+# test library location
+test.lib=${basedir}${file.separator}test${file.separator}lib
+
 # jars refererred
-file.reference.testng.jar=test/lib/testng.jar
+file.reference.testng.jar=${test.lib}${file.separator}testng.jar
 
 # Set testng verbose level
 # From TestNG docs: "the verbosity level (0 to 10 where 10 is most detailed)
@@ -243,9 +246,9 @@
     -fx \
     ${test.script.dir}${file.separator}jfx.js
 
-file.reference.jemmyfx.jar=test${file.separator}lib${file.separator}JemmyFX.jar
-file.reference.jemmycore.jar=test${file.separator}lib${file.separator}JemmyCore.jar
-file.reference.jemmyawtinput.jar=test${file.separator}lib${file.separator}JemmyAWTInput.jar
+file.reference.jemmyfx.jar=${test.lib}${file.separator}JemmyFX.jar
+file.reference.jemmycore.jar=${test.lib}${file.separator}JemmyCore.jar
+file.reference.jemmyawtinput.jar=${test.lib}${file.separator}JemmyAWTInput.jar
 file.reference.jfxrt.jar=${java.home}${file.separator}lib${file.separator}ext${file.separator}jfxrt.jar
 testjfx.run.test.classpath=\
     ${file.reference.jemmyfx.jar}${path.separator}\
--- a/nashorn/samples/find_nonfinals.js	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/samples/find_nonfinals.js	Thu Jun 04 18:49:16 2015 -0700
@@ -39,6 +39,7 @@
 
 var Class = Java.type("java.lang.Class");
 var System = Java.type("java.lang.System");
+var Thread = Java.type("java.lang.Thread");
 var File = Java.type("java.io.File");
 var JarFile = Java.type("java.util.jar.JarFile");
 var Modifier = Java.type("java.lang.reflect.Modifier");
@@ -58,6 +59,10 @@
 function analyzeClass(cls) {
     var methods = cls.getDeclaredMethods();
     for each (var method in methods) {
+        var methodModifiers = method.modifiers;
+        if (Modifier.isAbstract(methodModifiers) || Modifier.isNative(methodModifiers)) {
+            continue;
+        }
         // this requires -parameters option when compiling java sources
         var params = method.parameters;
         for each (var p in params) {
@@ -73,6 +78,8 @@
 }
 
 var jarFile = findNashorn();
+var ctxtLoader = Thread.currentThread().contextClassLoader;
+
 // load each class and use reflection to analyze each Class
 new JarFile(jarFile).stream().forEach(
     function(entry) {
@@ -80,8 +87,15 @@
         if (name.endsWith(".class")) {
             var clsName = name.substring(0, name.lastIndexOf('.class'));
             clsName = clsName.replace(/\//g, '.');
-            var cls = Class.forName(clsName);
-            analyzeClass(cls);
+            try {
+                // don't initialize to avoid for possible initialization errors 
+                var cls = Class.forName(clsName, false, ctxtLoader);
+                analyzeClass(cls);
+            } catch (e) {
+                // print exception and continue analysis for other classes
+                print("Failed to analyze " + clsName);
+                e.printStackTrace();
+            }
         }
     }
 )
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jun 04 18:49:16 2015 -0700
@@ -354,8 +354,7 @@
             }
         }, CREATE_GLOBAL_ACC_CTXT);
 
-        nashornContext.initGlobal(newGlobal, this);
-        newGlobal.setScriptContext(ctxt);
+        nashornContext.initGlobal(newGlobal, this, ctxt);
 
         return newGlobal;
     }
@@ -404,7 +403,7 @@
         return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
     }
 
-    private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+    private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
         final Global oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != ctxtGlobal);
         try {
@@ -413,8 +412,13 @@
             }
 
             final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
+            final ScriptContext oldCtxt = ctxtGlobal.getScriptContext();
             ctxtGlobal.setScriptContext(ctxt);
-            return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            try {
+                return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            } finally {
+                ctxtGlobal.setScriptContext(oldCtxt);
+            }
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
             throw new AssertionError("should not reach here");
@@ -425,7 +429,7 @@
         }
     }
 
-    private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
         if (script == null) {
             return null;
         }
@@ -436,8 +440,13 @@
                 Context.setGlobal(ctxtGlobal);
             }
 
+            final ScriptContext oldCtxt = ctxtGlobal.getScriptContext();
             ctxtGlobal.setScriptContext(ctxt);
-            return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            try {
+                return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            } finally {
+                ctxtGlobal.setScriptContext(oldCtxt);
+            }
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
             throw new AssertionError("should not reach here");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,6 +47,7 @@
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ECMAException;
+import jdk.nashorn.internal.runtime.JSONListAdapter;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -72,6 +73,7 @@
     private final ScriptObject sobj;
     private final Global  global;
     private final boolean strict;
+    private final boolean jsonCompatible;
 
     @Override
     public boolean equals(final Object other) {
@@ -110,9 +112,9 @@
             }
 
             if (sobj instanceof ScriptFunction) {
-                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-                final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz;
-                return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global);
+                final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args;
+                final Object self = globalChanged? wrapLikeMe(thiz, oldGlobal) : thiz;
+                return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)));
             }
 
             throw new RuntimeException("not a function: " + toString());
@@ -140,8 +142,8 @@
             }
 
             if (sobj instanceof ScriptFunction) {
-                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-                return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global);
+                final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args;
+                return wrapLikeMe(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)));
             }
 
             throw new RuntimeException("not a constructor: " + toString());
@@ -170,7 +172,7 @@
                                 return Context.getContext();
                             }
                         }, GET_CONTEXT_ACC_CTXT);
-                return wrap(context.eval(global, s, sobj, null, false), global);
+                return wrapLikeMe(context.eval(global, s, sobj, null, false));
             }
         });
     }
@@ -193,8 +195,8 @@
 
             final Object val = sobj.get(functionName);
             if (val instanceof ScriptFunction) {
-                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-                return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
+                final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args;
+                return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)));
             } else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
                 return ((JSObject)val).call(sobj, args);
             }
@@ -218,7 +220,7 @@
         Objects.requireNonNull(name);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.get(name), global);
+                return wrapLikeMe(sobj.get(name));
             }
         });
     }
@@ -227,7 +229,7 @@
     public Object getSlot(final int index) {
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.get(index), global);
+                return wrapLikeMe(sobj.get(index));
             }
         });
     }
@@ -368,7 +370,7 @@
 
                 while (iter.hasNext()) {
                     final String key   = iter.next();
-                    final Object value = translateUndefined(wrap(sobj.get(key), global));
+                    final Object value = translateUndefined(wrapLikeMe(sobj.get(key)));
                     entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value));
                 }
 
@@ -382,7 +384,7 @@
         checkKey(key);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return translateUndefined(wrap(sobj.get(key), global));
+                return translateUndefined(wrapLikeMe(sobj.get(key)));
             }
         });
     }
@@ -419,8 +421,8 @@
         final boolean globalChanged = (oldGlobal != global);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
-                return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global));
+                final Object modValue = globalChanged? wrapLikeMe(value, oldGlobal) : value;
+                return translateUndefined(wrapLikeMe(sobj.put(key, unwrap(modValue, global), strict)));
             }
         });
     }
@@ -434,7 +436,7 @@
             @Override public Object call() {
                 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
                     final Object value = entry.getValue();
-                    final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
+                    final Object modValue = globalChanged? wrapLikeMe(value, oldGlobal) : value;
                     final String key = entry.getKey();
                     checkKey(key);
                     sobj.set(key, unwrap(modValue, global), getCallSiteFlags());
@@ -449,7 +451,7 @@
         checkKey(key);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return translateUndefined(wrap(sobj.remove(key, strict), global));
+                return translateUndefined(wrapLikeMe(sobj.remove(key, strict)));
             }
         });
     }
@@ -486,7 +488,7 @@
                 final Iterator<Object> iter   = sobj.valueIterator();
 
                 while (iter.hasNext()) {
-                    values.add(translateUndefined(wrap(iter.next(), global)));
+                    values.add(translateUndefined(wrapLikeMe(iter.next())));
                 }
 
                 return Collections.unmodifiableList(values);
@@ -503,7 +505,7 @@
     public Object getProto() {
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.getProto(), global);
+                return wrapLikeMe(sobj.getProto());
             }
         });
     }
@@ -532,7 +534,7 @@
     public Object getOwnPropertyDescriptor(final String key) {
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.getOwnPropertyDescriptor(key), global);
+                return wrapLikeMe(sobj.getOwnPropertyDescriptor(key));
             }
         });
     }
@@ -661,16 +663,76 @@
      * @return wrapped/converted object
      */
     public static Object wrap(final Object obj, final Object homeGlobal) {
+        return wrap(obj, homeGlobal, false);
+    }
+
+    /**
+     * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. The
+     * created wrapper will implement the Java {@code List} interface if {@code obj} is a JavaScript
+     * {@code Array} object; this is compatible with Java JSON libraries expectations. Arrays retrieved through its
+     * properties (transitively) will also implement the list interface.
+     *
+     * @param obj object to be wrapped/converted
+     * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+     * @return wrapped/converted object
+     */
+    public static Object wrapAsJSONCompatible(final Object obj, final Object homeGlobal) {
+        return wrap(obj, homeGlobal, true);
+    }
+
+    /**
+     * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
+     *
+     * @param obj object to be wrapped/converted
+     * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+     * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if
+     * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively)
+     * will also implement the list interface.
+     * @return wrapped/converted object
+     */
+    private static Object wrap(final Object obj, final Object homeGlobal, final boolean jsonCompatible) {
         if(obj instanceof ScriptObject) {
-            return homeGlobal instanceof Global ? new ScriptObjectMirror((ScriptObject)obj, (Global)homeGlobal) : obj;
-        }
-        if(obj instanceof ConsString) {
+            if (!(homeGlobal instanceof Global)) {
+                return obj;
+            }
+            final ScriptObject sobj = (ScriptObject)obj;
+            final Global global = (Global)homeGlobal;
+            final ScriptObjectMirror mirror = new ScriptObjectMirror(sobj, global, jsonCompatible);
+            if (jsonCompatible && sobj.isArray()) {
+                return new JSONListAdapter(mirror, global);
+            }
+            return mirror;
+        } else if(obj instanceof ConsString) {
             return obj.toString();
+        } else if (jsonCompatible && obj instanceof ScriptObjectMirror) {
+            // Since choosing JSON compatible representation is an explicit decision on user's part, if we're asked to
+            // wrap a mirror that was not JSON compatible, explicitly create its compatible counterpart following the
+            // principle of least surprise.
+            return ((ScriptObjectMirror)obj).asJSONCompatible();
         }
         return obj;
     }
 
     /**
+     * Wraps the passed object with the same jsonCompatible flag as this mirror.
+     * @param obj the object
+     * @param homeGlobal the object's home global.
+     * @return a wrapper for the object.
+     */
+    private Object wrapLikeMe(final Object obj, final Object homeGlobal) {
+        return wrap(obj, homeGlobal, jsonCompatible);
+    }
+
+    /**
+     * Wraps the passed object with the same home global and jsonCompatible flag as this mirror.
+     * @param obj the object
+     * @return a wrapper for the object.
+     */
+    private Object wrapLikeMe(final Object obj) {
+        return wrapLikeMe(obj, global);
+    }
+
+    /**
      * Unwrap a script object mirror if needed.
      *
      * @param obj object to be unwrapped
@@ -681,6 +743,8 @@
         if (obj instanceof ScriptObjectMirror) {
             final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
             return (mirror.global == homeGlobal)? mirror.sobj : obj;
+        } else if (obj instanceof JSONListAdapter) {
+            return ((JSONListAdapter)obj).unwrap(homeGlobal);
         }
 
         return obj;
@@ -694,6 +758,10 @@
      * @return wrapped array
      */
     public static Object[] wrapArray(final Object[] args, final Object homeGlobal) {
+        return wrapArray(args, homeGlobal, false);
+    }
+
+    private static Object[] wrapArray(final Object[] args, final Object homeGlobal, final boolean jsonCompatible) {
         if (args == null || args.length == 0) {
             return args;
         }
@@ -701,12 +769,16 @@
         final Object[] newArgs = new Object[args.length];
         int index = 0;
         for (final Object obj : args) {
-            newArgs[index] = wrap(obj, homeGlobal);
+            newArgs[index] = wrap(obj, homeGlobal, jsonCompatible);
             index++;
         }
         return newArgs;
     }
 
+    private Object[] wrapArrayLikeMe(final Object[] args, final Object homeGlobal) {
+        return wrapArray(args, homeGlobal, jsonCompatible);
+    }
+
     /**
      * Unwrap an array of script object mirrors if needed.
      *
@@ -748,12 +820,17 @@
     // package-privates below this.
 
     ScriptObjectMirror(final ScriptObject sobj, final Global global) {
+        this(sobj, global, false);
+    }
+
+    private ScriptObjectMirror(final ScriptObject sobj, final Global global, final boolean jsonCompatible) {
         assert sobj != null : "ScriptObjectMirror on null!";
         assert global != null : "home Global is null";
 
         this.sobj = sobj;
         this.global = global;
         this.strict = global.isStrictContext();
+        this.jsonCompatible = jsonCompatible;
     }
 
     // accessors for script engine
@@ -838,4 +915,11 @@
             }
         });
     }
+
+    private ScriptObjectMirror asJSONCompatible() {
+        if (this.jsonCompatible) {
+            return this;
+        }
+        return new ScriptObjectMirror(sobj, global, true);
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ArrayAccessTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ArrayAccessTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitArrayAccess(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ArrayLiteralTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ArrayLiteralTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitArrayLiteral(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/AssignmentTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/AssignmentTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitAssignment(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/BinaryTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/BinaryTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitBinary(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/BlockTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/BlockTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitBlock(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/BreakTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/BreakTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitBreak(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CaseTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CaseTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitCase(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CatchTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CatchTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -63,7 +63,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitCatch(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompilationUnitTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompilationUnitTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -67,7 +67,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitCompilationUnit(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompoundAssignmentTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompoundAssignmentTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -57,7 +57,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitCompoundAssignment(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ConditionalExpressionTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ConditionalExpressionTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitConditionalExpression(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ContinueTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ContinueTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitContinue(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DebuggerTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DebuggerTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -38,7 +38,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitDebugger(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DoWhileLoopTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitDoWhileLoop(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/EmptyStatementTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/EmptyStatementTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -38,7 +38,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitEmptyStatement(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ErroneousTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ErroneousTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -38,7 +38,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitErroneous(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ExpressionStatementTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ExpressionStatementTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitExpressionStatement(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForInLoopTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -71,7 +71,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitForInLoop(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForLoopTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForLoopTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -72,7 +72,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitForLoop(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionCallTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionCallTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitFunctionCall(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitFunctionDeclaration(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionExpressionTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionExpressionTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -79,7 +79,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitFunctionExpression(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IdentifierTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IdentifierTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitIdentifier(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IfTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IfTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -63,7 +63,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitIf(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/InstanceOfTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/InstanceOfTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitInstanceOf(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/LabeledStatementTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/LabeledStatementTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitLabeledStatement(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/LineMapImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/LineMapImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -35,12 +35,12 @@
     }
 
     @Override
-    public long getLineNumber(long pos) {
+    public long getLineNumber(final long pos) {
         return source.getLine((int)pos);
     }
 
     @Override
-    public long getColumnNumber(long pos) {
+    public long getColumnNumber(final long pos) {
         return source.getColumn((int)pos);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/LiteralTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/LiteralTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitLiteral(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/MemberSelectTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/MemberSelectTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitMemberSelect(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/NewTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/NewTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
+    public <R, D> R accept(final TreeVisitor<R, D> visitor, final D data) {
         return visitor.visitNew(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ObjectLiteralTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ObjectLiteralTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitObjectLiteral(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/PropertyTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/PropertyTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -70,7 +70,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitProperty(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/RegExpLiteralTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/RegExpLiteralTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitRegExpLiteral(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ReturnTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ReturnTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitReturn(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SimpleTreeVisitorES5_1.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SimpleTreeVisitorES5_1.java	Thu Jun 04 18:49:16 2015 -0700
@@ -48,28 +48,28 @@
  */
 public class SimpleTreeVisitorES5_1<R, P> implements TreeVisitor<R, P> {
     @Override
-    public R visitAssignment(AssignmentTree node, P r) {
+    public R visitAssignment(final AssignmentTree node, final P r) {
         node.getVariable().accept(this, r);
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitCompoundAssignment(CompoundAssignmentTree node, P r) {
+    public R visitCompoundAssignment(final CompoundAssignmentTree node, final P r) {
         node.getVariable().accept(this, r);
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitBinary(BinaryTree node, P r) {
+    public R visitBinary(final BinaryTree node, final P r) {
         node.getLeftOperand().accept(this, r);
         node.getRightOperand().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitBlock(BlockTree node, P r) {
+    public R visitBlock(final BlockTree node, final P r) {
         node.getStatements().forEach((tree) -> {
             tree.accept(this, r);
         });
@@ -77,12 +77,12 @@
     }
 
     @Override
-    public R visitBreak(BreakTree node, P r) {
+    public R visitBreak(final BreakTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitCase(CaseTree node, P r) {
+    public R visitCase(final CaseTree node, final P r) {
         final Tree caseVal = node.getExpression();
         if (caseVal != null) {
             caseVal.accept(this, r);
@@ -95,7 +95,7 @@
     }
 
     @Override
-    public R visitCatch(CatchTree node, P r) {
+    public R visitCatch(final CatchTree node, final P r) {
         final Tree cond = node.getCondition();
         if (cond != null) {
             cond.accept(this, r);
@@ -106,7 +106,7 @@
     }
 
     @Override
-    public R visitConditionalExpression(ConditionalExpressionTree node, P r) {
+    public R visitConditionalExpression(final ConditionalExpressionTree node, final P r) {
         node.getCondition().accept(this, r);
         node.getTrueExpression().accept(this, r);
         node.getFalseExpression().accept(this, r);
@@ -114,35 +114,35 @@
     }
 
     @Override
-    public R visitContinue(ContinueTree node, P r) {
+    public R visitContinue(final ContinueTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitDebugger(DebuggerTree node, P r) {
+    public R visitDebugger(final DebuggerTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitDoWhileLoop(DoWhileLoopTree node, P r) {
+    public R visitDoWhileLoop(final DoWhileLoopTree node, final P r) {
         node.getStatement().accept(this, r);
         node.getCondition().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitErroneous(ErroneousTree node, P r) {
+    public R visitErroneous(final ErroneousTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitExpressionStatement(ExpressionStatementTree node, P r) {
+    public R visitExpressionStatement(final ExpressionStatementTree node, final P r) {
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitForLoop(ForLoopTree node, P r) {
+    public R visitForLoop(final ForLoopTree node, final P r) {
         final Tree init = node.getInitializer();
         if (init != null) {
             init.accept(this, r);
@@ -163,7 +163,7 @@
     }
 
     @Override
-    public R visitForInLoop(ForInLoopTree node, P r) {
+    public R visitForInLoop(final ForInLoopTree node, final P r) {
         node.getVariable().accept(this, r);
         node.getExpression().accept(this, r);
         final StatementTree stat = node.getStatement();
@@ -174,7 +174,7 @@
     }
 
     @Override
-    public R visitFunctionCall(FunctionCallTree node, P r) {
+    public R visitFunctionCall(final FunctionCallTree node, final P r) {
         node.getFunctionSelect().accept(this, r);
         node.getArguments().forEach((tree) -> {
             tree.accept(this, r);
@@ -183,7 +183,7 @@
     }
 
     @Override
-    public R visitFunctionDeclaration(FunctionDeclarationTree node, P r) {
+    public R visitFunctionDeclaration(final FunctionDeclarationTree node, final P r) {
         node.getParameters().forEach((tree) -> {
             tree.accept(this, r);
         });
@@ -192,7 +192,7 @@
     }
 
     @Override
-    public R visitFunctionExpression(FunctionExpressionTree node, P r) {
+    public R visitFunctionExpression(final FunctionExpressionTree node, final P r) {
         node.getParameters().forEach((tree) -> {
             tree.accept(this, r);
         });
@@ -201,12 +201,12 @@
     }
 
     @Override
-    public R visitIdentifier(IdentifierTree node, P r) {
+    public R visitIdentifier(final IdentifierTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitIf(IfTree node, P r) {
+    public R visitIf(final IfTree node, final P r) {
         node.getCondition().accept(this, r);
         node.getThenStatement().accept(this, r);
         final Tree elseStat = node.getElseStatement();
@@ -217,14 +217,14 @@
     }
 
     @Override
-    public R visitArrayAccess(ArrayAccessTree node, P r) {
+    public R visitArrayAccess(final ArrayAccessTree node, final P r) {
         node.getExpression().accept(this, r);
         node.getIndex().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitArrayLiteral(ArrayLiteralTree node, P r) {
+    public R visitArrayLiteral(final ArrayLiteralTree node, final P r) {
         node.getElements().stream().filter((tree) -> (tree != null)).forEach((tree) -> {
             tree.accept(this, r);
         });
@@ -232,24 +232,24 @@
     }
 
     @Override
-    public R visitLabeledStatement(LabeledStatementTree node, P r) {
+    public R visitLabeledStatement(final LabeledStatementTree node, final P r) {
         node.getStatement().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitLiteral(LiteralTree node, P r) {
+    public R visitLiteral(final LiteralTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitParenthesized(ParenthesizedTree node, P r) {
+    public R visitParenthesized(final ParenthesizedTree node, final P r) {
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitReturn(ReturnTree node, P r) {
+    public R visitReturn(final ReturnTree node, final P r) {
         final Tree retExpr = node.getExpression();
         if (retExpr != null) {
             retExpr.accept(this, r);
@@ -258,19 +258,19 @@
     }
 
     @Override
-    public R visitMemberSelect(MemberSelectTree node, P r) {
+    public R visitMemberSelect(final MemberSelectTree node, final P r) {
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitNew(NewTree node, P r) {
+    public R visitNew(final NewTree node, final P r) {
         node.getConstructorExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitObjectLiteral(ObjectLiteralTree node, P r) {
+    public R visitObjectLiteral(final ObjectLiteralTree node, final P r) {
         node.getProperties().forEach((tree) -> {
             tree.accept(this, r);
         });
@@ -278,7 +278,7 @@
     }
 
     @Override
-    public R visitProperty(PropertyTree node, P r) {
+    public R visitProperty(final PropertyTree node, final P r) {
         FunctionExpressionTree getter = node.getGetter();
         if (getter != null) {
             getter.accept(this, r);
@@ -301,17 +301,17 @@
     }
 
     @Override
-    public R visitRegExpLiteral(RegExpLiteralTree node, P r) {
+    public R visitRegExpLiteral(final RegExpLiteralTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitEmptyStatement(EmptyStatementTree node, P r) {
+    public R visitEmptyStatement(final EmptyStatementTree node, final P r) {
         return null;
     }
 
     @Override
-    public R visitSwitch(SwitchTree node, P r) {
+    public R visitSwitch(final SwitchTree node, final P r) {
         node.getExpression().accept(this, r);
         node.getCases().forEach((tree) -> {
             tree.accept(this, r);
@@ -320,13 +320,13 @@
     }
 
     @Override
-    public R visitThrow(ThrowTree node, P r) {
+    public R visitThrow(final ThrowTree node, final P r) {
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitCompilationUnit(CompilationUnitTree node, P r) {
+    public R visitCompilationUnit(final CompilationUnitTree node, final P r) {
         node.getSourceElements().forEach((tree) -> {
             tree.accept(this, r);
         });
@@ -334,7 +334,7 @@
     }
 
     @Override
-    public R visitTry(TryTree node, P r) {
+    public R visitTry(final TryTree node, final P r) {
         node.getBlock().accept(this, r);
         node.getCatches().forEach((tree) -> {
             tree.accept(this, r);
@@ -348,20 +348,20 @@
     }
 
     @Override
-    public R visitInstanceOf(InstanceOfTree node, P r) {
+    public R visitInstanceOf(final InstanceOfTree node, final P r) {
         node.getType().accept(this, r);
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitUnary(UnaryTree node, P r) {
+    public R visitUnary(final UnaryTree node, final P r) {
         node.getExpression().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitVariable(VariableTree node, P r) {
+    public R visitVariable(final VariableTree node, final P r) {
         if (node.getInitializer() != null) {
             node.getInitializer().accept(this, r);
         }
@@ -369,21 +369,21 @@
     }
 
     @Override
-    public R visitWhileLoop(WhileLoopTree node, P r) {
+    public R visitWhileLoop(final WhileLoopTree node, final P r) {
         node.getCondition().accept(this, r);
         node.getStatement().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitWith(WithTree node, P r) {
+    public R visitWith(final WithTree node, final P r) {
         node.getScope().accept(this, r);
         node.getStatement().accept(this, r);
         return null;
     }
 
     @Override
-    public R visitUnknown(Tree node, P r) {
+    public R visitUnknown(final Tree node, final P r) {
         // unknown in ECMAScript 5.1 edition
         throw new UnknownTreeException(node, r);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SwitchTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SwitchTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitSwitch(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ThrowTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ThrowTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitThrow(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitUnknown(this, data);
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TryTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TryTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -63,7 +63,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitTry(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/UnaryTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/UnaryTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitUnary(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/VariableTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/VariableTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitVariable(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WhileLoopTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitWhileLoop(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WithTreeImpl.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/WithTreeImpl.java	Thu Jun 04 18:49:16 2015 -0700
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public <R,D> R accept(TreeVisitor<R,D> visitor, D data) {
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitWith(this, data);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Jun 04 18:49:16 2015 -0700
@@ -363,7 +363,7 @@
             //partial code generation
             final FunctionNode newFunctionNode = transformFunction(fn, new ReplaceCompileUnits() {
                 @Override
-                CompileUnit getReplacement(CompileUnit original) {
+                CompileUnit getReplacement(final CompileUnit original) {
                     return map.get(original);
                 }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java	Thu Jun 04 18:49:16 2015 -0700
@@ -567,7 +567,7 @@
         final MessageDigest digest = MessageDigest.getInstance("SHA-1");
         Files.walk(nashorn).forEach(new Consumer<Path>() {
             @Override
-            public void accept(Path p) {
+            public void accept(final Path p) {
                 // take only the .class resources.
                 if (Files.isRegularFile(p) && p.toString().endsWith(".class")) {
                     try {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Thu Jun 04 18:49:16 2015 -0700
@@ -102,7 +102,7 @@
     public SplitIntoFunctions(final Compiler compiler) {
         super(new BlockLexicalContext() {
             @Override
-            protected Block afterSetStatements(Block block) {
+            protected Block afterSetStatements(final Block block) {
                 for(Statement stmt: block.getStatements()) {
                     assert !(stmt instanceof SplitNode);
                 }
@@ -305,7 +305,7 @@
     }
 
     @Override
-    public boolean enterVarNode(VarNode varNode) {
+    public boolean enterVarNode(final VarNode varNode) {
         if (!inSplitNode()) {
             return super.enterVarNode(varNode);
         }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitReturn.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitReturn.java	Thu Jun 04 18:49:16 2015 -0700
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public void toString(StringBuilder sb, boolean printType) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append(":splitreturn;");
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java	Thu Jun 04 18:49:16 2015 -0700
@@ -122,7 +122,7 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final LexicalContext lc, NodeVisitor<? extends LexicalContext> visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTryNode(this)) {
             // Need to do finallybody first for termination analysis. TODO still necessary?
             final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java	Thu Jun 04 18:49:16 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, 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
@@ -1109,7 +1109,7 @@
                 }
                 final String ex = catches.get(node);
                 if (ex != null) {
-                    sb.append("*** CATCH: ").append(ex).append(" ***\n");
+                    sb.append("*** CATCH: ").append(ex).append(" ***\\l");
                 }
                 sb.append(c);
                 sb.append("\"]\n");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Thu Jun 04 18:49:16 2015 -0700
@@ -928,9 +928,11 @@
     private final Context context;
 
     // current ScriptContext to use - can be null.
-    private ScriptContext scontext;
+    private ThreadLocal<ScriptContext> scontext;
     // current ScriptEngine associated - can be null.
     private ScriptEngine engine;
+    // initial ScriptContext - can be null
+    private volatile ScriptContext initscontext;
 
     // ES6 global lexical scope.
     private final LexicalScope lexicalScope;
@@ -940,10 +942,25 @@
 
     /**
      * Set the current script context
-     * @param scontext script context
+     * @param ctxt script context
      */
-    public void setScriptContext(final ScriptContext scontext) {
-        this.scontext = scontext;
+    public void setScriptContext(final ScriptContext ctxt) {
+        assert scontext != null;
+        scontext.set(ctxt);
+    }
+
+    /**
+     * Get the current script context
+     * @return current script context
+     */
+    public ScriptContext getScriptContext() {
+        assert scontext != null;
+        return scontext.get();
+    }
+
+    private ScriptContext currentContext() {
+        final ScriptContext sc = scontext != null? scontext.get() : null;
+        return sc == null? initscontext : sc;
     }
 
     @Override
@@ -1056,14 +1073,19 @@
      * of the global scope object.
      *
      * @param eng ScriptEngine to initialize
+     * @param ctxt ScriptContext to initialize
      */
-    public void initBuiltinObjects(final ScriptEngine eng) {
+    public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) {
         if (this.builtinObject != null) {
             // already initialized, just return
             return;
         }
 
         this.engine = eng;
+        this.initscontext = ctxt;
+        if (this.engine != null) {
+            this.scontext = new ThreadLocal<>();
+        }
         init(eng);
     }
 
@@ -1392,7 +1414,7 @@
      */
     public static Object __noSuchProperty__(final Object self, final Object name) {
         final Global global = Global.instance();
-        final ScriptContext sctxt = global.scontext;
+        final ScriptContext sctxt = global.currentContext();
         final String nameStr = name.toString();
 
         if (sctxt != null) {
@@ -2737,8 +2759,9 @@
     }
 
     private Object printImpl(final boolean newLine, final Object... objects) {
+        final ScriptContext sc = currentContext();
         @SuppressWarnings("resource")
-        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
+        final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
         final StringBuilder sb = new StringBuilder();
 
         for (final Object obj : objects) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java	Thu Jun 04 18:49:16 2015 -0700
@@ -33,10 +33,12 @@
 import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
+import java.util.Map;
 import java.util.Queue;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -656,4 +658,20 @@
     public static Object _super(final Object self, final Object adapter) {
         return Bootstrap.createSuperAdapter(adapter);
     }
+
+    /**
+     * Returns an object that is compatible with Java JSON libraries expectations; namely, that if it itself, or any
+     * object transitively reachable through it is a JavaScript array, then such objects will be exposed as
+     * {@link JSObject} that also implements the {@link List} interface for exposing the array elements. An explicit
+     * API is required as otherwise Nashorn exposes all objects externally as {@link JSObject}s that also implement the
+     * {@link Map} interface instead. By using this method, arrays will be exposed as {@link List}s and all other
+     * objects as {@link Map}s.
+     * @param self not used
+     * @param obj the object to be exposed in a Java JSON library compatible manner.
+     * @return a wrapper around the object that will enforce Java JSON library compatible exposure.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object asJSONCompatible(final Object self, final Object obj) {
+        return ScriptObjectMirror.wrapAsJSONCompatible(obj, Context.getGlobal());
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Thu Jun 04 18:49:16 2015 -0700
@@ -528,8 +528,9 @@
 
         final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
         final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
-        // We must match all incoming parameters, except "this". Starting from 1 to skip "this".
-        for(int i = 1; i < minParams; ++i) {
+        // We must match all incoming parameters, including "this". "this" will usually be Object, but there
+        // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
+        for(int i = 0; i < minParams; ++i) {
             final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
             final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
             if(!fnType.isEquivalentTo(csType)) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Jun 04 18:49:16 2015 -0700
@@ -66,6 +66,7 @@
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.logging.Level;
+import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
@@ -1095,16 +1096,17 @@
      *
      * @param global the global
      * @param engine the associated ScriptEngine instance, can be null
+     * @param ctxt the initial ScriptContext, can be null
      * @return the initialized global scope object.
      */
-    public Global initGlobal(final Global global, final ScriptEngine engine) {
+    public Global initGlobal(final Global global, final ScriptEngine engine, final ScriptContext ctxt) {
         // Need only minimal global object, if we are just compiling.
         if (!env._compile_only) {
             final Global oldGlobal = Context.getGlobal();
             try {
                 Context.setGlobal(global);
                 // initialize global scope with builtin global objects
-                global.initBuiltinObjects(engine);
+                global.initBuiltinObjects(engine, ctxt);
             } finally {
                 Context.setGlobal(oldGlobal);
             }
@@ -1120,7 +1122,7 @@
      * @return the initialized global scope object.
      */
     public Global initGlobal(final Global global) {
-        return initGlobal(global, null);
+        return initGlobal(global, null, null);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONListAdapter.java	Thu Jun 04 18:49:16 2015 -0700
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015, 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;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.objects.Global;
+
+/**
+ * A {@link ListAdapter} that also implements {@link JSObject}. Named {@code JSONListAdapter} as it is used as a
+ * {@code JSObject} implementing the {@link List} interface, which is the expected interface to be implemented by
+ * JSON-parsed arrays when they are handled in Java. We aren't implementing {@link JSObject} on {@link ListAdapter}
+ * directly since that'd have implications for other uses of list adapter (e.g. interferences of JSObject default
+ * value calculation vs. List's {@code toString()} etc.)
+ */
+public final class JSONListAdapter extends ListAdapter implements JSObject {
+    /**
+     * Creates a new JSON list adapter.
+     * @param obj the underlying object being exposed as a list.
+     * @param global the home global of the underlying object.
+     */
+    public JSONListAdapter(final JSObject obj, final Global global) {
+        super(obj, global);
+    }
+
+    /**
+     * Unwraps this adapter into its underlying non-JSObject representative.
+     * @param homeGlobal the home global for unwrapping
+     * @return either the unwrapped object or this if it should not be unwrapped in the specified global.
+     */
+    public Object unwrap(final Object homeGlobal) {
+        final Object unwrapped = ScriptObjectMirror.unwrap(obj, homeGlobal);
+        return unwrapped != obj ? unwrapped : this;
+    }
+
+    @Override
+    public Object call(final Object thiz, final Object... args) {
+        return obj.call(thiz, args);
+    }
+
+    @Override
+    public Object newObject(final Object... args) {
+        return obj.newObject(args);
+    }
+
+    @Override
+    public Object eval(final String s) {
+        return obj.eval(s);
+    }
+
+    @Override
+    public Object getMember(final String name) {
+        return obj.getMember(name);
+    }
+
+    @Override
+    public Object getSlot(final int index) {
+        return obj.getSlot(index);
+    }
+
+    @Override
+    public boolean hasMember(final String name) {
+        return obj.hasMember(name);
+    }
+
+    @Override
+    public boolean hasSlot(final int slot) {
+        return obj.hasSlot(slot);
+    }
+
+    @Override
+    public void removeMember(final String name) {
+        obj.removeMember(name);
+    }
+
+    @Override
+    public void setMember(final String name, final Object value) {
+        obj.setMember(name, value);
+    }
+
+    @Override
+    public void setSlot(final int index, final Object value) {
+        obj.setSlot(index, value);
+    }
+
+    @Override
+    public Set<String> keySet() {
+        return obj.keySet();
+    }
+
+    @Override
+    public Collection<Object> values() {
+        return obj.values();
+    }
+
+    @Override
+    public boolean isInstance(final Object instance) {
+        return obj.isInstance(instance);
+    }
+
+    @Override
+    public boolean isInstanceOf(final Object clazz) {
+        return obj.isInstanceOf(clazz);
+    }
+
+    @Override
+    public String getClassName() {
+        return obj.getClassName();
+    }
+
+    @Override
+    public boolean isFunction() {
+        return obj.isFunction();
+    }
+
+    @Override
+    public boolean isStrictFunction() {
+        return obj.isStrictFunction();
+    }
+
+    @Override
+    public boolean isArray() {
+        return obj.isArray();
+    }
+
+    @Override @Deprecated
+    public double toNumber() {
+        return obj.toNumber();
+    }
+
+    @Override
+    public Object getDefaultValue(Class<?> hint) throws UnsupportedOperationException {
+        return obj.getDefaultValue(hint);
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ListAdapter.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ListAdapter.java	Thu Jun 04 18:49:16 2015 -0700
@@ -52,7 +52,7 @@
  * operations respectively, while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and
  * {@code pop}.
  */
-public final class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
+public class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
     // Invoker creator for methods that add to the start or end of the list: PUSH and UNSHIFT. Takes fn, this, and value, returns void.
     private static final Callable<MethodHandle> ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, Object.class);
 
@@ -78,21 +78,17 @@
     private static final Callable<MethodHandle> SPLICE_REMOVE_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class);
 
     /** wrapped object */
-    private final JSObject obj;
+    final JSObject obj;
     private final Global global;
 
     // allow subclasses only in this package
-    ListAdapter(final JSObject obj) {
-        this.obj = obj;
-        this.global = getGlobalNonNull();
-    }
+    ListAdapter(final JSObject obj, final Global global) {
+        if (global == null) {
+            throw new IllegalStateException(ECMAErrors.getMessage("list.adapter.null.global"));
+        }
 
-    private static Global getGlobalNonNull() {
-        final Global global = Context.getGlobal();
-        if (global != null) {
-            return global;
-        }
-        throw new IllegalStateException(ECMAErrors.getMessage("list.adapter.null.global"));
+        this.obj = obj;
+        this.global = global;
     }
 
     /**
@@ -102,12 +98,13 @@
      * @return A ListAdapter wrapper object
      */
     public static ListAdapter create(final Object obj) {
-        return new ListAdapter(getJSObject(obj));
+        final Global global = Context.getGlobal();
+        return new ListAdapter(getJSObject(obj, global), global);
     }
 
-    private static JSObject getJSObject(final Object obj) {
+    private static JSObject getJSObject(final Object obj, final Global global) {
         if (obj instanceof ScriptObject) {
-            return (JSObject)ScriptObjectMirror.wrap(obj, Context.getGlobal());
+            return (JSObject)ScriptObjectMirror.wrap(obj, global);
         } else if (obj instanceof JSObject) {
             return (JSObject)obj;
         }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Jun 04 18:49:16 2015 -0700
@@ -137,7 +137,7 @@
         final ScriptObject global = Context.getGlobal();
 
         // Set up initial process.
-        final ProcessBuilder processBuilder = new ProcessBuilder(tokenizeCommandLine(JSType.toString(string)));
+        final ProcessBuilder processBuilder = new ProcessBuilder(tokenizeString(JSType.toString(string)));
 
         // Current ENV property state.
         final Object env = global.get(ENV_NAME);
@@ -237,23 +237,22 @@
     }
 
     /**
-     * Break an exec string into tokens, honoring quoted arguments and escaped
-     * spaces.
+     * Break a string into tokens, honoring quoted arguments and escaped spaces.
      *
-     * @param execString a {@link String} with the command line to execute.
+     * @param str a {@link String} to tokenize.
      * @return a {@link List} of {@link String}s representing the tokens that
-     * constitute the command line.
+     * constitute the string.
      * @throws IOException in case {@link StreamTokenizer#nextToken()} raises it.
      */
-    public static List<String> tokenizeCommandLine(final String execString) throws IOException {
-        final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(execString));
+    public static List<String> tokenizeString(final String str) throws IOException {
+        final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(str));
         tokenizer.resetSyntax();
         tokenizer.wordChars(0, 255);
         tokenizer.whitespaceChars(0, ' ');
         tokenizer.commentChar('#');
         tokenizer.quoteChar('"');
         tokenizer.quoteChar('\'');
-        final List<String> cmdList = new ArrayList<>();
+        final List<String> tokenList = new ArrayList<>();
         final StringBuilder toAppend = new StringBuilder();
         while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
             final String s = tokenizer.sval;
@@ -265,13 +264,13 @@
                 // omit trailing \, append space instead
                 toAppend.append(s.substring(0, s.length() - 1)).append(' ');
             } else {
-                cmdList.add(toAppend.append(s).toString());
+                tokenList.add(toAppend.append(s).toString());
                 toAppend.setLength(0);
             }
         }
         if (toAppend.length() != 0) {
-            cmdList.add(toAppend.toString());
+            tokenList.add(toAppend.toString());
         }
-        return cmdList;
+        return tokenList;
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java	Thu Jun 04 18:49:16 2015 -0700
@@ -934,14 +934,16 @@
             start = 2;
             cs = StandardCharsets.UTF_16BE;
         } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) {
-            start = 2;
-            cs = StandardCharsets.UTF_16LE;
+            if (bytes.length > 3 && bytes[2] == 0 && bytes[3] == 0) {
+                start = 4;
+                cs = Charset.forName("UTF-32LE");
+            } else {
+                start = 2;
+                cs = StandardCharsets.UTF_16LE;
+            }
         } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) {
             start = 3;
             cs = StandardCharsets.UTF_8;
-        } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) {
-            start = 4;
-            cs = Charset.forName("UTF-32LE");
         } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) {
             start = 4;
             cs = Charset.forName("UTF-32BE");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Thu Jun 04 18:49:16 2015 -0700
@@ -246,7 +246,7 @@
         }
 
         @Override
-        public MethodHandle filterInternalObjects(MethodHandle target) {
+        public MethodHandle filterInternalObjects(final MethodHandle target) {
             return linkerServices.filterInternalObjects(target);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/ProblemList.txt	Thu Jun 04 18:49:16 2015 -0700
@@ -0,0 +1,26 @@
+###########################################################################
+#
+# Copyright (c) 2015, 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.
+#
+###########################################################################
+
+# No nashorn tests are on the problem list.
--- a/nashorn/test/TEST.ROOT	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/test/TEST.ROOT	Thu Jun 04 18:49:16 2015 -0700
@@ -1,6 +1,11 @@
 # This file identifies the root of the test-suite hierarchy.
 # It also contains test-suite configuration information.
-# DO NOT EDIT without first contacting jdk-regtest@sun.com.
 
 # The list of keywords supported in the entire test suite
-keys=2d dnd i18n
+keys=intermittent randomness
+
+# Group definitions
+groups=TEST.groups
+
+# Minimum jtreg version
+requiredVersion=4.1 b11
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/TEST.groups	Thu Jun 04 18:49:16 2015 -0700
@@ -0,0 +1,29 @@
+#  Copyright (c) 2015, 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.
+#
+
+# Tiered testing definitions
+
+# No nashorn tests are tier 1.
+tier1 =
+
+# All nashorn tests are tier 2.
+tier2 = src
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066220.js	Thu Jun 04 18:49:16 2015 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 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-8066220: Fuzzing bug: MethodHandle bug (Object,Object) != (boolean)Object
+ *
+ * @test
+ * @run
+ */
+
+
+function f() {}
+// Call f with primitive this first, then as constructor
+f.call(1);
+new f();
+
+// Same as above in strict mode
+eval('"use strict"; function e() { print(typeof this); } e.call(1); new e();');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066220.js.EXPECTED	Thu Jun 04 18:49:16 2015 -0700
@@ -0,0 +1,2 @@
+number
+object
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/JSONCompatibleTest.java	Thu Jun 04 18:49:16 2015 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class JSONCompatibleTest {
+
+    /**
+     * Wrap a top-level array as a list.
+     */
+    @Test
+    public void testWrapArray() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible([1, 2, 3])");
+        assertEquals(asList(val), Arrays.asList(1, 2, 3));
+    }
+
+    /**
+     * Wrap an embedded array as a list.
+     */
+    @Test
+    public void testWrapObjectWithArray() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible({x: [1, 2, 3]})");
+        assertEquals(asList(asMap(val).get("x")), Arrays.asList(1, 2, 3));
+    }
+
+    /**
+     * Check it all works transitively several more levels down.
+     */
+    @Test
+    public void testDeepWrapping() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
+        final Map<String, Object> root = asMap(val);
+        final List<Object> x = asList(root.get("x"));
+        assertEquals(x.get(0), 1);
+        final Map<String, Object> x1 = asMap(x.get(1));
+        final List<Object> y = asList(x1.get("y"));
+        assertEquals(y.get(0), 2);
+        final Map<String, Object> y1 = asMap(y.get(1));
+        assertEquals(asList(y1.get("z")), Arrays.asList(3));
+        assertEquals(asList(x.get(2)), Arrays.asList(4, 5));
+    }
+
+    /**
+     * Ensure that the old behaviour (every object is a Map) is unchanged.
+     */
+    @Test
+    public void testNonWrapping() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
+        final Map<String, Object> root = asMap(val);
+        final Map<String, Object> x = asMap(root.get("x"));
+        assertEquals(x.get("0"), 1);
+        final Map<String, Object> x1 = asMap(x.get("1"));
+        final Map<String, Object> y = asMap(x1.get("y"));
+        assertEquals(y.get("0"), 2);
+        final Map<String, Object> y1 = asMap(y.get("1"));
+        final Map<String, Object> z = asMap(y1.get("z"));
+        assertEquals(z.get("0"), 3);
+        final Map<String, Object> x2 = asMap(x.get("2"));
+        assertEquals(x2.get("0"), 4);
+        assertEquals(x2.get("1"), 5);
+    }
+
+    private static List<Object> asList(final Object obj) {
+        assertJSObject(obj);
+        Assert.assertTrue(obj instanceof List);
+        return (List)obj;
+    }
+
+    private static Map<String, Object> asMap(final Object obj) {
+        assertJSObject(obj);
+        Assert.assertTrue(obj instanceof Map);
+        return (Map)obj;
+    }
+
+    private static void assertJSObject(final Object obj) {
+        assertTrue(obj instanceof JSObject);
+    }
+}
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java	Thu Jun 04 18:49:16 2015 -0700
@@ -31,10 +31,12 @@
 import javax.script.Bindings;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 import javax.script.SimpleBindings;
 import javax.script.SimpleScriptContext;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.api.scripting.URLReader;
 import org.testng.Assert;
@@ -778,4 +780,44 @@
             throw new AssertionError("should have thrown NPE");
         } catch (NullPointerException npe5) {}
     }
+
+    public static class RecursiveEval {
+        private final ScriptEngineFactory factory = new NashornScriptEngineFactory();
+        private final ScriptEngine engine = factory.getScriptEngine();
+        private final Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
+
+        public void program() throws ScriptException {
+            ScriptContext sc = new SimpleScriptContext();
+            Bindings global = new SimpleBindings();
+            sc.setBindings(global, ScriptContext.GLOBAL_SCOPE);
+            sc.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
+            global.put("text", "programText");
+            String value = engine.eval("text", sc).toString();
+            Assert.assertEquals(value, "programText");
+            engine.put("program", this);
+            engine.eval("program.method()");
+            // eval again from here!
+            value = engine.eval("text", sc).toString();
+            Assert.assertEquals(value, "programText");
+        }
+
+        public void method() throws ScriptException {
+            // a context with a new global bindings, same engine bindings
+            final ScriptContext sc = new SimpleScriptContext();
+            final Bindings global = new SimpleBindings();
+            sc.setBindings(global, ScriptContext.GLOBAL_SCOPE);
+            sc.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
+            global.put("text", "methodText");
+            String value = engine.eval("text", sc).toString();
+            Assert.assertEquals(value, "methodText");
+        }
+    }
+
+    // @bug 8081609: engine.eval call from a java method which
+    // was called from a previous engine.eval results in wrong
+    // ScriptContext being used.
+    @Test
+    public void recursiveEvalCallScriptContextTest() throws ScriptException {
+        new RecursiveEval().program();
+    }
 }
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Thu Jun 04 09:31:52 2015 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Thu Jun 04 18:49:16 2015 -0700
@@ -225,7 +225,7 @@
         boolean explicitOptimistic = false;
 
         String allContent = new String(Files.readAllBytes(testFile));
-        Iterator<String> scanner = ScriptingFunctions.tokenizeCommandLine(allContent).iterator();
+        Iterator<String> scanner = ScriptingFunctions.tokenizeString(allContent).iterator();
         while (scanner.hasNext()) {
             // TODO: Scan for /ref=file qualifiers, etc, to determine run
             // behavior