changeset 40:8b3cc4ad1810

8006635: Reduce access levels as much as possible Reviewed-by: jlaskey, lagergren, attila
author sundar
date Mon, 21 Jan 2013 21:17:38 +0530
parents 0cee498b330d
children 935dcec38e9a
files src/jdk/nashorn/api/scripting/NashornScriptEngine.java src/jdk/nashorn/api/scripting/ScriptObjectMirror.java src/jdk/nashorn/internal/codegen/Compiler.java src/jdk/nashorn/internal/ir/Symbol.java src/jdk/nashorn/internal/ir/debug/JSONWriter.java src/jdk/nashorn/internal/objects/Global.java src/jdk/nashorn/internal/objects/NativeArray.java src/jdk/nashorn/internal/objects/NativeDebug.java src/jdk/nashorn/internal/objects/NativeJava.java src/jdk/nashorn/internal/runtime/Context.java src/jdk/nashorn/internal/runtime/DebugLogger.java src/jdk/nashorn/internal/runtime/ECMAException.java src/jdk/nashorn/internal/runtime/OptionsObject.java src/jdk/nashorn/internal/runtime/ScriptObject.java src/jdk/nashorn/internal/runtime/StructureLoader.java src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java src/jdk/nashorn/tools/Shell.java test/src/jdk/nashorn/internal/access/BooleanAccessTest.java test/src/jdk/nashorn/internal/codegen/CompilerTest.java test/src/jdk/nashorn/internal/parser/ParserTest.java test/src/jdk/nashorn/internal/runtime/ContextTest.java test/src/jdk/nashorn/internal/runtime/JSTypeTest.java test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
diffstat 25 files changed, 330 insertions(+), 144 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Mon Jan 21 21:17:38 2013 +0530
@@ -86,13 +86,22 @@
         options.process(args);
 
         // throw ParseException on first error from script
