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

Fri, 09 Aug 2013 20:48:44 +0530

author
sundar
date
Fri, 09 Aug 2013 20:48:44 +0530
changeset 492
47e2b609fe31
parent 489
dd79c04ef7df
child 541
c3b6ce7b74bf
permissions
-rw-r--r--

8022707: Revisit all doPrivileged blocks
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.SoftReference;
    37 import java.lang.reflect.Field;
    38 import java.util.Arrays;
    39 import java.util.LinkedHashMap;
    40 import java.util.List;
    41 import java.util.Map;
    42 import java.util.concurrent.Callable;
    43 import java.util.concurrent.ConcurrentHashMap;
    44 import jdk.internal.dynalink.linker.GuardedInvocation;
    45 import jdk.internal.dynalink.linker.LinkRequest;
    46 import jdk.nashorn.internal.objects.annotations.Attribute;
    47 import jdk.nashorn.internal.objects.annotations.Property;
    48 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    49 import jdk.nashorn.internal.runtime.ConsString;
    50 import jdk.nashorn.internal.runtime.Context;
    51 import jdk.nashorn.internal.runtime.GlobalFunctions;
    52 import jdk.nashorn.internal.runtime.GlobalObject;
    53 import jdk.nashorn.internal.runtime.JSType;
    54 import jdk.nashorn.internal.runtime.NativeJavaPackage;
    55 import jdk.nashorn.internal.runtime.PropertyMap;
    56 import jdk.nashorn.internal.runtime.ScriptEnvironment;
    57 import jdk.nashorn.internal.runtime.PropertyDescriptor;
    58 import jdk.nashorn.internal.runtime.arrays.ArrayData;
    59 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    60 import jdk.nashorn.internal.runtime.Scope;
    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.linker.Bootstrap;
    67 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    68 import jdk.nashorn.internal.scripts.JO;
    70 /**
    71  * Representation of global scope.
    72  */
    73 @ScriptClass("Global")
    74 public final class Global extends ScriptObject implements GlobalObject, Scope {
    75     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    76     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
    78     /** ECMA 15.1.2.2 parseInt (string , radix) */
    79     @Property(attributes = Attribute.NOT_ENUMERABLE)
    80     public Object parseInt;
    82     /** ECMA 15.1.2.3 parseFloat (string) */
    83     @Property(attributes = Attribute.NOT_ENUMERABLE)
    84     public Object parseFloat;
    86     /** ECMA 15.1.2.4 isNaN (number) */
    87     @Property(attributes = Attribute.NOT_ENUMERABLE)
    88     public Object isNaN;
    90     /** ECMA 15.1.2.5 isFinite (number) */
    91     @Property(attributes = Attribute.NOT_ENUMERABLE)
    92     public Object isFinite;
    94     /** ECMA 15.1.3.3 encodeURI */
    95     @Property(attributes = Attribute.NOT_ENUMERABLE)
    96     public Object encodeURI;
    98     /** ECMA 15.1.3.4 encodeURIComponent */
    99     @Property(attributes = Attribute.NOT_ENUMERABLE)
   100     public Object encodeURIComponent;
   102     /** ECMA 15.1.3.1 decodeURI */
   103     @Property(attributes = Attribute.NOT_ENUMERABLE)
   104     public Object decodeURI;
   106     /** ECMA 15.1.3.2 decodeURIComponent */
   107     @Property(attributes = Attribute.NOT_ENUMERABLE)
   108     public Object decodeURIComponent;
   110     /** ECMA B.2.1 escape (string) */
   111     @Property(attributes = Attribute.NOT_ENUMERABLE)
   112     public Object escape;
   114     /** ECMA B.2.2 unescape (string) */
   115     @Property(attributes = Attribute.NOT_ENUMERABLE)
   116     public Object unescape;
   118     /** Nashorn extension: global.print */
   119     @Property(attributes = Attribute.NOT_ENUMERABLE)
   120     public Object print;
   122     /** Nashorn extension: global.load */
   123     @Property(attributes = Attribute.NOT_ENUMERABLE)
   124     public Object load;
   126     /** Nashorn extension: global.loadWithNewGlobal */
   127     @Property(attributes = Attribute.NOT_ENUMERABLE)
   128     public Object loadWithNewGlobal;
   130     /** Nashorn extension: global.exit */
   131     @Property(attributes = Attribute.NOT_ENUMERABLE)
   132     public Object exit;
   134     /** Nashorn extension: global.quit */
   135     @Property(attributes = Attribute.NOT_ENUMERABLE)
   136     public Object quit;
   138     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
   139     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   140     public final Object NaN = Double.NaN;
   142     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
   143     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   144     public final Object Infinity = Double.POSITIVE_INFINITY;
   146     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
   147     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   148     public final Object undefined = UNDEFINED;
   150     /** ECMA 15.1.2.1 eval(x) */
   151     @Property(attributes = Attribute.NOT_ENUMERABLE)
   152     public Object eval;
   154     /** ECMA 15.1.4.1 Object constructor. */
   155     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
   156     public volatile Object object;
   158     /** ECMA 15.1.4.2 Function constructor. */
   159     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
   160     public volatile Object function;
   162     /** ECMA 15.1.4.3 Array constructor. */
   163     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
   164     public volatile Object array;
   166     /** ECMA 15.1.4.4 String constructor */
   167     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
   168     public volatile Object string;
   170     /** ECMA 15.1.4.5 Boolean constructor */
   171     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
   172     public volatile Object _boolean;
   174     /** ECMA 15.1.4.6 - Number constructor */
   175     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
   176     public volatile Object number;
   178     /** ECMA 15.1.4.7 Date constructor */
   179     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   180     public volatile Object date;
   182     /** ECMA 15.1.4.8 RegExp constructor */
   183     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   184     public volatile Object regexp;
   186     /** ECMA 15.12 - The JSON object */
   187     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   188     public volatile Object json;
   190     /** Nashorn extension: global.JSAdapter */
   191     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   192     public volatile Object jsadapter;
   194     /** ECMA 15.8 - The Math object */
   195     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
   196     public volatile Object math;
   198     /** Error object */
   199     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
   200     public volatile Object error;
   202     /** EvalError object */
   203     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   204     public volatile Object evalError;
   206     /** RangeError object */
   207     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   208     public volatile Object rangeError;
   210     /** ReferenceError object */
   211     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
   212     public volatile Object referenceError;
   214     /** SyntaxError object */
   215     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
   216     public volatile Object syntaxError;
   218     /** TypeError object */
   219     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
   220     public volatile Object typeError;
   222     /** URIError object */
   223     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   224     public volatile Object uriError;
   226     /** ArrayBuffer object */
   227     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   228     public volatile Object arrayBuffer;
   230     /** TypedArray (int8) */
   231     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   232     public volatile Object int8Array;
   234     /** TypedArray (uint8) */
   235     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   236     public volatile Object uint8Array;
   238     /** TypedArray (uint8) - Clamped */
   239     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   240     public volatile Object uint8ClampedArray;
   242     /** TypedArray (int16) */
   243     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   244     public volatile Object int16Array;
   246     /** TypedArray (uint16) */
   247     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   248     public volatile Object uint16Array;
   250     /** TypedArray (int32) */
   251     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   252     public volatile Object int32Array;
   254     /** TypedArray (uint32) */
   255     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   256     public volatile Object uint32Array;
   258     /** TypedArray (float32) */
   259     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   260     public volatile Object float32Array;
   262     /** TypedArray (float64) */
   263     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   264     public volatile Object float64Array;
   266     /** Nashorn extension: Java access - global.Packages */
   267     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
   268     public volatile Object packages;
   270     /** Nashorn extension: Java access - global.com */
   271     @Property(attributes = Attribute.NOT_ENUMERABLE)
   272     public volatile Object com;
   274     /** Nashorn extension: Java access - global.edu */
   275     @Property(attributes = Attribute.NOT_ENUMERABLE)
   276     public volatile Object edu;
   278     /** Nashorn extension: Java access - global.java */
   279     @Property(attributes = Attribute.NOT_ENUMERABLE)
   280     public volatile Object java;
   282     /** Nashorn extension: Java access - global.javafx */
   283     @Property(attributes = Attribute.NOT_ENUMERABLE)
   284     public volatile Object javafx;
   286     /** Nashorn extension: Java access - global.javax */
   287     @Property(attributes = Attribute.NOT_ENUMERABLE)
   288     public volatile Object javax;
   290     /** Nashorn extension: Java access - global.org */
   291     @Property(attributes = Attribute.NOT_ENUMERABLE)
   292     public volatile Object org;
   294     /** Nashorn extension: Java access - global.javaImporter */
   295     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   296     public volatile Object javaImporter;
   298     /** Nashorn extension: global.Java Object constructor. */
   299     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   300     public volatile Object javaApi;
   302     /** Nashorn extension: current script's file name */
   303     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   304     public Object __FILE__;
   306     /** Nashorn extension: current script's directory */
   307     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   308     public Object __DIR__;
   310     /** Nashorn extension: current source line number being executed */
   311     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   312     public Object __LINE__;
   314     /** Used as Date.prototype's default value */
   315     public NativeDate   DEFAULT_DATE;
   317     /** Used as RegExp.prototype's default value */
   318     public NativeRegExp DEFAULT_REGEXP;
   320     /*
   321      * Built-in constructor objects: Even if user changes dynamic values of
   322      * "Object", "Array" etc., we still want to keep original values of these
   323      * constructors here. For example, we need to be able to create array,
   324      * regexp literals even after user overwrites global "Array" or "RegExp"
   325      * constructor - see also ECMA 262 spec. Annex D.
   326      */
   327     private ScriptFunction builtinFunction;
   328     private ScriptFunction builtinObject;
   329     private ScriptFunction builtinArray;
   330     private ScriptFunction builtinBoolean;
   331     private ScriptFunction builtinDate;
   332     private ScriptObject   builtinJSON;
   333     private ScriptFunction builtinJSAdapter;
   334     private ScriptObject   builtinMath;
   335     private ScriptFunction builtinNumber;
   336     private ScriptFunction builtinRegExp;
   337     private ScriptFunction builtinString;
   338     private ScriptFunction builtinError;
   339     private ScriptFunction builtinEval;
   340     private ScriptFunction builtinEvalError;
   341     private ScriptFunction builtinRangeError;
   342     private ScriptFunction builtinReferenceError;
   343     private ScriptFunction builtinSyntaxError;
   344     private ScriptFunction builtinTypeError;
   345     private ScriptFunction builtinURIError;
   346     private ScriptObject   builtinPackages;
   347     private ScriptObject   builtinCom;
   348     private ScriptObject   builtinEdu;
   349     private ScriptObject   builtinJava;
   350     private ScriptObject   builtinJavafx;
   351     private ScriptObject   builtinJavax;
   352     private ScriptObject   builtinOrg;
   353     private ScriptObject   builtinJavaImporter;
   354     private ScriptObject   builtinJavaApi;
   355     private ScriptObject   builtinArrayBuffer;
   356     private ScriptObject   builtinInt8Array;
   357     private ScriptObject   builtinUint8Array;
   358     private ScriptObject   builtinUint8ClampedArray;
   359     private ScriptObject   builtinInt16Array;
   360     private ScriptObject   builtinUint16Array;
   361     private ScriptObject   builtinInt32Array;
   362     private ScriptObject   builtinUint32Array;
   363     private ScriptObject   builtinFloat32Array;
   364     private ScriptObject   builtinFloat64Array;
   366     private PropertyMap    accessorPropertyDescriptorMap;
   367     private PropertyMap    arrayBufferViewMap;
   368     private PropertyMap    dataPropertyDescriptorMap;
   369     private PropertyMap    genericPropertyDescriptorMap;
   370     private PropertyMap    nativeArgumentsMap;
   371     private PropertyMap    nativeArrayMap;
   372     private PropertyMap    nativeArrayBufferMap;
   373     private PropertyMap    nativeBooleanMap;
   374     private PropertyMap    nativeDateMap;
   375     private PropertyMap    nativeErrorMap;
   376     private PropertyMap    nativeEvalErrorMap;
   377     private PropertyMap    nativeJSAdapterMap;
   378     private PropertyMap    nativeJavaImporterMap;
   379     private PropertyMap    nativeNumberMap;
   380     private PropertyMap    nativeRangeErrorMap;
   381     private PropertyMap    nativeReferenceErrorMap;
   382     private PropertyMap    nativeRegExpMap;
   383     private PropertyMap    nativeRegExpExecResultMap;
   384     private PropertyMap    nativeStrictArgumentsMap;
   385     private PropertyMap    nativeStringMap;
   386     private PropertyMap    nativeSyntaxErrorMap;
   387     private PropertyMap    nativeTypeErrorMap;
   388     private PropertyMap    nativeURIErrorMap;
   389     private PropertyMap    prototypeObjectMap;
   390     private PropertyMap    objectMap;
   391     private PropertyMap    functionMap;
   392     private PropertyMap    anonymousFunctionMap;
   393     private PropertyMap    strictFunctionMap;
   394     private PropertyMap    boundFunctionMap;
   396     // Flag to indicate that a split method issued a return statement
   397     private int splitState = -1;
   399     // class cache
   400     private ClassCache classCache;
   402     // Used to store the last RegExp result to support deprecated RegExp constructor properties
   403     private RegExpResult lastRegExpResult;
   405     private static final MethodHandle EVAL              = findOwnMH("eval",              Object.class, Object.class, Object.class);
   406     private static final MethodHandle PRINT             = findOwnMH("print",             Object.class, Object.class, Object[].class);
   407     private static final MethodHandle PRINTLN           = findOwnMH("println",           Object.class, Object.class, Object[].class);
   408     private static final MethodHandle LOAD              = findOwnMH("load",              Object.class, Object.class, Object.class);
   409     private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
   410     private static final MethodHandle EXIT              = findOwnMH("exit",              Object.class, Object.class, Object.class);
   412     // initialized by nasgen
   413     private static PropertyMap $nasgenmap$;
   415     // performs initialization checks for Global constructor and returns the
   416     // PropertyMap, if everything is fine.
   417     private static PropertyMap checkAndGetMap(final Context context) {
   418         // security check first
   419         final SecurityManager sm = System.getSecurityManager();
   420         if (sm != null) {
   421             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
   422         }
   424         // null check on context
   425         context.getClass();
   427         /*
   428          * Duplicate global's map and use it. This way the initial Map filled
   429          * by nasgen (referenced from static field in this class) is retained
   430          * 'as is' (as that one is process wide singleton.
   431          */
   432         return $nasgenmap$.duplicate();
   433     }
   435     /**
   436      * Constructor
   437      *
   438      * @param context the context
   439      */
   440     public Global(final Context context) {
   441         super(checkAndGetMap(context));
   442         this.setContext(context);
   443         this.setIsScope();
   445         final int cacheSize = context.getEnv()._class_cache_size;
   446         if (cacheSize > 0) {
   447             classCache = new ClassCache(cacheSize);
   448         }
   449     }
   451     /**
   452      * Script access to "current" Global instance
   453      *
   454      * @return the global singleton
   455      */
   456     public static Global instance() {
   457         ScriptObject global = Context.getGlobal();
   458         if (! (global instanceof Global)) {
   459             throw new IllegalStateException("no current global instance");
   460         }
   461         return (Global)global;
   462     }
   464     /**
   465      * Script access to {@link ScriptEnvironment}
   466      *
   467      * @return the script environment
   468      */
   469     static ScriptEnvironment getEnv() {
   470         return instance().getContext().getEnv();
   471     }
   473     /**
   474      * Script access to {@link Context}
   475      *
   476      * @return the context
   477      */
   478     static Context getThisContext() {
   479         return instance().getContext();
   480     }
   482     // GlobalObject interface implementation
   484     @Override
   485     public void initBuiltinObjects() {
   486         if (this.builtinObject != null) {
   487             // already initialized, just return
   488             return;
   489         }
   491         init();
   492     }
   494     @Override
   495     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
   496         return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
   497     }
   499     @Override
   500     public Object wrapAsObject(final Object obj) {
   501         if (obj instanceof Boolean) {
   502             return new NativeBoolean((Boolean)obj, this);
   503         } else if (obj instanceof Number) {
   504             return new NativeNumber(((Number)obj).doubleValue(), this);
   505         } else if (obj instanceof String || obj instanceof ConsString) {
   506             return new NativeString((CharSequence)obj, this);
   507         } else if (obj instanceof Object[]) { // extension
   508             return new NativeArray((Object[])obj);
   509         } else if (obj instanceof double[]) { // extension
   510             return new NativeArray((double[])obj);
   511         } else if (obj instanceof long[]) {
   512             return new NativeArray((long[])obj);
   513         } else if (obj instanceof int[]) {
   514             return new NativeArray((int[])obj);
   515         } else {
   516             // FIXME: more special cases? Map? List?
   517             return obj;
   518         }
   519     }
   521     @Override
   522     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
   523         if (self instanceof String || self instanceof ConsString) {
   524             return NativeString.lookupPrimitive(request, self);
   525         } else if (self instanceof Number) {
   526             return NativeNumber.lookupPrimitive(request, self);
   527         } else if (self instanceof Boolean) {
   528             return NativeBoolean.lookupPrimitive(request, self);
   529         }
   530         throw new IllegalArgumentException("Unsupported primitive: " + self);
   531     }
   533     @Override
   534     public ScriptObject newObject() {
   535         return new JO(getObjectPrototype(), getObjectMap());
   536     }
   538     @Override
   539     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
   540         // When the [[DefaultValue]] internal method of O is called with no hint,
   541         // then it behaves as if the hint were Number, unless O is a Date object
   542         // in which case it behaves as if the hint were String.
   543         Class<?> hint = typeHint;
   544         if (hint == null) {
   545             hint = Number.class;
   546         }
   548         try {
   549             if (hint == String.class) {
   551                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   553                 if (Bootstrap.isCallable(toString)) {
   554                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   555                     if (JSType.isPrimitive(value)) {
   556                         return value;
   557                     }
   558                 }
   560                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   561                 if (Bootstrap.isCallable(valueOf)) {
   562                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   563                     if (JSType.isPrimitive(value)) {
   564                         return value;
   565                     }
   566                 }
   567                 throw typeError(this, "cannot.get.default.string");
   568             }
   570             if (hint == Number.class) {
   571                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   572                 if (Bootstrap.isCallable(valueOf)) {
   573                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   574                     if (JSType.isPrimitive(value)) {
   575                         return value;
   576                     }
   577                 }
   579                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   580                 if (Bootstrap.isCallable(toString)) {
   581                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   582                     if (JSType.isPrimitive(value)) {
   583                         return value;
   584                     }
   585                 }
   587                 throw typeError(this, "cannot.get.default.number");
   588             }
   589         } catch (final RuntimeException | Error e) {
   590             throw e;
   591         } catch (final Throwable t) {
   592             throw new RuntimeException(t);
   593         }
   595         return UNDEFINED;
   596     }
   598     @Override
   599     public boolean isError(final ScriptObject sobj) {
   600         final ScriptObject errorProto = getErrorPrototype();
   601         ScriptObject proto = sobj.getProto();
   602         while (proto != null) {
   603             if (proto == errorProto) {
   604                 return true;
   605             }
   606             proto = proto.getProto();
   607         }
   608         return false;
   609     }
   611     @Override
   612     public ScriptObject newError(final String msg) {
   613         return new NativeError(msg, this);
   614     }
   616     @Override
   617     public ScriptObject newEvalError(final String msg) {
   618         return new NativeEvalError(msg, this);
   619     }
   621     @Override
   622     public ScriptObject newRangeError(final String msg) {
   623         return new NativeRangeError(msg, this);
   624     }
   626     @Override
   627     public ScriptObject newReferenceError(final String msg) {
   628         return new NativeReferenceError(msg, this);
   629     }
   631     @Override
   632     public ScriptObject newSyntaxError(final String msg) {
   633         return new NativeSyntaxError(msg, this);
   634     }
   636     @Override
   637     public ScriptObject newTypeError(final String msg) {
   638         return new NativeTypeError(msg, this);
   639     }
   641     @Override
   642     public ScriptObject newURIError(final String msg) {
   643         return new NativeURIError(msg, this);
   644     }
   646     @Override
   647     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
   648         return new GenericPropertyDescriptor(configurable, enumerable, this);
   649     }
   651     @Override
   652     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
   653         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
   654     }
   656     @Override
   657     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
   658         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
   660         if (get == null) {
   661             desc.delete(PropertyDescriptor.GET, false);
   662         }
   664         if (set == null) {
   665             desc.delete(PropertyDescriptor.SET, false);
   666         }
   668         return desc;
   669     }
   672     /**
   673      * Cache for compiled script classes.
   674      */
   675     @SuppressWarnings("serial")
   676     private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
   677         private final int size;
   679         ClassCache(int size) {
   680             super(size, 0.75f, true);
   681             this.size = size;
   682         }
   684         @Override
   685         protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
   686             return size() >= size;
   687         }
   688     }
   690     // Class cache management
   691     @Override
   692     public Class<?> findCachedClass(final Source source) {
   693         assert classCache != null : "Class cache used without being initialized";
   694         SoftReference<Class<?>> ref = classCache.get(source);
   695         if (ref != null) {
   696             final Class<?> clazz = ref.get();
   697             if (clazz == null) {
   698                 classCache.remove(source);
   699             }
   700             return clazz;
   701         }
   703         return null;
   704     }
   706     @Override
   707     public void cacheClass(final Source source, final Class<?> clazz) {
   708         assert classCache != null : "Class cache used without being initialized";
   709         classCache.put(source, new SoftReference<Class<?>>(clazz));
   710     }
   712     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
   713         final T obj = map.get(key);
   714         if (obj != null) {
   715             return obj;
   716         }
   718         try {
   719             final T newObj = creator.call();
   720             final T existingObj = map.putIfAbsent(key, newObj);
   721             return existingObj != null ? existingObj : newObj;
   722         } catch (final Exception exp) {
   723             throw new RuntimeException(exp);
   724         }
   725     }
   727     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
   729     @Override
   730     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
   731         return getLazilyCreatedValue(key, creator, namedInvokers);
   732     }
   734     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
   736     @Override
   737     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
   738         return getLazilyCreatedValue(key, creator, dynamicInvokers);
   739     }
   741     /**
   742      * This is the eval used when 'indirect' eval call is made.
   743      *
   744      * var global = this;
   745      * global.eval("print('hello')");
   746      *
   747      * @param self  eval scope
   748      * @param str   eval string
   749      *
   750      * @return the result of eval
   751      */
   752     public static Object eval(final Object self, final Object str) {
   753         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
   754     }
   756     /**
   757      * Direct eval
   758      *
   759      * @param self     The scope of eval passed as 'self'
   760      * @param str      Evaluated code
   761      * @param callThis "this" to be passed to the evaluated code
   762      * @param location location of the eval call
   763      * @param strict   is eval called a strict mode code?
   764      *
   765      * @return the return value of the eval
   766      *
   767      * This is directly invoked from generated when eval(code) is called in user code
   768      */
   769     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
   770         if (!(str instanceof String || str instanceof ConsString)) {
   771             return str;
   772         }
   773         final Global global = Global.instance();
   774         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   776         return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
   777     }
   779     /**
   780      * Global print implementation - Nashorn extension
   781      *
   782      * @param self    scope
   783      * @param objects arguments to print
   784      *
   785      * @return result of print (undefined)
   786      */
   787     public static Object print(final Object self, final Object... objects) {
   788         return printImpl(false, objects);
   789     }
   791     /**
   792      * Global println implementation - Nashorn extension
   793      *
   794      * @param self    scope
   795      * @param objects arguments to print
   796      *
   797      * @return result of println (undefined)
   798      */
   799     public static Object println(final Object self, final Object... objects) {
   800         return printImpl(true, objects);
   801     }
   803     /**
   804      * Global load implementation - Nashorn extension
   805      *
   806      * @param self    scope
   807      * @param source  source to load
   808      *
   809      * @return result of load (undefined)
   810      *
   811      * @throws IOException if source could not be read
   812      */
   813     public static Object load(final Object self, final Object source) throws IOException {
   814         final Global global = Global.instance();
   815         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   816         return global.getContext().load(scope, source);
   817     }
   819     /**
   820      * Global loadWithNewGlobal implementation - Nashorn extension
   821      *
   822      * @param self scope
   823      * @param args from plus (optional) arguments to be passed to the loaded script
   824      *
   825      * @return result of load (may be undefined)
   826      *
   827      * @throws IOException if source could not be read
   828      */
   829     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
   830         final Global global = Global.instance();
   831         final int length = args.length;
   832         final boolean hasArgs = 0 < length;
   833         final Object from = hasArgs ? args[0] : UNDEFINED;
   834         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
   836         return global.getContext().loadWithNewGlobal(from, arguments);
   837     }
   839     /**
   840      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
   841      *
   842      * @param self  self reference
   843      * @param code  exit code
   844      *
   845      * @return undefined (will never be reacheD)
   846      */
   847     public static Object exit(final Object self, final Object code) {
   848         System.exit(JSType.toInt32(code));
   849         return UNDEFINED;
   850     }
   852     // builtin prototype accessors
   853     ScriptObject getFunctionPrototype() {
   854         return ScriptFunction.getPrototype(builtinFunction);
   855     }
   857     ScriptObject getObjectPrototype() {
   858         return ScriptFunction.getPrototype(builtinObject);
   859     }
   861     ScriptObject getArrayPrototype() {
   862         return ScriptFunction.getPrototype(builtinArray);
   863     }
   865     ScriptObject getBooleanPrototype() {
   866         return ScriptFunction.getPrototype(builtinBoolean);
   867     }
   869     ScriptObject getNumberPrototype() {
   870         return ScriptFunction.getPrototype(builtinNumber);
   871     }
   873     ScriptObject getDatePrototype() {
   874         return ScriptFunction.getPrototype(builtinDate);
   875     }
   877     ScriptObject getRegExpPrototype() {
   878         return ScriptFunction.getPrototype(builtinRegExp);
   879     }
   881     ScriptObject getStringPrototype() {
   882         return ScriptFunction.getPrototype(builtinString);
   883     }
   885     ScriptObject getErrorPrototype() {
   886         return ScriptFunction.getPrototype(builtinError);
   887     }
   889     ScriptObject getEvalErrorPrototype() {
   890         return ScriptFunction.getPrototype(builtinEvalError);
   891     }
   893     ScriptObject getRangeErrorPrototype() {
   894         return ScriptFunction.getPrototype(builtinRangeError);
   895     }
   897     ScriptObject getReferenceErrorPrototype() {
   898         return ScriptFunction.getPrototype(builtinReferenceError);
   899     }
   901     ScriptObject getSyntaxErrorPrototype() {
   902         return ScriptFunction.getPrototype(builtinSyntaxError);
   903     }
   905     ScriptObject getTypeErrorPrototype() {
   906         return ScriptFunction.getPrototype(builtinTypeError);
   907     }
   909     ScriptObject getURIErrorPrototype() {
   910         return ScriptFunction.getPrototype(builtinURIError);
   911     }
   913     ScriptObject getJavaImporterPrototype() {
   914         return ScriptFunction.getPrototype(builtinJavaImporter);
   915     }
   917     ScriptObject getJSAdapterPrototype() {
   918         return ScriptFunction.getPrototype(builtinJSAdapter);
   919     }
   921     ScriptObject getArrayBufferPrototype() {
   922         return ScriptFunction.getPrototype(builtinArrayBuffer);
   923     }
   925     ScriptObject getInt8ArrayPrototype() {
   926         return ScriptFunction.getPrototype(builtinInt8Array);
   927     }
   929     ScriptObject getUint8ArrayPrototype() {
   930         return ScriptFunction.getPrototype(builtinUint8Array);
   931     }
   933     ScriptObject getUint8ClampedArrayPrototype() {
   934         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
   935     }
   937     ScriptObject getInt16ArrayPrototype() {
   938         return ScriptFunction.getPrototype(builtinInt16Array);
   939     }
   941     ScriptObject getUint16ArrayPrototype() {
   942         return ScriptFunction.getPrototype(builtinUint16Array);
   943     }
   945     ScriptObject getInt32ArrayPrototype() {
   946         return ScriptFunction.getPrototype(builtinInt32Array);
   947     }
   949     ScriptObject getUint32ArrayPrototype() {
   950         return ScriptFunction.getPrototype(builtinUint32Array);
   951     }
   953     ScriptObject getFloat32ArrayPrototype() {
   954         return ScriptFunction.getPrototype(builtinFloat32Array);
   955     }
   957     ScriptObject getFloat64ArrayPrototype() {
   958         return ScriptFunction.getPrototype(builtinFloat64Array);
   959     }
   961     // Builtin PropertyMap accessors
   962     PropertyMap getAccessorPropertyDescriptorMap() {
   963         return accessorPropertyDescriptorMap;
   964     }
   966     PropertyMap getArrayBufferViewMap() {
   967         return arrayBufferViewMap;
   968     }
   970     PropertyMap getDataPropertyDescriptorMap() {
   971         return dataPropertyDescriptorMap;
   972     }
   974     PropertyMap getGenericPropertyDescriptorMap() {
   975         return genericPropertyDescriptorMap;
   976     }
   978     PropertyMap getArgumentsMap() {
   979         return nativeArgumentsMap;
   980     }
   982     PropertyMap getArrayMap() {
   983         return nativeArrayMap;
   984     }
   986     PropertyMap getArrayBufferMap() {
   987         return nativeArrayBufferMap;
   988     }
   990     PropertyMap getBooleanMap() {
   991         return nativeBooleanMap;
   992     }
   994     PropertyMap getDateMap() {
   995         return nativeDateMap;
   996     }
   998     PropertyMap getErrorMap() {
   999         return nativeErrorMap;
  1002     PropertyMap getEvalErrorMap() {
  1003         return nativeEvalErrorMap;
  1006     PropertyMap getJSAdapterMap() {
  1007         return nativeJSAdapterMap;
  1010     PropertyMap getJavaImporterMap() {
  1011         return nativeJavaImporterMap;
  1014     PropertyMap getNumberMap() {
  1015         return nativeNumberMap;
  1018     PropertyMap getRangeErrorMap() {
  1019         return nativeRangeErrorMap;
  1022     PropertyMap getReferenceErrorMap() {
  1023         return nativeReferenceErrorMap;
  1026     PropertyMap getRegExpMap() {
  1027         return nativeRegExpMap;
  1030     PropertyMap getRegExpExecResultMap() {
  1031         return nativeRegExpExecResultMap;
  1034     PropertyMap getStrictArgumentsMap() {
  1035         return nativeStrictArgumentsMap;
  1038     PropertyMap getStringMap() {
  1039         return nativeStringMap;
  1042     PropertyMap getSyntaxErrorMap() {
  1043         return nativeSyntaxErrorMap;
  1046     PropertyMap getTypeErrorMap() {
  1047         return nativeTypeErrorMap;
  1050     PropertyMap getURIErrorMap() {
  1051         return nativeURIErrorMap;
  1054     PropertyMap getPrototypeObjectMap() {
  1055         return prototypeObjectMap;
  1058     PropertyMap getObjectMap() {
  1059         return objectMap;
  1062     PropertyMap getFunctionMap() {
  1063         return functionMap;
  1066     PropertyMap getAnonymousFunctionMap() {
  1067         return anonymousFunctionMap;
  1070     PropertyMap getStrictFunctionMap() {
  1071         return strictFunctionMap;
  1074     PropertyMap getBoundFunctionMap() {
  1075         return boundFunctionMap;
  1078     private ScriptFunction getBuiltinArray() {
  1079         return builtinArray;
  1082     /**
  1083      * Called from compiled script code to test if builtin has been overridden
  1085      * @return true if builtin array has not been overridden
  1086      */
  1087     public static boolean isBuiltinArray() {
  1088         final Global instance = Global.instance();
  1089         return instance.array == instance.getBuiltinArray();
  1092     private ScriptFunction getBuiltinBoolean() {
  1093         return builtinBoolean;
  1096     /**
  1097      * Called from compiled script code to test if builtin has been overridden
  1099      * @return true if builtin boolean has not been overridden
  1100      */
  1101     public static boolean isBuiltinBoolean() {
  1102         final Global instance = Global.instance();
  1103         return instance._boolean == instance.getBuiltinBoolean();
  1106     private ScriptFunction getBuiltinDate() {
  1107         return builtinDate;
  1110     /**
  1111      * Called from compiled script code to test if builtin has been overridden
  1113      * @return true if builtin date has not been overridden
  1114      */
  1115     public static boolean isBuiltinDate() {
  1116         final Global instance = Global.instance();
  1117         return instance.date == instance.getBuiltinDate();
  1120     private ScriptFunction getBuiltinError() {
  1121         return builtinError;
  1124     /**
  1125      * Called from compiled script code to test if builtin has been overridden
  1127      * @return true if builtin error has not been overridden
  1128      */
  1129     public static boolean isBuiltinError() {
  1130         final Global instance = Global.instance();
  1131         return instance.error == instance.getBuiltinError();
  1134     private ScriptFunction getBuiltinEvalError() {
  1135         return builtinEvalError;
  1138     /**
  1139      * Called from compiled script code to test if builtin has been overridden
  1141      * @return true if builtin eval error has not been overridden
  1142      */
  1143     public static boolean isBuiltinEvalError() {
  1144         final Global instance = Global.instance();
  1145         return instance.evalError == instance.getBuiltinEvalError();
  1148     private ScriptFunction getBuiltinFunction() {
  1149         return builtinFunction;
  1152     /**
  1153      * Called from compiled script code to test if builtin has been overridden
  1155      * @return true if builtin function has not been overridden
  1156      */
  1157     public static boolean isBuiltinFunction() {
  1158         final Global instance = Global.instance();
  1159         return instance.function == instance.getBuiltinFunction();
  1162     private ScriptFunction getBuiltinJSAdapter() {
  1163         return builtinJSAdapter;
  1166     /**
  1167      * Called from compiled script code to test if builtin has been overridden
  1169      * @return true if builtin JSAdapter has not been overridden
  1170      */
  1171     public static boolean isBuiltinJSAdapter() {
  1172         final Global instance = Global.instance();
  1173         return instance.jsadapter == instance.getBuiltinJSAdapter();
  1176     private ScriptObject getBuiltinJSON() {
  1177         return builtinJSON;
  1180     /**
  1181      * Called from compiled script code to test if builtin has been overridden
  1183      * @return true if builtin JSON has has not been overridden
  1184      */
  1185     public static boolean isBuiltinJSON() {
  1186         final Global instance = Global.instance();
  1187         return instance.json == instance.getBuiltinJSON();
  1190     private ScriptObject getBuiltinJava() {
  1191         return builtinJava;
  1194     /**
  1195      * Called from compiled script code to test if builtin has been overridden
  1197      * @return true if builtin Java has not been overridden
  1198      */
  1199     public static boolean isBuiltinJava() {
  1200         final Global instance = Global.instance();
  1201         return instance.java == instance.getBuiltinJava();
  1204     private ScriptObject getBuiltinJavax() {
  1205         return builtinJavax;
  1208     /**
  1209      * Called from compiled script code to test if builtin has been overridden
  1211      * @return true if builtin Javax has not been overridden
  1212      */
  1213     public static boolean isBuiltinJavax() {
  1214         final Global instance = Global.instance();
  1215         return instance.javax == instance.getBuiltinJavax();
  1218     private ScriptObject getBuiltinJavaImporter() {
  1219         return builtinJavaImporter;
  1222     /**
  1223      * Called from compiled script code to test if builtin has been overridden
  1225      * @return true if builtin Java importer has not been overridden
  1226      */
  1227     public static boolean isBuiltinJavaImporter() {
  1228         final Global instance = Global.instance();
  1229         return instance.javaImporter == instance.getBuiltinJavaImporter();
  1232     private ScriptObject getBuiltinMath() {
  1233         return builtinMath;
  1236     /**
  1237      * Called from compiled script code to test if builtin has been overridden
  1239      * @return true if builtin math has not been overridden
  1240      */
  1241     public static boolean isBuiltinMath() {
  1242         final Global instance = Global.instance();
  1243         return instance.math == instance.getBuiltinMath();
  1246     private ScriptFunction getBuiltinNumber() {
  1247         return builtinNumber;
  1250     /**
  1251      * Called from compiled script code to test if builtin has been overridden
  1253      * @return true if builtin number has not been overridden
  1254      */
  1255     public static boolean isBuiltinNumber() {
  1256         final Global instance = Global.instance();
  1257         return instance.number == instance.getBuiltinNumber();
  1260     private ScriptFunction getBuiltinObject() {
  1261         return builtinObject;
  1264     /**
  1265      * Called from compiled script code to test if builtin has been overridden
  1267      * @return true if builtin object has not been overridden
  1268      */
  1269     public static boolean isBuiltinObject() {
  1270         final Global instance = Global.instance();
  1271         return instance.object == instance.getBuiltinObject();
  1274     private ScriptObject getBuiltinPackages() {
  1275         return builtinPackages;
  1278     /**
  1279      * Called from compiled script code to test if builtin has been overridden
  1281      * @return true if builtin package has not been overridden
  1282      */
  1283     public static boolean isBuiltinPackages() {
  1284         final Global instance = Global.instance();
  1285         return instance.packages == instance.getBuiltinPackages();
  1288     private ScriptFunction getBuiltinRangeError() {
  1289         return builtinRangeError;
  1292     /**
  1293      * Called from compiled script code to test if builtin has been overridden
  1295      * @return true if builtin range error has not been overridden
  1296      */
  1297     public static boolean isBuiltinRangeError() {
  1298         final Global instance = Global.instance();
  1299         return instance.rangeError == instance.getBuiltinRangeError();
  1302     private ScriptFunction getBuiltinReferenceError() {
  1303         return builtinReferenceError;
  1306     /**
  1307      * Called from compiled script code to test if builtin has been overridden
  1309      * @return true if builtin reference error has not been overridden
  1310      */
  1311     public static boolean isBuiltinReferenceError() {
  1312         final Global instance = Global.instance();
  1313         return instance.referenceError == instance.getBuiltinReferenceError();
  1316     private ScriptFunction getBuiltinRegExp() {
  1317         return builtinRegExp;
  1320     /**
  1321      * Called from compiled script code to test if builtin has been overridden
  1323      * @return true if builtin regexp has not been overridden
  1324      */
  1325     public static boolean isBuiltinRegExp() {
  1326         final Global instance = Global.instance();
  1327         return instance.regexp == instance.getBuiltinRegExp();
  1330     private ScriptFunction getBuiltinString() {
  1331         return builtinString;
  1334     /**
  1335      * Called from compiled script code to test if builtin has been overridden
  1337      * @return true if builtin Java has not been overridden
  1338      */
  1339     public static boolean isBuiltinString() {
  1340         final Global instance = Global.instance();
  1341         return instance.string == instance.getBuiltinString();
  1344     private ScriptFunction getBuiltinSyntaxError() {
  1345         return builtinSyntaxError;
  1348     /**
  1349      * Called from compiled script code to test if builtin has been overridden
  1351      * @return true if builtin syntax error has not been overridden
  1352      */
  1353     public static boolean isBuiltinSyntaxError() {
  1354         final Global instance = Global.instance();
  1355         return instance.syntaxError == instance.getBuiltinSyntaxError();
  1358     private ScriptFunction getBuiltinTypeError() {
  1359         return builtinTypeError;
  1362     /**
  1363      * Called from compiled script code to test if builtin has been overridden
  1365      * @return true if builtin type error has not been overridden
  1366      */
  1367     public static boolean isBuiltinTypeError() {
  1368         final Global instance = Global.instance();
  1369         return instance.typeError == instance.getBuiltinTypeError();
  1372     private ScriptFunction getBuiltinURIError() {
  1373         return builtinURIError;
  1376     /**
  1377      * Called from compiled script code to test if builtin has been overridden
  1379      * @return true if builtin URI error has not been overridden
  1380      */
  1381     public static boolean isBuiltinURIError() {
  1382         final Global instance = Global.instance();
  1383         return instance.uriError == instance.getBuiltinURIError();
  1386     @Override
  1387     public String getClassName() {
  1388         return "global";
  1391     /**
  1392      * Copy function used to clone NativeRegExp objects.
  1394      * @param regexp a NativeRegExp to clone
  1396      * @return copy of the given regexp object
  1397      */
  1398     public static Object regExpCopy(final Object regexp) {
  1399         return new NativeRegExp((NativeRegExp)regexp);
  1402     /**
  1403      * Convert given object to NativeRegExp type.
  1405      * @param obj object to be converted
  1406      * @return NativeRegExp instance
  1407      */
  1408     public static NativeRegExp toRegExp(final Object obj) {
  1409         if (obj instanceof NativeRegExp) {
  1410             return (NativeRegExp)obj;
  1412         return new NativeRegExp(JSType.toString(obj));
  1415     /**
  1416      * ECMA 9.9 ToObject implementation
  1418      * @param obj  an item for which to run ToObject
  1419      * @return ToObject version of given item
  1420      */
  1421     public static Object toObject(final Object obj) {
  1422         if (obj == null || obj == UNDEFINED) {
  1423             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1426         if (obj instanceof ScriptObject) {
  1427             return obj;
  1430         return instance().wrapAsObject(obj);
  1433     /**
  1434      * Allocate a new object array.
  1436      * @param initial object values.
  1437      * @return the new array
  1438      */
  1439     public static NativeArray allocate(final Object[] initial) {
  1440         ArrayData arrayData = ArrayData.allocate(initial);
  1442         for (int index = 0; index < initial.length; index++) {
  1443             final Object value = initial[index];
  1445             if (value == ScriptRuntime.EMPTY) {
  1446                 arrayData = arrayData.delete(index);
  1450         return new NativeArray(arrayData);
  1453     /**
  1454      * Allocate a new number array.
  1456      * @param initial number values.
  1457      * @return the new array
  1458      */
  1459     public static NativeArray allocate(final double[] initial) {
  1460         return new NativeArray(ArrayData.allocate(initial));
  1463     /**
  1464      * Allocate a new long array.
  1466      * @param initial number values.
  1467      * @return the new array
  1468      */
  1469     public static NativeArray allocate(final long[] initial) {
  1470         return new NativeArray(ArrayData.allocate(initial));
  1473     /**
  1474      * Allocate a new integer array.
  1476      * @param initial number values.
  1477      * @return the new array
  1478      */
  1479     public static NativeArray allocate(final int[] initial) {
  1480         return new NativeArray(ArrayData.allocate(initial));
  1483     /**
  1484      * Allocate a new object array for arguments.
  1486      * @param arguments initial arguments passed.
  1487      * @param callee reference to the function that uses arguments object
  1488      * @param numParams actual number of declared parameters
  1490      * @return the new array
  1491      */
  1492     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
  1493         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
  1496     /**
  1497      * Called from generated to check if given function is the builtin 'eval'. If
  1498      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
  1500      * @param  fn function object that is checked
  1501      * @return true if fn is the builtin eval
  1502      */
  1503     public static boolean isEval(final Object fn) {
  1504         return fn == Global.instance().builtinEval;
  1507     /**
  1508      * Create a new RegExp object.
  1510      * @param expression Regular expression.
  1511      * @param options    Search options.
  1513      * @return New RegExp object.
  1514      */
  1515     public static Object newRegExp(final String expression, final String options) {
  1516         if (options == null) {
  1517             return new NativeRegExp(expression);
  1519         return new NativeRegExp(expression, options);
  1522     /**
  1523      * Get the object prototype
  1525      * @return the object prototype
  1526      */
  1527     public static ScriptObject objectPrototype() {
  1528         return Global.instance().getObjectPrototype();
  1531     /**
  1532      * Create a new empty object instance.
  1534      * @return New empty object.
  1535      */
  1536     public static ScriptObject newEmptyInstance() {
  1537         return Global.instance().newObject();
  1540     /**
  1541      * Check if a given object is a ScriptObject, raises an exception if this is
  1542      * not the case
  1544      * @param obj and object to check
  1545      */
  1546     public static void checkObject(final Object obj) {
  1547         if (!(obj instanceof ScriptObject)) {
  1548             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1552     /**
  1553      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
  1554      * if this object is null or undefined.
  1556      * @param obj an object to check
  1557      */
  1558     public static void checkObjectCoercible(final Object obj) {
  1559         if (obj == null || obj == UNDEFINED) {
  1560             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1564     /**
  1565      * Get the current split state.
  1567      * @return current split state
  1568      */
  1569     @Override
  1570     public int getSplitState() {
  1571         return splitState;
  1574     /**
  1575      * Set the current split state.
  1577      * @param state current split state
  1578      */
  1579     @Override
  1580     public void setSplitState(final int state) {
  1581         splitState = state;
  1584     private void init() {
  1585         assert Context.getGlobal() == this : "this global is not set as current";
  1587         final ScriptEnvironment env = getContext().getEnv();
  1589         // duplicate PropertyMaps of Native* classes
  1590         copyInitialMaps(env);
  1592         // initialize Function and Object constructor
  1593         initFunctionAndObject();
  1595         // Now fix Global's own proto.
  1596         this.setProto(getObjectPrototype());
  1598         // initialize global function properties
  1599         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  1601         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
  1602         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  1603         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
  1604         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
  1605         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
  1606         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
  1607         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
  1608         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
  1609         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
  1610         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
  1611         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
  1612         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
  1613         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
  1614         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
  1615         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
  1617         // built-in constructors
  1618         this.builtinArray     = (ScriptFunction)initConstructor("Array");
  1619         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
  1620         this.builtinDate      = (ScriptFunction)initConstructor("Date");
  1621         this.builtinJSON      = initConstructor("JSON");
  1622         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
  1623         this.builtinMath      = initConstructor("Math");
  1624         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
  1625         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
  1626         this.builtinString    = (ScriptFunction)initConstructor("String");
  1628         // initialize String.prototype.length to 0
  1629         // add String.prototype.length
  1630         final ScriptObject stringPrototype = getStringPrototype();
  1631         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  1633         // add Array.prototype.length
  1634         final ScriptObject arrayPrototype = getArrayPrototype();
  1635         arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0);
  1637         this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
  1639         // initialize default regexp object
  1640         this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
  1642         // RegExp.prototype should behave like a RegExp object. So copy the
  1643         // properties.
  1644         final ScriptObject regExpProto = getRegExpPrototype();
  1645         regExpProto.addBoundProperties(DEFAULT_REGEXP);
  1647         // Error stuff
  1648         initErrorObjects();
  1650         // java access
  1651         if (! env._no_java) {
  1652             initJavaAccess();
  1655         if (! env._no_typed_arrays) {
  1656             initTypedArray();
  1659         if (env._scripting) {
  1660             initScripting(env);
  1663         if (Context.DEBUG && System.getSecurityManager() == null) {
  1664             initDebug();
  1667         copyBuiltins();
  1669         // initialized with strings so that typeof will work as expected.
  1670         this.__FILE__ = "";
  1671         this.__DIR__  = "";
  1672         this.__LINE__ = 0.0;
  1674         // expose script (command line) arguments as "arguments" property of global
  1675         final List<String> arguments = env.getArguments();
  1676         final Object argsObj = wrapAsObject(arguments.toArray());
  1678         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
  1679         if (env._scripting) {
  1680             // synonym for "arguments" in scripting mode
  1681             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
  1685     private void initErrorObjects() {
  1686         // Error objects
  1687         this.builtinError = (ScriptFunction)initConstructor("Error");
  1688         final ScriptObject errorProto = getErrorPrototype();
  1690         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
  1691         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
  1692         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
  1693         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
  1694         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
  1695         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
  1696         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
  1697         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
  1698         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
  1699         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
  1700         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
  1701         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
  1702         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
  1704         // ECMA 15.11.4.2 Error.prototype.name
  1705         // Error.prototype.name = "Error";
  1706         errorProto.set(NativeError.NAME, "Error", false);
  1707         // ECMA 15.11.4.3 Error.prototype.message
  1708         // Error.prototype.message = "";
  1709         errorProto.set(NativeError.MESSAGE, "", false);
  1711         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
  1712         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
  1713         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
  1714         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
  1715         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
  1716         this.builtinURIError = initErrorSubtype("URIError", errorProto);
  1719     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
  1720         final ScriptObject cons = initConstructor(name);
  1721         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  1722         prototype.set(NativeError.NAME, name, false);
  1723         prototype.set(NativeError.MESSAGE, "", false);
  1724         prototype.setProto(errorProto);
  1725         return (ScriptFunction)cons;
  1728     private void initJavaAccess() {
  1729         final ScriptObject objectProto = getObjectPrototype();
  1730         this.builtinPackages = new NativeJavaPackage("", objectProto);
  1731         this.builtinCom = new NativeJavaPackage("com", objectProto);
  1732         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
  1733         this.builtinJava = new NativeJavaPackage("java", objectProto);
  1734         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
  1735         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
  1736         this.builtinOrg = new NativeJavaPackage("org", objectProto);
  1737         this.builtinJavaImporter = initConstructor("JavaImporter");
  1738         this.builtinJavaApi = initConstructor("Java");
  1741     private void initScripting(final ScriptEnvironment scriptEnv) {
  1742         Object value;
  1743         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
  1744         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
  1746         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
  1747         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
  1749         final String execName = ScriptingFunctions.EXEC_NAME;
  1750         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
  1751         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
  1753         // Nashorn extension: global.echo (scripting-mode-only)
  1754         // alias for "print"
  1755         value = get("print");
  1756         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
  1758         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
  1759         final ScriptObject options = newObject();
  1760         copyOptions(options, scriptEnv);
  1761         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
  1763         // Nashorn extension: global.$ENV (scripting-mode-only)
  1764         if (System.getSecurityManager() == null) {
  1765             // do not fill $ENV if we have a security manager around
  1766             // Retrieve current state of ENV variables.
  1767             final ScriptObject env = newObject();
  1768             env.putAll(System.getenv());
  1769             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
  1770         } else {
  1771             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1774         // add other special properties for exec support
  1775         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1776         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1777         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1780     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
  1781         for (Field f : scriptEnv.getClass().getFields()) {
  1782             try {
  1783                 options.set(f.getName(), f.get(scriptEnv), false);
  1784             } catch (final IllegalArgumentException | IllegalAccessException exp) {
  1785                 throw new RuntimeException(exp);
  1790     private void initTypedArray() {
  1791         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
  1792         this.builtinInt8Array         = initConstructor("Int8Array");
  1793         this.builtinUint8Array        = initConstructor("Uint8Array");
  1794         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
  1795         this.builtinInt16Array        = initConstructor("Int16Array");
  1796         this.builtinUint16Array       = initConstructor("Uint16Array");
  1797         this.builtinInt32Array        = initConstructor("Int32Array");
  1798         this.builtinUint32Array       = initConstructor("Uint32Array");
  1799         this.builtinFloat32Array      = initConstructor("Float32Array");
  1800         this.builtinFloat64Array      = initConstructor("Float64Array");
  1803     private void copyBuiltins() {
  1804         this.array             = this.builtinArray;
  1805         this._boolean          = this.builtinBoolean;
  1806         this.date              = this.builtinDate;
  1807         this.error             = this.builtinError;
  1808         this.evalError         = this.builtinEvalError;
  1809         this.function          = this.builtinFunction;
  1810         this.jsadapter         = this.builtinJSAdapter;
  1811         this.json              = this.builtinJSON;
  1812         this.com               = this.builtinCom;
  1813         this.edu               = this.builtinEdu;
  1814         this.java              = this.builtinJava;
  1815         this.javafx            = this.builtinJavafx;
  1816         this.javax             = this.builtinJavax;
  1817         this.org               = this.builtinOrg;
  1818         this.javaImporter      = this.builtinJavaImporter;
  1819         this.javaApi           = this.builtinJavaApi;
  1820         this.math              = this.builtinMath;
  1821         this.number            = this.builtinNumber;
  1822         this.object            = this.builtinObject;
  1823         this.packages          = this.builtinPackages;
  1824         this.rangeError        = this.builtinRangeError;
  1825         this.referenceError    = this.builtinReferenceError;
  1826         this.regexp            = this.builtinRegExp;
  1827         this.string            = this.builtinString;
  1828         this.syntaxError       = this.builtinSyntaxError;
  1829         this.typeError         = this.builtinTypeError;
  1830         this.uriError          = this.builtinURIError;
  1831         this.arrayBuffer       = this.builtinArrayBuffer;
  1832         this.int8Array         = this.builtinInt8Array;
  1833         this.uint8Array        = this.builtinUint8Array;
  1834         this.uint8ClampedArray = this.builtinUint8ClampedArray;
  1835         this.int16Array        = this.builtinInt16Array;
  1836         this.uint16Array       = this.builtinUint16Array;
  1837         this.int32Array        = this.builtinInt32Array;
  1838         this.uint32Array       = this.builtinUint32Array;
  1839         this.float32Array      = this.builtinFloat32Array;
  1840         this.float64Array      = this.builtinFloat64Array;
  1843     private void initDebug() {
  1844         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
  1847     @SuppressWarnings("resource")
  1848     private static Object printImpl(final boolean newLine, final Object... objects) {
  1849         final PrintWriter out = Global.getEnv().getOut();
  1850         final StringBuilder sb = new StringBuilder();
  1852         for (final Object object : objects) {
  1853             if (sb.length() != 0) {
  1854                 sb.append(' ');
  1857             sb.append(JSType.toString(object));
  1860         // Print all at once to ensure thread friendly result.
  1861         if (newLine) {
  1862             out.println(sb.toString());
  1863         } else {
  1864             out.print(sb.toString());
  1867         out.flush();
  1869         return UNDEFINED;
  1872     /**
  1873      * These classes are generated by nasgen tool and so we have to use
  1874      * reflection to load and create new instance of these classes.
  1875      */
  1876     private ScriptObject initConstructor(final String name) {
  1877         try {
  1878             // Assuming class name pattern for built-in JS constructors.
  1879             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
  1881             sb.append("Native");
  1882             sb.append(name);
  1883             sb.append("$Constructor");
  1885             final Class<?>     funcClass = Class.forName(sb.toString());
  1886             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
  1888             if (res instanceof ScriptFunction) {
  1889                 // All global constructor prototypes are not-writable,
  1890                 // not-enumerable and not-configurable.
  1891                 final ScriptFunction func = (ScriptFunction)res;
  1892                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
  1895             if (res.getProto() == null) {
  1896                 res.setProto(getObjectPrototype());
  1899             return res;
  1901         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  1902             throw new RuntimeException(e);
  1906     private void copyInitialMaps(final ScriptEnvironment env) {
  1907         this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
  1908         this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
  1909         this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
  1910         this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
  1911         this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
  1912         this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
  1913         this.nativeDateMap = NativeDate.getInitialMap().duplicate();
  1914         this.nativeErrorMap = NativeError.getInitialMap().duplicate();
  1915         this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
  1916         this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
  1917         this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
  1918         this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
  1919         this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
  1920         this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
  1921         this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
  1922         this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
  1923         this.nativeStringMap = NativeString.getInitialMap().duplicate();
  1924         this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
  1925         this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
  1926         this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
  1927         this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
  1928         this.objectMap = JO.getInitialMap().duplicate();
  1929         this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
  1930         this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
  1931         this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
  1932         this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
  1934         // java
  1935         if (! env._no_java) {
  1936             this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
  1939         // typed arrays
  1940         if (! env._no_typed_arrays) {
  1941             this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
  1942             this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
  1946     // Function and Object constructors are inter-dependent. Also,
  1947     // Function.prototype
  1948     // functions are not properly initialized. We fix the references here.
  1949     // NOTE: be careful if you want to re-order the operations here. You may
  1950     // have
  1951     // to play with object references carefully!!
  1952     private void initFunctionAndObject() {
  1953         // First-n-foremost is Function
  1954         this.builtinFunction = (ScriptFunction)initConstructor("Function");
  1956         // create global anonymous function
  1957         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
  1958         // need to copy over members of Function.prototype to anon function
  1959         anon.addBoundProperties(getFunctionPrototype());
  1961         // Function.prototype === Object.getPrototypeOf(Function) ===
  1962         // <anon-function>
  1963         builtinFunction.setProto(anon);
  1964         builtinFunction.setPrototype(anon);
  1965         anon.set("constructor", builtinFunction, false);
  1966         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  1968         // now initialize Object
  1969         this.builtinObject = (ScriptFunction)initConstructor("Object");
  1970         final ScriptObject ObjectPrototype = getObjectPrototype();
  1971         // Object.getPrototypeOf(Function.prototype) === Object.prototype
  1972         anon.setProto(ObjectPrototype);
  1974         // Function valued properties of Function.prototype were not properly
  1975         // initialized. Because, these were created before global.function and
  1976         // global.object were not initialized.
  1977         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
  1978         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1979             final Object key = property.getKey();
  1980             final Object value = builtinFunction.get(key);
  1982             if (value instanceof ScriptFunction && value != anon) {
  1983                 final ScriptFunction func = (ScriptFunction)value;
  1984                 func.setProto(getFunctionPrototype());
  1985                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1986                 if (prototype != null) {
  1987                     prototype.setProto(ObjectPrototype);
  1992         // For function valued properties of Object and Object.prototype, make
  1993         // sure prototype's proto chain ends with Object.prototype
  1994         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
  1995             final Object key = property.getKey();
  1996             final Object value = builtinObject.get(key);
  1998             if (value instanceof ScriptFunction) {
  1999                 final ScriptFunction func = (ScriptFunction)value;
  2000                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2001                 if (prototype != null) {
  2002                     prototype.setProto(ObjectPrototype);
  2007         properties = getObjectPrototype().getMap().getProperties();
  2008         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2009             final Object key   = property.getKey();
  2010             final Object value = ObjectPrototype.get(key);
  2012             if (key.equals("constructor")) {
  2013                 continue;
  2016             if (value instanceof ScriptFunction) {
  2017                 final ScriptFunction func = (ScriptFunction)value;
  2018                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2019                 if (prototype != null) {
  2020                     prototype.setProto(ObjectPrototype);
  2026     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
  2027         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
  2030     RegExpResult getLastRegExpResult() {
  2031         return lastRegExpResult;
  2034     void setLastRegExpResult(final RegExpResult regExpResult) {
  2035         this.lastRegExpResult = regExpResult;

mercurial