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

Wed, 06 Feb 2013 10:31:58 +0100

author
hannesw
date
Wed, 06 Feb 2013 10:31:58 +0100
changeset 72
f6fae6de6f4f
parent 69
c48e8a28da90
child 73
fcf541418304
permissions
-rw-r--r--

8007273: Creation of ScriptFunctions can be refactored
Reviewed-by: lagergren, attila

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.objects;
    28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    30 import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
    32 import java.io.IOException;
    33 import java.io.PrintWriter;
    34 import java.lang.invoke.MethodHandle;
    35 import java.lang.invoke.MethodHandles;
    36 import java.lang.ref.SoftReference;
    37 import java.util.LinkedHashMap;
    38 import java.util.List;
    39 import java.util.Map;
    40 import jdk.nashorn.internal.objects.annotations.Attribute;
    41 import jdk.nashorn.internal.objects.annotations.Property;
    42 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    43 import jdk.nashorn.internal.runtime.ConsString;
    44 import jdk.nashorn.internal.runtime.Context;
    45 import jdk.nashorn.internal.runtime.GlobalFunctions;
    46 import jdk.nashorn.internal.runtime.GlobalObject;
    47 import jdk.nashorn.internal.runtime.JSType;
    48 import jdk.nashorn.internal.runtime.NativeJavaPackage;
    49 import jdk.nashorn.internal.runtime.OptionsObject;
    50 import jdk.nashorn.internal.runtime.PropertyDescriptor;
    51 import jdk.nashorn.internal.runtime.Scope;
    52 import jdk.nashorn.internal.runtime.ScriptFunction;
    53 import jdk.nashorn.internal.runtime.ScriptObject;
    54 import jdk.nashorn.internal.runtime.ScriptRuntime;
    55 import jdk.nashorn.internal.runtime.ScriptingFunctions;
    56 import jdk.nashorn.internal.runtime.Source;
    57 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    58 import jdk.nashorn.internal.scripts.JO$;
    59 import org.dynalang.dynalink.linker.GuardedInvocation;
    60 import org.dynalang.dynalink.linker.LinkRequest;
    62 /**
    63  * Representation of global scope.
    64  */
    65 @ScriptClass("Global")
    66 public final class Global extends ScriptObject implements GlobalObject, Scope {
    67     private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    68     private static final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
    70     /** ECMA 15.1.2.2 parseInt (string , radix) */
    71     @Property(attributes = Attribute.NOT_ENUMERABLE)
    72     public Object parseInt;
    74     /** ECMA 15.1.2.3 parseFloat (string) */
    75     @Property(attributes = Attribute.NOT_ENUMERABLE)
    76     public Object parseFloat;
    78     /** ECMA 15.1.2.4 isNaN (number) */
    79     @Property(attributes = Attribute.NOT_ENUMERABLE)
    80     public Object isNaN;
    82     /** ECMA 15.1.2.5 isFinite (number) */
    83     @Property(attributes = Attribute.NOT_ENUMERABLE)
    84     public Object isFinite;
    86     /** ECMA 15.1.3.3 encodeURI */
    87     @Property(attributes = Attribute.NOT_ENUMERABLE)
    88     public Object encodeURI;
    90     /** ECMA 15.1.3.4 encodeURIComponent */
    91     @Property(attributes = Attribute.NOT_ENUMERABLE)
    92     public Object encodeURIComponent;
    94     /** ECMA 15.1.3.1 decodeURI */
    95     @Property(attributes = Attribute.NOT_ENUMERABLE)
    96     public Object decodeURI;
    98     /** ECMA 15.1.3.2 decodeURIComponent */
    99     @Property(attributes = Attribute.NOT_ENUMERABLE)
   100     public Object decodeURIComponent;
   102     /** ECMA B.2.1 escape (string) */
   103     @Property(attributes = Attribute.NOT_ENUMERABLE)
   104     public Object escape;
   106     /** ECMA B.2.2 unescape (string) */
   107     @Property(attributes = Attribute.NOT_ENUMERABLE)
   108     public Object unescape;
   110     /** Nashorn extension: global.print */
   111     @Property(attributes = Attribute.NOT_ENUMERABLE)
   112     public Object print;
   114     /** Nashorn extension: global.load */
   115     @Property(attributes = Attribute.NOT_ENUMERABLE)
   116     public Object load;
   118     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
   119     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   120     public final Object NaN = Double.NaN;
   122     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
   123     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   124     public final Object Infinity = Double.POSITIVE_INFINITY;
   126     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
   127     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   128     public final Object undefined = UNDEFINED;
   130     /** ECMA 15.1.2.1 eval(x) */
   131     @Property(attributes = Attribute.NOT_ENUMERABLE)
   132     public Object eval;
   134     /** ECMA 15.1.4.1 Object constructor. */
   135     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
   136     public volatile Object object;
   138     /** ECMA 15.1.4.2 Function constructor. */
   139     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
   140     public volatile Object function;
   142     /** ECMA 15.1.4.3 Array constructor. */
   143     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
   144     public volatile Object array;
   146     /** ECMA 15.1.4.4 String constructor */
   147     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
   148     public volatile Object string;
   150     /** ECMA 15.1.4.5 Boolean constructor */
   151     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
   152     public volatile Object _boolean;
   154     /** ECMA 15.1.4.6 - Number constructor */
   155     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
   156     public volatile Object number;
   158     /** ECMA 15.1.4.7 Date constructor */
   159     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   160     public volatile Object date;
   162     /** ECMA 15.1.4.8 RegExp constructor */
   163     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   164     public volatile Object regexp;
   166     /** ECMA 15.12 - The JSON object */
   167     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   168     public volatile Object json;
   170     /** Nashorn extension: global.JSAdapter */
   171     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   172     public volatile Object jsadapter;
   174     /** ECMA 15.8 - The Math object */
   175     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
   176     public volatile Object math;
   178     /** Error object */
   179     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
   180     public volatile Object error;
   182     /** EvalError object */
   183     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   184     public volatile Object evalError;
   186     /** RangeError object */
   187     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   188     public volatile Object rangeError;
   190     /** ReferenceError object */
   191     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
   192     public volatile Object referenceError;
   194     /** SyntaxError object */
   195     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
   196     public volatile Object syntaxError;
   198     /** TypeError object */
   199     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
   200     public volatile Object typeError;
   202     /** URIError object */
   203     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   204     public volatile Object uriError;
   206     /** ArrayBuffer object */
   207     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   208     public volatile Object arrayBuffer;
   210     /** TypedArray (int8) */
   211     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   212     public volatile Object int8Array;
   214     /** TypedArray (uint8) */
   215     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   216     public volatile Object uint8Array;
   218     /** TypedArray (uint8) - Clamped */
   219     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   220     public volatile Object uint8ClampedArray;
   222     /** TypedArray (int16) */
   223     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   224     public volatile Object int16Array;
   226     /** TypedArray (uint16) */
   227     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   228     public volatile Object uint16Array;
   230     /** TypedArray (int32) */
   231     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   232     public volatile Object int32Array;
   234     /** TypedArray (uint32) */
   235     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   236     public volatile Object uint32Array;
   238     /** TypedArray (float32) */
   239     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   240     public volatile Object float32Array;
   242     /** TypedArray (float64) */
   243     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   244     public volatile Object float64Array;
   246     /** Nashorn extension: Java access - global.Packages */
   247     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
   248     public volatile Object packages;
   250     /** Nashorn extension: Java access - global.java */
   251     @Property(attributes = Attribute.NOT_ENUMERABLE)
   252     public volatile Object java;
   254     /** Nashorn extension: Java access - global.javax */
   255     @Property(attributes = Attribute.NOT_ENUMERABLE)
   256     public Object javax;
   258     /** Nashorn extension: Java access - global.javaImporter */
   259     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   260     public volatile Object javaImporter;
   262     /** Nashorn extension: global.Java Object constructor. */
   263     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   264     public volatile Object javaApi;
   266     /** Nashorn extension: current script's file name */
   267     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   268     public Object __FILE__;
   270     /** Nashorn extension: current script's directory */
   271     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   272     public Object __DIR__;
   274     /** Nashorn extension: current source line number being executed */
   275     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   276     public Object __LINE__;
   278     /** Used as Date.prototype's default value */
   279     public NativeDate   DEFAULT_DATE;
   281     /** Used as RegExp.prototype's default value */
   282     public NativeRegExp DEFAULT_REGEXP;
   284     /*
   285      * Built-in constructor objects: Even if user changes dynamic values of
   286      * "Object", "Array" etc., we still want to keep original values of these
   287      * constructors here. For example, we need to be able to create array,
   288      * regexp literals even after user overwrites global "Array" or "RegExp"
   289      * constructor - see also ECMA 262 spec. Annex D.
   290      */
   291     private ScriptFunction builtinFunction;
   292     private ScriptFunction builtinObject;
   293     private ScriptFunction builtinArray;
   294     private ScriptFunction builtinBoolean;
   295     private ScriptFunction builtinDate;
   296     private ScriptObject   builtinJSON;
   297     private ScriptFunction builtinJSAdapter;
   298     private ScriptObject   builtinMath;
   299     private ScriptFunction builtinNumber;
   300     private ScriptFunction builtinRegExp;
   301     private ScriptFunction builtinString;
   302     private ScriptFunction builtinError;
   303     private ScriptFunction builtinEval;
   304     private ScriptFunction builtinEvalError;
   305     private ScriptFunction builtinRangeError;
   306     private ScriptFunction builtinReferenceError;
   307     private ScriptFunction builtinSyntaxError;
   308     private ScriptFunction builtinTypeError;
   309     private ScriptFunction builtinURIError;
   310     private ScriptObject   builtinPackages;
   311     private ScriptObject   builtinJava;
   312     private ScriptObject   builtinJavax;
   313     private ScriptObject   builtinJavaImporter;
   314     private ScriptObject   builtinJavaApi;
   315     private ScriptObject   builtinArrayBuffer;
   316     private ScriptObject   builtinInt8Array;
   317     private ScriptObject   builtinUint8Array;
   318     private ScriptObject   builtinUint8ClampedArray;
   319     private ScriptObject   builtinInt16Array;
   320     private ScriptObject   builtinUint16Array;
   321     private ScriptObject   builtinInt32Array;
   322     private ScriptObject   builtinUint32Array;
   323     private ScriptObject   builtinFloat32Array;
   324     private ScriptObject   builtinFloat64Array;
   326     // Flag to indicate that a split method issued a return statement
   327     private int splitState = -1;
   329     // class cache
   330     private ClassCache classCache;
   332     private static final MethodHandle EVAL    = findOwnMH("eval",    Object.class, Object.class, Object.class);
   333     private static final MethodHandle PRINT   = findOwnMH("print",   Object.class, Object.class, Object[].class);
   334     private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
   335     private static final MethodHandle LOAD    = findOwnMH("load",    Object.class, Object.class, Object.class);
   337     /**
   338      * Constructor
   339      */
   340     public Global() {
   341         this.setIsScope();
   342         /*
   343          * Duplicate global's map and use it. This way the initial Map filled
   344          * by nasgen (referenced from static field in this class) is retained
   345          * 'as is'. This allows multiple globals to be used within a context.
   346          */
   347         this.setMap(getMap().duplicate());
   349         final int cacheSize = getContext()._class_cache_size;
   350         if (cacheSize > 0) {
   351             classCache = new ClassCache(cacheSize);
   352         }
   353     }
   355     /**
   356      * Script access to unique context specific Global instance
   357      *
   358      * @return the global singleton
   359      */
   360     public static Global instance() {
   361         return (Global)Context.getGlobal();
   362     }
   364     /**
   365      * Script access to {@link Context}
   366      *
   367      * @return the context
   368      */
   369     static Context getThisContext() {
   370         return instance().getContext();
   371     }
   373     /**
   374      * Script access check for strict mode
   375      *
   376      * @return true if strict mode enabled in {@link Global#getThisContext()}
   377      */
   378     static boolean isStrict() {
   379         return getThisContext()._strict;
   380     }
   382     // GlobalObject interface implementation
   384     @Override
   385     public void initBuiltinObjects() {
   386         if (this.builtinObject != null) {
   387             // already initialized, just return
   388             return;
   389         }
   391         init();
   392     }
   394     @Override
   395     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
   396         return new ScriptFunctionImpl(name, handle, scope, null, strict, false);
   397     }
   399     @Override
   400     public Object wrapAsObject(final Object obj) {
   401         if (obj instanceof Boolean) {
   402             return new NativeBoolean((Boolean)obj);
   403         } else if (obj instanceof Number) {
   404             return new NativeNumber(((Number)obj).doubleValue());
   405         } else if (obj instanceof String || obj instanceof ConsString) {
   406             return new NativeString((CharSequence)obj);
   407         } else if (obj instanceof Object[]) { // extension
   408             return new NativeArray((Object[])obj);
   409         } else if (obj instanceof double[]) { // extension
   410             return new NativeArray((double[])obj);
   411         } else if (obj instanceof long[]) {
   412             return new NativeArray((long[])obj);
   413         } else if (obj instanceof int[]) {
   414             return new NativeArray((int[])obj);
   415         } else {
   416             // FIXME: more special cases? Map? List?
   417             return obj;
   418         }
   419     }
   421     @Override
   422     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
   423         if (self instanceof String || self instanceof ConsString) {
   424             return NativeString.lookupPrimitive(request, self);
   425         } else if (self instanceof Number) {
   426             return NativeNumber.lookupPrimitive(request, self);
   427         } else if (self instanceof Boolean) {
   428             return NativeBoolean.lookupPrimitive(request, self);
   429         }
   430         throw new IllegalArgumentException("Unsupported primitive: " + self);
   431     }
   433     @Override
   434     public ScriptObject newObject() {
   435         return newEmptyInstance();
   436     }
   438     @Override
   439     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
   440         // When the [[DefaultValue]] internal method of O is called with no hint,
   441         // then it behaves as if the hint were Number, unless O is a Date object
   442         // in which case it behaves as if the hint were String.
   443         Class<?> hint = typeHint;
   444         if (hint == null) {
   445             hint = Number.class;
   446         }
   448         try {
   449             if (hint == String.class) {
   451                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   452                 if (toString instanceof ScriptFunction) {
   453                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   454                     if (JSType.isPrimitive(value)) {
   455                         return value;
   456                     }
   457                 }
   459                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   460                 if (valueOf instanceof ScriptFunction) {
   461                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   462                     if (JSType.isPrimitive(value)) {
   463                         return value;
   464                     }
   465                 }
   466                 typeError(this, "cannot.get.default.string");
   467             }
   469             if (hint == Number.class) {
   470                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   471                 if (valueOf instanceof ScriptFunction) {
   472                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   473                     if (JSType.isPrimitive(value)) {
   474                         return value;
   475                     }
   476                 }
   478                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   479                 if (toString instanceof ScriptFunction) {
   480                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   481                     if (JSType.isPrimitive(value)) {
   482                         return value;
   483                     }
   484                 }
   486                 typeError(this, "cannot.get.default.number");
   487             }
   488         } catch (final RuntimeException | Error e) {
   489             throw e;
   490         } catch (final Throwable t) {
   491             throw new RuntimeException(t);
   492         }
   494         return UNDEFINED;
   495     }
   497     @Override
   498     public boolean isError(final ScriptObject sobj) {
   499         final ScriptObject errorProto = getErrorPrototype();
   500         ScriptObject proto = sobj.getProto();
   501         while (proto != null) {
   502             if (proto == errorProto) {
   503                 return true;
   504             }
   505             proto = proto.getProto();
   506         }
   507         return false;
   508     }
   510     @Override
   511     public ScriptObject newError(final String msg) {
   512         return new NativeError(msg);
   513     }
   515     @Override
   516     public ScriptObject newEvalError(final String msg) {
   517         return new NativeEvalError(msg);
   518     }
   520     @Override
   521     public ScriptObject newRangeError(final String msg) {
   522         return new NativeRangeError(msg);
   523     }
   525     @Override
   526     public ScriptObject newReferenceError(final String msg) {
   527         return new NativeReferenceError(msg);
   528     }
   530     @Override
   531     public ScriptObject newSyntaxError(final String msg) {
   532         return new NativeSyntaxError(msg);
   533     }
   535     @Override
   536     public ScriptObject newTypeError(final String msg) {
   537         return new NativeTypeError(msg);
   538     }
   540     @Override
   541     public ScriptObject newURIError(final String msg) {
   542         return new NativeURIError(msg);
   543     }
   545     @Override
   546     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
   547         return new GenericPropertyDescriptor(configurable, enumerable);
   548     }
   550     @Override
   551     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
   552         return new DataPropertyDescriptor(configurable, enumerable, writable, value);
   553     }
   555     @Override
   556     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
   557         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
   559         final boolean strict = getContext()._strict;
   561         if (get == null) {
   562             desc.delete(PropertyDescriptor.GET, strict);
   563         }
   565         if (set == null) {
   566             desc.delete(PropertyDescriptor.SET, strict);
   567         }
   569         return desc;
   570     }
   573     /**
   574      * Cache for compiled script classes.
   575      */
   576     @SuppressWarnings("serial")
   577     private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
   578         private final int size;
   580         ClassCache(int size) {
   581             super(size, 0.75f, true);
   582             this.size = size;
   583         }
   585         @Override
   586         protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
   587             return size() >= size;
   588         }
   589     }
   591     // Class cache management
   592     @Override
   593     public Class<?> findCachedClass(final Source source) {
   594         assert classCache != null : "Class cache used without being initialized";
   595         SoftReference<Class<?>> ref = classCache.get(source);
   596         if (ref != null) {
   597             final Class<?> clazz = ref.get();
   598             if (clazz == null) {
   599                 classCache.remove(source);
   600             }
   601             return clazz;
   602         }
   604         return null;
   605     }
   607     @Override
   608     public void cacheClass(final Source source, final Class<?> clazz) {
   609         assert classCache != null : "Class cache used without being initialized";
   610         classCache.put(source, new SoftReference<Class<?>>(clazz));
   611     }
   613     /**
   614      * This is the eval used when 'indirect' eval call is made.
   615      *
   616      * var global = this;
   617      * global.eval("print('hello')");
   618      *
   619      * @param self  eval scope
   620      * @param str   eval string
   621      *
   622      * @return the result of eval
   623      */
   624     public static Object eval(final Object self, final Object str) {
   625         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
   626     }
   628     /**
   629      * Direct eval
   630      *
   631      * @param self     The scope of eval passed as 'self'
   632      * @param str      Evaluated code
   633      * @param callThis "this" to be passed to the evaluated code
   634      * @param location location of the eval call
   635      * @param strict   is eval called a strict mode code?
   636      *
   637      * @return the return value of the eval
   638      *
   639      * This is directly invoked from generated when eval(code) is called in user code
   640      */
   641     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
   642         if (!(str instanceof String || str instanceof ConsString)) {
   643             return str;
   644         }
   645         final Global global = Global.instance();
   646         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   648         return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
   649     }
   651     /**
   652      * Global print implementation - Nashorn extension
   653      *
   654      * @param self    scope
   655      * @param objects arguments to print
   656      *
   657      * @return result of print (undefined)
   658      */
   659     public static Object print(final Object self, final Object... objects) {
   660         return printImpl(false, objects);
   661     }
   663     /**
   664      * Global println implementation - Nashorn extension
   665      *
   666      * @param self    scope
   667      * @param objects arguments to print
   668      *
   669      * @return result of println (undefined)
   670      */
   671     public static Object println(final Object self, final Object... objects) {
   672         return printImpl(true, objects);
   673     }
   675     /**
   676      * Global load implementation - Nashorn extension
   677      *
   678      * @param self    scope
   679      * @param source  source to load
   680      *
   681      * @return result of load (undefined)
   682      *
   683      * @throws IOException if source could not be read
   684      */
   685     public static Object load(final Object self, final Object source) throws IOException {
   686         final Global global = Global.instance();
   687         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   688         return global.getContext().load(scope, source);
   689     }
   691     ScriptObject getFunctionPrototype() {
   692         return ScriptFunction.getPrototype(builtinFunction);
   693     }
   695     ScriptObject getObjectPrototype() {
   696         return ScriptFunction.getPrototype(builtinObject);
   697     }
   699     ScriptObject getArrayPrototype() {
   700         return ScriptFunction.getPrototype(builtinArray);
   701     }
   703     ScriptObject getBooleanPrototype() {
   704         return ScriptFunction.getPrototype(builtinBoolean);
   705     }
   707     ScriptObject getNumberPrototype() {
   708         return ScriptFunction.getPrototype(builtinNumber);
   709     }
   711     ScriptObject getDatePrototype() {
   712         return ScriptFunction.getPrototype(builtinDate);
   713     }
   715     ScriptObject getRegExpPrototype() {
   716         return ScriptFunction.getPrototype(builtinRegExp);
   717     }
   719     ScriptObject getStringPrototype() {
   720         return ScriptFunction.getPrototype(builtinString);
   721     }
   723     ScriptObject getErrorPrototype() {
   724         return ScriptFunction.getPrototype(builtinError);
   725     }
   727     ScriptObject getEvalErrorPrototype() {
   728         return ScriptFunction.getPrototype(builtinEvalError);
   729     }
   731     ScriptObject getRangeErrorPrototype() {
   732         return ScriptFunction.getPrototype(builtinRangeError);
   733     }
   735     ScriptObject getReferenceErrorPrototype() {
   736         return ScriptFunction.getPrototype(builtinReferenceError);
   737     }
   739     ScriptObject getSyntaxErrorPrototype() {
   740         return ScriptFunction.getPrototype(builtinSyntaxError);
   741     }
   743     ScriptObject getTypeErrorPrototype() {
   744         return ScriptFunction.getPrototype(builtinTypeError);
   745     }
   747     ScriptObject getURIErrorPrototype() {
   748         return ScriptFunction.getPrototype(builtinURIError);
   749     }
   751     ScriptObject getJavaImporterPrototype() {
   752         return ScriptFunction.getPrototype(builtinJavaImporter);
   753     }
   755     ScriptObject getJSAdapterPrototype() {
   756         return ScriptFunction.getPrototype(builtinJSAdapter);
   757     }
   759     ScriptObject getArrayBufferPrototype() {
   760         return ScriptFunction.getPrototype(builtinArrayBuffer);
   761     }
   763     ScriptObject getInt8ArrayPrototype() {
   764         return ScriptFunction.getPrototype(builtinInt8Array);
   765     }
   767     ScriptObject getUint8ArrayPrototype() {
   768         return ScriptFunction.getPrototype(builtinUint8Array);
   769     }
   771     ScriptObject getUint8ClampedArrayPrototype() {
   772         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
   773     }
   775     ScriptObject getInt16ArrayPrototype() {
   776         return ScriptFunction.getPrototype(builtinInt16Array);
   777     }
   779     ScriptObject getUint16ArrayPrototype() {
   780         return ScriptFunction.getPrototype(builtinUint16Array);
   781     }
   783     ScriptObject getInt32ArrayPrototype() {
   784         return ScriptFunction.getPrototype(builtinInt32Array);
   785     }
   787     ScriptObject getUint32ArrayPrototype() {
   788         return ScriptFunction.getPrototype(builtinUint32Array);
   789     }
   791     ScriptObject getFloat32ArrayPrototype() {
   792         return ScriptFunction.getPrototype(builtinFloat32Array);
   793     }
   795     ScriptObject getFloat64ArrayPrototype() {
   796         return ScriptFunction.getPrototype(builtinFloat64Array);
   797     }
   799     private ScriptFunction getBuiltinArray() {
   800         return builtinArray;
   801     }
   804     /**
   805      * Called from compiled script code to test if builtin has been overridden
   806      *
   807      * @return true if builtin array has not been overridden
   808      */
   809     public static boolean isBuiltinArray() {
   810         final Global instance = Global.instance();
   811         return instance.array == instance.getBuiltinArray();
   812     }
   814     private ScriptFunction getBuiltinBoolean() {
   815         return builtinBoolean;
   816     }
   818     /**
   819      * Called from compiled script code to test if builtin has been overridden
   820      *
   821      * @return true if builtin boolean has not been overridden
   822      */
   823     public static boolean isBuiltinBoolean() {
   824         final Global instance = Global.instance();
   825         return instance._boolean == instance.getBuiltinBoolean();
   826     }
   828     private ScriptFunction getBuiltinDate() {
   829         return builtinDate;
   830     }
   832     /**
   833      * Called from compiled script code to test if builtin has been overridden
   834      *
   835      * @return true if builtin date has not been overridden
   836      */
   837     public static boolean isBuiltinDate() {
   838         final Global instance = Global.instance();
   839         return instance.date == instance.getBuiltinDate();
   840     }
   842     private ScriptFunction getBuiltinError() {
   843         return builtinError;
   844     }
   846     /**
   847      * Called from compiled script code to test if builtin has been overridden
   848      *
   849      * @return true if builtin error has not been overridden
   850      */
   851     public static boolean isBuiltinError() {
   852         final Global instance = Global.instance();
   853         return instance.error == instance.getBuiltinError();
   854     }
   856     private ScriptFunction getBuiltinEvalError() {
   857         return builtinEvalError;
   858     }
   860     /**
   861      * Called from compiled script code to test if builtin has been overridden
   862      *
   863      * @return true if builtin eval error has not been overridden
   864      */
   865     public static boolean isBuiltinEvalError() {
   866         final Global instance = Global.instance();
   867         return instance.evalError == instance.getBuiltinEvalError();
   868     }
   870     private ScriptFunction getBuiltinFunction() {
   871         return builtinFunction;
   872     }
   874     /**
   875      * Called from compiled script code to test if builtin has been overridden
   876      *
   877      * @return true if builtin function has not been overridden
   878      */
   879     public static boolean isBuiltinFunction() {
   880         final Global instance = Global.instance();
   881         return instance.function == instance.getBuiltinFunction();
   882     }
   884     private ScriptFunction getBuiltinJSAdapter() {
   885         return builtinJSAdapter;
   886     }
   888     /**
   889      * Called from compiled script code to test if builtin has been overridden
   890      *
   891      * @return true if builtin JSAdapter has not been overridden
   892      */
   893     public static boolean isBuiltinJSAdapter() {
   894         final Global instance = Global.instance();
   895         return instance.jsadapter == instance.getBuiltinJSAdapter();
   896     }
   898     private ScriptObject getBuiltinJSON() {
   899         return builtinJSON;
   900     }
   902     /**
   903      * Called from compiled script code to test if builtin has been overridden
   904      *
   905      * @return true if builtin JSON has has not been overridden
   906      */
   907     public static boolean isBuiltinJSON() {
   908         final Global instance = Global.instance();
   909         return instance.json == instance.getBuiltinJSON();
   910     }
   912     private ScriptObject getBuiltinJava() {
   913         return builtinJava;
   914     }
   916     /**
   917      * Called from compiled script code to test if builtin has been overridden
   918      *
   919      * @return true if builtin Java has not been overridden
   920      */
   921     public static boolean isBuiltinJava() {
   922         final Global instance = Global.instance();
   923         return instance.java == instance.getBuiltinJava();
   924     }
   926     private ScriptObject getBuiltinJavax() {
   927         return builtinJavax;
   928     }
   930     /**
   931      * Called from compiled script code to test if builtin has been overridden
   932      *
   933      * @return true if builtin Javax has not been overridden
   934      */
   935     public static boolean isBuiltinJavax() {
   936         final Global instance = Global.instance();
   937         return instance.javax == instance.getBuiltinJavax();
   938     }
   940     private ScriptObject getBuiltinJavaImporter() {
   941         return builtinJavaImporter;
   942     }
   944     /**
   945      * Called from compiled script code to test if builtin has been overridden
   946      *
   947      * @return true if builtin Java importer has not been overridden
   948      */
   949     public static boolean isBuiltinJavaImporter() {
   950         final Global instance = Global.instance();
   951         return instance.javaImporter == instance.getBuiltinJavaImporter();
   952     }
   954     private ScriptObject getBuiltinMath() {
   955         return builtinMath;
   956     }
   958     /**
   959      * Called from compiled script code to test if builtin has been overridden
   960      *
   961      * @return true if builtin math has not been overridden
   962      */
   963     public static boolean isBuiltinMath() {
   964         final Global instance = Global.instance();
   965         return instance.math == instance.getBuiltinMath();
   966     }
   968     private ScriptFunction getBuiltinNumber() {
   969         return builtinNumber;
   970     }
   972     /**
   973      * Called from compiled script code to test if builtin has been overridden
   974      *
   975      * @return true if builtin number has not been overridden
   976      */
   977     public static boolean isBuiltinNumber() {
   978         final Global instance = Global.instance();
   979         return instance.number == instance.getBuiltinNumber();
   980     }
   982     private ScriptFunction getBuiltinObject() {
   983         return builtinObject;
   984     }
   986     /**
   987      * Called from compiled script code to test if builtin has been overridden
   988      *
   989      * @return true if builtin object has not been overridden
   990      */
   991     public static boolean isBuiltinObject() {
   992         final Global instance = Global.instance();
   993         return instance.object == instance.getBuiltinObject();
   994     }
   996     private ScriptObject getBuiltinPackages() {
   997         return builtinPackages;
   998     }
  1000     /**
  1001      * Called from compiled script code to test if builtin has been overridden
  1003      * @return true if builtin package has not been overridden
  1004      */
  1005     public static boolean isBuiltinPackages() {
  1006         final Global instance = Global.instance();
  1007         return instance.packages == instance.getBuiltinPackages();
  1010     private ScriptFunction getBuiltinRangeError() {
  1011         return builtinRangeError;
  1014     /**
  1015      * Called from compiled script code to test if builtin has been overridden
  1017      * @return true if builtin range error has not been overridden
  1018      */
  1019     public static boolean isBuiltinRangeError() {
  1020         final Global instance = Global.instance();
  1021         return instance.rangeError == instance.getBuiltinRangeError();
  1024     private ScriptFunction getBuiltinReferenceError() {
  1025         return builtinReferenceError;
  1028     /**
  1029      * Called from compiled script code to test if builtin has been overridden
  1031      * @return true if builtin reference error has not been overridden
  1032      */
  1033     public static boolean isBuiltinReferenceError() {
  1034         final Global instance = Global.instance();
  1035         return instance.referenceError == instance.getBuiltinReferenceError();
  1038     private ScriptFunction getBuiltinRegExp() {
  1039         return builtinRegExp;
  1042     /**
  1043      * Called from compiled script code to test if builtin has been overridden
  1045      * @return true if builtin regexp has not been overridden
  1046      */
  1047     public static boolean isBuiltinRegExp() {
  1048         final Global instance = Global.instance();
  1049         return instance.regexp == instance.getBuiltinRegExp();
  1052     private ScriptFunction getBuiltinString() {
  1053         return builtinString;
  1056     /**
  1057      * Called from compiled script code to test if builtin has been overridden
  1059      * @return true if builtin Java has not been overridden
  1060      */
  1061     public static boolean isBuiltinString() {
  1062         final Global instance = Global.instance();
  1063         return instance.string == instance.getBuiltinString();
  1066     private ScriptFunction getBuiltinSyntaxError() {
  1067         return builtinSyntaxError;
  1070     /**
  1071      * Called from compiled script code to test if builtin has been overridden
  1073      * @return true if builtin syntax error has not been overridden
  1074      */
  1075     public static boolean isBuiltinSyntaxError() {
  1076         final Global instance = Global.instance();
  1077         return instance.syntaxError == instance.getBuiltinSyntaxError();
  1080     private ScriptFunction getBuiltinTypeError() {
  1081         return builtinTypeError;
  1084     /**
  1085      * Called from compiled script code to test if builtin has been overridden
  1087      * @return true if builtin type error has not been overridden
  1088      */
  1089     public static boolean isBuiltinTypeError() {
  1090         final Global instance = Global.instance();
  1091         return instance.typeError == instance.getBuiltinTypeError();
  1094     private ScriptFunction getBuiltinURIError() {
  1095         return builtinURIError;
  1098     /**
  1099      * Called from compiled script code to test if builtin has been overridden
  1101      * @return true if builtin URI error has not been overridden
  1102      */
  1103     public static boolean isBuiltinURIError() {
  1104         final Global instance = Global.instance();
  1105         return instance.uriError == instance.getBuiltinURIError();
  1108     @Override
  1109     public String getClassName() {
  1110         return "global";
  1113     /**
  1114      * Copy function used to clone NativeRegExp objects.
  1116      * @param regexp a NativeRegExp to clone
  1118      * @return copy of the given regexp object
  1119      */
  1120     public static Object regExpCopy(final Object regexp) {
  1121         return new NativeRegExp((NativeRegExp)regexp);
  1124     /**
  1125      * Convert given object to NativeRegExp type.
  1127      * @param obj object to be converted
  1128      * @return NativeRegExp instance
  1129      */
  1130     public static NativeRegExp toRegExp(final Object obj) {
  1131         if (obj instanceof NativeRegExp) {
  1132             return (NativeRegExp)obj;
  1134         return new NativeRegExp(JSType.toString(obj));
  1137     /**
  1138      * ECMA 9.9 ToObject implementation
  1140      * @param obj  an item for which to run ToObject
  1141      * @return ToObject version of given item
  1142      */
  1143     public static Object toObject(final Object obj) {
  1144         if (obj == null || obj == UNDEFINED) {
  1145             typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1148         if (obj instanceof ScriptObject) {
  1149             return obj;
  1152         return instance().wrapAsObject(obj);
  1155     /**
  1156      * Allocate a new object array.
  1158      * @param initial object values.
  1159      * @return the new array
  1160      */
  1161     public static NativeArray allocate(final Object[] initial) {
  1162         return new NativeArray(initial);
  1165     /**
  1166      * Allocate a new number array.
  1168      * @param initial number values.
  1169      * @return the new array
  1170      */
  1171     public static NativeArray allocate(final double[] initial) {
  1172         return new NativeArray(initial);
  1175     /**
  1176      * Allocate a new long array.
  1178      * @param initial number values.
  1179      * @return the new array
  1180      */
  1181     public static NativeArray allocate(final long[] initial) {
  1182         return new NativeArray(initial);
  1185     /**
  1186      * Allocate a new integer array.
  1188      * @param initial number values.
  1189      * @return the new array
  1190      */
  1191     public static NativeArray allocate(final int[] initial) {
  1192         return new NativeArray(initial);
  1195     /**
  1196      * Allocate a new object array for arguments.
  1198      * @param arguments initial arguments passed.
  1199      * @param callee reference to the function that uses arguments object
  1200      * @param numParams actual number of declared parameters
  1202      * @return the new array
  1203      */
  1204     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
  1205         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
  1208     /**
  1209      * Called from generated to check if given function is the builtin 'eval'. If
  1210      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
  1212      * @param  fn function object that is checked
  1213      * @return true if fn is the builtin eval
  1214      */
  1215     public static boolean isEval(final Object fn) {
  1216         return fn == Global.instance().builtinEval;
  1219     /**
  1220      * Create a new RegExp object.
  1222      * @param expression Regular expression.
  1223      * @param options    Search options.
  1225      * @return New RegExp object.
  1226      */
  1227     public static Object newRegExp(final String expression, final String options) {
  1228         if (options == null) {
  1229             return new NativeRegExp(expression);
  1231         return new NativeRegExp(expression, options);
  1234     /**
  1235      * Get the object prototype
  1237      * @return the object prototype
  1238      */
  1239     public static ScriptObject objectPrototype() {
  1240         return Global.instance().getObjectPrototype();
  1243     /**
  1244      * Create a new empty object instance.
  1246      * @return New empty object.
  1247      */
  1248     public static ScriptObject newEmptyInstance() {
  1249         final ScriptObject sobj = new JO$();
  1250         sobj.setProto(objectPrototype());
  1251         return sobj;
  1254     /**
  1255      * Check if a given object is a ScriptObject, raises an exception if this is
  1256      * not the case
  1258      * @param obj and object to check
  1259      */
  1260     public static void checkObject(final Object obj) {
  1261         if (!(obj instanceof ScriptObject)) {
  1262             typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1266     /**
  1267      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
  1268      * if this object is null or undefined.
  1270      * @param obj an object to check
  1271      */
  1272     public static void checkObjectCoercible(final Object obj) {
  1273         if (obj == null || obj == UNDEFINED) {
  1274             typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1278     /**
  1279      * Get the current split state.
  1281      * @return current split state
  1282      */
  1283     @Override
  1284     public int getSplitState() {
  1285         return splitState;
  1288     /**
  1289      * Set the current split state.
  1291      * @param state current split state
  1292      */
  1293     @Override
  1294     public void setSplitState(final int state) {
  1295         splitState = state;
  1298     private void init() {
  1299         assert Context.getGlobal() == this : "this global is not set as current";
  1301         // initialize Function and Object constructor
  1302         initFunctionAndObject();
  1304         // Now fix Global's own proto.
  1305         this.setProto(getObjectPrototype());
  1307         // initialize global function properties
  1308         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  1309         ((ScriptFunction)this.eval).setArity(1);
  1311         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
  1312         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  1313         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
  1314         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
  1315         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
  1316         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
  1317         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
  1318         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
  1319         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
  1320         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
  1321         this.print              = ScriptFunctionImpl.makeFunction("print",      getContext()._print_no_newline ? PRINT : PRINTLN);
  1322         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
  1324         // built-in constructors
  1325         this.builtinArray     = (ScriptFunction)initConstructor("Array");
  1326         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
  1327         this.builtinDate      = (ScriptFunction)initConstructor("Date");
  1328         this.builtinJSON      = initConstructor("JSON");
  1329         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
  1330         this.builtinMath      = initConstructor("Math");
  1331         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
  1332         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
  1333         this.builtinString    = (ScriptFunction)initConstructor("String");
  1335         // initialize String.prototype.length to 0
  1336         // add String.prototype.length
  1337         final ScriptObject stringPrototype = getStringPrototype();
  1338         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  1340         // add Array.prototype.length
  1341         final ScriptObject arrayPrototype = getArrayPrototype();
  1342         arrayPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  1344         this.DEFAULT_DATE = new NativeDate(Double.NaN);
  1346         // initialize default regexp object
  1347         this.DEFAULT_REGEXP = new NativeRegExp("(?:)");
  1349         // RegExp.prototype should behave like a RegExp object. So copy the
  1350         // properties.
  1351         final ScriptObject regExpProto = getRegExpPrototype();
  1352         regExpProto.addBoundProperties(DEFAULT_REGEXP);
  1354         // Error stuff
  1355         initErrorObjects();
  1357         // java access
  1358         initJavaAccess();
  1360         initTypedArray();
  1362         if (getContext()._scripting) {
  1363             initScripting();
  1366         if (Context.DEBUG && System.getSecurityManager() == null) {
  1367             initDebug();
  1370         copyBuiltins();
  1372         // initialized with strings so that typeof will work as expected.
  1373         this.__FILE__ = "";
  1374         this.__DIR__  = "";
  1375         this.__LINE__ = 0.0;
  1377         // expose script (command line) arguments as "arguments" property of global
  1378         final List<String> arguments = getContext().getOptions().getArguments();
  1379         final Object argsObj = wrapAsObject(arguments.toArray());
  1381         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
  1382         if (getContext()._scripting) {
  1383             // synonym for "arguments" in scripting mode
  1384             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
  1388     private void initErrorObjects() {
  1389         // Error objects
  1390         this.builtinError = (ScriptFunction)initConstructor("Error");
  1391         final ScriptObject errorProto = getErrorPrototype();
  1392         final boolean strict = Global.isStrict();
  1394         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
  1395         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
  1396         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
  1397         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
  1398         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
  1399         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
  1400         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
  1401         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
  1402         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
  1403         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
  1404         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
  1405         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
  1406         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
  1408         // ECMA 15.11.4.2 Error.prototype.name
  1409         // Error.prototype.name = "Error";
  1410         errorProto.set(NativeError.NAME, "Error", strict);
  1411         // ECMA 15.11.4.3 Error.prototype.message
  1412         // Error.prototype.message = "";
  1413         errorProto.set(NativeError.MESSAGE, "", strict);
  1415         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
  1416         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
  1417         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
  1418         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
  1419         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
  1420         this.builtinURIError = initErrorSubtype("URIError", errorProto);
  1423     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
  1424         final ScriptObject cons = initConstructor(name);
  1425         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  1426         final boolean strict = Global.isStrict();
  1427         prototype.set(NativeError.NAME, name, strict);
  1428         prototype.set(NativeError.MESSAGE, "", strict);
  1429         prototype.setProto(errorProto);
  1430         return (ScriptFunction)cons;
  1433     private void initJavaAccess() {
  1434         final ScriptObject objectProto = getObjectPrototype();
  1435         this.builtinPackages = new NativeJavaPackage("", objectProto);
  1436         this.builtinJava = new NativeJavaPackage("java", objectProto);
  1437         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
  1438         this.builtinJavaImporter = initConstructor("JavaImporter");
  1439         this.builtinJavaApi = initConstructor("Java");
  1442     private void initScripting() {
  1443         Object value;
  1444         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
  1445         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
  1447         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
  1448         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
  1450         value = ScriptFunctionImpl.makeFunction("quit", ScriptingFunctions.QUIT);
  1451         addOwnProperty("quit", Attribute.NOT_ENUMERABLE, value);
  1453         final String execName = ScriptingFunctions.EXEC_NAME;
  1454         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
  1455         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
  1457         // Nashorn extension: global.echo (scripting-mode-only)
  1458         // alias for "print"
  1459         value = get("print");
  1460         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
  1462         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
  1463         value = new OptionsObject(this.getContext());
  1464         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, value);
  1466         // Nashorn extension: global.$ENV (scripting-mode-only)
  1467         if (System.getSecurityManager() == null) {
  1468             // do not fill $ENV if we have a security manager around
  1469             // Retrieve current state of ENV variables.
  1470             final ScriptObject env = newEmptyInstance();
  1471             env.putAll(System.getenv());
  1472             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
  1473         } else {
  1474             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1477         // add other special properties for exec support
  1478         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1479         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1480         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1483     private void initTypedArray() {
  1484         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
  1485         this.builtinInt8Array         = initConstructor("Int8Array");
  1486         this.builtinUint8Array        = initConstructor("Uint8Array");
  1487         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
  1488         this.builtinInt16Array        = initConstructor("Int16Array");
  1489         this.builtinUint16Array       = initConstructor("Uint16Array");
  1490         this.builtinInt32Array        = initConstructor("Int32Array");
  1491         this.builtinUint32Array       = initConstructor("Uint32Array");
  1492         this.builtinFloat32Array      = initConstructor("Float32Array");
  1493         this.builtinFloat64Array      = initConstructor("Float64Array");
  1496     private void copyBuiltins() {
  1497         this.array             = this.builtinArray;
  1498         this._boolean          = this.builtinBoolean;
  1499         this.date              = this.builtinDate;
  1500         this.error             = this.builtinError;
  1501         this.evalError         = this.builtinEvalError;
  1502         this.function          = this.builtinFunction;
  1503         this.jsadapter         = this.builtinJSAdapter;
  1504         this.json              = this.builtinJSON;
  1505         this.java              = this.builtinJava;
  1506         this.javax             = this.builtinJavax;
  1507         this.javaImporter      = this.builtinJavaImporter;
  1508         this.javaApi           = this.builtinJavaApi;
  1509         this.math              = this.builtinMath;
  1510         this.number            = this.builtinNumber;
  1511         this.object            = this.builtinObject;
  1512         this.packages          = this.builtinPackages;
  1513         this.rangeError        = this.builtinRangeError;
  1514         this.referenceError    = this.builtinReferenceError;
  1515         this.regexp            = this.builtinRegExp;
  1516         this.string            = this.builtinString;
  1517         this.syntaxError       = this.builtinSyntaxError;
  1518         this.typeError         = this.builtinTypeError;
  1519         this.uriError          = this.builtinURIError;
  1520         this.arrayBuffer       = this.builtinArrayBuffer;
  1521         this.int8Array         = this.builtinInt8Array;
  1522         this.uint8Array        = this.builtinUint8Array;
  1523         this.uint8ClampedArray = this.builtinUint8ClampedArray;
  1524         this.int16Array        = this.builtinInt16Array;
  1525         this.uint16Array       = this.builtinUint16Array;
  1526         this.int32Array        = this.builtinInt32Array;
  1527         this.uint32Array       = this.builtinUint32Array;
  1528         this.float32Array      = this.builtinFloat32Array;
  1529         this.float64Array      = this.builtinFloat64Array;
  1532     private void initDebug() {
  1533         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
  1536     @SuppressWarnings("resource")
  1537     private static Object printImpl(final boolean newLine, final Object... objects) {
  1538         final PrintWriter out = Global.getThisContext().getOut();
  1540         boolean first = true;
  1541         for (final Object object : objects) {
  1542             if (first) {
  1543                 first = false;
  1544             } else {
  1545                 out.print(' ');
  1548             out.print(JSType.toString(object));
  1551         if (newLine) {
  1552             out.println();
  1555         out.flush();
  1557         return UNDEFINED;
  1560     /**
  1561      * These classes are generated by nasgen tool and so we have to use
  1562      * reflection to load and create new instance of these classes.
  1563      */
  1564     private ScriptObject initConstructor(final String name) {
  1565         try {
  1566             // Assuming class name pattern for built-in JS constructors.
  1567             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
  1569             sb.append("Native");
  1570             sb.append(name);
  1571             sb.append("$Constructor");
  1573             final Class<?>     funcClass = Class.forName(sb.toString());
  1574             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
  1576             if (res instanceof ScriptFunction) {
  1577                 // All global constructor prototypes are not-writable,
  1578                 // not-enumerable and not-configurable.
  1579                 final ScriptFunction func = (ScriptFunction)res;
  1580                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
  1583             if (res.getProto() == null) {
  1584                 res.setProto(getObjectPrototype());
  1587             return res;
  1589         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  1590             throw new RuntimeException(e);
  1594     // Function and Object constructors are inter-dependent. Also,
  1595     // Function.prototype
  1596     // functions are not properly initialized. We fix the references here.
  1597     // NOTE: be careful if you want to re-order the operations here. You may
  1598     // have
  1599     // to play with object references carefully!!
  1600     private void initFunctionAndObject() {
  1601         // First-n-foremost is Function
  1602         this.builtinFunction = (ScriptFunction)initConstructor("Function");
  1604         // create global anonymous function
  1605         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
  1606         // need to copy over members of Function.prototype to anon function
  1607         anon.addBoundProperties(getFunctionPrototype());
  1609         // Function.prototype === Object.getPrototypeOf(Function) ===
  1610         // <anon-function>
  1611         builtinFunction.setProto(anon);
  1612         builtinFunction.setPrototype(anon);
  1613         anon.set("constructor", builtinFunction, anon.isStrict());
  1614         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  1616         // now initialize Object
  1617         this.builtinObject = (ScriptFunction)initConstructor("Object");
  1618         final ScriptObject ObjectPrototype = getObjectPrototype();
  1619         // Object.getPrototypeOf(Function.prototype) === Object.prototype
  1620         anon.setProto(ObjectPrototype);
  1622         // Function valued properties of Function.prototype were not properly
  1623         // initialized. Because, these were created before global.function and
  1624         // global.object were not initialized.
  1625         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
  1626         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1627             final Object key = property.getKey();
  1628             final Object value = builtinFunction.get(key);
  1630             if (value instanceof ScriptFunction && value != anon) {
  1631                 final ScriptFunction func = (ScriptFunction)value;
  1632                 func.setProto(getFunctionPrototype());
  1633                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1634                 if (prototype != null) {
  1635                     prototype.setProto(ObjectPrototype);
  1640         // For function valued properties of Object and Object.prototype, make
  1641         // sure prototype's proto chain ends with Object.prototype
  1642         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
  1643             final Object key = property.getKey();
  1644             final Object value = builtinObject.get(key);
  1646             if (value instanceof ScriptFunction) {
  1647                 final ScriptFunction func = (ScriptFunction)value;
  1648                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1649                 if (prototype != null) {
  1650                     prototype.setProto(ObjectPrototype);
  1655         properties = getObjectPrototype().getMap().getProperties();
  1656         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1657             final Object key   = property.getKey();
  1658             final Object value = ObjectPrototype.get(key);
  1660             if (key.equals("constructor")) {
  1661                 continue;
  1664             if (value instanceof ScriptFunction) {
  1665                 final ScriptFunction func = (ScriptFunction)value;
  1666                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1667                 if (prototype != null) {
  1668                     prototype.setProto(ObjectPrototype);
  1675     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
  1676         return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types));

mercurial