src/jdk/nashorn/internal/objects/Global.java

Tue, 12 Mar 2013 18:12:42 +0530

author
sundar
date
Tue, 12 Mar 2013 18:12:42 +0530
changeset 136
c54e218333be
parent 133
5759f600fcf7
child 139
390d44ba90cf
permissions
-rw-r--r--

8009757: Package access clean up and refactoring
Reviewed-by: jlaskey, lagergren, attila

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.objects;
    28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    30 import static jdk.nashorn.internal.lookup.Lookup.MH;
    32 import java.io.IOException;
    33 import java.io.PrintWriter;
    34 import java.lang.invoke.MethodHandle;
    35 import java.lang.invoke.MethodHandles;
    36 import java.lang.ref.SoftReference;
    37 import java.lang.reflect.Field;
    38 import java.security.AccessController;
    39 import java.security.PrivilegedAction;
    40 import java.util.LinkedHashMap;
    41 import java.util.List;
    42 import java.util.Map;
    43 import jdk.internal.dynalink.linker.GuardedInvocation;
    44 import jdk.internal.dynalink.linker.LinkRequest;
    45 import jdk.nashorn.internal.objects.annotations.Attribute;
    46 import jdk.nashorn.internal.objects.annotations.Property;
    47 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    48 import jdk.nashorn.internal.runtime.ConsString;
    49 import jdk.nashorn.internal.runtime.Context;
    50 import jdk.nashorn.internal.runtime.GlobalFunctions;
    51 import jdk.nashorn.internal.runtime.GlobalObject;
    52 import jdk.nashorn.internal.runtime.JSType;
    53 import jdk.nashorn.internal.runtime.NativeJavaPackage;
    54 import jdk.nashorn.internal.runtime.ScriptEnvironment;
    55 import jdk.nashorn.internal.runtime.PropertyDescriptor;
    56 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    57 import jdk.nashorn.internal.runtime.Scope;
    58 import jdk.nashorn.internal.runtime.ScriptFunction;
    59 import jdk.nashorn.internal.runtime.ScriptObject;
    60 import jdk.nashorn.internal.runtime.ScriptRuntime;
    61 import jdk.nashorn.internal.runtime.ScriptingFunctions;
    62 import jdk.nashorn.internal.runtime.Source;
    63 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    64 import jdk.nashorn.internal.scripts.JO;
    66 /**
    67  * Representation of global scope.
    68  */
    69 @ScriptClass("Global")
    70 public final class Global extends ScriptObject implements GlobalObject, Scope {
    71     private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    72     private static final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
    74     /** ECMA 15.1.2.2 parseInt (string , radix) */
    75     @Property(attributes = Attribute.NOT_ENUMERABLE)
    76     public Object parseInt;
    78     /** ECMA 15.1.2.3 parseFloat (string) */
    79     @Property(attributes = Attribute.NOT_ENUMERABLE)
    80     public Object parseFloat;
    82     /** ECMA 15.1.2.4 isNaN (number) */
    83     @Property(attributes = Attribute.NOT_ENUMERABLE)
    84     public Object isNaN;
    86     /** ECMA 15.1.2.5 isFinite (number) */
    87     @Property(attributes = Attribute.NOT_ENUMERABLE)
    88     public Object isFinite;
    90     /** ECMA 15.1.3.3 encodeURI */
    91     @Property(attributes = Attribute.NOT_ENUMERABLE)
    92     public Object encodeURI;
    94     /** ECMA 15.1.3.4 encodeURIComponent */
    95     @Property(attributes = Attribute.NOT_ENUMERABLE)
    96     public Object encodeURIComponent;
    98     /** ECMA 15.1.3.1 decodeURI */
    99     @Property(attributes = Attribute.NOT_ENUMERABLE)
   100     public Object decodeURI;
   102     /** ECMA 15.1.3.2 decodeURIComponent */
   103     @Property(attributes = Attribute.NOT_ENUMERABLE)
   104     public Object decodeURIComponent;
   106     /** ECMA B.2.1 escape (string) */
   107     @Property(attributes = Attribute.NOT_ENUMERABLE)
   108     public Object escape;
   110     /** ECMA B.2.2 unescape (string) */
   111     @Property(attributes = Attribute.NOT_ENUMERABLE)
   112     public Object unescape;
   114     /** Nashorn extension: global.print */
   115     @Property(attributes = Attribute.NOT_ENUMERABLE)
   116     public Object print;
   118     /** Nashorn extension: global.load */
   119     @Property(attributes = Attribute.NOT_ENUMERABLE)
   120     public Object load;
   122     /** Nashorn extension: global.exit */
   123     @Property(attributes = Attribute.NOT_ENUMERABLE)
   124     public Object exit;
   126     /** Nashorn extension: global.quit */
   127     @Property(attributes = Attribute.NOT_ENUMERABLE)
   128     public Object quit;
   130     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
   131     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   132     public final Object NaN = Double.NaN;
   134     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
   135     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   136     public final Object Infinity = Double.POSITIVE_INFINITY;
   138     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
   139     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   140     public final Object undefined = UNDEFINED;
   142     /** ECMA 15.1.2.1 eval(x) */
   143     @Property(attributes = Attribute.NOT_ENUMERABLE)
   144     public Object eval;
   146     /** ECMA 15.1.4.1 Object constructor. */
   147     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
   148     public volatile Object object;
   150     /** ECMA 15.1.4.2 Function constructor. */
   151     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
   152     public volatile Object function;
   154     /** ECMA 15.1.4.3 Array constructor. */
   155     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
   156     public volatile Object array;
   158     /** ECMA 15.1.4.4 String constructor */
   159     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
   160     public volatile Object string;
   162     /** ECMA 15.1.4.5 Boolean constructor */
   163     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
   164     public volatile Object _boolean;
   166     /** ECMA 15.1.4.6 - Number constructor */
   167     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
   168     public volatile Object number;
   170     /** ECMA 15.1.4.7 Date constructor */
   171     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   172     public volatile Object date;
   174     /** ECMA 15.1.4.8 RegExp constructor */
   175     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   176     public volatile Object regexp;
   178     /** ECMA 15.12 - The JSON object */
   179     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   180     public volatile Object json;
   182     /** Nashorn extension: global.JSAdapter */
   183     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   184     public volatile Object jsadapter;
   186     /** ECMA 15.8 - The Math object */
   187     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
   188     public volatile Object math;
   190     /** Error object */
   191     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
   192     public volatile Object error;
   194     /** EvalError object */
   195     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   196     public volatile Object evalError;
   198     /** RangeError object */
   199     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   200     public volatile Object rangeError;
   202     /** ReferenceError object */
   203     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
   204     public volatile Object referenceError;
   206     /** SyntaxError object */
   207     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
   208     public volatile Object syntaxError;
   210     /** TypeError object */
   211     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
   212     public volatile Object typeError;
   214     /** URIError object */
   215     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   216     public volatile Object uriError;
   218     /** ArrayBuffer object */
   219     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   220     public volatile Object arrayBuffer;
   222     /** TypedArray (int8) */
   223     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   224     public volatile Object int8Array;
   226     /** TypedArray (uint8) */
   227     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   228     public volatile Object uint8Array;
   230     /** TypedArray (uint8) - Clamped */
   231     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   232     public volatile Object uint8ClampedArray;
   234     /** TypedArray (int16) */
   235     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   236     public volatile Object int16Array;
   238     /** TypedArray (uint16) */
   239     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   240     public volatile Object uint16Array;
   242     /** TypedArray (int32) */
   243     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   244     public volatile Object int32Array;
   246     /** TypedArray (uint32) */
   247     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   248     public volatile Object uint32Array;
   250     /** TypedArray (float32) */
   251     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   252     public volatile Object float32Array;
   254     /** TypedArray (float64) */
   255     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   256     public volatile Object float64Array;
   258     /** Nashorn extension: Java access - global.Packages */
   259     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
   260     public volatile Object packages;
   262     /** Nashorn extension: Java access - global.java */
   263     @Property(attributes = Attribute.NOT_ENUMERABLE)
   264     public volatile Object java;
   266     /** Nashorn extension: Java access - global.javax */
   267     @Property(attributes = Attribute.NOT_ENUMERABLE)
   268     public Object javax;
   270     /** Nashorn extension: Java access - global.javaImporter */
   271     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   272     public volatile Object javaImporter;
   274     /** Nashorn extension: global.Java Object constructor. */
   275     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   276     public volatile Object javaApi;
   278     /** Nashorn extension: current script's file name */
   279     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   280     public Object __FILE__;
   282     /** Nashorn extension: current script's directory */
   283     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   284     public Object __DIR__;
   286     /** Nashorn extension: current source line number being executed */
   287     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   288     public Object __LINE__;
   290     /** Used as Date.prototype's default value */
   291     public NativeDate   DEFAULT_DATE;
   293     /** Used as RegExp.prototype's default value */
   294     public NativeRegExp DEFAULT_REGEXP;
   296     /*
   297      * Built-in constructor objects: Even if user changes dynamic values of
   298      * "Object", "Array" etc., we still want to keep original values of these
   299      * constructors here. For example, we need to be able to create array,
   300      * regexp literals even after user overwrites global "Array" or "RegExp"
   301      * constructor - see also ECMA 262 spec. Annex D.
   302      */
   303     private ScriptFunction builtinFunction;
   304     private ScriptFunction builtinObject;
   305     private ScriptFunction builtinArray;
   306     private ScriptFunction builtinBoolean;
   307     private ScriptFunction builtinDate;
   308     private ScriptObject   builtinJSON;
   309     private ScriptFunction builtinJSAdapter;
   310     private ScriptObject   builtinMath;
   311     private ScriptFunction builtinNumber;
   312     private ScriptFunction builtinRegExp;
   313     private ScriptFunction builtinString;
   314     private ScriptFunction builtinError;
   315     private ScriptFunction builtinEval;
   316     private ScriptFunction builtinEvalError;
   317     private ScriptFunction builtinRangeError;
   318     private ScriptFunction builtinReferenceError;
   319     private ScriptFunction builtinSyntaxError;
   320     private ScriptFunction builtinTypeError;
   321     private ScriptFunction builtinURIError;
   322     private ScriptObject   builtinPackages;
   323     private ScriptObject   builtinJava;
   324     private ScriptObject   builtinJavax;
   325     private ScriptObject   builtinJavaImporter;
   326     private ScriptObject   builtinJavaApi;
   327     private ScriptObject   builtinArrayBuffer;
   328     private ScriptObject   builtinInt8Array;
   329     private ScriptObject   builtinUint8Array;
   330     private ScriptObject   builtinUint8ClampedArray;
   331     private ScriptObject   builtinInt16Array;
   332     private ScriptObject   builtinUint16Array;
   333     private ScriptObject   builtinInt32Array;
   334     private ScriptObject   builtinUint32Array;
   335     private ScriptObject   builtinFloat32Array;
   336     private ScriptObject   builtinFloat64Array;
   338     // Flag to indicate that a split method issued a return statement
   339     private int splitState = -1;
   341     // class cache
   342     private ClassCache classCache;
   344     // Used to store the last RegExp result to support deprecated RegExp constructor properties
   345     private RegExpResult lastRegExpResult;
   347     private static final MethodHandle EVAL    = findOwnMH("eval",    Object.class, Object.class, Object.class);
   348     private static final MethodHandle PRINT   = findOwnMH("print",   Object.class, Object.class, Object[].class);
   349     private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
   350     private static final MethodHandle LOAD    = findOwnMH("load",    Object.class, Object.class, Object.class);
   351     private static final MethodHandle EXIT    = findOwnMH("exit",    Object.class, Object.class, Object.class);
   353     private final Context context;
   355     /**
   356      * Constructor
   357      *
   358      * @param context the context
   359      */
   360     public Global(final Context context) {
   361         this.context = context;
   362         this.setIsScope();
   363         /*
   364          * Duplicate global's map and use it. This way the initial Map filled
   365          * by nasgen (referenced from static field in this class) is retained
   366          * 'as is'. This allows multiple globals to be used within a context.
   367          */
   368         this.setMap(getMap().duplicate());
   370         final int cacheSize = context.getEnv()._class_cache_size;
   371         if (cacheSize > 0) {
   372             classCache = new ClassCache(cacheSize);
   373         }
   374     }
   376     /**
   377      * Script access to "current" Global instance
   378      *
   379      * @return the global singleton
   380      */
   381     public static Global instance() {
   382         ScriptObject global = Context.getGlobal();
   383         if (! (global instanceof Global)) {
   384             throw new IllegalStateException("no current global instance");
   385         }
   386         return (Global)global;
   387     }
   389     /**
   390      * Script access to {@link ScriptEnvironment}
   391      *
   392      * @return the script environment
   393      */
   394     static ScriptEnvironment getEnv() {
   395         return instance().context.getEnv();
   396     }
   398     /**
   399      * Script access to {@link Context}
   400      *
   401      * @return the context
   402      */
   403     static Context getThisContext() {
   404         return instance().context;
   405     }
   407     /**
   408      * Script access check for strict mode
   409      *
   410      * @return true if strict mode enabled in {@link Global#getThisContext()}
   411      */
   412     static boolean isStrict() {
   413         return getEnv()._strict;
   414     }
   416     // GlobalObject interface implementation
   418     @Override
   419     public void initBuiltinObjects() {
   420         if (this.builtinObject != null) {
   421             // already initialized, just return
   422             return;
   423         }
   425         init();
   426     }
   428     @Override
   429     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
   430         return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
   431     }
   433     @Override
   434     public Object wrapAsObject(final Object obj) {
   435         if (obj instanceof Boolean) {
   436             return new NativeBoolean((Boolean)obj);
   437         } else if (obj instanceof Number) {
   438             return new NativeNumber(((Number)obj).doubleValue());
   439         } else if (obj instanceof String || obj instanceof ConsString) {
   440             return new NativeString((CharSequence)obj);
   441         } else if (obj instanceof Object[]) { // extension
   442             return new NativeArray((Object[])obj);
   443         } else if (obj instanceof double[]) { // extension
   444             return new NativeArray((double[])obj);
   445         } else if (obj instanceof long[]) {
   446             return new NativeArray((long[])obj);
   447         } else if (obj instanceof int[]) {
   448             return new NativeArray((int[])obj);
   449         } else {
   450             // FIXME: more special cases? Map? List?
   451             return obj;
   452         }
   453     }
   455     @Override
   456     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
   457         if (self instanceof String || self instanceof ConsString) {
   458             return NativeString.lookupPrimitive(request, self);
   459         } else if (self instanceof Number) {
   460             return NativeNumber.lookupPrimitive(request, self);
   461         } else if (self instanceof Boolean) {
   462             return NativeBoolean.lookupPrimitive(request, self);
   463         }
   464         throw new IllegalArgumentException("Unsupported primitive: " + self);
   465     }
   467     @Override
   468     public ScriptObject newObject() {
   469         return newEmptyInstance();
   470     }
   472     @Override
   473     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
   474         // When the [[DefaultValue]] internal method of O is called with no hint,
   475         // then it behaves as if the hint were Number, unless O is a Date object
   476         // in which case it behaves as if the hint were String.
   477         Class<?> hint = typeHint;
   478         if (hint == null) {
   479             hint = Number.class;
   480         }
   482         try {
   483             if (hint == String.class) {
   485                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   486                 if (toString instanceof ScriptFunction) {
   487                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   488                     if (JSType.isPrimitive(value)) {
   489                         return value;
   490                     }
   491                 }
   493                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   494                 if (valueOf instanceof ScriptFunction) {
   495                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   496                     if (JSType.isPrimitive(value)) {
   497                         return value;
   498                     }
   499                 }
   500                 throw typeError(this, "cannot.get.default.string");
   501             }
   503             if (hint == Number.class) {
   504                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   505                 if (valueOf instanceof ScriptFunction) {
   506                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   507                     if (JSType.isPrimitive(value)) {
   508                         return value;
   509                     }
   510                 }
   512                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   513                 if (toString instanceof ScriptFunction) {
   514                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   515                     if (JSType.isPrimitive(value)) {
   516                         return value;
   517                     }
   518                 }
   520                 throw typeError(this, "cannot.get.default.number");
   521             }
   522         } catch (final RuntimeException | Error e) {
   523             throw e;
   524         } catch (final Throwable t) {
   525             throw new RuntimeException(t);
   526         }
   528         return UNDEFINED;
   529     }
   531     @Override
   532     public boolean isError(final ScriptObject sobj) {
   533         final ScriptObject errorProto = getErrorPrototype();
   534         ScriptObject proto = sobj.getProto();
   535         while (proto != null) {
   536             if (proto == errorProto) {
   537                 return true;
   538             }
   539             proto = proto.getProto();
   540         }
   541         return false;
   542     }
   544     @Override
   545     public ScriptObject newError(final String msg) {
   546         return new NativeError(msg);
   547     }
   549     @Override
   550     public ScriptObject newEvalError(final String msg) {
   551         return new NativeEvalError(msg);
   552     }
   554     @Override
   555     public ScriptObject newRangeError(final String msg) {
   556         return new NativeRangeError(msg);
   557     }
   559     @Override
   560     public ScriptObject newReferenceError(final String msg) {
   561         return new NativeReferenceError(msg);
   562     }
   564     @Override
   565     public ScriptObject newSyntaxError(final String msg) {
   566         return new NativeSyntaxError(msg);
   567     }
   569     @Override
   570     public ScriptObject newTypeError(final String msg) {
   571         return new NativeTypeError(msg);
   572     }
   574     @Override
   575     public ScriptObject newURIError(final String msg) {
   576         return new NativeURIError(msg);
   577     }
   579     @Override
   580     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
   581         return new GenericPropertyDescriptor(configurable, enumerable);
   582     }
   584     @Override
   585     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
   586         return new DataPropertyDescriptor(configurable, enumerable, writable, value);
   587     }
   589     @Override
   590     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
   591         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
   593         final boolean strict = context.getEnv()._strict;
   595         if (get == null) {
   596             desc.delete(PropertyDescriptor.GET, strict);
   597         }
   599         if (set == null) {
   600             desc.delete(PropertyDescriptor.SET, strict);
   601         }
   603         return desc;
   604     }
   607     /**
   608      * Cache for compiled script classes.
   609      */
   610     @SuppressWarnings("serial")
   611     private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
   612         private final int size;
   614         ClassCache(int size) {
   615             super(size, 0.75f, true);
   616             this.size = size;
   617         }
   619         @Override
   620         protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
   621             return size() >= size;
   622         }
   623     }
   625     // Class cache management
   626     @Override
   627     public Class<?> findCachedClass(final Source source) {
   628         assert classCache != null : "Class cache used without being initialized";
   629         SoftReference<Class<?>> ref = classCache.get(source);
   630         if (ref != null) {
   631             final Class<?> clazz = ref.get();
   632             if (clazz == null) {
   633                 classCache.remove(source);
   634             }
   635             return clazz;
   636         }
   638         return null;
   639     }
   641     @Override
   642     public void cacheClass(final Source source, final Class<?> clazz) {
   643         assert classCache != null : "Class cache used without being initialized";
   644         classCache.put(source, new SoftReference<Class<?>>(clazz));
   645     }
   647     /**
   648      * This is the eval used when 'indirect' eval call is made.
   649      *
   650      * var global = this;
   651      * global.eval("print('hello')");
   652      *
   653      * @param self  eval scope
   654      * @param str   eval string
   655      *
   656      * @return the result of eval
   657      */
   658     public static Object eval(final Object self, final Object str) {
   659         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
   660     }
   662     /**
   663      * Direct eval
   664      *
   665      * @param self     The scope of eval passed as 'self'
   666      * @param str      Evaluated code
   667      * @param callThis "this" to be passed to the evaluated code
   668      * @param location location of the eval call
   669      * @param strict   is eval called a strict mode code?
   670      *
   671      * @return the return value of the eval
   672      *
   673      * This is directly invoked from generated when eval(code) is called in user code
   674      */
   675     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
   676         if (!(str instanceof String || str instanceof ConsString)) {
   677             return str;
   678         }
   679         final Global global = Global.instance();
   680         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   682         return global.context.eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
   683     }
   685     /**
   686      * Global print implementation - Nashorn extension
   687      *
   688      * @param self    scope
   689      * @param objects arguments to print
   690      *
   691      * @return result of print (undefined)
   692      */
   693     public static Object print(final Object self, final Object... objects) {
   694         return printImpl(false, objects);
   695     }
   697     /**
   698      * Global println implementation - Nashorn extension
   699      *
   700      * @param self    scope
   701      * @param objects arguments to print
   702      *
   703      * @return result of println (undefined)
   704      */
   705     public static Object println(final Object self, final Object... objects) {
   706         return printImpl(true, objects);
   707     }
   709     /**
   710      * Global load implementation - Nashorn extension
   711      *
   712      * @param self    scope
   713      * @param source  source to load
   714      *
   715      * @return result of load (undefined)
   716      *
   717      * @throws IOException if source could not be read
   718      */
   719     public static Object load(final Object self, final Object source) throws IOException {
   720         final Global global = Global.instance();
   721         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   722         return global.context.load(scope, source);
   723     }
   725     /**
   726      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
   727      *
   728      * @param self  self reference
   729      * @param code  exit code
   730      *
   731      * @return undefined (will never be reacheD)
   732      */
   733     public static Object exit(final Object self, final Object code) {
   734         System.exit(JSType.toInt32(code));
   735         return UNDEFINED;
   736     }
   738     ScriptObject getFunctionPrototype() {
   739         return ScriptFunction.getPrototype(builtinFunction);
   740     }
   742     ScriptObject getObjectPrototype() {
   743         return ScriptFunction.getPrototype(builtinObject);
   744     }
   746     ScriptObject getArrayPrototype() {
   747         return ScriptFunction.getPrototype(builtinArray);
   748     }
   750     ScriptObject getBooleanPrototype() {
   751         return ScriptFunction.getPrototype(builtinBoolean);
   752     }
   754     ScriptObject getNumberPrototype() {
   755         return ScriptFunction.getPrototype(builtinNumber);
   756     }
   758     ScriptObject getDatePrototype() {
   759         return ScriptFunction.getPrototype(builtinDate);
   760     }
   762     ScriptObject getRegExpPrototype() {
   763         return ScriptFunction.getPrototype(builtinRegExp);
   764     }
   766     ScriptObject getStringPrototype() {
   767         return ScriptFunction.getPrototype(builtinString);
   768     }
   770     ScriptObject getErrorPrototype() {
   771         return ScriptFunction.getPrototype(builtinError);
   772     }
   774     ScriptObject getEvalErrorPrototype() {
   775         return ScriptFunction.getPrototype(builtinEvalError);
   776     }
   778     ScriptObject getRangeErrorPrototype() {
   779         return ScriptFunction.getPrototype(builtinRangeError);
   780     }
   782     ScriptObject getReferenceErrorPrototype() {
   783         return ScriptFunction.getPrototype(builtinReferenceError);
   784     }
   786     ScriptObject getSyntaxErrorPrototype() {
   787         return ScriptFunction.getPrototype(builtinSyntaxError);
   788     }
   790     ScriptObject getTypeErrorPrototype() {
   791         return ScriptFunction.getPrototype(builtinTypeError);
   792     }
   794     ScriptObject getURIErrorPrototype() {
   795         return ScriptFunction.getPrototype(builtinURIError);
   796     }
   798     ScriptObject getJavaImporterPrototype() {
   799         return ScriptFunction.getPrototype(builtinJavaImporter);
   800     }
   802     ScriptObject getJSAdapterPrototype() {
   803         return ScriptFunction.getPrototype(builtinJSAdapter);
   804     }
   806     ScriptObject getArrayBufferPrototype() {
   807         return ScriptFunction.getPrototype(builtinArrayBuffer);
   808     }
   810     ScriptObject getInt8ArrayPrototype() {
   811         return ScriptFunction.getPrototype(builtinInt8Array);
   812     }
   814     ScriptObject getUint8ArrayPrototype() {
   815         return ScriptFunction.getPrototype(builtinUint8Array);
   816     }
   818     ScriptObject getUint8ClampedArrayPrototype() {
   819         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
   820     }
   822     ScriptObject getInt16ArrayPrototype() {
   823         return ScriptFunction.getPrototype(builtinInt16Array);
   824     }
   826     ScriptObject getUint16ArrayPrototype() {
   827         return ScriptFunction.getPrototype(builtinUint16Array);
   828     }
   830     ScriptObject getInt32ArrayPrototype() {
   831         return ScriptFunction.getPrototype(builtinInt32Array);
   832     }
   834     ScriptObject getUint32ArrayPrototype() {
   835         return ScriptFunction.getPrototype(builtinUint32Array);
   836     }
   838     ScriptObject getFloat32ArrayPrototype() {
   839         return ScriptFunction.getPrototype(builtinFloat32Array);
   840     }
   842     ScriptObject getFloat64ArrayPrototype() {
   843         return ScriptFunction.getPrototype(builtinFloat64Array);
   844     }
   846     private ScriptFunction getBuiltinArray() {
   847         return builtinArray;
   848     }
   851     /**
   852      * Called from compiled script code to test if builtin has been overridden
   853      *
   854      * @return true if builtin array has not been overridden
   855      */
   856     public static boolean isBuiltinArray() {
   857         final Global instance = Global.instance();
   858         return instance.array == instance.getBuiltinArray();
   859     }
   861     private ScriptFunction getBuiltinBoolean() {
   862         return builtinBoolean;
   863     }
   865     /**
   866      * Called from compiled script code to test if builtin has been overridden
   867      *
   868      * @return true if builtin boolean has not been overridden
   869      */
   870     public static boolean isBuiltinBoolean() {
   871         final Global instance = Global.instance();
   872         return instance._boolean == instance.getBuiltinBoolean();
   873     }
   875     private ScriptFunction getBuiltinDate() {
   876         return builtinDate;
   877     }
   879     /**
   880      * Called from compiled script code to test if builtin has been overridden
   881      *
   882      * @return true if builtin date has not been overridden
   883      */
   884     public static boolean isBuiltinDate() {
   885         final Global instance = Global.instance();
   886         return instance.date == instance.getBuiltinDate();
   887     }
   889     private ScriptFunction getBuiltinError() {
   890         return builtinError;
   891     }
   893     /**
   894      * Called from compiled script code to test if builtin has been overridden
   895      *
   896      * @return true if builtin error has not been overridden
   897      */
   898     public static boolean isBuiltinError() {
   899         final Global instance = Global.instance();
   900         return instance.error == instance.getBuiltinError();
   901     }
   903     private ScriptFunction getBuiltinEvalError() {
   904         return builtinEvalError;
   905     }
   907     /**
   908      * Called from compiled script code to test if builtin has been overridden
   909      *
   910      * @return true if builtin eval error has not been overridden
   911      */
   912     public static boolean isBuiltinEvalError() {
   913         final Global instance = Global.instance();
   914         return instance.evalError == instance.getBuiltinEvalError();
   915     }
   917     private ScriptFunction getBuiltinFunction() {
   918         return builtinFunction;
   919     }
   921     /**
   922      * Called from compiled script code to test if builtin has been overridden
   923      *
   924      * @return true if builtin function has not been overridden
   925      */
   926     public static boolean isBuiltinFunction() {
   927         final Global instance = Global.instance();
   928         return instance.function == instance.getBuiltinFunction();
   929     }
   931     private ScriptFunction getBuiltinJSAdapter() {
   932         return builtinJSAdapter;
   933     }
   935     /**
   936      * Called from compiled script code to test if builtin has been overridden
   937      *
   938      * @return true if builtin JSAdapter has not been overridden
   939      */
   940     public static boolean isBuiltinJSAdapter() {
   941         final Global instance = Global.instance();
   942         return instance.jsadapter == instance.getBuiltinJSAdapter();
   943     }
   945     private ScriptObject getBuiltinJSON() {
   946         return builtinJSON;
   947     }
   949     /**
   950      * Called from compiled script code to test if builtin has been overridden
   951      *
   952      * @return true if builtin JSON has has not been overridden
   953      */
   954     public static boolean isBuiltinJSON() {
   955         final Global instance = Global.instance();
   956         return instance.json == instance.getBuiltinJSON();
   957     }
   959     private ScriptObject getBuiltinJava() {
   960         return builtinJava;
   961     }
   963     /**
   964      * Called from compiled script code to test if builtin has been overridden
   965      *
   966      * @return true if builtin Java has not been overridden
   967      */
   968     public static boolean isBuiltinJava() {
   969         final Global instance = Global.instance();
   970         return instance.java == instance.getBuiltinJava();
   971     }
   973     private ScriptObject getBuiltinJavax() {
   974         return builtinJavax;
   975     }
   977     /**
   978      * Called from compiled script code to test if builtin has been overridden
   979      *
   980      * @return true if builtin Javax has not been overridden
   981      */
   982     public static boolean isBuiltinJavax() {
   983         final Global instance = Global.instance();
   984         return instance.javax == instance.getBuiltinJavax();
   985     }
   987     private ScriptObject getBuiltinJavaImporter() {
   988         return builtinJavaImporter;
   989     }
   991     /**
   992      * Called from compiled script code to test if builtin has been overridden
   993      *
   994      * @return true if builtin Java importer has not been overridden
   995      */
   996     public static boolean isBuiltinJavaImporter() {
   997         final Global instance = Global.instance();
   998         return instance.javaImporter == instance.getBuiltinJavaImporter();
   999     }
  1001     private ScriptObject getBuiltinMath() {
  1002         return builtinMath;
  1005     /**
  1006      * Called from compiled script code to test if builtin has been overridden
  1008      * @return true if builtin math has not been overridden
  1009      */
  1010     public static boolean isBuiltinMath() {
  1011         final Global instance = Global.instance();
  1012         return instance.math == instance.getBuiltinMath();
  1015     private ScriptFunction getBuiltinNumber() {
  1016         return builtinNumber;
  1019     /**
  1020      * Called from compiled script code to test if builtin has been overridden
  1022      * @return true if builtin number has not been overridden
  1023      */
  1024     public static boolean isBuiltinNumber() {
  1025         final Global instance = Global.instance();
  1026         return instance.number == instance.getBuiltinNumber();
  1029     private ScriptFunction getBuiltinObject() {
  1030         return builtinObject;
  1033     /**
  1034      * Called from compiled script code to test if builtin has been overridden
  1036      * @return true if builtin object has not been overridden
  1037      */
  1038     public static boolean isBuiltinObject() {
  1039         final Global instance = Global.instance();
  1040         return instance.object == instance.getBuiltinObject();
  1043     private ScriptObject getBuiltinPackages() {
  1044         return builtinPackages;
  1047     /**
  1048      * Called from compiled script code to test if builtin has been overridden
  1050      * @return true if builtin package has not been overridden
  1051      */
  1052     public static boolean isBuiltinPackages() {
  1053         final Global instance = Global.instance();
  1054         return instance.packages == instance.getBuiltinPackages();
  1057     private ScriptFunction getBuiltinRangeError() {
  1058         return builtinRangeError;
  1061     /**
  1062      * Called from compiled script code to test if builtin has been overridden
  1064      * @return true if builtin range error has not been overridden
  1065      */
  1066     public static boolean isBuiltinRangeError() {
  1067         final Global instance = Global.instance();
  1068         return instance.rangeError == instance.getBuiltinRangeError();
  1071     private ScriptFunction getBuiltinReferenceError() {
  1072         return builtinReferenceError;
  1075     /**
  1076      * Called from compiled script code to test if builtin has been overridden
  1078      * @return true if builtin reference error has not been overridden
  1079      */
  1080     public static boolean isBuiltinReferenceError() {
  1081         final Global instance = Global.instance();
  1082         return instance.referenceError == instance.getBuiltinReferenceError();
  1085     private ScriptFunction getBuiltinRegExp() {
  1086         return builtinRegExp;
  1089     /**
  1090      * Called from compiled script code to test if builtin has been overridden
  1092      * @return true if builtin regexp has not been overridden
  1093      */
  1094     public static boolean isBuiltinRegExp() {
  1095         final Global instance = Global.instance();
  1096         return instance.regexp == instance.getBuiltinRegExp();
  1099     private ScriptFunction getBuiltinString() {
  1100         return builtinString;
  1103     /**
  1104      * Called from compiled script code to test if builtin has been overridden
  1106      * @return true if builtin Java has not been overridden
  1107      */
  1108     public static boolean isBuiltinString() {
  1109         final Global instance = Global.instance();
  1110         return instance.string == instance.getBuiltinString();
  1113     private ScriptFunction getBuiltinSyntaxError() {
  1114         return builtinSyntaxError;
  1117     /**
  1118      * Called from compiled script code to test if builtin has been overridden
  1120      * @return true if builtin syntax error has not been overridden
  1121      */
  1122     public static boolean isBuiltinSyntaxError() {
  1123         final Global instance = Global.instance();
  1124         return instance.syntaxError == instance.getBuiltinSyntaxError();
  1127     private ScriptFunction getBuiltinTypeError() {
  1128         return builtinTypeError;
  1131     /**
  1132      * Called from compiled script code to test if builtin has been overridden
  1134      * @return true if builtin type error has not been overridden
  1135      */
  1136     public static boolean isBuiltinTypeError() {
  1137         final Global instance = Global.instance();
  1138         return instance.typeError == instance.getBuiltinTypeError();
  1141     private ScriptFunction getBuiltinURIError() {
  1142         return builtinURIError;
  1145     /**
  1146      * Called from compiled script code to test if builtin has been overridden
  1148      * @return true if builtin URI error has not been overridden
  1149      */
  1150     public static boolean isBuiltinURIError() {
  1151         final Global instance = Global.instance();
  1152         return instance.uriError == instance.getBuiltinURIError();
  1155     @Override
  1156     public String getClassName() {
  1157         return "global";
  1160     /**
  1161      * Copy function used to clone NativeRegExp objects.
  1163      * @param regexp a NativeRegExp to clone
  1165      * @return copy of the given regexp object
  1166      */
  1167     public static Object regExpCopy(final Object regexp) {
  1168         return new NativeRegExp((NativeRegExp)regexp);
  1171     /**
  1172      * Convert given object to NativeRegExp type.
  1174      * @param obj object to be converted
  1175      * @return NativeRegExp instance
  1176      */
  1177     public static NativeRegExp toRegExp(final Object obj) {
  1178         if (obj instanceof NativeRegExp) {
  1179             return (NativeRegExp)obj;
  1181         return new NativeRegExp(JSType.toString(obj));
  1184     /**
  1185      * ECMA 9.9 ToObject implementation
  1187      * @param obj  an item for which to run ToObject
  1188      * @return ToObject version of given item
  1189      */
  1190     public static Object toObject(final Object obj) {
  1191         if (obj == null || obj == UNDEFINED) {
  1192             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1195         if (obj instanceof ScriptObject) {
  1196             return obj;
  1199         return instance().wrapAsObject(obj);
  1202     /**
  1203      * Allocate a new object array.
  1205      * @param initial object values.
  1206      * @return the new array
  1207      */
  1208     public static NativeArray allocate(final Object[] initial) {
  1209         return new NativeArray(initial);
  1212     /**
  1213      * Allocate a new number array.
  1215      * @param initial number values.
  1216      * @return the new array
  1217      */
  1218     public static NativeArray allocate(final double[] initial) {
  1219         return new NativeArray(initial);
  1222     /**
  1223      * Allocate a new long array.
  1225      * @param initial number values.
  1226      * @return the new array
  1227      */
  1228     public static NativeArray allocate(final long[] initial) {
  1229         return new NativeArray(initial);
  1232     /**
  1233      * Allocate a new integer array.
  1235      * @param initial number values.
  1236      * @return the new array
  1237      */
  1238     public static NativeArray allocate(final int[] initial) {
  1239         return new NativeArray(initial);
  1242     /**
  1243      * Allocate a new object array for arguments.
  1245      * @param arguments initial arguments passed.
  1246      * @param callee reference to the function that uses arguments object
  1247      * @param numParams actual number of declared parameters
  1249      * @return the new array
  1250      */
  1251     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
  1252         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
  1255     /**
  1256      * Called from generated to check if given function is the builtin 'eval'. If
  1257      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
  1259      * @param  fn function object that is checked
  1260      * @return true if fn is the builtin eval
  1261      */
  1262     public static boolean isEval(final Object fn) {
  1263         return fn == Global.instance().builtinEval;
  1266     /**
  1267      * Create a new RegExp object.
  1269      * @param expression Regular expression.
  1270      * @param options    Search options.
  1272      * @return New RegExp object.
  1273      */
  1274     public static Object newRegExp(final String expression, final String options) {
  1275         if (options == null) {
  1276             return new NativeRegExp(expression);
  1278         return new NativeRegExp(expression, options);
  1281     /**
  1282      * Get the object prototype
  1284      * @return the object prototype
  1285      */
  1286     public static ScriptObject objectPrototype() {
  1287         return Global.instance().getObjectPrototype();
  1290     /**
  1291      * Create a new empty object instance.
  1293      * @return New empty object.
  1294      */
  1295     public static ScriptObject newEmptyInstance() {
  1296         final ScriptObject sobj = new JO();
  1297         sobj.setProto(objectPrototype());
  1298         return sobj;
  1301     /**
  1302      * Check if a given object is a ScriptObject, raises an exception if this is
  1303      * not the case
  1305      * @param obj and object to check
  1306      */
  1307     public static void checkObject(final Object obj) {
  1308         if (!(obj instanceof ScriptObject)) {
  1309             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1313     /**
  1314      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
  1315      * if this object is null or undefined.
  1317      * @param obj an object to check
  1318      */
  1319     public static void checkObjectCoercible(final Object obj) {
  1320         if (obj == null || obj == UNDEFINED) {
  1321             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1325     /**
  1326      * Get the current split state.
  1328      * @return current split state
  1329      */
  1330     @Override
  1331     public int getSplitState() {
  1332         return splitState;
  1335     /**
  1336      * Set the current split state.
  1338      * @param state current split state
  1339      */
  1340     @Override
  1341     public void setSplitState(final int state) {
  1342         splitState = state;
  1345     private void init() {
  1346         assert Context.getGlobal() == this : "this global is not set as current";
  1348         final ScriptEnvironment env = context.getEnv();
  1349         // initialize Function and Object constructor
  1350         initFunctionAndObject();
  1352         // Now fix Global's own proto.
  1353         this.setProto(getObjectPrototype());
  1355         // initialize global function properties
  1356         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  1358         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
  1359         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  1360         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
  1361         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
  1362         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
  1363         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
  1364         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
  1365         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
  1366         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
  1367         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
  1368         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
  1369         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
  1370         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
  1371         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
  1373         // built-in constructors
  1374         this.builtinArray     = (ScriptFunction)initConstructor("Array");
  1375         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
  1376         this.builtinDate      = (ScriptFunction)initConstructor("Date");
  1377         this.builtinJSON      = initConstructor("JSON");
  1378         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
  1379         this.builtinMath      = initConstructor("Math");
  1380         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
  1381         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
  1382         this.builtinString    = (ScriptFunction)initConstructor("String");
  1384         // initialize String.prototype.length to 0
  1385         // add String.prototype.length
  1386         final ScriptObject stringPrototype = getStringPrototype();
  1387         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  1389         // add Array.prototype.length
  1390         final ScriptObject arrayPrototype = getArrayPrototype();
  1391         arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0);
  1393         this.DEFAULT_DATE = new NativeDate(Double.NaN);
  1395         // initialize default regexp object
  1396         this.DEFAULT_REGEXP = new NativeRegExp("(?:)");
  1398         // RegExp.prototype should behave like a RegExp object. So copy the
  1399         // properties.
  1400         final ScriptObject regExpProto = getRegExpPrototype();
  1401         regExpProto.addBoundProperties(DEFAULT_REGEXP);
  1403         // Error stuff
  1404         initErrorObjects();
  1406         // java access
  1407         initJavaAccess();
  1409         initTypedArray();
  1411         if (env._scripting) {
  1412             initScripting();
  1415         if (Context.DEBUG && System.getSecurityManager() == null) {
  1416             initDebug();
  1419         copyBuiltins();
  1421         // initialized with strings so that typeof will work as expected.
  1422         this.__FILE__ = "";
  1423         this.__DIR__  = "";
  1424         this.__LINE__ = 0.0;
  1426         // expose script (command line) arguments as "arguments" property of global
  1427         final List<String> arguments = env.getArguments();
  1428         final Object argsObj = wrapAsObject(arguments.toArray());
  1430         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
  1431         if (env._scripting) {
  1432             // synonym for "arguments" in scripting mode
  1433             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
  1437     private void initErrorObjects() {
  1438         // Error objects
  1439         this.builtinError = (ScriptFunction)initConstructor("Error");
  1440         final ScriptObject errorProto = getErrorPrototype();
  1441         final boolean strict = Global.isStrict();
  1443         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
  1444         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
  1445         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
  1446         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
  1447         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
  1448         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
  1449         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
  1450         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
  1451         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
  1452         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
  1453         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
  1454         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
  1455         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
  1457         // ECMA 15.11.4.2 Error.prototype.name
  1458         // Error.prototype.name = "Error";
  1459         errorProto.set(NativeError.NAME, "Error", strict);
  1460         // ECMA 15.11.4.3 Error.prototype.message
  1461         // Error.prototype.message = "";
  1462         errorProto.set(NativeError.MESSAGE, "", strict);
  1464         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
  1465         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
  1466         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
  1467         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
  1468         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
  1469         this.builtinURIError = initErrorSubtype("URIError", errorProto);
  1472     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
  1473         final ScriptObject cons = initConstructor(name);
  1474         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  1475         final boolean strict = Global.isStrict();
  1476         prototype.set(NativeError.NAME, name, strict);
  1477         prototype.set(NativeError.MESSAGE, "", strict);
  1478         prototype.setProto(errorProto);
  1479         return (ScriptFunction)cons;
  1482     private void initJavaAccess() {
  1483         final ScriptObject objectProto = getObjectPrototype();
  1484         this.builtinPackages = new NativeJavaPackage("", objectProto);
  1485         this.builtinJava = new NativeJavaPackage("java", objectProto);
  1486         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
  1487         this.builtinJavaImporter = initConstructor("JavaImporter");
  1488         this.builtinJavaApi = initConstructor("Java");
  1491     private void initScripting() {
  1492         Object value;
  1493         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
  1494         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
  1496         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
  1497         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
  1499         final String execName = ScriptingFunctions.EXEC_NAME;
  1500         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
  1501         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
  1503         // Nashorn extension: global.echo (scripting-mode-only)
  1504         // alias for "print"
  1505         value = get("print");
  1506         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
  1508         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
  1509         final ScriptObject options = newEmptyInstance();
  1510         final ScriptEnvironment scriptEnv = context.getEnv();
  1511         copyOptions(options, scriptEnv);
  1512         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
  1514         // Nashorn extension: global.$ENV (scripting-mode-only)
  1515         if (System.getSecurityManager() == null) {
  1516             // do not fill $ENV if we have a security manager around
  1517             // Retrieve current state of ENV variables.
  1518             final ScriptObject env = newEmptyInstance();
  1519             env.putAll(System.getenv());
  1520             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
  1521         } else {
  1522             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1525         // add other special properties for exec support
  1526         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1527         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1528         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1531     private void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
  1532         AccessController.doPrivileged(new PrivilegedAction<Void>() {
  1533             public Void run() {
  1534                 for (Field f : scriptEnv.getClass().getFields()) {
  1535                     try {
  1536                         options.set(f.getName(), f.get(scriptEnv), false);
  1537                     } catch (final IllegalArgumentException | IllegalAccessException exp) {
  1538                         throw new RuntimeException(exp);
  1541                 return null;
  1543         });
  1546     private void initTypedArray() {
  1547         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
  1548         this.builtinInt8Array         = initConstructor("Int8Array");
  1549         this.builtinUint8Array        = initConstructor("Uint8Array");
  1550         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
  1551         this.builtinInt16Array        = initConstructor("Int16Array");
  1552         this.builtinUint16Array       = initConstructor("Uint16Array");
  1553         this.builtinInt32Array        = initConstructor("Int32Array");
  1554         this.builtinUint32Array       = initConstructor("Uint32Array");
  1555         this.builtinFloat32Array      = initConstructor("Float32Array");
  1556         this.builtinFloat64Array      = initConstructor("Float64Array");
  1559     private void copyBuiltins() {
  1560         this.array             = this.builtinArray;
  1561         this._boolean          = this.builtinBoolean;
  1562         this.date              = this.builtinDate;
  1563         this.error             = this.builtinError;
  1564         this.evalError         = this.builtinEvalError;
  1565         this.function          = this.builtinFunction;
  1566         this.jsadapter         = this.builtinJSAdapter;
  1567         this.json              = this.builtinJSON;
  1568         this.java              = this.builtinJava;
  1569         this.javax             = this.builtinJavax;
  1570         this.javaImporter      = this.builtinJavaImporter;
  1571         this.javaApi           = this.builtinJavaApi;
  1572         this.math              = this.builtinMath;
  1573         this.number            = this.builtinNumber;
  1574         this.object            = this.builtinObject;
  1575         this.packages          = this.builtinPackages;
  1576         this.rangeError        = this.builtinRangeError;
  1577         this.referenceError    = this.builtinReferenceError;
  1578         this.regexp            = this.builtinRegExp;
  1579         this.string            = this.builtinString;
  1580         this.syntaxError       = this.builtinSyntaxError;
  1581         this.typeError         = this.builtinTypeError;
  1582         this.uriError          = this.builtinURIError;
  1583         this.arrayBuffer       = this.builtinArrayBuffer;
  1584         this.int8Array         = this.builtinInt8Array;
  1585         this.uint8Array        = this.builtinUint8Array;
  1586         this.uint8ClampedArray = this.builtinUint8ClampedArray;
  1587         this.int16Array        = this.builtinInt16Array;
  1588         this.uint16Array       = this.builtinUint16Array;
  1589         this.int32Array        = this.builtinInt32Array;
  1590         this.uint32Array       = this.builtinUint32Array;
  1591         this.float32Array      = this.builtinFloat32Array;
  1592         this.float64Array      = this.builtinFloat64Array;
  1595     private void initDebug() {
  1596         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
  1599     @SuppressWarnings("resource")
  1600     private static Object printImpl(final boolean newLine, final Object... objects) {
  1601         final PrintWriter out = Global.getEnv().getOut();
  1603         boolean first = true;
  1604         for (final Object object : objects) {
  1605             if (first) {
  1606                 first = false;
  1607             } else {
  1608                 out.print(' ');
  1611             out.print(JSType.toString(object));
  1614         if (newLine) {
  1615             out.println();
  1618         out.flush();
  1620         return UNDEFINED;
  1623     /**
  1624      * These classes are generated by nasgen tool and so we have to use
  1625      * reflection to load and create new instance of these classes.
  1626      */
  1627     private ScriptObject initConstructor(final String name) {
  1628         try {
  1629             // Assuming class name pattern for built-in JS constructors.
  1630             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
  1632             sb.append("Native");
  1633             sb.append(name);
  1634             sb.append("$Constructor");
  1636             final Class<?>     funcClass = Class.forName(sb.toString());
  1637             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
  1639             if (res instanceof ScriptFunction) {
  1640                 // All global constructor prototypes are not-writable,
  1641                 // not-enumerable and not-configurable.
  1642                 final ScriptFunction func = (ScriptFunction)res;
  1643                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
  1646             if (res.getProto() == null) {
  1647                 res.setProto(getObjectPrototype());
  1650             return res;
  1652         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  1653             throw new RuntimeException(e);
  1657     // Function and Object constructors are inter-dependent. Also,
  1658     // Function.prototype
  1659     // functions are not properly initialized. We fix the references here.
  1660     // NOTE: be careful if you want to re-order the operations here. You may
  1661     // have
  1662     // to play with object references carefully!!
  1663     private void initFunctionAndObject() {
  1664         // First-n-foremost is Function
  1665         this.builtinFunction = (ScriptFunction)initConstructor("Function");
  1667         // create global anonymous function
  1668         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
  1669         // need to copy over members of Function.prototype to anon function
  1670         anon.addBoundProperties(getFunctionPrototype());
  1672         // Function.prototype === Object.getPrototypeOf(Function) ===
  1673         // <anon-function>
  1674         builtinFunction.setProto(anon);
  1675         builtinFunction.setPrototype(anon);
  1676         anon.set("constructor", builtinFunction, anon.isStrict());
  1677         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  1679         // now initialize Object
  1680         this.builtinObject = (ScriptFunction)initConstructor("Object");
  1681         final ScriptObject ObjectPrototype = getObjectPrototype();
  1682         // Object.getPrototypeOf(Function.prototype) === Object.prototype
  1683         anon.setProto(ObjectPrototype);
  1685         // Function valued properties of Function.prototype were not properly
  1686         // initialized. Because, these were created before global.function and
  1687         // global.object were not initialized.
  1688         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
  1689         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1690             final Object key = property.getKey();
  1691             final Object value = builtinFunction.get(key);
  1693             if (value instanceof ScriptFunction && value != anon) {
  1694                 final ScriptFunction func = (ScriptFunction)value;
  1695                 func.setProto(getFunctionPrototype());
  1696                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1697                 if (prototype != null) {
  1698                     prototype.setProto(ObjectPrototype);
  1703         // For function valued properties of Object and Object.prototype, make
  1704         // sure prototype's proto chain ends with Object.prototype
  1705         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
  1706             final Object key = property.getKey();
  1707             final Object value = builtinObject.get(key);
  1709             if (value instanceof ScriptFunction) {
  1710                 final ScriptFunction func = (ScriptFunction)value;
  1711                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1712                 if (prototype != null) {
  1713                     prototype.setProto(ObjectPrototype);
  1718         properties = getObjectPrototype().getMap().getProperties();
  1719         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1720             final Object key   = property.getKey();
  1721             final Object value = ObjectPrototype.get(key);
  1723             if (key.equals("constructor")) {
  1724                 continue;
  1727             if (value instanceof ScriptFunction) {
  1728                 final ScriptFunction func = (ScriptFunction)value;
  1729                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1730                 if (prototype != null) {
  1731                     prototype.setProto(ObjectPrototype);
  1738     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
  1739         return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types));
  1742     RegExpResult getLastRegExpResult() {
  1743         return lastRegExpResult;
  1746     void setLastRegExpResult(final RegExpResult regExpResult) {
  1747         this.lastRegExpResult = regExpResult;

mercurial