-        final ErrorManager errors = new Context.ThrowErrorManager();
+        final ErrorManager errMgr = new Context.ThrowErrorManager();
+        // application loader for the context
+        ClassLoader tmp;
+        try {
+            tmp = Thread.currentThread().getContextClassLoader();
+        } catch (final SecurityException se) {
+            tmp = null;
+        }
+        final ClassLoader appLoader = tmp;
+
         // create new Nashorn Context
         this.nashornContext = AccessController.doPrivileged(new PrivilegedAction<Context>() {
             @Override
             public Context run() {
                 try {
-                    return new Context(options, errors);
+                    return new Context(options, errMgr, appLoader);
                 } catch (final RuntimeException e) {
                     if (Context.DEBUG) {
                         e.printStackTrace();
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Mon Jan 21 21:17:38 2013 +0530
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.api.scripting;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -141,7 +143,14 @@
         return inGlobal(new Callable<Object>() {
             @Override
             public Object call() {
-                return wrap(global.getContext().eval(global, s, null, null, false), global);
+                final Context context = AccessController.doPrivileged(
+                        new PrivilegedAction<Context>() {
+                            @Override
+                            public Context run() {
+                                return Context.getContext();
+                            }
+                        });
+                return wrap(context.eval(global, s, null, null, false), global);
             }
         });
     }
@@ -178,7 +187,7 @@
     public void setSlot(final int index, final Object value) {
         inGlobal(new Callable<Void>() {
             @Override public Void call() {
-                sobj.set(index, unwrap(value, global), global.getContext()._strict);
+                sobj.set(index, unwrap(value, global), global.isStrictContext());
                 return null;
             }
         });
@@ -275,7 +284,7 @@
 
     @Override
     public void putAll(final Map<? extends String, ? extends Object> map) {
-        final boolean strict = sobj.getContext()._strict;
+        final boolean strict = sobj.isStrictContext();
         inGlobal(new Callable<Object>() {
             @Override public Object call() {
                 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
--- a/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Jan 21 21:17:38 2013 +0530
@@ -186,7 +186,7 @@
      * @return compiler instance
      */
     public static Compiler compiler(final Source source, final Context context) {
-        return Compiler.compiler(source, context, context.getErrors(), context._strict);
+        return Compiler.compiler(source, context, context.getErrorManager(), context._strict);
     }
 
     /**
--- a/src/jdk/nashorn/internal/ir/Symbol.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/ir/Symbol.java	Mon Jan 21 21:17:38 2013 +0530
@@ -605,7 +605,7 @@
     private void trace(final String desc) {
         if (TRACE_SYMBOL != null && TRACE_SYMBOL.equals(name)) {
             Context.err("SYMBOL: '" + name + "' " + desc);
-            new Throwable().printStackTrace(Context.getContext().getErr());
+            new Throwable().printStackTrace(Context.getCurrentErr());
         }
     }
 }
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Mon Jan 21 21:17:38 2013 +0530
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.ir.debug;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Arrays;
 import java.util.List;
 import jdk.nashorn.internal.codegen.Compiler;
@@ -86,7 +88,13 @@
      */
     public static String parse(final String code, final String name, final boolean includeLoc) {
         final ScriptObject global     = Context.getGlobal();
-        final Context      context    = global.getContext();
+        final Context      context    = AccessController.doPrivileged(
+                new PrivilegedAction<Context>() {
+                    @Override
+                    public Context run() {
+                        return Context.getContext();
+                    }
+                });
         final Compiler     compiler   = Compiler.compiler(new Source(name, code), context, new Context.ThrowErrorManager(), context._strict);
         final Parser       parser     = new Parser(compiler, context._strict);
         final JSONWriter   jsonWriter = new JSONWriter(includeLoc);
--- a/src/jdk/nashorn/internal/objects/Global.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/objects/Global.java	Mon Jan 21 21:17:38 2013 +0530
@@ -46,6 +46,7 @@
 import jdk.nashorn.internal.runtime.GlobalObject;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.NativeJavaPackage;
+import jdk.nashorn.internal.runtime.OptionsObject;
 import jdk.nashorn.internal.runtime.PropertyDescriptor;
 import jdk.nashorn.internal.runtime.Scope;
 import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -365,7 +366,7 @@
      *
      * @return the context
      */
-    public static Context getThisContext() {
+    static Context getThisContext() {
         return instance().getContext();
     }
 
@@ -374,7 +375,7 @@
      *
      * @return true if strict mode enabled in {@link Global#getThisContext()}
      */
-    public static boolean isStrict() {
+    static boolean isStrict() {
         return getThisContext()._strict;
     }
 
@@ -387,13 +388,7 @@
             return;
         }
 
-        final ScriptObject oldGlobal = Context.getGlobal();
-        Context.setGlobal(this);
-        try {
-            init();
-        } finally {
-            Context.setGlobal(oldGlobal);
-        }
+        init();
     }
 
     @Override
@@ -650,9 +645,10 @@
         if (!(str instanceof String || str instanceof ConsString)) {
             return str;
         }
-        final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : Global.instance();
+        final Global global = Global.instance();
+        final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
 
-        return Global.getThisContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
+        return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
     }
 
     /**
@@ -690,8 +686,9 @@
      * @throws IOException if source could not be read
      */
     public static Object load(final Object self, final Object source) throws IOException {
-        final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : Global.instance();
-        return getThisContext().load(scope, source);
+        final Global global = Global.instance();
+        final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+        return global.getContext().load(scope, source);
     }
 
     ScriptObject getFunctionPrototype() {
@@ -1302,6 +1299,8 @@
     }
 
     private void init() {
+        assert Context.getGlobal() == this : "this global is not set as current";
+
         // initialize Function and Object constructor
         initFunctionAndObject();
 
@@ -1367,7 +1366,7 @@
             initScripting();
         }
 
-        if (Context.DEBUG) {
+        if (Context.DEBUG && System.getSecurityManager() == null) {
             initDebug();
         }
 
@@ -1460,8 +1459,7 @@
         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
-        // expose current Context to access command line options
-        value = this.getContext();
+        value = new OptionsObject(this.getContext());
         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, value);
     }
 
--- a/src/jdk/nashorn/internal/objects/NativeArray.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Mon Jan 21 21:17:38 2013 +0530
@@ -603,7 +603,7 @@
     public static Object pop(final Object self) {
         try {
             final ScriptObject sobj = (ScriptObject)self;
-            final boolean strict    = sobj.getContext()._strict;
+            final boolean strict    = sobj.isStrictContext();
 
             if (bulkable(sobj)) {
                 return ((NativeArray)sobj).getArray().pop();
@@ -640,7 +640,7 @@
     public static Object push(final Object self, final Object... args) {
         try {
             final ScriptObject sobj   = (ScriptObject)self;
-            final boolean      strict = sobj.getContext()._strict;
+            final boolean      strict = sobj.isStrictContext();
 
             if (bulkable(sobj)) {
                 final NativeArray nativeArray = (NativeArray)sobj;
@@ -675,7 +675,7 @@
     public static Object reverse(final Object self) {
         try {
             final ScriptObject sobj   = (ScriptObject)self;
-            final boolean      strict = sobj.getContext()._strict;
+            final boolean      strict = sobj.isStrictContext();
             final long         len    = JSType.toUint32(sobj.getLength());
             final long         middle = len / 2;
 
@@ -846,8 +846,7 @@
     public static Object sort(final Object self, final Object comparefn) {
         try {
             final ScriptObject sobj    = (ScriptObject) self;
-            final Context      context = sobj.getContext();
-            final boolean      strict  = context._strict;
+            final boolean      strict  = sobj.isStrictContext();
             final long         len     = JSType.toUint32(sobj.getLength());
 
             if (len > 1) {
@@ -994,7 +993,7 @@
             nativeArray.getArray().shiftRight(items.length);
 
             for (int j = 0; j < items.length; j++) {
-                nativeArray.setArray(nativeArray.getArray().set(j, items[j], sobj.getContext()._strict));
+                nativeArray.setArray(nativeArray.getArray().set(j, items[j], sobj.isStrictContext()));
             }
         } else {
             for (long k = len; k > 0; k--) {
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java	Mon Jan 21 21:17:38 2013 +0530
@@ -252,7 +252,7 @@
     @SuppressWarnings("resource")
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object dumpCounters(final Object self) {
-        final PrintWriter out = Context.getContext().getErr();
+        final PrintWriter out = Context.getCurrentErr();
 
         out.println("ScriptObject count " + ScriptObject.getCount());
         out.println("Scope count " + ScriptObject.getScopeCount());
--- a/src/jdk/nashorn/internal/objects/NativeJava.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Mon Jan 21 21:17:38 2013 +0530
@@ -334,7 +334,7 @@
 
     private static Class<?> simpleType(final String typeName) throws ClassNotFoundException {
         final Class<?> primClass = TypeUtilities.getPrimitiveTypeByName(typeName);
-        return primClass != null ? primClass : Global.instance().getContext().findClass(typeName);
+        return primClass != null ? primClass : Global.getThisContext().findClass(typeName);
     }
 
     private static Class<?> arrayType(final String typeName) throws ClassNotFoundException {
--- a/src/jdk/nashorn/internal/runtime/Context.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/Context.java	Mon Jan 21 21:17:38 2013 +0530
@@ -72,12 +72,6 @@
         };
 
     /**
-     * Get the error stream if applicable and initialized, otherwise stderr
-     * Usually this is the error stream given the context, but for testing and
-     * certain bootstrapping situations we need a default stream
-     */
-
-    /**
      * Return the current global scope
      * @return current global scope
      */
@@ -107,7 +101,21 @@
      * @return current global scope's context.
      */
     public static Context getContext() {
-        return Context.getGlobal().getContext();
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("getNashornContext"));
+        }
+        return getContextTrusted();
+    }
+
+    /**
+     * Get current context's error writer
+     *
+     * @return error writer of the current context
+     */
+    public static PrintWriter getCurrentErr() {
+        final ScriptObject global = getGlobal();
+        return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
     }
 
     /**
@@ -127,7 +135,7 @@
      */
     @SuppressWarnings("resource")
     public static void err(final String str, final boolean crlf) {
-        final PrintWriter err = Context.getContext().getErr();
+        final PrintWriter err = Context.getCurrentErr();
         if (err != null) {
             if (crlf) {
                 err.println(str);
@@ -137,6 +145,9 @@
         }
     }
 
+    /** class loader to resolve classes from script. */
+    private final ClassLoader  appLoader;
+
     /** Class loader to load classes from -classpath option, if set. */
     private final ClassLoader  classPathLoader;
 
@@ -242,13 +253,14 @@
     /** time zone for this context */
     public final TimeZone _timezone;
 
+    private static final ClassLoader myLoader = Context.class.getClassLoader();
     private static final StructureLoader sharedLoader;
 
     static {
         sharedLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() {
             @Override
             public StructureLoader run() {
-                return new StructureLoader(Context.class.getClassLoader(), null);
+                return new StructureLoader(myLoader, null);
             }
         });
     }
@@ -273,9 +285,10 @@
      *
      * @param options options from command line or Context creator
      * @param errors  error manger
+     * @param appLoader application class loader
      */
-    public Context(final Options options, final ErrorManager errors) {
-        this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true));
+    public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
+        this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader);
     }
 
     /**
@@ -285,13 +298,15 @@
      * @param errors  error manger
      * @param out     output writer for this Context
      * @param err     error writer for this Context
+     * @param appLoader application class loader
      */
-    public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err) {
+    public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new RuntimePermission("createNashornContext"));
         }
 
+        this.appLoader = appLoader;
         this.scriptLoader = (ScriptLoader)AccessController.doPrivileged(
              new PrivilegedAction<ClassLoader>() {
                 @Override
@@ -389,7 +404,7 @@
      * Get the error manager for this context
      * @return error manger
      */
-    public ErrorManager getErrors() {
+    public ErrorManager getErrorManager() {
         return errors;
     }
 
@@ -652,28 +667,17 @@
             }
         }
 
-        // try script loader first
-        try {
-            return Class.forName(fullName, true, scriptLoader);
-        } catch (final ClassNotFoundException e) {
-            // ignored, continue search
-        }
-
-        // try script -classpath loader, if set
+        // try the script -classpath loader, if that is set
         if (classPathLoader != null) {
             try {
                 return Class.forName(fullName, true, classPathLoader);
-            } catch (final ClassNotFoundException e) {
+            } catch (final ClassNotFoundException ignored) {
                 // ignore, continue search
             }
         }
 
-        // This helps in finding using "app" loader - which is typically set as thread context loader
-        try {
-            return Class.forName(fullName, true, Thread.currentThread().getContextClassLoader());
-        } catch (final ClassNotFoundException e) {
-            throw e;
-        }
+        // Try finding using the "app" loader.
+        return Class.forName(fullName, true, appLoader);
     }
 
     /**
@@ -684,7 +688,7 @@
      */
     public static void printStackTrace(final Throwable t) {
         if (Context.DEBUG) {
-            t.printStackTrace(Context.getContext().getErr());
+            t.printStackTrace(Context.getCurrentErr());
         }
     }
 
@@ -714,18 +718,35 @@
      * @return the global script object
      */
     public ScriptObject createGlobal() {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RuntimePermission("createNashornGlobal"));
+        }
+
         final ScriptObject global = newGlobal();
-
         // Need only minimal global object, if we are just compiling.
         if (!_compile_only) {
-            // initialize global scope with builtin global objects
-            ((GlobalObject)global).initBuiltinObjects();
+            final ScriptObject oldGlobal = Context.getGlobal();
+            try {
+                Context.setGlobal(global);
+                // initialize global scope with builtin global objects
+                ((GlobalObject)global).initBuiltinObjects();
+            } finally {
+                Context.setGlobal(oldGlobal);
+            }
         }
 
         return global;
     }
 
     /**
+     * Trusted variant package-private
+     */
+    static Context getContextTrusted() {
+        return Context.getGlobal().getContext();
+    }
+
+    /**
      * Try to infer Context instance from the Class. If we cannot,
      * then get it from the thread local variable.
      *
@@ -740,7 +761,7 @@
             context = ((NashornLoader)loader).getContext();
         }
 
-        return (context != null) ? context : Context.getContext();
+        return (context != null) ? context : Context.getContextTrusted();
     }
 
     private Object evaluateSource(final String name, final URL url, final ScriptObject scope, final ScriptObject thiz) throws IOException {
--- a/src/jdk/nashorn/internal/runtime/DebugLogger.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/DebugLogger.java	Mon Jan 21 21:17:38 2013 +0530
@@ -74,7 +74,7 @@
      * @return print writer for log output.
      */
     public PrintWriter getOutputStream() {
-        return Context.getContext().getErr();
+        return Context.getCurrentErr();
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/ECMAException.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/ECMAException.java	Mon Jan 21 21:17:38 2013 +0530
@@ -182,7 +182,7 @@
     public static Object printStackTrace(final ScriptObject errObj) {
         final Object exception = getException(errObj);
         if (exception instanceof Throwable) {
-            ((Throwable)exception).printStackTrace(Context.getContext().getErr());
+            ((Throwable)exception).printStackTrace(Context.getCurrentErr());
         } else {
             Context.err("<stack trace not available>");
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/nashorn/internal/runtime/OptionsObject.java	Mon Jan 21 21:17:38 2013 +0530
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.util.TimeZone;
+
+/**
+ * A convenience object to expose only command line options from a Context.
+ */
+public final class OptionsObject {
+    /** Always allow functions as statements */
+    public final boolean _anon_functions;
+
+    /** Size of the per-global Class cache size */
+    public final int     _class_cache_size;
+
+    /** Only compile script, do not run it or generate other ScriptObjects */
+    public final boolean _compile_only;
+
+    /** Accumulated callsite flags that will be used when boostrapping script callsites */
+    public final int     _callsite_flags;
+
+    /** Genereate line number table in class files */
+    public final boolean _debug_lines;
+
+    /** Package to which generated class files are added */
+    public final String  _dest_dir;
+
+    /** Display stack trace upon error, default is false */
+    public final boolean _dump_on_error;
+
+    /** Invalid lvalue expressions should be reported as early errors */
+    public final boolean _early_lvalue_error;
+
+    /** Empty statements should be preserved in the AST */
+    public final boolean _empty_statements;
+
+    /** Show full Nashorn version */
+    public final boolean _fullversion;
+
+    /** Create a new class loaded for each compilation */
+    public final boolean _loader_per_compile;
+
+    /** Package to which generated class files are added */
+    public final String  _package;
+
+    /** Only parse the source code, do not compile */
+    public final boolean _parse_only;
+
+    /** Print the AST before lowering */
+    public final boolean _print_ast;
+
+    /** Print the AST after lowering */
+    public final boolean _print_lower_ast;
+
+    /** Print resulting bytecode for script */
+    public final boolean _print_code;
+
+    /** Print function will no print newline characters */
+    public final boolean _print_no_newline;
+
+    /** Print AST in more human readable form */
+    public final boolean _print_parse;
+
+    /** Print AST in more human readable form after Lowering */
+    public final boolean _print_lower_parse;
+
+    /** print symbols and their contents for the script */
+    public final boolean _print_symbols;
+
+    /** is this context in scripting mode? */
+    public final boolean _scripting;
+
+    /** is this context in strict mode? */
+    public final boolean _strict;
+
+    /** print version info of Nashorn */
+    public final boolean _version;
+
+    /** should code verification be done of generated bytecode */
+    public final boolean _verify_code;
+
+    /** time zone for this context */
+    public final TimeZone _timezone;
+
+    public OptionsObject(final Context context) {
+        this._anon_functions = context._anon_functions;
+        this._callsite_flags = context._callsite_flags;
+        this._class_cache_size = context._class_cache_size;
+        this._compile_only = context._compile_only;
+        this._debug_lines = context._debug_lines;
+        this._dest_dir = context._dest_dir;
+        this._dump_on_error = context._dump_on_error;
+        this._early_lvalue_error = context._early_lvalue_error;
+        this._empty_statements = context._empty_statements;
+        this._fullversion = context._fullversion;
+        this._loader_per_compile = context._loader_per_compile;
+        this._package = context._package;
+        this._parse_only = context._parse_only;
+        this._print_ast = context._print_ast;
+        this._print_code = context._print_code;
+        this._print_lower_ast = context._print_lower_ast;
+        this._print_lower_parse = context._print_lower_parse;
+        this._print_no_newline = context._print_no_newline;
+        this._print_parse = context._print_parse;
+        this._print_symbols = context._print_symbols;
+        this._scripting = context._scripting;
+        this._strict = context._strict;
+        this._timezone = context._timezone;
+        this._verify_code = context._verify_code;
+        this._version = context._version;
+    }
+}
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Jan 21 21:17:38 2013 +0530
@@ -1043,11 +1043,15 @@
         set(key, value, getContext()._strict);
     }
 
+    public final boolean isStrictContext() {
+        return getContext()._strict;
+    }
+
     /**
      * Return the current context from the object's map.
      * @return Current context.
      */
-    public final Context getContext() {
+    protected final Context getContext() {
         return getMap().getContext();
     }
 
--- a/src/jdk/nashorn/internal/runtime/StructureLoader.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java	Mon Jan 21 21:17:38 2013 +0530
@@ -129,7 +129,7 @@
         Context context = getContext();
 
         if (context == null) {
-            context = Context.getContext();
+            context = Context.getContextTrusted();
         }
 
         final byte[] code = new ObjectClassGenerator(context).generate(descriptor);
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java	Mon Jan 21 21:17:38 2013 +0530
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
@@ -83,6 +84,6 @@
 
     @Override
     public void remove() {
-        array.delete(index, array.getContext()._strict);
+        array.delete(index, array.isStrictContext());
     }
 }
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Mon Jan 21 21:17:38 2013 +0530
@@ -136,7 +136,7 @@
  * </p>
  */
 
-public class JavaAdapterFactory {
+public final class JavaAdapterFactory {
     private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
     private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
     private static final Type OBJECT_TYPE = Type.getType(Object.class);
@@ -470,7 +470,7 @@
         // private final ScriptObject global;
         w.visitField(ACC_PRIVATE | ACC_FINAL, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd();
 
-        // private ContextSetter(ScriptObject global) {
+        // private GlobalSetter(ScriptObject global) {
         InstructionAdapter mv = new InstructionAdapter(w.visitMethod(ACC_PRIVATE, INIT,
                 SET_GLOBAL_METHOD_DESCRIPTOR, null, new String[0]));
         mv.visitCode();
--- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java	Mon Jan 21 21:17:38 2013 +0530
@@ -285,7 +285,7 @@
                         out = new PrintWriter(new FileOutputStream(PROFILEFILE));
                         fileOutput = true;
                     } catch (final FileNotFoundException e) {
-                        out = Context.getContext().getErr();
+                        out = Context.getCurrentErr();
                     }
 
                     dump(out);
@@ -317,8 +317,6 @@
         private static final MethodHandle TRACEVOID   = findOwnMH("traceVoid", void.class, MethodHandle.class, Object[].class);
         private static final MethodHandle TRACEMISS   = findOwnMH("traceMiss", void.class, Object[].class);
 
-        private static final PrintWriter out = Context.getContext().getErr();
-
         TracingLinkerCallSite(final NashornCallSiteDescriptor desc) {
            super(desc);
         }
@@ -366,7 +364,7 @@
             return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.bindTo(TRACEMISS, this), Object[].class, type.parameterCount()), type.changeReturnType(void.class)));
         }
 
-        private void printObject(final Object arg) {
+        private void printObject(final PrintWriter out, final Object arg) {
             if (!getNashornDescriptor().isTraceObjects()) {
                 out.print((arg instanceof ScriptObject) ? "ScriptObject" : arg);
                 return;
@@ -396,7 +394,7 @@
                         if (value instanceof ScriptObject) {
                             out.print("...");
                         } else {
-                            printObject(value);
+                            printObject(out, value);
                         }
 
                         isFirst = false;
@@ -409,19 +407,19 @@
             }
         }
 
-        private void tracePrint(final String tag, final Object[] args, final Object result) {
+        private void tracePrint(final PrintWriter out, final String tag, final Object[] args, final Object result) {
             //boolean isVoid = type().returnType() == void.class;
             out.print(Debug.id(this) + " TAG " + tag);
             out.print(getDescriptor().getName() + "(");
 
             if (args.length > 0) {
-                printObject(args[0]);
+                printObject(out, args[0]);
                 for (int i = 1; i < args.length; i++) {
                     final Object arg = args[i];
                     out.print(", ");
 
                     if (getNashornDescriptor().isTraceScope() || !(arg instanceof ScriptObject && ((ScriptObject)arg).isScope())) {
-                        printObject(arg);
+                        printObject(out, arg);
                     } else {
                         out.print("SCOPE");
                     }
@@ -432,7 +430,7 @@
 
             if (tag.equals("EXIT  ")) {
                 out.print(" --> ");
-                printObject(result);
+                printObject(out, result);
             }
 
             out.println();
@@ -450,9 +448,10 @@
          */
         @SuppressWarnings("unused")
         public Object traceObject(final MethodHandle mh, final Object... args) throws Throwable {
-            tracePrint("ENTER ", args, null);
+            final PrintWriter out = Context.getCurrentErr();
+            tracePrint(out, "ENTER ", args, null);
             final Object result = mh.invokeWithArguments(args);
-            tracePrint("EXIT  ", args, result);
+            tracePrint(out, "EXIT  ", args, result);
 
             return result;
         }
@@ -467,9 +466,10 @@
          */
         @SuppressWarnings("unused")
         public void traceVoid(final MethodHandle mh, final Object... args) throws Throwable {
-            tracePrint("ENTER ", args, null);
+            final PrintWriter out = Context.getCurrentErr();
+            tracePrint(out, "ENTER ", args, null);
             mh.invokeWithArguments(args);
-            tracePrint("EXIT  ", args, null);
+            tracePrint(out, "EXIT  ", args, null);
         }
 
         /**
@@ -481,7 +481,7 @@
          */
         @SuppressWarnings("unused")
         public void traceMiss(final Object... args) throws Throwable {
-            tracePrint("MISS ", args, null);
+            tracePrint(Context.getCurrentErr(), "MISS ", args, null);
         }
 
         private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
--- a/src/jdk/nashorn/tools/Shell.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/src/jdk/nashorn/tools/Shell.java	Mon Jan 21 21:17:38 2013 +0530
@@ -148,7 +148,7 @@
      *
      * @throws IOException if there's a problem setting up the streams
      */
-    protected int run(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
+    protected final int run(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
         final Context context = makeContext(in, out, err, args);
         if (context == null) {
             return COMMANDLINE_ERROR;
@@ -157,14 +157,14 @@
         final ScriptObject global = context.createGlobal();
         final List<String> files = context.getOptions().getFiles();
         if (files.isEmpty()) {
-            return readEvalPrint(global);
+            return readEvalPrint(context, global);
         }
 
         if (context._compile_only) {
-            return compileScripts(global, files);
+            return compileScripts(context, global, files);
         }
 
-        return runScripts(global, files);
+        return runScripts(context, global, files);
     }
 
     /**
@@ -178,7 +178,7 @@
      * @return null if there are problems with option parsing.
      */
     @SuppressWarnings("resource")
-    protected Context makeContext(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) {
+    private Context makeContext(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) {
         final PrintStream pout = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
         final PrintStream perr = err instanceof PrintStream ? (PrintStream) err : new PrintStream(err);
         final PrintWriter wout = new PrintWriter(pout, true);
@@ -217,27 +217,27 @@
             }
         }
 
-        return new Context(options, errors, wout, werr);
+        return new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader());
     }
 
     /**
      * Compiles the given script files in the command line
      *
+     * @param context the nashorn context
      * @param global the global scope
      * @param files the list of script files to compile
      *
      * @return error code
      * @throws IOException when any script file read results in I/O error
      */
-    protected int compileScripts(final ScriptObject global, final List<String> files) throws IOException {
-        final Context context = global.getContext();
+    private int compileScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
         final ScriptObject oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != global);
         try {
             if (globalChanged) {
                 Context.setGlobal(global);
             }
-            final ErrorManager errors = context.getErrors();
+            final ErrorManager errors = context.getErrorManager();
 
             // For each file on the command line.
             for (final String fileName : files) {
@@ -263,21 +263,21 @@
     /**
      * Runs the given JavaScript files in the command line
      *
+     * @param context the nashorn context
      * @param global the global scope
      * @param files the list of script files to run
      *
      * @return error code
      * @throws IOException when any script file read results in I/O error
      */
-    protected int runScripts(final ScriptObject global, final List<String> files) throws IOException {
-        final Context context = global.getContext();
+    private int runScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
         final ScriptObject oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != global);
         try {
             if (globalChanged) {
                 Context.setGlobal(global);
             }
-            final ErrorManager errors = context.getErrors();
+            final ErrorManager errors = context.getErrorManager();
 
             // For each file on the command line.
             for (final String fileName : files) {
@@ -325,12 +325,12 @@
     /**
      * read-eval-print loop for Nashorn shell.
      *
+     * @param context the nashorn context
      * @param global  global scope object to use
      * @return return code
      */
     @SuppressWarnings("resource")
-    protected int readEvalPrint(final ScriptObject global) {
-        final Context context = global.getContext();
+    private int readEvalPrint(final Context context, final ScriptObject global) {
         final String prompt = bundle.getString("shell.prompt");
         final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
         final PrintWriter err = context.getErr();
--- a/test/src/jdk/nashorn/internal/access/BooleanAccessTest.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/test/src/jdk/nashorn/internal/access/BooleanAccessTest.java	Mon Jan 21 21:17:38 2013 +0530
@@ -25,8 +25,8 @@
 
 package jdk.nashorn.internal.access;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
 
 import java.util.Arrays;
 import javax.script.ScriptEngine;
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java	Mon Jan 21 21:17:38 2013 +0530
@@ -74,7 +74,7 @@
 
         final StringWriter sw = new StringWriter();
         final PrintWriter pw = new PrintWriter(sw);
-        this.context = new Context(options, errors, pw, pw);
+        this.context = new Context(options, errors, pw, pw, Thread.currentThread().getContextClassLoader());
         this.global = context.createGlobal();
     }
 
@@ -160,7 +160,7 @@
             }
             final Source source = new Source(file.getAbsolutePath(), buffer);
             final ScriptFunction script = context.compileScript(source, global, context._strict);
-            if (script == null || context.getErrors().getNumberOfErrors() > 0) {
+            if (script == null || context.getErrorManager().getNumberOfErrors() > 0) {
                 log("Compile failed: " + file.getAbsolutePath());
                 failed++;
             } else {
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java	Mon Jan 21 21:17:38 2013 +0530
@@ -65,7 +65,7 @@
         options.set("scripting", true);
 
         ErrorManager errors = new ErrorManager();
-        this.context = new Context(options, errors);
+        this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader());
         this.global = context.createGlobal();
     }
 
--- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java	Mon Jan 21 21:17:38 2013 +0530
@@ -41,7 +41,7 @@
     public void evalTest() {
         final Options options = new Options("");
         final ErrorManager errors = new ErrorManager();
-        final Context cx = new Context(options, errors);
+        final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
         final ScriptObject oldGlobal = Context.getGlobal();
         Context.setGlobal(cx.createGlobal());
         try {
@@ -60,7 +60,7 @@
     public void reflectionTest() {
         final Options options = new Options("");
         final ErrorManager errors = new ErrorManager();
-        final Context cx = new Context(options, errors);
+        final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
         final ScriptObject oldGlobal = Context.getGlobal();
         Context.setGlobal(cx.createGlobal());
 
--- a/test/src/jdk/nashorn/internal/runtime/JSTypeTest.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/test/src/jdk/nashorn/internal/runtime/JSTypeTest.java	Mon Jan 21 21:17:38 2013 +0530
@@ -27,6 +27,7 @@
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
 
 import org.testng.annotations.Test;
 
@@ -39,16 +40,16 @@
      */
     @Test
     public void testIsPrimitive() {
-        assertEquals(true,  JSType.isPrimitive(null));
-        assertEquals(true,  JSType.isPrimitive(ScriptRuntime.UNDEFINED));
-        assertEquals(true,  JSType.isPrimitive(Double.NaN));
-        assertEquals(true,  JSType.isPrimitive(Double.NEGATIVE_INFINITY));
-        assertEquals(true,  JSType.isPrimitive(Double.POSITIVE_INFINITY));
-        assertEquals(true,  JSType.isPrimitive(0.0));
-        assertEquals(true,  JSType.isPrimitive(3.14));
-        assertEquals(true,  JSType.isPrimitive("hello"));
-        assertEquals(true,  JSType.isPrimitive(""));
-        assertEquals(false, JSType.isPrimitive(new Object()));
+        assertTrue(JSType.isPrimitive(null));
+        assertTrue(JSType.isPrimitive(ScriptRuntime.UNDEFINED));
+        assertTrue(JSType.isPrimitive(Double.NaN));
+        assertTrue(JSType.isPrimitive(Double.NEGATIVE_INFINITY));
+        assertTrue(JSType.isPrimitive(Double.POSITIVE_INFINITY));
+        assertTrue(JSType.isPrimitive(0.0));
+        assertTrue(JSType.isPrimitive(3.14));
+        assertTrue(JSType.isPrimitive("hello"));
+        assertTrue(JSType.isPrimitive(""));
+        assertFalse(JSType.isPrimitive(new Object()));
     }
 
     /**
@@ -56,17 +57,17 @@
      */
     @Test
     public void testToBoolean() {
-        assertEquals(false, JSType.toBoolean(ScriptRuntime.UNDEFINED));
-        assertEquals(false, JSType.toBoolean(null));
-        assertEquals(false, JSType.toBoolean(Boolean.FALSE));
-        assertEquals(true,  JSType.toBoolean(Boolean.TRUE));
-        assertEquals(false, JSType.toBoolean(-0.0));
-        assertEquals(false, JSType.toBoolean(0.0));
-        assertEquals(false, JSType.toBoolean(Double.NaN));
-        assertEquals(true,  JSType.toBoolean(3.14));
-        assertEquals(false, JSType.toBoolean(""));
-        assertEquals(true,  JSType.toBoolean("javascript"));
-        assertEquals(true,  JSType.toBoolean(new Object()));
+        assertFalse(JSType.toBoolean(ScriptRuntime.UNDEFINED));
+        assertFalse(JSType.toBoolean(null));
+        assertFalse(JSType.toBoolean(Boolean.FALSE));
+        assertTrue(JSType.toBoolean(Boolean.TRUE));
+        assertFalse(JSType.toBoolean(-0.0));
+        assertFalse(JSType.toBoolean(0.0));
+        assertFalse(JSType.toBoolean(Double.NaN));
+        assertTrue(JSType.toBoolean(3.14));
+        assertFalse(JSType.toBoolean(""));
+        assertTrue(JSType.toBoolean("javascript"));
+        assertTrue(JSType.toBoolean(new Object()));
     }
 
     /**
@@ -75,10 +76,10 @@
     @Test
     public void testToNumber_Object() {
         assertTrue(Double.isNaN(JSType.toNumber(ScriptRuntime.UNDEFINED)));
-        assertEquals(0.0,  JSType.toNumber((Object)null), 0.0);
-        assertEquals(1.0,  JSType.toNumber(Boolean.TRUE), 0.0);
-        assertEquals(0.0,  JSType.toNumber(Boolean.FALSE), 0.0);
-        assertEquals(3.14, JSType.toNumber(3.14), 0.0);
+        assertEquals(JSType.toNumber((Object)null), 0.0, 0.0);
+        assertEquals(JSType.toNumber(Boolean.TRUE), 1.0, 0.0);
+        assertEquals(JSType.toNumber(Boolean.FALSE), 0.0, 0.0);
+        assertEquals(JSType.toNumber(3.14), 3.14, 0.0);
         // FIXME: add more assertions for specific String to number cases
         // FIXME: add case for Object type (JSObject with getDefaultValue)
     }
@@ -88,16 +89,16 @@
      */
     @Test
     public void testToString_Object() {
-        assertEquals("undefined", JSType.toString(ScriptRuntime.UNDEFINED));
-        assertEquals("null", JSType.toString(null));
-        assertEquals("true", JSType.toString(Boolean.TRUE));
-        assertEquals("false", JSType.toString(Boolean.FALSE));
-        assertEquals("", JSType.toString(""));
-        assertEquals("nashorn", JSType.toString("nashorn"));
-        assertEquals("NaN", JSType.toString(Double.NaN));
-        assertEquals("Infinity", JSType.toString(Double.POSITIVE_INFINITY));
-        assertEquals("-Infinity", JSType.toString(Double.NEGATIVE_INFINITY));
-        assertEquals("0", JSType.toString(0.0));
+        assertEquals(JSType.toString(ScriptRuntime.UNDEFINED), "undefined");
+        assertEquals(JSType.toString(null), "null");
+        assertEquals(JSType.toString(Boolean.TRUE), "true");
+        assertEquals(JSType.toString(Boolean.FALSE), "false");
+        assertEquals(JSType.toString(""), "");
+        assertEquals(JSType.toString("nashorn"), "nashorn");
+        assertEquals(JSType.toString(Double.NaN), "NaN");
+        assertEquals(JSType.toString(Double.POSITIVE_INFINITY), "Infinity");
+        assertEquals(JSType.toString(Double.NEGATIVE_INFINITY), "-Infinity");
+        assertEquals(JSType.toString(0.0), "0");
         // FIXME: add more number-to-string test cases
         // FIXME: add case for Object type (JSObject with getDefaultValue)
     }
--- a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java	Mon Jan 21 11:03:56 2013 +0100
+++ b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java	Mon Jan 21 21:17:38 2013 +0530
@@ -104,7 +104,7 @@
         Options options = new Options("nashorn", werr);
         options.process(args);
         ErrorManager errors = new ErrorManager(werr);
-        this.context = new Context(options, errors, wout, werr);
+        this.context = new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader());
     }
 
     @Override
@@ -113,7 +113,7 @@
         try {
             ctxOut.setDelegatee(out);
             ctxErr.setDelegatee(err);
-            final ErrorManager errors = context.getErrors();
+            final ErrorManager errors = context.getErrorManager();
             final ScriptObject global = context.createGlobal();
             Context.setGlobal(global);