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

Fri, 17 Jan 2014 20:09:47 +0530

author
sundar
date
Fri, 17 Jan 2014 20:09:47 +0530
changeset 760
aef781b882c0
parent 690
752554d45a07
child 766
06ee95f094b4
permissions
-rw-r--r--

8032060: PropertyMap of Error objects is not stable
Reviewed-by: jlaskey, hannesw

     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.lookup.Lookup.MH;
    29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    30 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    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.ReferenceQueue;
    37 import java.lang.ref.SoftReference;
    38 import java.lang.reflect.Field;
    39 import java.util.Arrays;
    40 import java.util.LinkedHashMap;
    41 import java.util.List;
    42 import java.util.Map;
    43 import java.util.concurrent.Callable;
    44 import java.util.concurrent.ConcurrentHashMap;
    45 import jdk.internal.dynalink.linker.GuardedInvocation;
    46 import jdk.internal.dynalink.linker.LinkRequest;
    47 import jdk.nashorn.internal.lookup.Lookup;
    48 import jdk.nashorn.internal.objects.annotations.Attribute;
    49 import jdk.nashorn.internal.objects.annotations.Property;
    50 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    51 import jdk.nashorn.internal.runtime.ConsString;
    52 import jdk.nashorn.internal.runtime.Context;
    53 import jdk.nashorn.internal.runtime.GlobalFunctions;
    54 import jdk.nashorn.internal.runtime.GlobalObject;
    55 import jdk.nashorn.internal.runtime.JSType;
    56 import jdk.nashorn.internal.runtime.NativeJavaPackage;
    57 import jdk.nashorn.internal.runtime.PropertyDescriptor;
    58 import jdk.nashorn.internal.runtime.PropertyMap;
    59 import jdk.nashorn.internal.runtime.Scope;
    60 import jdk.nashorn.internal.runtime.ScriptEnvironment;
    61 import jdk.nashorn.internal.runtime.ScriptFunction;
    62 import jdk.nashorn.internal.runtime.ScriptObject;
    63 import jdk.nashorn.internal.runtime.ScriptRuntime;
    64 import jdk.nashorn.internal.runtime.ScriptingFunctions;
    65 import jdk.nashorn.internal.runtime.Source;
    66 import jdk.nashorn.internal.runtime.arrays.ArrayData;
    67 import jdk.nashorn.internal.runtime.linker.Bootstrap;
    68 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    69 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    70 import jdk.nashorn.internal.scripts.JO;
    72 /**
    73  * Representation of global scope.
    74  */
    75 @ScriptClass("Global")
    76 public final class Global extends ScriptObject implements GlobalObject, Scope {
    77     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    78     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
    80     /** ECMA 15.1.2.2 parseInt (string , radix) */
    81     @Property(attributes = Attribute.NOT_ENUMERABLE)
    82     public Object parseInt;
    84     /** ECMA 15.1.2.3 parseFloat (string) */
    85     @Property(attributes = Attribute.NOT_ENUMERABLE)
    86     public Object parseFloat;
    88     /** ECMA 15.1.2.4 isNaN (number) */
    89     @Property(attributes = Attribute.NOT_ENUMERABLE)
    90     public Object isNaN;
    92     /** ECMA 15.1.2.5 isFinite (number) */
    93     @Property(attributes = Attribute.NOT_ENUMERABLE)
    94     public Object isFinite;
    96     /** ECMA 15.1.3.3 encodeURI */
    97     @Property(attributes = Attribute.NOT_ENUMERABLE)
    98     public Object encodeURI;
   100     /** ECMA 15.1.3.4 encodeURIComponent */
   101     @Property(attributes = Attribute.NOT_ENUMERABLE)
   102     public Object encodeURIComponent;
   104     /** ECMA 15.1.3.1 decodeURI */
   105     @Property(attributes = Attribute.NOT_ENUMERABLE)
   106     public Object decodeURI;
   108     /** ECMA 15.1.3.2 decodeURIComponent */
   109     @Property(attributes = Attribute.NOT_ENUMERABLE)
   110     public Object decodeURIComponent;
   112     /** ECMA B.2.1 escape (string) */
   113     @Property(attributes = Attribute.NOT_ENUMERABLE)
   114     public Object escape;
   116     /** ECMA B.2.2 unescape (string) */
   117     @Property(attributes = Attribute.NOT_ENUMERABLE)
   118     public Object unescape;
   120     /** Nashorn extension: global.print */
   121     @Property(attributes = Attribute.NOT_ENUMERABLE)
   122     public Object print;
   124     /** Nashorn extension: global.load */
   125     @Property(attributes = Attribute.NOT_ENUMERABLE)
   126     public Object load;
   128     /** Nashorn extension: global.loadWithNewGlobal */
   129     @Property(attributes = Attribute.NOT_ENUMERABLE)
   130     public Object loadWithNewGlobal;
   132     /** Nashorn extension: global.exit */
   133     @Property(attributes = Attribute.NOT_ENUMERABLE)
   134     public Object exit;
   136     /** Nashorn extension: global.quit */
   137     @Property(attributes = Attribute.NOT_ENUMERABLE)
   138     public Object quit;
   140     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
   141     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   142     public final Object NaN = Double.NaN;
   144     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
   145     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   146     public final Object Infinity = Double.POSITIVE_INFINITY;
   148     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
   149     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   150     public final Object undefined = UNDEFINED;
   152     /** ECMA 15.1.2.1 eval(x) */
   153     @Property(attributes = Attribute.NOT_ENUMERABLE)
   154     public Object eval;
   156     /** ECMA 15.1.4.1 Object constructor. */
   157     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
   158     public volatile Object object;
   160     /** ECMA 15.1.4.2 Function constructor. */
   161     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
   162     public volatile Object function;
   164     /** ECMA 15.1.4.3 Array constructor. */
   165     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
   166     public volatile Object array;
   168     /** ECMA 15.1.4.4 String constructor */
   169     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
   170     public volatile Object string;
   172     /** ECMA 15.1.4.5 Boolean constructor */
   173     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
   174     public volatile Object _boolean;
   176     /** ECMA 15.1.4.6 - Number constructor */
   177     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
   178     public volatile Object number;
   180     /** ECMA 15.1.4.7 Date constructor */
   181     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   182     public volatile Object date;
   184     /** ECMA 15.1.4.8 RegExp constructor */
   185     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   186     public volatile Object regexp;
   188     /** ECMA 15.12 - The JSON object */
   189     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   190     public volatile Object json;
   192     /** Nashorn extension: global.JSAdapter */
   193     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   194     public volatile Object jsadapter;
   196     /** ECMA 15.8 - The Math object */
   197     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
   198     public volatile Object math;
   200     /** Error object */
   201     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
   202     public volatile Object error;
   204     /** EvalError object */
   205     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   206     public volatile Object evalError;
   208     /** RangeError object */
   209     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   210     public volatile Object rangeError;
   212     /** ReferenceError object */
   213     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
   214     public volatile Object referenceError;
   216     /** SyntaxError object */
   217     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
   218     public volatile Object syntaxError;
   220     /** TypeError object */
   221     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
   222     public volatile Object typeError;
   224     /** URIError object */
   225     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   226     public volatile Object uriError;
   228     /** ArrayBuffer object */
   229     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   230     public volatile Object arrayBuffer;
   232     /** TypedArray (int8) */
   233     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   234     public volatile Object int8Array;
   236     /** TypedArray (uint8) */
   237     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   238     public volatile Object uint8Array;
   240     /** TypedArray (uint8) - Clamped */
   241     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   242     public volatile Object uint8ClampedArray;
   244     /** TypedArray (int16) */
   245     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   246     public volatile Object int16Array;
   248     /** TypedArray (uint16) */
   249     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   250     public volatile Object uint16Array;
   252     /** TypedArray (int32) */
   253     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   254     public volatile Object int32Array;
   256     /** TypedArray (uint32) */
   257     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   258     public volatile Object uint32Array;
   260     /** TypedArray (float32) */
   261     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   262     public volatile Object float32Array;
   264     /** TypedArray (float64) */
   265     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   266     public volatile Object float64Array;
   268     /** Nashorn extension: Java access - global.Packages */
   269     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
   270     public volatile Object packages;
   272     /** Nashorn extension: Java access - global.com */
   273     @Property(attributes = Attribute.NOT_ENUMERABLE)
   274     public volatile Object com;
   276     /** Nashorn extension: Java access - global.edu */
   277     @Property(attributes = Attribute.NOT_ENUMERABLE)
   278     public volatile Object edu;
   280     /** Nashorn extension: Java access - global.java */
   281     @Property(attributes = Attribute.NOT_ENUMERABLE)
   282     public volatile Object java;
   284     /** Nashorn extension: Java access - global.javafx */
   285     @Property(attributes = Attribute.NOT_ENUMERABLE)
   286     public volatile Object javafx;
   288     /** Nashorn extension: Java access - global.javax */
   289     @Property(attributes = Attribute.NOT_ENUMERABLE)
   290     public volatile Object javax;
   292     /** Nashorn extension: Java access - global.org */
   293     @Property(attributes = Attribute.NOT_ENUMERABLE)
   294     public volatile Object org;
   296     /** Nashorn extension: Java access - global.javaImporter */
   297     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   298     public volatile Object javaImporter;
   300     /** Nashorn extension: global.Java Object constructor. */
   301     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   302     public volatile Object javaApi;
   304     /** Nashorn extension: current script's file name */
   305     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   306     public Object __FILE__;
   308     /** Nashorn extension: current script's directory */
   309     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   310     public Object __DIR__;
   312     /** Nashorn extension: current source line number being executed */
   313     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   314     public Object __LINE__;
   316     /** Used as Date.prototype's default value */
   317     public NativeDate   DEFAULT_DATE;
   319     /** Used as RegExp.prototype's default value */
   320     public NativeRegExp DEFAULT_REGEXP;
   322     /*
   323      * Built-in constructor objects: Even if user changes dynamic values of
   324      * "Object", "Array" etc., we still want to keep original values of these
   325      * constructors here. For example, we need to be able to create array,
   326      * regexp literals even after user overwrites global "Array" or "RegExp"
   327      * constructor - see also ECMA 262 spec. Annex D.
   328      */
   329     private ScriptFunction builtinFunction;
   330     private ScriptFunction builtinObject;
   331     private ScriptFunction builtinArray;
   332     private ScriptFunction builtinBoolean;
   333     private ScriptFunction builtinDate;
   334     private ScriptObject   builtinJSON;
   335     private ScriptFunction builtinJSAdapter;
   336     private ScriptObject   builtinMath;
   337     private ScriptFunction builtinNumber;
   338     private ScriptFunction builtinRegExp;
   339     private ScriptFunction builtinString;
   340     private ScriptFunction builtinError;
   341     private ScriptFunction builtinEval;
   342     private ScriptFunction builtinEvalError;
   343     private ScriptFunction builtinRangeError;
   344     private ScriptFunction builtinReferenceError;
   345     private ScriptFunction builtinSyntaxError;
   346     private ScriptFunction builtinTypeError;
   347     private ScriptFunction builtinURIError;
   348     private ScriptObject   builtinPackages;
   349     private ScriptObject   builtinCom;
   350     private ScriptObject   builtinEdu;
   351     private ScriptObject   builtinJava;
   352     private ScriptObject   builtinJavafx;
   353     private ScriptObject   builtinJavax;
   354     private ScriptObject   builtinOrg;
   355     private ScriptObject   builtinJavaImporter;
   356     private ScriptObject   builtinJavaApi;
   357     private ScriptObject   builtinArrayBuffer;
   358     private ScriptObject   builtinInt8Array;
   359     private ScriptObject   builtinUint8Array;
   360     private ScriptObject   builtinUint8ClampedArray;
   361     private ScriptObject   builtinInt16Array;
   362     private ScriptObject   builtinUint16Array;
   363     private ScriptObject   builtinInt32Array;
   364     private ScriptObject   builtinUint32Array;
   365     private ScriptObject   builtinFloat32Array;
   366     private ScriptObject   builtinFloat64Array;
   368     /*
   369      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
   370      */
   371     private ScriptFunction typeErrorThrower;
   373     private PropertyMap    accessorPropertyDescriptorMap;
   374     private PropertyMap    arrayBufferViewMap;
   375     private PropertyMap    dataPropertyDescriptorMap;
   376     private PropertyMap    genericPropertyDescriptorMap;
   377     private PropertyMap    nativeArgumentsMap;
   378     private PropertyMap    nativeArrayMap;
   379     private PropertyMap    nativeArrayBufferMap;
   380     private PropertyMap    nativeBooleanMap;
   381     private PropertyMap    nativeDateMap;
   382     private PropertyMap    nativeErrorMap;
   383     private PropertyMap    nativeEvalErrorMap;
   384     private PropertyMap    nativeJSAdapterMap;
   385     private PropertyMap    nativeJavaImporterMap;
   386     private PropertyMap    nativeNumberMap;
   387     private PropertyMap    nativeRangeErrorMap;
   388     private PropertyMap    nativeReferenceErrorMap;
   389     private PropertyMap    nativeRegExpMap;
   390     private PropertyMap    nativeRegExpExecResultMap;
   391     private PropertyMap    nativeStrictArgumentsMap;
   392     private PropertyMap    nativeStringMap;
   393     private PropertyMap    nativeSyntaxErrorMap;
   394     private PropertyMap    nativeTypeErrorMap;
   395     private PropertyMap    nativeURIErrorMap;
   396     private PropertyMap    prototypeObjectMap;
   397     private PropertyMap    objectMap;
   398     private PropertyMap    functionMap;
   399     private PropertyMap    anonymousFunctionMap;
   400     private PropertyMap    strictFunctionMap;
   401     private PropertyMap    boundFunctionMap;
   403     // Flag to indicate that a split method issued a return statement
   404     private int splitState = -1;
   406     // class cache
   407     private ClassCache classCache;
   409     // Used to store the last RegExp result to support deprecated RegExp constructor properties
   410     private RegExpResult lastRegExpResult;
   412     private static final MethodHandle EVAL              = findOwnMH("eval",              Object.class, Object.class, Object.class);
   413     private static final MethodHandle PRINT             = findOwnMH("print",             Object.class, Object.class, Object[].class);
   414     private static final MethodHandle PRINTLN           = findOwnMH("println",           Object.class, Object.class, Object[].class);
   415     private static final MethodHandle LOAD              = findOwnMH("load",              Object.class, Object.class, Object.class);
   416     private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
   417     private static final MethodHandle EXIT              = findOwnMH("exit",              Object.class, Object.class, Object.class);
   419     // initialized by nasgen
   420     private static PropertyMap $nasgenmap$;
   422     // context to which this global belongs to
   423     private final Context context;
   425     @Override
   426     protected Context getContext() {
   427         return context;
   428     }
   430     // performs initialization checks for Global constructor and returns the
   431     // PropertyMap, if everything is fine.
   432     private static PropertyMap checkAndGetMap(final Context context) {
   433         // security check first
   434         final SecurityManager sm = System.getSecurityManager();
   435         if (sm != null) {
   436             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
   437         }
   439         // null check on context
   440         context.getClass();
   442         /*
   443          * Duplicate global's map and use it. This way the initial Map filled
   444          * by nasgen (referenced from static field in this class) is retained
   445          * 'as is' (as that one is process wide singleton.
   446          */
   447         return $nasgenmap$.duplicate();
   448     }
   450     /**
   451      * Constructor
   452      *
   453      * @param context the context
   454      */
   455     public Global(final Context context) {
   456         super(checkAndGetMap(context));
   457         this.context = context;
   458         this.setIsScope();
   460         final int cacheSize = context.getEnv()._class_cache_size;
   461         if (cacheSize > 0) {
   462             classCache = new ClassCache(cacheSize);
   463         }
   464     }
   466     /**
   467      * Script access to "current" Global instance
   468      *
   469      * @return the global singleton
   470      */
   471     public static Global instance() {
   472         ScriptObject global = Context.getGlobal();
   473         if (! (global instanceof Global)) {
   474             throw new IllegalStateException("no current global instance");
   475         }
   476         return (Global)global;
   477     }
   479     /**
   480      * Script access to {@link ScriptEnvironment}
   481      *
   482      * @return the script environment
   483      */
   484     static ScriptEnvironment getEnv() {
   485         return instance().getContext().getEnv();
   486     }
   488     /**
   489      * Script access to {@link Context}
   490      *
   491      * @return the context
   492      */
   493     static Context getThisContext() {
   494         return instance().getContext();
   495     }
   497     // GlobalObject interface implementation
   499     @Override
   500     public boolean isOfContext(final Context ctxt) {
   501         return this.context == ctxt;
   502     }
   504     @Override
   505     public boolean isStrictContext() {
   506         return context.getEnv()._strict;
   507     }
   509     @Override
   510     public void initBuiltinObjects() {
   511         if (this.builtinObject != null) {
   512             // already initialized, just return
   513             return;
   514         }
   516         init();
   517     }
   519     @Override
   520     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
   521         return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
   522     }
   524     @Override
   525     public Object wrapAsObject(final Object obj) {
   526         if (obj instanceof Boolean) {
   527             return new NativeBoolean((Boolean)obj, this);
   528         } else if (obj instanceof Number) {
   529             return new NativeNumber(((Number)obj).doubleValue(), this);
   530         } else if (obj instanceof String || obj instanceof ConsString) {
   531             return new NativeString((CharSequence)obj, this);
   532         } else if (obj instanceof Object[]) { // extension
   533             return new NativeArray((Object[])obj);
   534         } else if (obj instanceof double[]) { // extension
   535             return new NativeArray((double[])obj);
   536         } else if (obj instanceof long[]) {
   537             return new NativeArray((long[])obj);
   538         } else if (obj instanceof int[]) {
   539             return new NativeArray((int[])obj);
   540         } else {
   541             // FIXME: more special cases? Map? List?
   542             return obj;
   543         }
   544     }
   546     @Override
   547     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
   548         if (self instanceof String || self instanceof ConsString) {
   549             return NativeString.lookupPrimitive(request, self);
   550         } else if (self instanceof Number) {
   551             return NativeNumber.lookupPrimitive(request, self);
   552         } else if (self instanceof Boolean) {
   553             return NativeBoolean.lookupPrimitive(request, self);
   554         }
   555         throw new IllegalArgumentException("Unsupported primitive: " + self);
   556     }
   558     @Override
   559     public ScriptObject newObject() {
   560         return new JO(getObjectPrototype(), getObjectMap());
   561     }
   563     @Override
   564     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
   565         // When the [[DefaultValue]] internal method of O is called with no hint,
   566         // then it behaves as if the hint were Number, unless O is a Date object
   567         // in which case it behaves as if the hint were String.
   568         Class<?> hint = typeHint;
   569         if (hint == null) {
   570             hint = Number.class;
   571         }
   573         try {
   574             if (hint == String.class) {
   576                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   578                 if (Bootstrap.isCallable(toString)) {
   579                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   580                     if (JSType.isPrimitive(value)) {
   581                         return value;
   582                     }
   583                 }
   585                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   586                 if (Bootstrap.isCallable(valueOf)) {
   587                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   588                     if (JSType.isPrimitive(value)) {
   589                         return value;
   590                     }
   591                 }
   592                 throw typeError(this, "cannot.get.default.string");
   593             }
   595             if (hint == Number.class) {
   596                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   597                 if (Bootstrap.isCallable(valueOf)) {
   598                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   599                     if (JSType.isPrimitive(value)) {
   600                         return value;
   601                     }
   602                 }
   604                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   605                 if (Bootstrap.isCallable(toString)) {
   606                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   607                     if (JSType.isPrimitive(value)) {
   608                         return value;
   609                     }
   610                 }
   612                 throw typeError(this, "cannot.get.default.number");
   613             }
   614         } catch (final RuntimeException | Error e) {
   615             throw e;
   616         } catch (final Throwable t) {
   617             throw new RuntimeException(t);
   618         }
   620         return UNDEFINED;
   621     }
   623     @Override
   624     public boolean isError(final ScriptObject sobj) {
   625         final ScriptObject errorProto = getErrorPrototype();
   626         ScriptObject proto = sobj.getProto();
   627         while (proto != null) {
   628             if (proto == errorProto) {
   629                 return true;
   630             }
   631             proto = proto.getProto();
   632         }
   633         return false;
   634     }
   636     @Override
   637     public ScriptObject newError(final String msg) {
   638         return new NativeError(msg, this);
   639     }
   641     @Override
   642     public ScriptObject newEvalError(final String msg) {
   643         return new NativeEvalError(msg, this);
   644     }
   646     @Override
   647     public ScriptObject newRangeError(final String msg) {
   648         return new NativeRangeError(msg, this);
   649     }
   651     @Override
   652     public ScriptObject newReferenceError(final String msg) {
   653         return new NativeReferenceError(msg, this);
   654     }
   656     @Override
   657     public ScriptObject newSyntaxError(final String msg) {
   658         return new NativeSyntaxError(msg, this);
   659     }
   661     @Override
   662     public ScriptObject newTypeError(final String msg) {
   663         return new NativeTypeError(msg, this);
   664     }
   666     @Override
   667     public ScriptObject newURIError(final String msg) {
   668         return new NativeURIError(msg, this);
   669     }
   671     @Override
   672     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
   673         return new GenericPropertyDescriptor(configurable, enumerable, this);
   674     }
   676     @Override
   677     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
   678         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
   679     }
   681     @Override
   682     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
   683         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
   685         if (get == null) {
   686             desc.delete(PropertyDescriptor.GET, false);
   687         }
   689         if (set == null) {
   690             desc.delete(PropertyDescriptor.SET, false);
   691         }
   693         return desc;
   694     }
   697     /**
   698      * Cache for compiled script classes.
   699      */
   700     @SuppressWarnings("serial")
   701     private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
   702         private final int size;
   703         private final ReferenceQueue<Class<?>> queue;
   705         ClassCache(int size) {
   706             super(size, 0.75f, true);
   707             this.size = size;
   708             this.queue = new ReferenceQueue<>();
   709         }
   711         void cache(final Source source, final Class<?> clazz) {
   712             put(source, new ClassReference(clazz, queue, source));
   713         }
   715         @Override
   716         protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
   717             return size() > size;
   718         }
   720         @Override
   721         public ClassReference get(Object key) {
   722             for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
   723                 remove(ref.source);
   724             }
   725             return super.get(key);
   726         }
   728     }
   730     private static class ClassReference extends SoftReference<Class<?>> {
   731         private final Source source;
   733         ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
   734             super(clazz, queue);
   735             this.source = source;
   736         }
   737     }
   739     // Class cache management
   740     @Override
   741     public Class<?> findCachedClass(final Source source) {
   742         assert classCache != null : "Class cache used without being initialized";
   743         ClassReference ref = classCache.get(source);
   744         return ref != null ? ref.get() : null;
   745     }
   747     @Override
   748     public void cacheClass(final Source source, final Class<?> clazz) {
   749         assert classCache != null : "Class cache used without being initialized";
   750         classCache.cache(source, clazz);
   751     }
   753     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
   754         final T obj = map.get(key);
   755         if (obj != null) {
   756             return obj;
   757         }
   759         try {
   760             final T newObj = creator.call();
   761             final T existingObj = map.putIfAbsent(key, newObj);
   762             return existingObj != null ? existingObj : newObj;
   763         } catch (final Exception exp) {
   764             throw new RuntimeException(exp);
   765         }
   766     }
   768     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
   770     @Override
   771     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
   772         return getLazilyCreatedValue(key, creator, namedInvokers);
   773     }
   775     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
   777     @Override
   778     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
   779         return getLazilyCreatedValue(key, creator, dynamicInvokers);
   780     }
   782     /**
   783      * This is the eval used when 'indirect' eval call is made.
   784      *
   785      * var global = this;
   786      * global.eval("print('hello')");
   787      *
   788      * @param self  eval scope
   789      * @param str   eval string
   790      *
   791      * @return the result of eval
   792      */
   793     public static Object eval(final Object self, final Object str) {
   794         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
   795     }
   797     /**
   798      * Direct eval
   799      *
   800      * @param self     The scope of eval passed as 'self'
   801      * @param str      Evaluated code
   802      * @param callThis "this" to be passed to the evaluated code
   803      * @param location location of the eval call
   804      * @param strict   is eval called a strict mode code?
   805      *
   806      * @return the return value of the eval
   807      *
   808      * This is directly invoked from generated when eval(code) is called in user code
   809      */
   810     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
   811         if (!(str instanceof String || str instanceof ConsString)) {
   812             return str;
   813         }
   814         final Global global = Global.instance();
   815         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   817         return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
   818     }
   820     /**
   821      * Global print implementation - Nashorn extension
   822      *
   823      * @param self    scope
   824      * @param objects arguments to print
   825      *
   826      * @return result of print (undefined)
   827      */
   828     public static Object print(final Object self, final Object... objects) {
   829         return printImpl(false, objects);
   830     }
   832     /**
   833      * Global println implementation - Nashorn extension
   834      *
   835      * @param self    scope
   836      * @param objects arguments to print
   837      *
   838      * @return result of println (undefined)
   839      */
   840     public static Object println(final Object self, final Object... objects) {
   841         return printImpl(true, objects);
   842     }
   844     /**
   845      * Global load implementation - Nashorn extension
   846      *
   847      * @param self    scope
   848      * @param source  source to load
   849      *
   850      * @return result of load (undefined)
   851      *
   852      * @throws IOException if source could not be read
   853      */
   854     public static Object load(final Object self, final Object source) throws IOException {
   855         final Global global = Global.instance();
   856         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   857         return global.getContext().load(scope, source);
   858     }
   860     /**
   861      * Global loadWithNewGlobal implementation - Nashorn extension
   862      *
   863      * @param self scope
   864      * @param args from plus (optional) arguments to be passed to the loaded script
   865      *
   866      * @return result of load (may be undefined)
   867      *
   868      * @throws IOException if source could not be read
   869      */
   870     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
   871         final Global global = Global.instance();
   872         final int length = args.length;
   873         final boolean hasArgs = 0 < length;
   874         final Object from = hasArgs ? args[0] : UNDEFINED;
   875         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
   877         return global.getContext().loadWithNewGlobal(from, arguments);
   878     }
   880     /**
   881      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
   882      *
   883      * @param self  self reference
   884      * @param code  exit code
   885      *
   886      * @return undefined (will never be reacheD)
   887      */
   888     public static Object exit(final Object self, final Object code) {
   889         System.exit(JSType.toInt32(code));
   890         return UNDEFINED;
   891     }
   893     // builtin prototype accessors
   894     ScriptObject getFunctionPrototype() {
   895         return ScriptFunction.getPrototype(builtinFunction);
   896     }
   898     ScriptObject getObjectPrototype() {
   899         return ScriptFunction.getPrototype(builtinObject);
   900     }
   902     ScriptObject getArrayPrototype() {
   903         return ScriptFunction.getPrototype(builtinArray);
   904     }
   906     ScriptObject getBooleanPrototype() {
   907         return ScriptFunction.getPrototype(builtinBoolean);
   908     }
   910     ScriptObject getNumberPrototype() {
   911         return ScriptFunction.getPrototype(builtinNumber);
   912     }
   914     ScriptObject getDatePrototype() {
   915         return ScriptFunction.getPrototype(builtinDate);
   916     }
   918     ScriptObject getRegExpPrototype() {
   919         return ScriptFunction.getPrototype(builtinRegExp);
   920     }
   922     ScriptObject getStringPrototype() {
   923         return ScriptFunction.getPrototype(builtinString);
   924     }
   926     ScriptObject getErrorPrototype() {
   927         return ScriptFunction.getPrototype(builtinError);
   928     }
   930     ScriptObject getEvalErrorPrototype() {
   931         return ScriptFunction.getPrototype(builtinEvalError);
   932     }
   934     ScriptObject getRangeErrorPrototype() {
   935         return ScriptFunction.getPrototype(builtinRangeError);
   936     }
   938     ScriptObject getReferenceErrorPrototype() {
   939         return ScriptFunction.getPrototype(builtinReferenceError);
   940     }
   942     ScriptObject getSyntaxErrorPrototype() {
   943         return ScriptFunction.getPrototype(builtinSyntaxError);
   944     }
   946     ScriptObject getTypeErrorPrototype() {
   947         return ScriptFunction.getPrototype(builtinTypeError);
   948     }
   950     ScriptObject getURIErrorPrototype() {
   951         return ScriptFunction.getPrototype(builtinURIError);
   952     }
   954     ScriptObject getJavaImporterPrototype() {
   955         return ScriptFunction.getPrototype(builtinJavaImporter);
   956     }
   958     ScriptObject getJSAdapterPrototype() {
   959         return ScriptFunction.getPrototype(builtinJSAdapter);
   960     }
   962     ScriptObject getArrayBufferPrototype() {
   963         return ScriptFunction.getPrototype(builtinArrayBuffer);
   964     }
   966     ScriptObject getInt8ArrayPrototype() {
   967         return ScriptFunction.getPrototype(builtinInt8Array);
   968     }
   970     ScriptObject getUint8ArrayPrototype() {
   971         return ScriptFunction.getPrototype(builtinUint8Array);
   972     }
   974     ScriptObject getUint8ClampedArrayPrototype() {
   975         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
   976     }
   978     ScriptObject getInt16ArrayPrototype() {
   979         return ScriptFunction.getPrototype(builtinInt16Array);
   980     }
   982     ScriptObject getUint16ArrayPrototype() {
   983         return ScriptFunction.getPrototype(builtinUint16Array);
   984     }
   986     ScriptObject getInt32ArrayPrototype() {
   987         return ScriptFunction.getPrototype(builtinInt32Array);
   988     }
   990     ScriptObject getUint32ArrayPrototype() {
   991         return ScriptFunction.getPrototype(builtinUint32Array);
   992     }
   994     ScriptObject getFloat32ArrayPrototype() {
   995         return ScriptFunction.getPrototype(builtinFloat32Array);
   996     }
   998     ScriptObject getFloat64ArrayPrototype() {
   999         return ScriptFunction.getPrototype(builtinFloat64Array);
  1002     // Builtin PropertyMap accessors
  1003     PropertyMap getAccessorPropertyDescriptorMap() {
  1004         return accessorPropertyDescriptorMap;
  1007     PropertyMap getArrayBufferViewMap() {
  1008         return arrayBufferViewMap;
  1011     PropertyMap getDataPropertyDescriptorMap() {
  1012         return dataPropertyDescriptorMap;
  1015     PropertyMap getGenericPropertyDescriptorMap() {
  1016         return genericPropertyDescriptorMap;
  1019     PropertyMap getArgumentsMap() {
  1020         return nativeArgumentsMap;
  1023     PropertyMap getArrayMap() {
  1024         return nativeArrayMap;
  1027     PropertyMap getArrayBufferMap() {
  1028         return nativeArrayBufferMap;
  1031     PropertyMap getBooleanMap() {
  1032         return nativeBooleanMap;
  1035     PropertyMap getDateMap() {
  1036         return nativeDateMap;
  1039     PropertyMap getErrorMap() {
  1040         return nativeErrorMap;
  1043     PropertyMap getEvalErrorMap() {
  1044         return nativeEvalErrorMap;
  1047     PropertyMap getJSAdapterMap() {
  1048         return nativeJSAdapterMap;
  1051     PropertyMap getJavaImporterMap() {
  1052         return nativeJavaImporterMap;
  1055     PropertyMap getNumberMap() {
  1056         return nativeNumberMap;
  1059     PropertyMap getRangeErrorMap() {
  1060         return nativeRangeErrorMap;
  1063     PropertyMap getReferenceErrorMap() {
  1064         return nativeReferenceErrorMap;
  1067     PropertyMap getRegExpMap() {
  1068         return nativeRegExpMap;
  1071     PropertyMap getRegExpExecResultMap() {
  1072         return nativeRegExpExecResultMap;
  1075     PropertyMap getStrictArgumentsMap() {
  1076         return nativeStrictArgumentsMap;
  1079     PropertyMap getStringMap() {
  1080         return nativeStringMap;
  1083     PropertyMap getSyntaxErrorMap() {
  1084         return nativeSyntaxErrorMap;
  1087     PropertyMap getTypeErrorMap() {
  1088         return nativeTypeErrorMap;
  1091     PropertyMap getURIErrorMap() {
  1092         return nativeURIErrorMap;
  1095     PropertyMap getPrototypeObjectMap() {
  1096         return prototypeObjectMap;
  1099     PropertyMap getObjectMap() {
  1100         return objectMap;
  1103     PropertyMap getFunctionMap() {
  1104         return functionMap;
  1107     PropertyMap getAnonymousFunctionMap() {
  1108         return anonymousFunctionMap;
  1111     PropertyMap getStrictFunctionMap() {
  1112         return strictFunctionMap;
  1115     PropertyMap getBoundFunctionMap() {
  1116         return boundFunctionMap;
  1119     private ScriptFunction getBuiltinArray() {
  1120         return builtinArray;
  1123     ScriptFunction getTypeErrorThrower() {
  1124         return typeErrorThrower;
  1127     /**
  1128      * Called from compiled script code to test if builtin has been overridden
  1130      * @return true if builtin array has not been overridden
  1131      */
  1132     public static boolean isBuiltinArray() {
  1133         final Global instance = Global.instance();
  1134         return instance.array == instance.getBuiltinArray();
  1137     private ScriptFunction getBuiltinBoolean() {
  1138         return builtinBoolean;
  1141     /**
  1142      * Called from compiled script code to test if builtin has been overridden
  1144      * @return true if builtin boolean has not been overridden
  1145      */
  1146     public static boolean isBuiltinBoolean() {
  1147         final Global instance = Global.instance();
  1148         return instance._boolean == instance.getBuiltinBoolean();
  1151     private ScriptFunction getBuiltinDate() {
  1152         return builtinDate;
  1155     /**
  1156      * Called from compiled script code to test if builtin has been overridden
  1158      * @return true if builtin date has not been overridden
  1159      */
  1160     public static boolean isBuiltinDate() {
  1161         final Global instance = Global.instance();
  1162         return instance.date == instance.getBuiltinDate();
  1165     private ScriptFunction getBuiltinError() {
  1166         return builtinError;
  1169     /**
  1170      * Called from compiled script code to test if builtin has been overridden
  1172      * @return true if builtin error has not been overridden
  1173      */
  1174     public static boolean isBuiltinError() {
  1175         final Global instance = Global.instance();
  1176         return instance.error == instance.getBuiltinError();
  1179     private ScriptFunction getBuiltinEvalError() {
  1180         return builtinEvalError;
  1183     /**
  1184      * Called from compiled script code to test if builtin has been overridden
  1186      * @return true if builtin eval error has not been overridden
  1187      */
  1188     public static boolean isBuiltinEvalError() {
  1189         final Global instance = Global.instance();
  1190         return instance.evalError == instance.getBuiltinEvalError();
  1193     private ScriptFunction getBuiltinFunction() {
  1194         return builtinFunction;
  1197     /**
  1198      * Called from compiled script code to test if builtin has been overridden
  1200      * @return true if builtin function has not been overridden
  1201      */
  1202     public static boolean isBuiltinFunction() {
  1203         final Global instance = Global.instance();
  1204         return instance.function == instance.getBuiltinFunction();
  1207     private ScriptFunction getBuiltinJSAdapter() {
  1208         return builtinJSAdapter;
  1211     /**
  1212      * Called from compiled script code to test if builtin has been overridden
  1214      * @return true if builtin JSAdapter has not been overridden
  1215      */
  1216     public static boolean isBuiltinJSAdapter() {
  1217         final Global instance = Global.instance();
  1218         return instance.jsadapter == instance.getBuiltinJSAdapter();
  1221     private ScriptObject getBuiltinJSON() {
  1222         return builtinJSON;
  1225     /**
  1226      * Called from compiled script code to test if builtin has been overridden
  1228      * @return true if builtin JSON has has not been overridden
  1229      */
  1230     public static boolean isBuiltinJSON() {
  1231         final Global instance = Global.instance();
  1232         return instance.json == instance.getBuiltinJSON();
  1235     private ScriptObject getBuiltinJava() {
  1236         return builtinJava;
  1239     /**
  1240      * Called from compiled script code to test if builtin has been overridden
  1242      * @return true if builtin Java has not been overridden
  1243      */
  1244     public static boolean isBuiltinJava() {
  1245         final Global instance = Global.instance();
  1246         return instance.java == instance.getBuiltinJava();
  1249     private ScriptObject getBuiltinJavax() {
  1250         return builtinJavax;
  1253     /**
  1254      * Called from compiled script code to test if builtin has been overridden
  1256      * @return true if builtin Javax has not been overridden
  1257      */
  1258     public static boolean isBuiltinJavax() {
  1259         final Global instance = Global.instance();
  1260         return instance.javax == instance.getBuiltinJavax();
  1263     private ScriptObject getBuiltinJavaImporter() {
  1264         return builtinJavaImporter;
  1267     /**
  1268      * Called from compiled script code to test if builtin has been overridden
  1270      * @return true if builtin Java importer has not been overridden
  1271      */
  1272     public static boolean isBuiltinJavaImporter() {
  1273         final Global instance = Global.instance();
  1274         return instance.javaImporter == instance.getBuiltinJavaImporter();
  1277     private ScriptObject getBuiltinMath() {
  1278         return builtinMath;
  1281     /**
  1282      * Called from compiled script code to test if builtin has been overridden
  1284      * @return true if builtin math has not been overridden
  1285      */
  1286     public static boolean isBuiltinMath() {
  1287         final Global instance = Global.instance();
  1288         return instance.math == instance.getBuiltinMath();
  1291     private ScriptFunction getBuiltinNumber() {
  1292         return builtinNumber;
  1295     /**
  1296      * Called from compiled script code to test if builtin has been overridden
  1298      * @return true if builtin number has not been overridden
  1299      */
  1300     public static boolean isBuiltinNumber() {
  1301         final Global instance = Global.instance();
  1302         return instance.number == instance.getBuiltinNumber();
  1305     private ScriptFunction getBuiltinObject() {
  1306         return builtinObject;
  1309     /**
  1310      * Called from compiled script code to test if builtin has been overridden
  1312      * @return true if builtin object has not been overridden
  1313      */
  1314     public static boolean isBuiltinObject() {
  1315         final Global instance = Global.instance();
  1316         return instance.object == instance.getBuiltinObject();
  1319     private ScriptObject getBuiltinPackages() {
  1320         return builtinPackages;
  1323     /**
  1324      * Called from compiled script code to test if builtin has been overridden
  1326      * @return true if builtin package has not been overridden
  1327      */
  1328     public static boolean isBuiltinPackages() {
  1329         final Global instance = Global.instance();
  1330         return instance.packages == instance.getBuiltinPackages();
  1333     private ScriptFunction getBuiltinRangeError() {
  1334         return builtinRangeError;
  1337     /**
  1338      * Called from compiled script code to test if builtin has been overridden
  1340      * @return true if builtin range error has not been overridden
  1341      */
  1342     public static boolean isBuiltinRangeError() {
  1343         final Global instance = Global.instance();
  1344         return instance.rangeError == instance.getBuiltinRangeError();
  1347     private ScriptFunction getBuiltinReferenceError() {
  1348         return builtinReferenceError;
  1351     /**
  1352      * Called from compiled script code to test if builtin has been overridden
  1354      * @return true if builtin reference error has not been overridden
  1355      */
  1356     public static boolean isBuiltinReferenceError() {
  1357         final Global instance = Global.instance();
  1358         return instance.referenceError == instance.getBuiltinReferenceError();
  1361     private ScriptFunction getBuiltinRegExp() {
  1362         return builtinRegExp;
  1365     /**
  1366      * Called from compiled script code to test if builtin has been overridden
  1368      * @return true if builtin regexp has not been overridden
  1369      */
  1370     public static boolean isBuiltinRegExp() {
  1371         final Global instance = Global.instance();
  1372         return instance.regexp == instance.getBuiltinRegExp();
  1375     private ScriptFunction getBuiltinString() {
  1376         return builtinString;
  1379     /**
  1380      * Called from compiled script code to test if builtin has been overridden
  1382      * @return true if builtin Java has not been overridden
  1383      */
  1384     public static boolean isBuiltinString() {
  1385         final Global instance = Global.instance();
  1386         return instance.string == instance.getBuiltinString();
  1389     private ScriptFunction getBuiltinSyntaxError() {
  1390         return builtinSyntaxError;
  1393     /**
  1394      * Called from compiled script code to test if builtin has been overridden
  1396      * @return true if builtin syntax error has not been overridden
  1397      */
  1398     public static boolean isBuiltinSyntaxError() {
  1399         final Global instance = Global.instance();
  1400         return instance.syntaxError == instance.getBuiltinSyntaxError();
  1403     private ScriptFunction getBuiltinTypeError() {
  1404         return builtinTypeError;
  1407     /**
  1408      * Called from compiled script code to test if builtin has been overridden
  1410      * @return true if builtin type error has not been overridden
  1411      */
  1412     public static boolean isBuiltinTypeError() {
  1413         final Global instance = Global.instance();
  1414         return instance.typeError == instance.getBuiltinTypeError();
  1417     private ScriptFunction getBuiltinURIError() {
  1418         return builtinURIError;
  1421     /**
  1422      * Called from compiled script code to test if builtin has been overridden
  1424      * @return true if builtin URI error has not been overridden
  1425      */
  1426     public static boolean isBuiltinURIError() {
  1427         final Global instance = Global.instance();
  1428         return instance.uriError == instance.getBuiltinURIError();
  1431     @Override
  1432     public String getClassName() {
  1433         return "global";
  1436     /**
  1437      * Copy function used to clone NativeRegExp objects.
  1439      * @param regexp a NativeRegExp to clone
  1441      * @return copy of the given regexp object
  1442      */
  1443     public static Object regExpCopy(final Object regexp) {
  1444         return new NativeRegExp((NativeRegExp)regexp);
  1447     /**
  1448      * Convert given object to NativeRegExp type.
  1450      * @param obj object to be converted
  1451      * @return NativeRegExp instance
  1452      */
  1453     public static NativeRegExp toRegExp(final Object obj) {
  1454         if (obj instanceof NativeRegExp) {
  1455             return (NativeRegExp)obj;
  1457         return new NativeRegExp(JSType.toString(obj));
  1460     /**
  1461      * ECMA 9.9 ToObject implementation
  1463      * @param obj  an item for which to run ToObject
  1464      * @return ToObject version of given item
  1465      */
  1466     public static Object toObject(final Object obj) {
  1467         if (obj == null || obj == UNDEFINED) {
  1468             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1471         if (obj instanceof ScriptObject) {
  1472             return obj;
  1475         return instance().wrapAsObject(obj);
  1478     /**
  1479      * Allocate a new object array.
  1481      * @param initial object values.
  1482      * @return the new array
  1483      */
  1484     public static NativeArray allocate(final Object[] initial) {
  1485         ArrayData arrayData = ArrayData.allocate(initial);
  1487         for (int index = 0; index < initial.length; index++) {
  1488             final Object value = initial[index];
  1490             if (value == ScriptRuntime.EMPTY) {
  1491                 arrayData = arrayData.delete(index);
  1495         return new NativeArray(arrayData);
  1498     /**
  1499      * Allocate a new number array.
  1501      * @param initial number values.
  1502      * @return the new array
  1503      */
  1504     public static NativeArray allocate(final double[] initial) {
  1505         return new NativeArray(ArrayData.allocate(initial));
  1508     /**
  1509      * Allocate a new long array.
  1511      * @param initial number values.
  1512      * @return the new array
  1513      */
  1514     public static NativeArray allocate(final long[] initial) {
  1515         return new NativeArray(ArrayData.allocate(initial));
  1518     /**
  1519      * Allocate a new integer array.
  1521      * @param initial number values.
  1522      * @return the new array
  1523      */
  1524     public static NativeArray allocate(final int[] initial) {
  1525         return new NativeArray(ArrayData.allocate(initial));
  1528     /**
  1529      * Allocate a new object array for arguments.
  1531      * @param arguments initial arguments passed.
  1532      * @param callee reference to the function that uses arguments object
  1533      * @param numParams actual number of declared parameters
  1535      * @return the new array
  1536      */
  1537     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
  1538         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
  1541     /**
  1542      * Called from generated to check if given function is the builtin 'eval'. If
  1543      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
  1545      * @param  fn function object that is checked
  1546      * @return true if fn is the builtin eval
  1547      */
  1548     public static boolean isEval(final Object fn) {
  1549         return fn == Global.instance().builtinEval;
  1552     /**
  1553      * Create a new RegExp object.
  1555      * @param expression Regular expression.
  1556      * @param options    Search options.
  1558      * @return New RegExp object.
  1559      */
  1560     public static Object newRegExp(final String expression, final String options) {
  1561         if (options == null) {
  1562             return new NativeRegExp(expression);
  1564         return new NativeRegExp(expression, options);
  1567     /**
  1568      * Get the object prototype
  1570      * @return the object prototype
  1571      */
  1572     public static ScriptObject objectPrototype() {
  1573         return Global.instance().getObjectPrototype();
  1576     /**
  1577      * Create a new empty object instance.
  1579      * @return New empty object.
  1580      */
  1581     public static ScriptObject newEmptyInstance() {
  1582         return Global.instance().newObject();
  1585     /**
  1586      * Check if a given object is a ScriptObject, raises an exception if this is
  1587      * not the case
  1589      * @param obj and object to check
  1590      */
  1591     public static void checkObject(final Object obj) {
  1592         if (!(obj instanceof ScriptObject)) {
  1593             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1597     /**
  1598      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
  1599      * if this object is null or undefined.
  1601      * @param obj an object to check
  1602      */
  1603     public static void checkObjectCoercible(final Object obj) {
  1604         if (obj == null || obj == UNDEFINED) {
  1605             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1609     /**
  1610      * Get the current split state.
  1612      * @return current split state
  1613      */
  1614     @Override
  1615     public int getSplitState() {
  1616         return splitState;
  1619     /**
  1620      * Set the current split state.
  1622      * @param state current split state
  1623      */
  1624     @Override
  1625     public void setSplitState(final int state) {
  1626         splitState = state;
  1629     private void init() {
  1630         assert Context.getGlobal() == this : "this global is not set as current";
  1632         final ScriptEnvironment env = getContext().getEnv();
  1634         // duplicate PropertyMaps of Native* classes
  1635         copyInitialMaps(env);
  1637         // initialize Function and Object constructor
  1638         initFunctionAndObject();
  1640         // Now fix Global's own proto.
  1641         this.setProto(getObjectPrototype());
  1643         // initialize global function properties
  1644         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  1646         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
  1647         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  1648         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
  1649         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
  1650         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
  1651         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
  1652         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
  1653         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
  1654         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
  1655         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
  1656         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
  1657         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
  1658         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
  1659         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
  1660         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
  1662         // built-in constructors
  1663         this.builtinArray     = (ScriptFunction)initConstructor("Array");
  1664         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
  1665         this.builtinDate      = (ScriptFunction)initConstructor("Date");
  1666         this.builtinJSON      = initConstructor("JSON");
  1667         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
  1668         this.builtinMath      = initConstructor("Math");
  1669         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
  1670         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
  1671         this.builtinString    = (ScriptFunction)initConstructor("String");
  1673         // initialize String.prototype.length to 0
  1674         // add String.prototype.length
  1675         final ScriptObject stringPrototype = getStringPrototype();
  1676         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  1678         // set isArray flag on Array.prototype
  1679         final ScriptObject arrayPrototype = getArrayPrototype();
  1680         arrayPrototype.setIsArray();
  1682         this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
  1684         // initialize default regexp object
  1685         this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
  1687         // RegExp.prototype should behave like a RegExp object. So copy the
  1688         // properties.
  1689         final ScriptObject regExpProto = getRegExpPrototype();
  1690         regExpProto.addBoundProperties(DEFAULT_REGEXP);
  1692         // Error stuff
  1693         initErrorObjects();
  1695         // java access
  1696         if (! env._no_java) {
  1697             initJavaAccess();
  1700         if (! env._no_typed_arrays) {
  1701             initTypedArray();
  1704         if (env._scripting) {
  1705             initScripting(env);
  1708         if (Context.DEBUG) {
  1709             boolean debugOkay;
  1710             final SecurityManager sm = System.getSecurityManager();
  1711             if (sm != null) {
  1712                 try {
  1713                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
  1714                     debugOkay = true;
  1715                 } catch (final SecurityException ignored) {
  1716                     // if no permission, don't initialize Debug object
  1717                     debugOkay = false;
  1720             } else {
  1721                 debugOkay = true;
  1724             if (debugOkay) {
  1725                 initDebug();
  1729         copyBuiltins();
  1731         // initialized with strings so that typeof will work as expected.
  1732         this.__FILE__ = "";
  1733         this.__DIR__  = "";
  1734         this.__LINE__ = 0.0;
  1736         // expose script (command line) arguments as "arguments" property of global
  1737         final List<String> arguments = env.getArguments();
  1738         final Object argsObj = wrapAsObject(arguments.toArray());
  1740         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
  1741         if (env._scripting) {
  1742             // synonym for "arguments" in scripting mode
  1743             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
  1747     private void initErrorObjects() {
  1748         // Error objects
  1749         this.builtinError = (ScriptFunction)initConstructor("Error");
  1750         final ScriptObject errorProto = getErrorPrototype();
  1752         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
  1753         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
  1754         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
  1755         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
  1756         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
  1757         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
  1758         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
  1759         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
  1760         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
  1761         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
  1762         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
  1763         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
  1764         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
  1766         // ECMA 15.11.4.2 Error.prototype.name
  1767         // Error.prototype.name = "Error";
  1768         errorProto.set(NativeError.NAME, "Error", false);
  1769         // ECMA 15.11.4.3 Error.prototype.message
  1770         // Error.prototype.message = "";
  1771         errorProto.set(NativeError.MESSAGE, "", false);
  1773         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
  1774         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
  1775         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
  1776         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
  1777         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
  1778         this.builtinURIError = initErrorSubtype("URIError", errorProto);
  1781     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
  1782         final ScriptObject cons = initConstructor(name);
  1783         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  1784         prototype.set(NativeError.NAME, name, false);
  1785         prototype.set(NativeError.MESSAGE, "", false);
  1786         prototype.setProto(errorProto);
  1787         return (ScriptFunction)cons;
  1790     private void initJavaAccess() {
  1791         final ScriptObject objectProto = getObjectPrototype();
  1792         this.builtinPackages = new NativeJavaPackage("", objectProto);
  1793         this.builtinCom = new NativeJavaPackage("com", objectProto);
  1794         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
  1795         this.builtinJava = new NativeJavaPackage("java", objectProto);
  1796         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
  1797         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
  1798         this.builtinOrg = new NativeJavaPackage("org", objectProto);
  1799         this.builtinJavaImporter = initConstructor("JavaImporter");
  1800         this.builtinJavaApi = initConstructor("Java");
  1803     private void initScripting(final ScriptEnvironment scriptEnv) {
  1804         Object value;
  1805         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
  1806         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
  1808         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
  1809         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
  1811         final String execName = ScriptingFunctions.EXEC_NAME;
  1812         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
  1813         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
  1815         // Nashorn extension: global.echo (scripting-mode-only)
  1816         // alias for "print"
  1817         value = get("print");
  1818         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
  1820         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
  1821         final ScriptObject options = newObject();
  1822         copyOptions(options, scriptEnv);
  1823         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
  1825         // Nashorn extension: global.$ENV (scripting-mode-only)
  1826         if (System.getSecurityManager() == null) {
  1827             // do not fill $ENV if we have a security manager around
  1828             // Retrieve current state of ENV variables.
  1829             final ScriptObject env = newObject();
  1830             env.putAll(System.getenv(), scriptEnv._strict);
  1831             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
  1832         } else {
  1833             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1836         // add other special properties for exec support
  1837         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1838         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1839         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1842     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
  1843         for (Field f : scriptEnv.getClass().getFields()) {
  1844             try {
  1845                 options.set(f.getName(), f.get(scriptEnv), false);
  1846             } catch (final IllegalArgumentException | IllegalAccessException exp) {
  1847                 throw new RuntimeException(exp);
  1852     private void initTypedArray() {
  1853         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
  1854         this.builtinInt8Array         = initConstructor("Int8Array");
  1855         this.builtinUint8Array        = initConstructor("Uint8Array");
  1856         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
  1857         this.builtinInt16Array        = initConstructor("Int16Array");
  1858         this.builtinUint16Array       = initConstructor("Uint16Array");
  1859         this.builtinInt32Array        = initConstructor("Int32Array");
  1860         this.builtinUint32Array       = initConstructor("Uint32Array");
  1861         this.builtinFloat32Array      = initConstructor("Float32Array");
  1862         this.builtinFloat64Array      = initConstructor("Float64Array");
  1865     private void copyBuiltins() {
  1866         this.array             = this.builtinArray;
  1867         this._boolean          = this.builtinBoolean;
  1868         this.date              = this.builtinDate;
  1869         this.error             = this.builtinError;
  1870         this.evalError         = this.builtinEvalError;
  1871         this.function          = this.builtinFunction;
  1872         this.jsadapter         = this.builtinJSAdapter;
  1873         this.json              = this.builtinJSON;
  1874         this.com               = this.builtinCom;
  1875         this.edu               = this.builtinEdu;
  1876         this.java              = this.builtinJava;
  1877         this.javafx            = this.builtinJavafx;
  1878         this.javax             = this.builtinJavax;
  1879         this.org               = this.builtinOrg;
  1880         this.javaImporter      = this.builtinJavaImporter;
  1881         this.javaApi           = this.builtinJavaApi;
  1882         this.math              = this.builtinMath;
  1883         this.number            = this.builtinNumber;
  1884         this.object            = this.builtinObject;
  1885         this.packages          = this.builtinPackages;
  1886         this.rangeError        = this.builtinRangeError;
  1887         this.referenceError    = this.builtinReferenceError;
  1888         this.regexp            = this.builtinRegExp;
  1889         this.string            = this.builtinString;
  1890         this.syntaxError       = this.builtinSyntaxError;
  1891         this.typeError         = this.builtinTypeError;
  1892         this.uriError          = this.builtinURIError;
  1893         this.arrayBuffer       = this.builtinArrayBuffer;
  1894         this.int8Array         = this.builtinInt8Array;
  1895         this.uint8Array        = this.builtinUint8Array;
  1896         this.uint8ClampedArray = this.builtinUint8ClampedArray;
  1897         this.int16Array        = this.builtinInt16Array;
  1898         this.uint16Array       = this.builtinUint16Array;
  1899         this.int32Array        = this.builtinInt32Array;
  1900         this.uint32Array       = this.builtinUint32Array;
  1901         this.float32Array      = this.builtinFloat32Array;
  1902         this.float64Array      = this.builtinFloat64Array;
  1905     private void initDebug() {
  1906         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
  1909     @SuppressWarnings("resource")
  1910     private static Object printImpl(final boolean newLine, final Object... objects) {
  1911         final PrintWriter out = Global.getEnv().getOut();
  1912         final StringBuilder sb = new StringBuilder();
  1914         for (final Object object : objects) {
  1915             if (sb.length() != 0) {
  1916                 sb.append(' ');
  1919             sb.append(JSType.toString(object));
  1922         // Print all at once to ensure thread friendly result.
  1923         if (newLine) {
  1924             out.println(sb.toString());
  1925         } else {
  1926             out.print(sb.toString());
  1929         out.flush();
  1931         return UNDEFINED;
  1934     /**
  1935      * These classes are generated by nasgen tool and so we have to use
  1936      * reflection to load and create new instance of these classes.
  1937      */
  1938     private ScriptObject initConstructor(final String name) {
  1939         try {
  1940             // Assuming class name pattern for built-in JS constructors.
  1941             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
  1943             sb.append("Native");
  1944             sb.append(name);
  1945             sb.append("$Constructor");
  1947             final Class<?>     funcClass = Class.forName(sb.toString());
  1948             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
  1950             if (res instanceof ScriptFunction) {
  1951                 // All global constructor prototypes are not-writable,
  1952                 // not-enumerable and not-configurable.
  1953                 final ScriptFunction func = (ScriptFunction)res;
  1954                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
  1957             if (res.getProto() == null) {
  1958                 res.setProto(getObjectPrototype());
  1961             return res;
  1963         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  1964             throw new RuntimeException(e);
  1968     private void copyInitialMaps(final ScriptEnvironment env) {
  1969         this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
  1970         this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
  1971         this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
  1972         this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
  1973         this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
  1974         this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
  1975         this.nativeDateMap = NativeDate.getInitialMap().duplicate();
  1976         this.nativeErrorMap = NativeError.getInitialMap().duplicate();
  1977         this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
  1978         this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
  1979         this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
  1980         this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
  1981         this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
  1982         this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
  1983         this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
  1984         this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
  1985         this.nativeStringMap = NativeString.getInitialMap().duplicate();
  1986         this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
  1987         this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
  1988         this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
  1989         this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
  1990         this.objectMap = JO.getInitialMap().duplicate();
  1991         this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
  1992         this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
  1993         this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
  1994         this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
  1996         // java
  1997         if (! env._no_java) {
  1998             this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
  2001         // typed arrays
  2002         if (! env._no_typed_arrays) {
  2003             this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
  2004             this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
  2008     // Function and Object constructors are inter-dependent. Also,
  2009     // Function.prototype
  2010     // functions are not properly initialized. We fix the references here.
  2011     // NOTE: be careful if you want to re-order the operations here. You may
  2012     // have
  2013     // to play with object references carefully!!
  2014     private void initFunctionAndObject() {
  2015         // First-n-foremost is Function
  2016         this.builtinFunction = (ScriptFunction)initConstructor("Function");
  2018         // create global anonymous function
  2019         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
  2020         // need to copy over members of Function.prototype to anon function
  2021         anon.addBoundProperties(getFunctionPrototype());
  2023         // Function.prototype === Object.getPrototypeOf(Function) ===
  2024         // <anon-function>
  2025         builtinFunction.setProto(anon);
  2026         builtinFunction.setPrototype(anon);
  2027         anon.set("constructor", builtinFunction, false);
  2028         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  2030         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
  2031         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, false, false, false);
  2032         typeErrorThrower.setPrototype(UNDEFINED);
  2033         // Non-constructor built-in functions do not have "prototype" property
  2034         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
  2035         typeErrorThrower.preventExtensions();
  2037         // now initialize Object
  2038         this.builtinObject = (ScriptFunction)initConstructor("Object");
  2039         final ScriptObject ObjectPrototype = getObjectPrototype();
  2040         // Object.getPrototypeOf(Function.prototype) === Object.prototype
  2041         anon.setProto(ObjectPrototype);
  2043         // Function valued properties of Function.prototype were not properly
  2044         // initialized. Because, these were created before global.function and
  2045         // global.object were not initialized.
  2046         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
  2047         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2048             final Object key = property.getKey();
  2049             final Object value = builtinFunction.get(key);
  2051             if (value instanceof ScriptFunction && value != anon) {
  2052                 final ScriptFunction func = (ScriptFunction)value;
  2053                 func.setProto(getFunctionPrototype());
  2054                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2055                 if (prototype != null) {
  2056                     prototype.setProto(ObjectPrototype);
  2061         // For function valued properties of Object and Object.prototype, make
  2062         // sure prototype's proto chain ends with Object.prototype
  2063         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
  2064             final Object key = property.getKey();
  2065             final Object value = builtinObject.get(key);
  2067             if (value instanceof ScriptFunction) {
  2068                 final ScriptFunction func = (ScriptFunction)value;
  2069                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2070                 if (prototype != null) {
  2071                     prototype.setProto(ObjectPrototype);
  2076         properties = getObjectPrototype().getMap().getProperties();
  2077         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2078             final Object key   = property.getKey();
  2079             final Object value = ObjectPrototype.get(key);
  2081             if (key.equals("constructor")) {
  2082                 continue;
  2085             if (value instanceof ScriptFunction) {
  2086                 final ScriptFunction func = (ScriptFunction)value;
  2087                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2088                 if (prototype != null) {
  2089                     prototype.setProto(ObjectPrototype);
  2095     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
  2096         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
  2099     RegExpResult getLastRegExpResult() {
  2100         return lastRegExpResult;
  2103     void setLastRegExpResult(final RegExpResult regExpResult) {
  2104         this.lastRegExpResult = regExpResult;

mercurial