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

Fri, 03 May 2013 16:01:33 +0200

author
lagergren
date
Fri, 03 May 2013 16:01:33 +0200
changeset 248
829b06307fb2
parent 146
15dac7439921
child 253
fb1d7ea3e1b6
permissions
-rw-r--r--

8013871: mem usage histograms enabled with compiler logging level set to more specific than or equals to info when --print-mem-usage flag is used
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.runtime.ECMAErrors.typeError;
    29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    30 import static jdk.nashorn.internal.lookup.Lookup.MH;
    32 import java.io.IOException;
    33 import java.io.PrintWriter;
    34 import java.lang.invoke.MethodHandle;
    35 import java.lang.invoke.MethodHandles;
    36 import java.lang.ref.SoftReference;
    37 import java.lang.reflect.Field;
    38 import java.security.AccessController;
    39 import java.security.PrivilegedAction;
    40 import java.util.LinkedHashMap;
    41 import java.util.List;
    42 import java.util.Map;
    43 import jdk.internal.dynalink.linker.GuardedInvocation;
    44 import jdk.internal.dynalink.linker.LinkRequest;
    45 import jdk.nashorn.internal.objects.annotations.Attribute;
    46 import jdk.nashorn.internal.objects.annotations.Property;
    47 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    48 import jdk.nashorn.internal.runtime.ConsString;
    49 import jdk.nashorn.internal.runtime.Context;
    50 import jdk.nashorn.internal.runtime.GlobalFunctions;
    51 import jdk.nashorn.internal.runtime.GlobalObject;
    52 import jdk.nashorn.internal.runtime.JSType;
    53 import jdk.nashorn.internal.runtime.NativeJavaPackage;
    54 import jdk.nashorn.internal.runtime.ScriptEnvironment;
    55 import jdk.nashorn.internal.runtime.PropertyDescriptor;
    56 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    57 import jdk.nashorn.internal.runtime.Scope;
    58 import jdk.nashorn.internal.runtime.ScriptFunction;
    59 import jdk.nashorn.internal.runtime.ScriptObject;
    60 import jdk.nashorn.internal.runtime.ScriptRuntime;
    61 import jdk.nashorn.internal.runtime.ScriptingFunctions;
    62 import jdk.nashorn.internal.runtime.Source;
    63 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    64 import jdk.nashorn.internal.scripts.JO;
    66 /**
    67  * Representation of global scope.
    68  */
    69 @ScriptClass("Global")
    70 public final class Global extends ScriptObject implements GlobalObject, Scope {
    71     private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    72     private static final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
    74     /** ECMA 15.1.2.2 parseInt (string , radix) */
    75     @Property(attributes = Attribute.NOT_ENUMERABLE)
    76     public Object parseInt;
    78     /** ECMA 15.1.2.3 parseFloat (string) */
    79     @Property(attributes = Attribute.NOT_ENUMERABLE)
    80     public Object parseFloat;
    82     /** ECMA 15.1.2.4 isNaN (number) */
    83     @Property(attributes = Attribute.NOT_ENUMERABLE)
    84     public Object isNaN;
    86     /** ECMA 15.1.2.5 isFinite (number) */
    87     @Property(attributes = Attribute.NOT_ENUMERABLE)
    88     public Object isFinite;
    90     /** ECMA 15.1.3.3 encodeURI */
    91     @Property(attributes = Attribute.NOT_ENUMERABLE)
    92     public Object encodeURI;
    94     /** ECMA 15.1.3.4 encodeURIComponent */
    95     @Property(attributes = Attribute.NOT_ENUMERABLE)
    96     public Object encodeURIComponent;
    98     /** ECMA 15.1.3.1 decodeURI */
    99     @Property(attributes = Attribute.NOT_ENUMERABLE)
   100     public Object decodeURI;
   102     /** ECMA 15.1.3.2 decodeURIComponent */
   103     @Property(attributes = Attribute.NOT_ENUMERABLE)
   104     public Object decodeURIComponent;
   106     /** ECMA B.2.1 escape (string) */
   107     @Property(attributes = Attribute.NOT_ENUMERABLE)
   108     public Object escape;
   110     /** ECMA B.2.2 unescape (string) */
   111     @Property(attributes = Attribute.NOT_ENUMERABLE)
   112     public Object unescape;
   114     /** Nashorn extension: global.print */
   115     @Property(attributes = Attribute.NOT_ENUMERABLE)
   116     public Object print;
   118     /** Nashorn extension: global.load */
   119     @Property(attributes = Attribute.NOT_ENUMERABLE)
   120     public Object load;
   122     /** Nashorn extension: global.exit */
   123     @Property(attributes = Attribute.NOT_ENUMERABLE)
   124     public Object exit;
   126     /** Nashorn extension: global.quit */
   127     @Property(attributes = Attribute.NOT_ENUMERABLE)
   128     public Object quit;
   130     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
   131     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   132     public final Object NaN = Double.NaN;
   134     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
   135     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   136     public final Object Infinity = Double.POSITIVE_INFINITY;
   138     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
   139     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   140     public final Object undefined = UNDEFINED;
   142     /** ECMA 15.1.2.1 eval(x) */
   143     @Property(attributes = Attribute.NOT_ENUMERABLE)
   144     public Object eval;
   146     /** ECMA 15.1.4.1 Object constructor. */
   147     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
   148     public volatile Object object;
   150     /** ECMA 15.1.4.2 Function constructor. */
   151     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
   152     public volatile Object function;
   154     /** ECMA 15.1.4.3 Array constructor. */
   155     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
   156     public volatile Object array;
   158     /** ECMA 15.1.4.4 String constructor */
   159     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
   160     public volatile Object string;
   162     /** ECMA 15.1.4.5 Boolean constructor */
   163     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
   164     public volatile Object _boolean;
   166     /** ECMA 15.1.4.6 - Number constructor */
   167     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
   168     public volatile Object number;
   170     /** ECMA 15.1.4.7 Date constructor */
   171     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   172     public volatile Object date;
   174     /** ECMA 15.1.4.8 RegExp constructor */
   175     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   176     public volatile Object regexp;
   178     /** ECMA 15.12 - The JSON object */
   179     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   180     public volatile Object json;
   182     /** Nashorn extension: global.JSAdapter */
   183     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   184     public volatile Object jsadapter;
   186     /** ECMA 15.8 - The Math object */
   187     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
   188     public volatile Object math;
   190     /** Error object */
   191     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
   192     public volatile Object error;
   194     /** EvalError object */
   195     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   196     public volatile Object evalError;
   198     /** RangeError object */
   199     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   200     public volatile Object rangeError;
   202     /** ReferenceError object */
   203     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
   204     public volatile Object referenceError;
   206     /** SyntaxError object */
   207     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
   208     public volatile Object syntaxError;
   210     /** TypeError object */
   211     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
   212     public volatile Object typeError;
   214     /** URIError object */
   215     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   216     public volatile Object uriError;
   218     /** ArrayBuffer object */
   219     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   220     public volatile Object arrayBuffer;
   222     /** TypedArray (int8) */
   223     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   224     public volatile Object int8Array;
   226     /** TypedArray (uint8) */
   227     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   228     public volatile Object uint8Array;
   230     /** TypedArray (uint8) - Clamped */
   231     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   232     public volatile Object uint8ClampedArray;
   234     /** TypedArray (int16) */
   235     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   236     public volatile Object int16Array;
   238     /** TypedArray (uint16) */
   239     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   240     public volatile Object uint16Array;
   242     /** TypedArray (int32) */
   243     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   244     public volatile Object int32Array;
   246     /** TypedArray (uint32) */
   247     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   248     public volatile Object uint32Array;
   250     /** TypedArray (float32) */
   251     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   252     public volatile Object float32Array;
   254     /** TypedArray (float64) */
   255     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   256     public volatile Object float64Array;
   258     /** Nashorn extension: Java access - global.Packages */
   259     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
   260     public volatile Object packages;
   262     /** Nashorn extension: Java access - global.com */
   263     @Property(attributes = Attribute.NOT_ENUMERABLE)
   264     public volatile Object com;
   266     /** Nashorn extension: Java access - global.edu */
   267     @Property(attributes = Attribute.NOT_ENUMERABLE)
   268     public volatile Object edu;
   270     /** Nashorn extension: Java access - global.java */
   271     @Property(attributes = Attribute.NOT_ENUMERABLE)
   272     public volatile Object java;
   274     /** Nashorn extension: Java access - global.javafx */
   275     @Property(attributes = Attribute.NOT_ENUMERABLE)
   276     public volatile Object javafx;
   278     /** Nashorn extension: Java access - global.javax */
   279     @Property(attributes = Attribute.NOT_ENUMERABLE)
   280     public volatile Object javax;
   282     /** Nashorn extension: Java access - global.org */
   283     @Property(attributes = Attribute.NOT_ENUMERABLE)
   284     public volatile Object org;
   286     /** Nashorn extension: Java access - global.javaImporter */
   287     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   288     public volatile Object javaImporter;
   290     /** Nashorn extension: global.Java Object constructor. */
   291     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   292     public volatile Object javaApi;
   294     /** Nashorn extension: current script's file name */
   295     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   296     public Object __FILE__;
   298     /** Nashorn extension: current script's directory */
   299     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   300     public Object __DIR__;
   302     /** Nashorn extension: current source line number being executed */
   303     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   304     public Object __LINE__;
   306     /** Used as Date.prototype's default value */
   307     public NativeDate   DEFAULT_DATE;
   309     /** Used as RegExp.prototype's default value */
   310     public NativeRegExp DEFAULT_REGEXP;
   312     /*
   313      * Built-in constructor objects: Even if user changes dynamic values of
   314      * "Object", "Array" etc., we still want to keep original values of these
   315      * constructors here. For example, we need to be able to create array,
   316      * regexp literals even after user overwrites global "Array" or "RegExp"
   317      * constructor - see also ECMA 262 spec. Annex D.
   318      */
   319     private ScriptFunction builtinFunction;
   320     private ScriptFunction builtinObject;
   321     private ScriptFunction builtinArray;
   322     private ScriptFunction builtinBoolean;
   323     private ScriptFunction builtinDate;
   324     private ScriptObject   builtinJSON;
   325     private ScriptFunction builtinJSAdapter;
   326     private ScriptObject   builtinMath;
   327     private ScriptFunction builtinNumber;
   328     private ScriptFunction builtinRegExp;
   329     private ScriptFunction builtinString;
   330     private ScriptFunction builtinError;
   331     private ScriptFunction builtinEval;
   332     private ScriptFunction builtinEvalError;
   333     private ScriptFunction builtinRangeError;
   334     private ScriptFunction builtinReferenceError;
   335     private ScriptFunction builtinSyntaxError;
   336     private ScriptFunction builtinTypeError;
   337     private ScriptFunction builtinURIError;
   338     private ScriptObject   builtinPackages;
   339     private ScriptObject   builtinCom;
   340     private ScriptObject   builtinEdu;
   341     private ScriptObject   builtinJava;
   342     private ScriptObject   builtinJavafx;
   343     private ScriptObject   builtinJavax;
   344     private ScriptObject   builtinOrg;
   345     private ScriptObject   builtinJavaImporter;
   346     private ScriptObject   builtinJavaApi;
   347     private ScriptObject   builtinArrayBuffer;
   348     private ScriptObject   builtinInt8Array;
   349     private ScriptObject   builtinUint8Array;
   350     private ScriptObject   builtinUint8ClampedArray;
   351     private ScriptObject   builtinInt16Array;
   352     private ScriptObject   builtinUint16Array;
   353     private ScriptObject   builtinInt32Array;
   354     private ScriptObject   builtinUint32Array;
   355     private ScriptObject   builtinFloat32Array;
   356     private ScriptObject   builtinFloat64Array;
   358     // Flag to indicate that a split method issued a return statement
   359     private int splitState = -1;
   361     // class cache
   362     private ClassCache classCache;
   364     // Used to store the last RegExp result to support deprecated RegExp constructor properties
   365     private RegExpResult lastRegExpResult;
   367     private static final MethodHandle EVAL    = findOwnMH("eval",    Object.class, Object.class, Object.class);
   368     private static final MethodHandle PRINT   = findOwnMH("print",   Object.class, Object.class, Object[].class);
   369     private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
   370     private static final MethodHandle LOAD    = findOwnMH("load",    Object.class, Object.class, Object.class);
   371     private static final MethodHandle EXIT    = findOwnMH("exit",    Object.class, Object.class, Object.class);
   373     private final Context context;
   375     /**
   376      * Constructor
   377      *
   378      * @param context the context
   379      */
   380     public Global(final Context context) {
   381         this.context = context;
   382         this.setIsScope();
   383         /*
   384          * Duplicate global's map and use it. This way the initial Map filled
   385          * by nasgen (referenced from static field in this class) is retained
   386          * 'as is'. This allows multiple globals to be used within a context.
   387          */
   388         this.setMap(getMap().duplicate());
   390         final int cacheSize = context.getEnv()._class_cache_size;
   391         if (cacheSize > 0) {
   392             classCache = new ClassCache(cacheSize);
   393         }
   394     }
   396     /**
   397      * Script access to "current" Global instance
   398      *
   399      * @return the global singleton
   400      */
   401     public static Global instance() {
   402         ScriptObject global = Context.getGlobal();
   403         if (! (global instanceof Global)) {
   404             throw new IllegalStateException("no current global instance");
   405         }
   406         return (Global)global;
   407     }
   409     /**
   410      * Script access to {@link ScriptEnvironment}
   411      *
   412      * @return the script environment
   413      */
   414     static ScriptEnvironment getEnv() {
   415         return instance().context.getEnv();
   416     }
   418     /**
   419      * Script access to {@link Context}
   420      *
   421      * @return the context
   422      */
   423     static Context getThisContext() {
   424         return instance().context;
   425     }
   427     /**
   428      * Script access check for strict mode
   429      *
   430      * @return true if strict mode enabled in {@link Global#getThisContext()}
   431      */
   432     static boolean isStrict() {
   433         return getEnv()._strict;
   434     }
   436     // GlobalObject interface implementation
   438     @Override
   439     public void initBuiltinObjects() {
   440         if (this.builtinObject != null) {
   441             // already initialized, just return
   442             return;
   443         }
   445         init();
   446     }
   448     @Override
   449     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
   450         return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
   451     }
   453     @Override
   454     public Object wrapAsObject(final Object obj) {
   455         if (obj instanceof Boolean) {
   456             return new NativeBoolean((Boolean)obj);
   457         } else if (obj instanceof Number) {
   458             return new NativeNumber(((Number)obj).doubleValue());
   459         } else if (obj instanceof String || obj instanceof ConsString) {
   460             return new NativeString((CharSequence)obj);
   461         } else if (obj instanceof Object[]) { // extension
   462             return new NativeArray((Object[])obj);
   463         } else if (obj instanceof double[]) { // extension
   464             return new NativeArray((double[])obj);
   465         } else if (obj instanceof long[]) {
   466             return new NativeArray((long[])obj);
   467         } else if (obj instanceof int[]) {
   468             return new NativeArray((int[])obj);
   469         } else {
   470             // FIXME: more special cases? Map? List?
   471             return obj;
   472         }
   473     }
   475     @Override
   476     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
   477         if (self instanceof String || self instanceof ConsString) {
   478             return NativeString.lookupPrimitive(request, self);
   479         } else if (self instanceof Number) {
   480             return NativeNumber.lookupPrimitive(request, self);
   481         } else if (self instanceof Boolean) {
   482             return NativeBoolean.lookupPrimitive(request, self);
   483         }
   484         throw new IllegalArgumentException("Unsupported primitive: " + self);
   485     }
   487     @Override
   488     public ScriptObject newObject() {
   489         return newEmptyInstance();
   490     }
   492     @Override
   493     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
   494         // When the [[DefaultValue]] internal method of O is called with no hint,
   495         // then it behaves as if the hint were Number, unless O is a Date object
   496         // in which case it behaves as if the hint were String.
   497         Class<?> hint = typeHint;
   498         if (hint == null) {
   499             hint = Number.class;
   500         }
   502         try {
   503             if (hint == String.class) {
   505                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   506                 if (toString instanceof ScriptFunction) {
   507                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   508                     if (JSType.isPrimitive(value)) {
   509                         return value;
   510                     }
   511                 }
   513                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   514                 if (valueOf instanceof ScriptFunction) {
   515                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   516                     if (JSType.isPrimitive(value)) {
   517                         return value;
   518                     }
   519                 }
   520                 throw typeError(this, "cannot.get.default.string");
   521             }
   523             if (hint == Number.class) {
   524                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
   525                 if (valueOf instanceof ScriptFunction) {
   526                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
   527                     if (JSType.isPrimitive(value)) {
   528                         return value;
   529                     }
   530                 }
   532                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
   533                 if (toString instanceof ScriptFunction) {
   534                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
   535                     if (JSType.isPrimitive(value)) {
   536                         return value;
   537                     }
   538                 }
   540                 throw typeError(this, "cannot.get.default.number");
   541             }
   542         } catch (final RuntimeException | Error e) {
   543             throw e;
   544         } catch (final Throwable t) {
   545             throw new RuntimeException(t);
   546         }
   548         return UNDEFINED;
   549     }
   551     @Override
   552     public boolean isError(final ScriptObject sobj) {
   553         final ScriptObject errorProto = getErrorPrototype();
   554         ScriptObject proto = sobj.getProto();
   555         while (proto != null) {
   556             if (proto == errorProto) {
   557                 return true;
   558             }
   559             proto = proto.getProto();
   560         }
   561         return false;
   562     }
   564     @Override
   565     public ScriptObject newError(final String msg) {
   566         return new NativeError(msg);
   567     }
   569     @Override
   570     public ScriptObject newEvalError(final String msg) {
   571         return new NativeEvalError(msg);
   572     }
   574     @Override
   575     public ScriptObject newRangeError(final String msg) {
   576         return new NativeRangeError(msg);
   577     }
   579     @Override
   580     public ScriptObject newReferenceError(final String msg) {
   581         return new NativeReferenceError(msg);
   582     }
   584     @Override
   585     public ScriptObject newSyntaxError(final String msg) {
   586         return new NativeSyntaxError(msg);
   587     }
   589     @Override
   590     public ScriptObject newTypeError(final String msg) {
   591         return new NativeTypeError(msg);
   592     }
   594     @Override
   595     public ScriptObject newURIError(final String msg) {
   596         return new NativeURIError(msg);
   597     }
   599     @Override
   600     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
   601         return new GenericPropertyDescriptor(configurable, enumerable);
   602     }
   604     @Override
   605     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
   606         return new DataPropertyDescriptor(configurable, enumerable, writable, value);
   607     }
   609     @Override
   610     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
   611         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
   613         final boolean strict = context.getEnv()._strict;
   615         if (get == null) {
   616             desc.delete(PropertyDescriptor.GET, strict);
   617         }
   619         if (set == null) {
   620             desc.delete(PropertyDescriptor.SET, strict);
   621         }
   623         return desc;
   624     }
   627     /**
   628      * Cache for compiled script classes.
   629      */
   630     @SuppressWarnings("serial")
   631     private static class ClassCache extends LinkedHashMap<Source, SoftReference<Class<?>>> {
   632         private final int size;
   634         ClassCache(int size) {
   635             super(size, 0.75f, true);
   636             this.size = size;
   637         }
   639         @Override
   640         protected boolean removeEldestEntry(final Map.Entry<Source, SoftReference<Class<?>>> eldest) {
   641             return size() >= size;
   642         }
   643     }
   645     // Class cache management
   646     @Override
   647     public Class<?> findCachedClass(final Source source) {
   648         assert classCache != null : "Class cache used without being initialized";
   649         SoftReference<Class<?>> ref = classCache.get(source);
   650         if (ref != null) {
   651             final Class<?> clazz = ref.get();
   652             if (clazz == null) {
   653                 classCache.remove(source);
   654             }
   655             return clazz;
   656         }
   658         return null;
   659     }
   661     @Override
   662     public void cacheClass(final Source source, final Class<?> clazz) {
   663         assert classCache != null : "Class cache used without being initialized";
   664         classCache.put(source, new SoftReference<Class<?>>(clazz));
   665     }
   667     /**
   668      * This is the eval used when 'indirect' eval call is made.
   669      *
   670      * var global = this;
   671      * global.eval("print('hello')");
   672      *
   673      * @param self  eval scope
   674      * @param str   eval string
   675      *
   676      * @return the result of eval
   677      */
   678     public static Object eval(final Object self, final Object str) {
   679         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
   680     }
   682     /**
   683      * Direct eval
   684      *
   685      * @param self     The scope of eval passed as 'self'
   686      * @param str      Evaluated code
   687      * @param callThis "this" to be passed to the evaluated code
   688      * @param location location of the eval call
   689      * @param strict   is eval called a strict mode code?
   690      *
   691      * @return the return value of the eval
   692      *
   693      * This is directly invoked from generated when eval(code) is called in user code
   694      */
   695     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
   696         if (!(str instanceof String || str instanceof ConsString)) {
   697             return str;
   698         }
   699         final Global global = Global.instance();
   700         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   702         return global.context.eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
   703     }
   705     /**
   706      * Global print implementation - Nashorn extension
   707      *
   708      * @param self    scope
   709      * @param objects arguments to print
   710      *
   711      * @return result of print (undefined)
   712      */
   713     public static Object print(final Object self, final Object... objects) {
   714         return printImpl(false, objects);
   715     }
   717     /**
   718      * Global println implementation - Nashorn extension
   719      *
   720      * @param self    scope
   721      * @param objects arguments to print
   722      *
   723      * @return result of println (undefined)
   724      */
   725     public static Object println(final Object self, final Object... objects) {
   726         return printImpl(true, objects);
   727     }
   729     /**
   730      * Global load implementation - Nashorn extension
   731      *
   732      * @param self    scope
   733      * @param source  source to load
   734      *
   735      * @return result of load (undefined)
   736      *
   737      * @throws IOException if source could not be read
   738      */
   739     public static Object load(final Object self, final Object source) throws IOException {
   740         final Global global = Global.instance();
   741         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
   742         return global.context.load(scope, source);
   743     }
   745     /**
   746      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
   747      *
   748      * @param self  self reference
   749      * @param code  exit code
   750      *
   751      * @return undefined (will never be reacheD)
   752      */
   753     public static Object exit(final Object self, final Object code) {
   754         System.exit(JSType.toInt32(code));
   755         return UNDEFINED;
   756     }
   758     ScriptObject getFunctionPrototype() {
   759         return ScriptFunction.getPrototype(builtinFunction);
   760     }
   762     ScriptObject getObjectPrototype() {
   763         return ScriptFunction.getPrototype(builtinObject);
   764     }
   766     ScriptObject getArrayPrototype() {
   767         return ScriptFunction.getPrototype(builtinArray);
   768     }
   770     ScriptObject getBooleanPrototype() {
   771         return ScriptFunction.getPrototype(builtinBoolean);
   772     }
   774     ScriptObject getNumberPrototype() {
   775         return ScriptFunction.getPrototype(builtinNumber);
   776     }
   778     ScriptObject getDatePrototype() {
   779         return ScriptFunction.getPrototype(builtinDate);
   780     }
   782     ScriptObject getRegExpPrototype() {
   783         return ScriptFunction.getPrototype(builtinRegExp);
   784     }
   786     ScriptObject getStringPrototype() {
   787         return ScriptFunction.getPrototype(builtinString);
   788     }
   790     ScriptObject getErrorPrototype() {
   791         return ScriptFunction.getPrototype(builtinError);
   792     }
   794     ScriptObject getEvalErrorPrototype() {
   795         return ScriptFunction.getPrototype(builtinEvalError);
   796     }
   798     ScriptObject getRangeErrorPrototype() {
   799         return ScriptFunction.getPrototype(builtinRangeError);
   800     }
   802     ScriptObject getReferenceErrorPrototype() {
   803         return ScriptFunction.getPrototype(builtinReferenceError);
   804     }
   806     ScriptObject getSyntaxErrorPrototype() {
   807         return ScriptFunction.getPrototype(builtinSyntaxError);
   808     }
   810     ScriptObject getTypeErrorPrototype() {
   811         return ScriptFunction.getPrototype(builtinTypeError);
   812     }
   814     ScriptObject getURIErrorPrototype() {
   815         return ScriptFunction.getPrototype(builtinURIError);
   816     }
   818     ScriptObject getJavaImporterPrototype() {
   819         return ScriptFunction.getPrototype(builtinJavaImporter);
   820     }
   822     ScriptObject getJSAdapterPrototype() {
   823         return ScriptFunction.getPrototype(builtinJSAdapter);
   824     }
   826     ScriptObject getArrayBufferPrototype() {
   827         return ScriptFunction.getPrototype(builtinArrayBuffer);
   828     }
   830     ScriptObject getInt8ArrayPrototype() {
   831         return ScriptFunction.getPrototype(builtinInt8Array);
   832     }
   834     ScriptObject getUint8ArrayPrototype() {
   835         return ScriptFunction.getPrototype(builtinUint8Array);
   836     }
   838     ScriptObject getUint8ClampedArrayPrototype() {
   839         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
   840     }
   842     ScriptObject getInt16ArrayPrototype() {
   843         return ScriptFunction.getPrototype(builtinInt16Array);
   844     }
   846     ScriptObject getUint16ArrayPrototype() {
   847         return ScriptFunction.getPrototype(builtinUint16Array);
   848     }
   850     ScriptObject getInt32ArrayPrototype() {
   851         return ScriptFunction.getPrototype(builtinInt32Array);
   852     }
   854     ScriptObject getUint32ArrayPrototype() {
   855         return ScriptFunction.getPrototype(builtinUint32Array);
   856     }
   858     ScriptObject getFloat32ArrayPrototype() {
   859         return ScriptFunction.getPrototype(builtinFloat32Array);
   860     }
   862     ScriptObject getFloat64ArrayPrototype() {
   863         return ScriptFunction.getPrototype(builtinFloat64Array);
   864     }
   866     private ScriptFunction getBuiltinArray() {
   867         return builtinArray;
   868     }
   871     /**
   872      * Called from compiled script code to test if builtin has been overridden
   873      *
   874      * @return true if builtin array has not been overridden
   875      */
   876     public static boolean isBuiltinArray() {
   877         final Global instance = Global.instance();
   878         return instance.array == instance.getBuiltinArray();
   879     }
   881     private ScriptFunction getBuiltinBoolean() {
   882         return builtinBoolean;
   883     }
   885     /**
   886      * Called from compiled script code to test if builtin has been overridden
   887      *
   888      * @return true if builtin boolean has not been overridden
   889      */
   890     public static boolean isBuiltinBoolean() {
   891         final Global instance = Global.instance();
   892         return instance._boolean == instance.getBuiltinBoolean();
   893     }
   895     private ScriptFunction getBuiltinDate() {
   896         return builtinDate;
   897     }
   899     /**
   900      * Called from compiled script code to test if builtin has been overridden
   901      *
   902      * @return true if builtin date has not been overridden
   903      */
   904     public static boolean isBuiltinDate() {
   905         final Global instance = Global.instance();
   906         return instance.date == instance.getBuiltinDate();
   907     }
   909     private ScriptFunction getBuiltinError() {
   910         return builtinError;
   911     }
   913     /**
   914      * Called from compiled script code to test if builtin has been overridden
   915      *
   916      * @return true if builtin error has not been overridden
   917      */
   918     public static boolean isBuiltinError() {
   919         final Global instance = Global.instance();
   920         return instance.error == instance.getBuiltinError();
   921     }
   923     private ScriptFunction getBuiltinEvalError() {
   924         return builtinEvalError;
   925     }
   927     /**
   928      * Called from compiled script code to test if builtin has been overridden
   929      *
   930      * @return true if builtin eval error has not been overridden
   931      */
   932     public static boolean isBuiltinEvalError() {
   933         final Global instance = Global.instance();
   934         return instance.evalError == instance.getBuiltinEvalError();
   935     }
   937     private ScriptFunction getBuiltinFunction() {
   938         return builtinFunction;
   939     }
   941     /**
   942      * Called from compiled script code to test if builtin has been overridden
   943      *
   944      * @return true if builtin function has not been overridden
   945      */
   946     public static boolean isBuiltinFunction() {
   947         final Global instance = Global.instance();
   948         return instance.function == instance.getBuiltinFunction();
   949     }
   951     private ScriptFunction getBuiltinJSAdapter() {
   952         return builtinJSAdapter;
   953     }
   955     /**
   956      * Called from compiled script code to test if builtin has been overridden
   957      *
   958      * @return true if builtin JSAdapter has not been overridden
   959      */
   960     public static boolean isBuiltinJSAdapter() {
   961         final Global instance = Global.instance();
   962         return instance.jsadapter == instance.getBuiltinJSAdapter();
   963     }
   965     private ScriptObject getBuiltinJSON() {
   966         return builtinJSON;
   967     }
   969     /**
   970      * Called from compiled script code to test if builtin has been overridden
   971      *
   972      * @return true if builtin JSON has has not been overridden
   973      */
   974     public static boolean isBuiltinJSON() {
   975         final Global instance = Global.instance();
   976         return instance.json == instance.getBuiltinJSON();
   977     }
   979     private ScriptObject getBuiltinJava() {
   980         return builtinJava;
   981     }
   983     /**
   984      * Called from compiled script code to test if builtin has been overridden
   985      *
   986      * @return true if builtin Java has not been overridden
   987      */
   988     public static boolean isBuiltinJava() {
   989         final Global instance = Global.instance();
   990         return instance.java == instance.getBuiltinJava();
   991     }
   993     private ScriptObject getBuiltinJavax() {
   994         return builtinJavax;
   995     }
   997     /**
   998      * Called from compiled script code to test if builtin has been overridden
   999      *
  1000      * @return true if builtin Javax has not been overridden
  1001      */
  1002     public static boolean isBuiltinJavax() {
  1003         final Global instance = Global.instance();
  1004         return instance.javax == instance.getBuiltinJavax();
  1007     private ScriptObject getBuiltinJavaImporter() {
  1008         return builtinJavaImporter;
  1011     /**
  1012      * Called from compiled script code to test if builtin has been overridden
  1014      * @return true if builtin Java importer has not been overridden
  1015      */
  1016     public static boolean isBuiltinJavaImporter() {
  1017         final Global instance = Global.instance();
  1018         return instance.javaImporter == instance.getBuiltinJavaImporter();
  1021     private ScriptObject getBuiltinMath() {
  1022         return builtinMath;
  1025     /**
  1026      * Called from compiled script code to test if builtin has been overridden
  1028      * @return true if builtin math has not been overridden
  1029      */
  1030     public static boolean isBuiltinMath() {
  1031         final Global instance = Global.instance();
  1032         return instance.math == instance.getBuiltinMath();
  1035     private ScriptFunction getBuiltinNumber() {
  1036         return builtinNumber;
  1039     /**
  1040      * Called from compiled script code to test if builtin has been overridden
  1042      * @return true if builtin number has not been overridden
  1043      */
  1044     public static boolean isBuiltinNumber() {
  1045         final Global instance = Global.instance();
  1046         return instance.number == instance.getBuiltinNumber();
  1049     private ScriptFunction getBuiltinObject() {
  1050         return builtinObject;
  1053     /**
  1054      * Called from compiled script code to test if builtin has been overridden
  1056      * @return true if builtin object has not been overridden
  1057      */
  1058     public static boolean isBuiltinObject() {
  1059         final Global instance = Global.instance();
  1060         return instance.object == instance.getBuiltinObject();
  1063     private ScriptObject getBuiltinPackages() {
  1064         return builtinPackages;
  1067     /**
  1068      * Called from compiled script code to test if builtin has been overridden
  1070      * @return true if builtin package has not been overridden
  1071      */
  1072     public static boolean isBuiltinPackages() {
  1073         final Global instance = Global.instance();
  1074         return instance.packages == instance.getBuiltinPackages();
  1077     private ScriptFunction getBuiltinRangeError() {
  1078         return builtinRangeError;
  1081     /**
  1082      * Called from compiled script code to test if builtin has been overridden
  1084      * @return true if builtin range error has not been overridden
  1085      */
  1086     public static boolean isBuiltinRangeError() {
  1087         final Global instance = Global.instance();
  1088         return instance.rangeError == instance.getBuiltinRangeError();
  1091     private ScriptFunction getBuiltinReferenceError() {
  1092         return builtinReferenceError;
  1095     /**
  1096      * Called from compiled script code to test if builtin has been overridden
  1098      * @return true if builtin reference error has not been overridden
  1099      */
  1100     public static boolean isBuiltinReferenceError() {
  1101         final Global instance = Global.instance();
  1102         return instance.referenceError == instance.getBuiltinReferenceError();
  1105     private ScriptFunction getBuiltinRegExp() {
  1106         return builtinRegExp;
  1109     /**
  1110      * Called from compiled script code to test if builtin has been overridden
  1112      * @return true if builtin regexp has not been overridden
  1113      */
  1114     public static boolean isBuiltinRegExp() {
  1115         final Global instance = Global.instance();
  1116         return instance.regexp == instance.getBuiltinRegExp();
  1119     private ScriptFunction getBuiltinString() {
  1120         return builtinString;
  1123     /**
  1124      * Called from compiled script code to test if builtin has been overridden
  1126      * @return true if builtin Java has not been overridden
  1127      */
  1128     public static boolean isBuiltinString() {
  1129         final Global instance = Global.instance();
  1130         return instance.string == instance.getBuiltinString();
  1133     private ScriptFunction getBuiltinSyntaxError() {
  1134         return builtinSyntaxError;
  1137     /**
  1138      * Called from compiled script code to test if builtin has been overridden
  1140      * @return true if builtin syntax error has not been overridden
  1141      */
  1142     public static boolean isBuiltinSyntaxError() {
  1143         final Global instance = Global.instance();
  1144         return instance.syntaxError == instance.getBuiltinSyntaxError();
  1147     private ScriptFunction getBuiltinTypeError() {
  1148         return builtinTypeError;
  1151     /**
  1152      * Called from compiled script code to test if builtin has been overridden
  1154      * @return true if builtin type error has not been overridden
  1155      */
  1156     public static boolean isBuiltinTypeError() {
  1157         final Global instance = Global.instance();
  1158         return instance.typeError == instance.getBuiltinTypeError();
  1161     private ScriptFunction getBuiltinURIError() {
  1162         return builtinURIError;
  1165     /**
  1166      * Called from compiled script code to test if builtin has been overridden
  1168      * @return true if builtin URI error has not been overridden
  1169      */
  1170     public static boolean isBuiltinURIError() {
  1171         final Global instance = Global.instance();
  1172         return instance.uriError == instance.getBuiltinURIError();
  1175     @Override
  1176     public String getClassName() {
  1177         return "global";
  1180     /**
  1181      * Copy function used to clone NativeRegExp objects.
  1183      * @param regexp a NativeRegExp to clone
  1185      * @return copy of the given regexp object
  1186      */
  1187     public static Object regExpCopy(final Object regexp) {
  1188         return new NativeRegExp((NativeRegExp)regexp);
  1191     /**
  1192      * Convert given object to NativeRegExp type.
  1194      * @param obj object to be converted
  1195      * @return NativeRegExp instance
  1196      */
  1197     public static NativeRegExp toRegExp(final Object obj) {
  1198         if (obj instanceof NativeRegExp) {
  1199             return (NativeRegExp)obj;
  1201         return new NativeRegExp(JSType.toString(obj));
  1204     /**
  1205      * ECMA 9.9 ToObject implementation
  1207      * @param obj  an item for which to run ToObject
  1208      * @return ToObject version of given item
  1209      */
  1210     public static Object toObject(final Object obj) {
  1211         if (obj == null || obj == UNDEFINED) {
  1212             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1215         if (obj instanceof ScriptObject) {
  1216             return obj;
  1219         return instance().wrapAsObject(obj);
  1222     /**
  1223      * Allocate a new object array.
  1225      * @param initial object values.
  1226      * @return the new array
  1227      */
  1228     public static NativeArray allocate(final Object[] initial) {
  1229         return new NativeArray(initial);
  1232     /**
  1233      * Allocate a new number array.
  1235      * @param initial number values.
  1236      * @return the new array
  1237      */
  1238     public static NativeArray allocate(final double[] initial) {
  1239         return new NativeArray(initial);
  1242     /**
  1243      * Allocate a new long array.
  1245      * @param initial number values.
  1246      * @return the new array
  1247      */
  1248     public static NativeArray allocate(final long[] initial) {
  1249         return new NativeArray(initial);
  1252     /**
  1253      * Allocate a new integer array.
  1255      * @param initial number values.
  1256      * @return the new array
  1257      */
  1258     public static NativeArray allocate(final int[] initial) {
  1259         return new NativeArray(initial);
  1262     /**
  1263      * Allocate a new object array for arguments.
  1265      * @param arguments initial arguments passed.
  1266      * @param callee reference to the function that uses arguments object
  1267      * @param numParams actual number of declared parameters
  1269      * @return the new array
  1270      */
  1271     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
  1272         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
  1275     /**
  1276      * Called from generated to check if given function is the builtin 'eval'. If
  1277      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
  1279      * @param  fn function object that is checked
  1280      * @return true if fn is the builtin eval
  1281      */
  1282     public static boolean isEval(final Object fn) {
  1283         return fn == Global.instance().builtinEval;
  1286     /**
  1287      * Create a new RegExp object.
  1289      * @param expression Regular expression.
  1290      * @param options    Search options.
  1292      * @return New RegExp object.
  1293      */
  1294     public static Object newRegExp(final String expression, final String options) {
  1295         if (options == null) {
  1296             return new NativeRegExp(expression);
  1298         return new NativeRegExp(expression, options);
  1301     /**
  1302      * Get the object prototype
  1304      * @return the object prototype
  1305      */
  1306     public static ScriptObject objectPrototype() {
  1307         return Global.instance().getObjectPrototype();
  1310     /**
  1311      * Create a new empty object instance.
  1313      * @return New empty object.
  1314      */
  1315     public static ScriptObject newEmptyInstance() {
  1316         final ScriptObject sobj = new JO();
  1317         sobj.setProto(objectPrototype());
  1318         return sobj;
  1321     /**
  1322      * Check if a given object is a ScriptObject, raises an exception if this is
  1323      * not the case
  1325      * @param obj and object to check
  1326      */
  1327     public static void checkObject(final Object obj) {
  1328         if (!(obj instanceof ScriptObject)) {
  1329             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1333     /**
  1334      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
  1335      * if this object is null or undefined.
  1337      * @param obj an object to check
  1338      */
  1339     public static void checkObjectCoercible(final Object obj) {
  1340         if (obj == null || obj == UNDEFINED) {
  1341             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  1345     /**
  1346      * Get the current split state.
  1348      * @return current split state
  1349      */
  1350     @Override
  1351     public int getSplitState() {
  1352         return splitState;
  1355     /**
  1356      * Set the current split state.
  1358      * @param state current split state
  1359      */
  1360     @Override
  1361     public void setSplitState(final int state) {
  1362         splitState = state;
  1365     private void init() {
  1366         assert Context.getGlobal() == this : "this global is not set as current";
  1368         final ScriptEnvironment env = context.getEnv();
  1369         // initialize Function and Object constructor
  1370         initFunctionAndObject();
  1372         // Now fix Global's own proto.
  1373         this.setProto(getObjectPrototype());
  1375         // initialize global function properties
  1376         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  1378         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
  1379         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  1380         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
  1381         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
  1382         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
  1383         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
  1384         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
  1385         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
  1386         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
  1387         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
  1388         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
  1389         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
  1390         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
  1391         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
  1393         // built-in constructors
  1394         this.builtinArray     = (ScriptFunction)initConstructor("Array");
  1395         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
  1396         this.builtinDate      = (ScriptFunction)initConstructor("Date");
  1397         this.builtinJSON      = initConstructor("JSON");
  1398         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
  1399         this.builtinMath      = initConstructor("Math");
  1400         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
  1401         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
  1402         this.builtinString    = (ScriptFunction)initConstructor("String");
  1404         // initialize String.prototype.length to 0
  1405         // add String.prototype.length
  1406         final ScriptObject stringPrototype = getStringPrototype();
  1407         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  1409         // add Array.prototype.length
  1410         final ScriptObject arrayPrototype = getArrayPrototype();
  1411         arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0);
  1413         this.DEFAULT_DATE = new NativeDate(Double.NaN);
  1415         // initialize default regexp object
  1416         this.DEFAULT_REGEXP = new NativeRegExp("(?:)");
  1418         // RegExp.prototype should behave like a RegExp object. So copy the
  1419         // properties.
  1420         final ScriptObject regExpProto = getRegExpPrototype();
  1421         regExpProto.addBoundProperties(DEFAULT_REGEXP);
  1423         // Error stuff
  1424         initErrorObjects();
  1426         // java access
  1427         initJavaAccess();
  1429         initTypedArray();
  1431         if (env._scripting) {
  1432             initScripting();
  1435         if (Context.DEBUG && System.getSecurityManager() == null) {
  1436             initDebug();
  1439         copyBuiltins();
  1441         // initialized with strings so that typeof will work as expected.
  1442         this.__FILE__ = "";
  1443         this.__DIR__  = "";
  1444         this.__LINE__ = 0.0;
  1446         // expose script (command line) arguments as "arguments" property of global
  1447         final List<String> arguments = env.getArguments();
  1448         final Object argsObj = wrapAsObject(arguments.toArray());
  1450         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
  1451         if (env._scripting) {
  1452             // synonym for "arguments" in scripting mode
  1453             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
  1457     private void initErrorObjects() {
  1458         // Error objects
  1459         this.builtinError = (ScriptFunction)initConstructor("Error");
  1460         final ScriptObject errorProto = getErrorPrototype();
  1461         final boolean strict = Global.isStrict();
  1463         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
  1464         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
  1465         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
  1466         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
  1467         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
  1468         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
  1469         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
  1470         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
  1471         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
  1472         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
  1473         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
  1474         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
  1475         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
  1477         // ECMA 15.11.4.2 Error.prototype.name
  1478         // Error.prototype.name = "Error";
  1479         errorProto.set(NativeError.NAME, "Error", strict);
  1480         // ECMA 15.11.4.3 Error.prototype.message
  1481         // Error.prototype.message = "";
  1482         errorProto.set(NativeError.MESSAGE, "", strict);
  1484         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
  1485         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
  1486         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
  1487         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
  1488         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
  1489         this.builtinURIError = initErrorSubtype("URIError", errorProto);
  1492     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
  1493         final ScriptObject cons = initConstructor(name);
  1494         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  1495         final boolean strict = Global.isStrict();
  1496         prototype.set(NativeError.NAME, name, strict);
  1497         prototype.set(NativeError.MESSAGE, "", strict);
  1498         prototype.setProto(errorProto);
  1499         return (ScriptFunction)cons;
  1502     private void initJavaAccess() {
  1503         final ScriptObject objectProto = getObjectPrototype();
  1504         this.builtinPackages = new NativeJavaPackage("", objectProto);
  1505         this.builtinCom = new NativeJavaPackage("com", objectProto);
  1506         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
  1507         this.builtinJava = new NativeJavaPackage("java", objectProto);
  1508         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
  1509         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
  1510         this.builtinOrg = new NativeJavaPackage("org", objectProto);
  1511         this.builtinJavaImporter = initConstructor("JavaImporter");
  1512         this.builtinJavaApi = initConstructor("Java");
  1515     private void initScripting() {
  1516         Object value;
  1517         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
  1518         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
  1520         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
  1521         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
  1523         final String execName = ScriptingFunctions.EXEC_NAME;
  1524         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
  1525         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
  1527         // Nashorn extension: global.echo (scripting-mode-only)
  1528         // alias for "print"
  1529         value = get("print");
  1530         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
  1532         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
  1533         final ScriptObject options = newEmptyInstance();
  1534         final ScriptEnvironment scriptEnv = context.getEnv();
  1535         copyOptions(options, scriptEnv);
  1536         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
  1538         // Nashorn extension: global.$ENV (scripting-mode-only)
  1539         if (System.getSecurityManager() == null) {
  1540             // do not fill $ENV if we have a security manager around
  1541             // Retrieve current state of ENV variables.
  1542             final ScriptObject env = newEmptyInstance();
  1543             env.putAll(System.getenv());
  1544             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
  1545         } else {
  1546             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1549         // add other special properties for exec support
  1550         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1551         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1552         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  1555     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
  1556         AccessController.doPrivileged(new PrivilegedAction<Void>() {
  1557             @Override
  1558             public Void run() {
  1559                 for (Field f : scriptEnv.getClass().getFields()) {
  1560                     try {
  1561                         options.set(f.getName(), f.get(scriptEnv), false);
  1562                     } catch (final IllegalArgumentException | IllegalAccessException exp) {
  1563                         throw new RuntimeException(exp);
  1566                 return null;
  1568         });
  1571     private void initTypedArray() {
  1572         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
  1573         this.builtinInt8Array         = initConstructor("Int8Array");
  1574         this.builtinUint8Array        = initConstructor("Uint8Array");
  1575         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
  1576         this.builtinInt16Array        = initConstructor("Int16Array");
  1577         this.builtinUint16Array       = initConstructor("Uint16Array");
  1578         this.builtinInt32Array        = initConstructor("Int32Array");
  1579         this.builtinUint32Array       = initConstructor("Uint32Array");
  1580         this.builtinFloat32Array      = initConstructor("Float32Array");
  1581         this.builtinFloat64Array      = initConstructor("Float64Array");
  1584     private void copyBuiltins() {
  1585         this.array             = this.builtinArray;
  1586         this._boolean          = this.builtinBoolean;
  1587         this.date              = this.builtinDate;
  1588         this.error             = this.builtinError;
  1589         this.evalError         = this.builtinEvalError;
  1590         this.function          = this.builtinFunction;
  1591         this.jsadapter         = this.builtinJSAdapter;
  1592         this.json              = this.builtinJSON;
  1593         this.com               = this.builtinCom;
  1594         this.edu               = this.builtinEdu;
  1595         this.java              = this.builtinJava;
  1596         this.javafx            = this.builtinJavafx;
  1597         this.javax             = this.builtinJavax;
  1598         this.org               = this.builtinOrg;
  1599         this.javaImporter      = this.builtinJavaImporter;
  1600         this.javaApi           = this.builtinJavaApi;
  1601         this.math              = this.builtinMath;
  1602         this.number            = this.builtinNumber;
  1603         this.object            = this.builtinObject;
  1604         this.packages          = this.builtinPackages;
  1605         this.rangeError        = this.builtinRangeError;
  1606         this.referenceError    = this.builtinReferenceError;
  1607         this.regexp            = this.builtinRegExp;
  1608         this.string            = this.builtinString;
  1609         this.syntaxError       = this.builtinSyntaxError;
  1610         this.typeError         = this.builtinTypeError;
  1611         this.uriError          = this.builtinURIError;
  1612         this.arrayBuffer       = this.builtinArrayBuffer;
  1613         this.int8Array         = this.builtinInt8Array;
  1614         this.uint8Array        = this.builtinUint8Array;
  1615         this.uint8ClampedArray = this.builtinUint8ClampedArray;
  1616         this.int16Array        = this.builtinInt16Array;
  1617         this.uint16Array       = this.builtinUint16Array;
  1618         this.int32Array        = this.builtinInt32Array;
  1619         this.uint32Array       = this.builtinUint32Array;
  1620         this.float32Array      = this.builtinFloat32Array;
  1621         this.float64Array      = this.builtinFloat64Array;
  1624     private void initDebug() {
  1625         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
  1628     private static Object printImpl(final boolean newLine, final Object... objects) {
  1629         final PrintWriter out = Global.getEnv().getOut();
  1631         boolean first = true;
  1632         for (final Object object : objects) {
  1633             if (first) {
  1634                 first = false;
  1635             } else {
  1636                 out.print(' ');
  1639             out.print(JSType.toString(object));
  1642         if (newLine) {
  1643             out.println();
  1646         out.flush();
  1648         return UNDEFINED;
  1651     /**
  1652      * These classes are generated by nasgen tool and so we have to use
  1653      * reflection to load and create new instance of these classes.
  1654      */
  1655     private ScriptObject initConstructor(final String name) {
  1656         try {
  1657             // Assuming class name pattern for built-in JS constructors.
  1658             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
  1660             sb.append("Native");
  1661             sb.append(name);
  1662             sb.append("$Constructor");
  1664             final Class<?>     funcClass = Class.forName(sb.toString());
  1665             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
  1667             if (res instanceof ScriptFunction) {
  1668                 // All global constructor prototypes are not-writable,
  1669                 // not-enumerable and not-configurable.
  1670                 final ScriptFunction func = (ScriptFunction)res;
  1671                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
  1674             if (res.getProto() == null) {
  1675                 res.setProto(getObjectPrototype());
  1678             return res;
  1680         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  1681             throw new RuntimeException(e);
  1685     // Function and Object constructors are inter-dependent. Also,
  1686     // Function.prototype
  1687     // functions are not properly initialized. We fix the references here.
  1688     // NOTE: be careful if you want to re-order the operations here. You may
  1689     // have
  1690     // to play with object references carefully!!
  1691     private void initFunctionAndObject() {
  1692         // First-n-foremost is Function
  1693         this.builtinFunction = (ScriptFunction)initConstructor("Function");
  1695         // create global anonymous function
  1696         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
  1697         // need to copy over members of Function.prototype to anon function
  1698         anon.addBoundProperties(getFunctionPrototype());
  1700         // Function.prototype === Object.getPrototypeOf(Function) ===
  1701         // <anon-function>
  1702         builtinFunction.setProto(anon);
  1703         builtinFunction.setPrototype(anon);
  1704         anon.set("constructor", builtinFunction, anon.isStrict());
  1705         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  1707         // now initialize Object
  1708         this.builtinObject = (ScriptFunction)initConstructor("Object");
  1709         final ScriptObject ObjectPrototype = getObjectPrototype();
  1710         // Object.getPrototypeOf(Function.prototype) === Object.prototype
  1711         anon.setProto(ObjectPrototype);
  1713         // Function valued properties of Function.prototype were not properly
  1714         // initialized. Because, these were created before global.function and
  1715         // global.object were not initialized.
  1716         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
  1717         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1718             final Object key = property.getKey();
  1719             final Object value = builtinFunction.get(key);
  1721             if (value instanceof ScriptFunction && value != anon) {
  1722                 final ScriptFunction func = (ScriptFunction)value;
  1723                 func.setProto(getFunctionPrototype());
  1724                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1725                 if (prototype != null) {
  1726                     prototype.setProto(ObjectPrototype);
  1731         // For function valued properties of Object and Object.prototype, make
  1732         // sure prototype's proto chain ends with Object.prototype
  1733         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
  1734             final Object key = property.getKey();
  1735             final Object value = builtinObject.get(key);
  1737             if (value instanceof ScriptFunction) {
  1738                 final ScriptFunction func = (ScriptFunction)value;
  1739                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1740                 if (prototype != null) {
  1741                     prototype.setProto(ObjectPrototype);
  1746         properties = getObjectPrototype().getMap().getProperties();
  1747         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  1748             final Object key   = property.getKey();
  1749             final Object value = ObjectPrototype.get(key);
  1751             if (key.equals("constructor")) {
  1752                 continue;
  1755             if (value instanceof ScriptFunction) {
  1756                 final ScriptFunction func = (ScriptFunction)value;
  1757                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  1758                 if (prototype != null) {
  1759                     prototype.setProto(ObjectPrototype);
  1766     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
  1767         return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types));
  1770     RegExpResult getLastRegExpResult() {
  1771         return lastRegExpResult;
  1774     void setLastRegExpResult(final RegExpResult regExpResult) {
  1775         this.lastRegExpResult = regExpResult;

mercurial