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

Wed, 20 May 2015 14:16:19 +0530

author
sundar
date
Wed, 20 May 2015 14:16:19 +0530
changeset 1372
644d9b9c97ed
parent 1330
d82b07c9c6e3
child 1385
b4a5485d6ff3
permissions
-rw-r--r--

8080598: Javadoc warnings in Global.java after lazy initialization
Reviewed-by: lagergren, hannesw

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.objects;
    28 import static jdk.nashorn.internal.lookup.Lookup.MH;
    29 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
    30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    31 import static jdk.nashorn.internal.runtime.JSType.isString;
    32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    34 import java.io.IOException;
    35 import java.io.PrintWriter;
    36 import java.lang.invoke.MethodHandle;
    37 import java.lang.invoke.MethodHandles;
    38 import java.lang.invoke.MethodType;
    39 import java.lang.invoke.SwitchPoint;
    40 import java.lang.reflect.Field;
    41 import java.util.ArrayList;
    42 import java.util.Arrays;
    43 import java.util.List;
    44 import java.util.Map;
    45 import java.util.Objects;
    46 import java.util.concurrent.Callable;
    47 import java.util.concurrent.ConcurrentHashMap;
    48 import javax.script.ScriptContext;
    49 import javax.script.ScriptEngine;
    50 import jdk.internal.dynalink.CallSiteDescriptor;
    51 import jdk.internal.dynalink.linker.GuardedInvocation;
    52 import jdk.internal.dynalink.linker.LinkRequest;
    53 import jdk.nashorn.api.scripting.ClassFilter;
    54 import jdk.nashorn.api.scripting.ScriptObjectMirror;
    55 import jdk.nashorn.internal.lookup.Lookup;
    56 import jdk.nashorn.internal.objects.annotations.Attribute;
    57 import jdk.nashorn.internal.objects.annotations.Getter;
    58 import jdk.nashorn.internal.objects.annotations.Property;
    59 import jdk.nashorn.internal.objects.annotations.ScriptClass;
    60 import jdk.nashorn.internal.objects.annotations.Setter;
    61 import jdk.nashorn.internal.runtime.Context;
    62 import jdk.nashorn.internal.runtime.ECMAErrors;
    63 import jdk.nashorn.internal.runtime.FindProperty;
    64 import jdk.nashorn.internal.runtime.GlobalConstants;
    65 import jdk.nashorn.internal.runtime.GlobalFunctions;
    66 import jdk.nashorn.internal.runtime.JSType;
    67 import jdk.nashorn.internal.runtime.NativeJavaPackage;
    68 import jdk.nashorn.internal.runtime.PropertyDescriptor;
    69 import jdk.nashorn.internal.runtime.PropertyMap;
    70 import jdk.nashorn.internal.runtime.Scope;
    71 import jdk.nashorn.internal.runtime.ScriptEnvironment;
    72 import jdk.nashorn.internal.runtime.ScriptFunction;
    73 import jdk.nashorn.internal.runtime.ScriptObject;
    74 import jdk.nashorn.internal.runtime.ScriptRuntime;
    75 import jdk.nashorn.internal.runtime.ScriptingFunctions;
    76 import jdk.nashorn.internal.runtime.Specialization;
    77 import jdk.nashorn.internal.runtime.arrays.ArrayData;
    78 import jdk.nashorn.internal.runtime.linker.Bootstrap;
    79 import jdk.nashorn.internal.runtime.linker.InvokeByName;
    80 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
    81 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    82 import jdk.nashorn.internal.scripts.JD;
    83 import jdk.nashorn.internal.scripts.JO;
    84 import jdk.nashorn.tools.ShellFunctions;
    86 /**
    87  * Representation of global scope.
    88  */
    89 @ScriptClass("Global")
    90 public final class Global extends ScriptObject implements Scope {
    91     // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
    92     private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
    93     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
    94     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
    96     // placeholder value for lazily initialized global objects
    97     private static final Object LAZY_SENTINEL = new Object();
    99     /**
   100      * Optimistic builtin names that require switchpoint invalidation
   101      * upon assignment. Overly conservative, but works for now, to avoid
   102      * any complicated scope checks and especially heavy weight guards
   103      * like
   104      *
   105      * <pre>
   106      *     public boolean setterGuard(final Object receiver) {
   107      *         final Global          global = Global.instance();
   108      *         final ScriptObject    sobj   = global.getFunctionPrototype();
   109      *         final Object          apply  = sobj.get("apply");
   110      *         return apply == receiver;
   111      *     }
   112      * </pre>
   113      *
   114      * Naturally, checking for builtin classes like NativeFunction is cheaper,
   115      * it's when you start adding property checks for said builtins you have
   116      * problems with guard speed.
   117      */
   119     /** Nashorn extension: arguments array */
   120     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
   121     public Object arguments;
   123     /** ECMA 15.1.2.2 parseInt (string , radix) */
   124     @Property(attributes = Attribute.NOT_ENUMERABLE)
   125     public Object parseInt;
   127     /** ECMA 15.1.2.3 parseFloat (string) */
   128     @Property(attributes = Attribute.NOT_ENUMERABLE)
   129     public Object parseFloat;
   131     /** ECMA 15.1.2.4 isNaN (number) */
   132     @Property(attributes = Attribute.NOT_ENUMERABLE)
   133     public Object isNaN;
   135     /** ECMA 15.1.2.5 isFinite (number) */
   136     @Property(attributes = Attribute.NOT_ENUMERABLE)
   137     public Object isFinite;
   139     /** ECMA 15.1.3.3 encodeURI */
   140     @Property(attributes = Attribute.NOT_ENUMERABLE)
   141     public Object encodeURI;
   143     /** ECMA 15.1.3.4 encodeURIComponent */
   144     @Property(attributes = Attribute.NOT_ENUMERABLE)
   145     public Object encodeURIComponent;
   147     /** ECMA 15.1.3.1 decodeURI */
   148     @Property(attributes = Attribute.NOT_ENUMERABLE)
   149     public Object decodeURI;
   151     /** ECMA 15.1.3.2 decodeURIComponent */
   152     @Property(attributes = Attribute.NOT_ENUMERABLE)
   153     public Object decodeURIComponent;
   155     /** ECMA B.2.1 escape (string) */
   156     @Property(attributes = Attribute.NOT_ENUMERABLE)
   157     public Object escape;
   159     /** ECMA B.2.2 unescape (string) */
   160     @Property(attributes = Attribute.NOT_ENUMERABLE)
   161     public Object unescape;
   163     /** Nashorn extension: global.print */
   164     @Property(attributes = Attribute.NOT_ENUMERABLE)
   165     public Object print;
   167     /** Nashorn extension: global.load */
   168     @Property(attributes = Attribute.NOT_ENUMERABLE)
   169     public Object load;
   171     /** Nashorn extension: global.loadWithNewGlobal */
   172     @Property(attributes = Attribute.NOT_ENUMERABLE)
   173     public Object loadWithNewGlobal;
   175     /** Nashorn extension: global.exit */
   176     @Property(attributes = Attribute.NOT_ENUMERABLE)
   177     public Object exit;
   179     /** Nashorn extension: global.quit */
   180     @Property(attributes = Attribute.NOT_ENUMERABLE)
   181     public Object quit;
   183     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
   184     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   185     public final double NaN = Double.NaN;
   187     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
   188     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   189     public final double Infinity = Double.POSITIVE_INFINITY;
   191     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
   192     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   193     public final Object undefined = UNDEFINED;
   195     /** ECMA 15.1.2.1 eval(x) */
   196     @Property(attributes = Attribute.NOT_ENUMERABLE)
   197     public Object eval;
   199     /** ECMA 15.1.4.1 Object constructor. */
   200     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
   201     public volatile Object object;
   203     /** ECMA 15.1.4.2 Function constructor. */
   204     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
   205     public volatile Object function;
   207     /** ECMA 15.1.4.3 Array constructor. */
   208     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
   209     public volatile Object array;
   211     /** ECMA 15.1.4.4 String constructor */
   212     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
   213     public volatile Object string;
   215     /** ECMA 15.1.4.5 Boolean constructor */
   216     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
   217     public volatile Object _boolean;
   219     /** ECMA 15.1.4.6 - Number constructor */
   220     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
   221     public volatile Object number;
   223     /**
   224      * Getter for ECMA 15.1.4.7 Date property
   225      *
   226      * @param self self reference
   227      * @return Date property value
   228      */
   229     @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   230     public static Object getDate(final Object self) {
   231         final Global global = Global.instanceFrom(self);
   232         if (global.date == LAZY_SENTINEL) {
   233             global.date = global.getBuiltinDate();
   234         }
   235         return global.date;
   236     }
   238     /**
   239      * Setter for ECMA 15.1.4.7 Date property
   240      *
   241      * @param self self reference
   242      * @param value value for the Date property
   243      */
   244     @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
   245     public static void setDate(final Object self, final Object value) {
   246         final Global global = Global.instanceFrom(self);
   247         global.date = value;
   248     }
   250     private volatile Object date = LAZY_SENTINEL;
   252     /**
   253      * Getter for ECMA 15.1.4.8 RegExp property
   254      *
   255      * @param self self reference
   256      * @return RegExp property value
   257      */
   258     @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   259     public static Object getRegExp(final Object self) {
   260         final Global global = Global.instanceFrom(self);
   261         if (global.regexp == LAZY_SENTINEL) {
   262             global.regexp = global.getBuiltinRegExp();
   263         }
   264         return global.regexp;
   265     }
   267     /**
   268      * Setter for ECMA 15.1.4.8 RegExp property
   269      *
   270      * @param self self reference
   271      * @param value value for the RegExp property
   272      */
   273     @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
   274     public static void setRegExp(final Object self, final Object value) {
   275         final Global global = Global.instanceFrom(self);
   276         global.regexp = value;
   277     }
   279     private volatile Object regexp = LAZY_SENTINEL;
   281     /**
   282      * Getter for ECMA 15.12 - The JSON property
   283      * @param self self reference
   284      * @return the value of JSON property
   285      */
   286     @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   287     public static Object getJSON(final Object self) {
   288         final Global global = Global.instanceFrom(self);
   289         if (global.json == LAZY_SENTINEL) {
   290             global.json = global.getBuiltinJSON();
   291         }
   292         return global.json;
   293     }
   295     /**
   296      * Setter for ECMA 15.12 - The JSON property
   297      * @param self self reference
   298      * @param value value for the JSON property
   299      */
   300     @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
   301     public static void setJSON(final Object self, final Object value) {
   302         final Global global = Global.instanceFrom(self);
   303         global.json = value;
   304     }
   306     private volatile Object json = LAZY_SENTINEL;
   308     /**
   309      * Getter for Nashorn extension: global.JSAdapter
   310      * @param self self reference
   311      * @return value of the JSAdapter property
   312      */
   313     @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   314     public static Object getJSAdapter(final Object self) {
   315         final Global global = Global.instanceFrom(self);
   316         if (global.jsadapter == LAZY_SENTINEL) {
   317             global.jsadapter = global.getBuiltinJSAdapter();
   318         }
   319         return global.jsadapter;
   320     }
   322     /**
   323      * Setter for Nashorn extension: global.JSAdapter
   324      * @param self self reference
   325      * @param value value for the JSAdapter property
   326      */
   327     @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
   328     public static void setJSAdapter(final Object self, final Object value) {
   329         final Global global = Global.instanceFrom(self);
   330         global.jsadapter = value;
   331     }
   333     private volatile Object jsadapter = LAZY_SENTINEL;
   335     /** ECMA 15.8 - The Math object */
   336     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
   337     public volatile Object math;
   339     /** Error object */
   340     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
   341     public volatile Object error;
   343     /**
   344      * Getter for the EvalError property
   345      * @param self self reference
   346      * @return the value of EvalError property
   347      */
   348     @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   349     public static Object getEvalError(final Object self) {
   350         final Global global = Global.instanceFrom(self);
   351         if (global.evalError == LAZY_SENTINEL) {
   352             global.evalError = global.getBuiltinEvalError();
   353         }
   354         return global.evalError;
   355     }
   357     /**
   358      * Setter for the EvalError property
   359      * @param self self reference
   360      * @param value value of the EvalError property
   361      */
   362     @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
   363     public static void setEvalError(final Object self, final Object value) {
   364         final Global global = Global.instanceFrom(self);
   365         global.evalError = value;
   366     }
   368     private volatile Object evalError = LAZY_SENTINEL;
   370     /**
   371      * Getter for the RangeError property.
   372      * @param self self reference
   373      * @return the value of RangeError property
   374      */
   375     @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   376     public static Object getRangeError(final Object self) {
   377         final Global global = Global.instanceFrom(self);
   378         if (global.rangeError == LAZY_SENTINEL) {
   379             global.rangeError = global.getBuiltinRangeError();
   380         }
   381         return global.rangeError;
   382     }
   385     /**
   386      * Setter for the RangeError property.
   387      * @param self self reference
   388      * @param value value for the RangeError property
   389      */
   390     @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
   391     public static void setRangeError(final Object self, final Object value) {
   392         final Global global = Global.instanceFrom(self);
   393         global.rangeError = value;
   394     }
   396     private volatile Object rangeError = LAZY_SENTINEL;
   398     /** ReferenceError object */
   399     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
   400     public volatile Object referenceError;
   402     /** SyntaxError object */
   403     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
   404     public volatile Object syntaxError;
   406     /** TypeError object */
   407     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
   408     public volatile Object typeError;
   410     /**
   411      * Getter for the URIError property.
   412      * @param self self reference
   413      * @return the value of URIError property
   414      */
   415     @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   416     public static Object getURIError(final Object self) {
   417         final Global global = Global.instanceFrom(self);
   418         if (global.uriError == LAZY_SENTINEL) {
   419             global.uriError = global.getBuiltinURIError();
   420         }
   421         return global.uriError;
   422     }
   424     /**
   425      * Setter for the URIError property.
   426      * @param self self reference
   427      * @param value value for the URIError property
   428      */
   429     @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
   430     public static void setURIError(final Object self, final Object value) {
   431         final Global global = Global.instanceFrom(self);
   432         global.uriError = value;
   433     }
   435     private volatile Object uriError = LAZY_SENTINEL;
   437     /**
   438      * Getter for the ArrayBuffer property.
   439      * @param self self reference
   440      * @return the value of the ArrayBuffer property
   441      */
   442     @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   443     public static Object getArrayBuffer(final Object self) {
   444         final Global global = Global.instanceFrom(self);
   445         if (global.arrayBuffer == LAZY_SENTINEL) {
   446             global.arrayBuffer = global.getBuiltinArrayBuffer();
   447         }
   448         return global.arrayBuffer;
   449     }
   451     /**
   452      * Setter for the ArrayBuffer property.
   453      * @param self self reference
   454      * @param value value of the ArrayBuffer property
   455      */
   456     @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
   457     public static void setArrayBuffer(final Object self, final Object value) {
   458         final Global global = Global.instanceFrom(self);
   459         global.arrayBuffer = value;
   460     }
   462     private volatile Object arrayBuffer;
   464     /**
   465      * Getter for the DataView property.
   466      * @param self self reference
   467      * @return the value of the DataView property
   468      */
   469     @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
   470     public static Object getDataView(final Object self) {
   471         final Global global = Global.instanceFrom(self);
   472         if (global.dataView == LAZY_SENTINEL) {
   473             global.dataView = global.getBuiltinDataView();
   474         }
   475         return global.dataView;
   476     }
   479     /**
   480      * Setter for the DataView property.
   481      * @param self self reference
   482      * @param value value of the DataView property
   483      */
   484     @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
   485     public static void setDataView(final Object self, final Object value) {
   486         final Global global = Global.instanceFrom(self);
   487         global.dataView = value;
   488     }
   490     private volatile Object dataView;
   492     /**
   493      * Getter for the Int8Array property.
   494      * @param self self reference
   495      * @return the value of the Int8Array property.
   496      */
   497     @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   498     public static Object getInt8Array(final Object self) {
   499         final Global global = Global.instanceFrom(self);
   500         if (global.int8Array == LAZY_SENTINEL) {
   501             global.int8Array = global.getBuiltinInt8Array();
   502         }
   503         return global.int8Array;
   504     }
   506     /**
   507      * Setter for the Int8Array property.
   508      * @param self self reference
   509      * @param value value of the Int8Array property
   510      */
   511     @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
   512     public static void setInt8Array(final Object self, final Object value) {
   513         final Global global = Global.instanceFrom(self);
   514         global.int8Array = value;
   515     }
   517     private volatile Object int8Array;
   519     /**
   520      * Getter for the Uin8Array property.
   521      * @param self self reference
   522      * @return the value of the Uint8Array property
   523      */
   524     @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   525     public static Object getUint8Array(final Object self) {
   526         final Global global = Global.instanceFrom(self);
   527         if (global.uint8Array == LAZY_SENTINEL) {
   528             global.uint8Array = global.getBuiltinUint8Array();
   529         }
   530         return global.uint8Array;
   531     }
   533     /**
   534      * Setter for the Uin8Array property.
   535      * @param self self reference
   536      * @param value value of the Uin8Array property
   537      */
   538     @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
   539     public static void setUint8Array(final Object self, final Object value) {
   540         final Global global = Global.instanceFrom(self);
   541         global.uint8Array = value;
   542     }
   544     private volatile Object uint8Array;
   546     /**
   547      * Getter for the Uint8ClampedArray property.
   548      * @param self self reference
   549      * @return the value of the Uint8ClampedArray property
   550      */
   551     @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   552     public static Object getUint8ClampedArray(final Object self) {
   553         final Global global = Global.instanceFrom(self);
   554         if (global.uint8ClampedArray == LAZY_SENTINEL) {
   555             global.uint8ClampedArray = global.getBuiltinUint8ClampedArray();
   556         }
   557         return global.uint8ClampedArray;
   558     }
   560     /**
   561      * Setter for the Uint8ClampedArray property.
   562      * @param self self reference
   563      * @param value value of the Uint8ClampedArray property
   564      */
   565     @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
   566     public static void setUint8ClampedArray(final Object self, final Object value) {
   567         final Global global = Global.instanceFrom(self);
   568         global.uint8ClampedArray = value;
   569     }
   571     private volatile Object uint8ClampedArray;
   573     /**
   574      * Getter for the Int16Array property.
   575      * @param self self reference
   576      * @return the value of the Int16Array property
   577      */
   578     @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   579     public static Object getInt16Array(final Object self) {
   580         final Global global = Global.instanceFrom(self);
   581         if (global.int16Array == LAZY_SENTINEL) {
   582             global.int16Array = global.getBuiltinInt16Array();
   583         }
   584         return global.int16Array;
   585     }
   587     /**
   588      * Setter for the Int16Array property.
   589      * @param self self reference
   590      * @param value value of the Int16Array property
   591      */
   592     @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
   593     public static void setInt16Array(final Object self, final Object value) {
   594         final Global global = Global.instanceFrom(self);
   595         global.int16Array = value;
   596     }
   598     private volatile Object int16Array;
   600     /**
   601      * Getter for the Uint16Array property.
   602      * @param self self reference
   603      * @return the value of the Uint16Array property
   604      */
   605     @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   606     public static Object getUint16Array(final Object self) {
   607         final Global global = Global.instanceFrom(self);
   608         if (global.uint16Array == LAZY_SENTINEL) {
   609             global.uint16Array = global.getBuiltinUint16Array();
   610         }
   611         return global.uint16Array;
   612     }
   614     /**
   615      * Setter for the Uint16Array property.
   616      * @param self self reference
   617      * @param value value of the Uint16Array property
   618      */
   619     @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
   620     public static void setUint16Array(final Object self, final Object value) {
   621         final Global global = Global.instanceFrom(self);
   622         global.uint16Array = value;
   623     }
   625     private volatile Object uint16Array;
   627     /**
   628      * Getter for the Int32Array property.
   629      *
   630      * @param self self reference
   631      * @return the value of the Int32Array property
   632      */
   633     @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   634     public static Object getInt32Array(final Object self) {
   635         final Global global = Global.instanceFrom(self);
   636         if (global.int32Array == LAZY_SENTINEL) {
   637             global.int32Array = global.getBuiltinInt32Array();
   638         }
   639         return global.int32Array;
   640     }
   643     /**
   644      * Setter for the Int32Array property.
   645      *
   646      * @param self self reference
   647      * @param value value of the Int32Array property
   648      */
   649     @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
   650     public static void setInt32Array(final Object self, final Object value) {
   651         final Global global = Global.instanceFrom(self);
   652         global.int32Array = value;
   653     }
   655     private volatile Object int32Array;
   657     /**
   658      * Getter of the Uint32Array property.
   659      *
   660      * @param self self reference
   661      * @return the value of the Uint32Array property
   662      */
   663     @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   664     public static Object getUint32Array(final Object self) {
   665         final Global global = Global.instanceFrom(self);
   666         if (global.uint32Array == LAZY_SENTINEL) {
   667             global.uint32Array = global.getBuiltinUint32Array();
   668         }
   669         return global.uint32Array;
   670     }
   673     /**
   674      * Setter of the Uint32Array property.
   675      *
   676      * @param self self reference
   677      * @param value value of the Uint32Array property
   678      */
   679     @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
   680     public static void setUint32Array(final Object self, final Object value) {
   681         final Global global = Global.instanceFrom(self);
   682         global.uint32Array = value;
   683     }
   685     private volatile Object uint32Array;
   687     /**
   688      * Getter for the Float32Array property.
   689      *
   690      * @param self self reference
   691      * @return the value of the Float32Array property
   692      */
   693     @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   694     public static Object getFloat32Array(final Object self) {
   695         final Global global = Global.instanceFrom(self);
   696         if (global.float32Array == LAZY_SENTINEL) {
   697             global.float32Array = global.getBuiltinFloat32Array();
   698         }
   699         return global.float32Array;
   700     }
   702     /**
   703      * Setter for the Float32Array property.
   704      *
   705      * @param self self reference
   706      * @param value value of the Float32Array property
   707      */
   708     @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
   709     public static void setFloat32Array(final Object self, final Object value) {
   710         final Global global = Global.instanceFrom(self);
   711         global.float32Array = value;
   712     }
   714     private volatile Object float32Array;
   716     /**
   717      * Getter for the Float64Array property.
   718      *
   719      * @param self self reference
   720      * @return the value of the Float64Array property
   721      */
   722     @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   723     public static Object getFloat64Array(final Object self) {
   724         final Global global = Global.instanceFrom(self);
   725         if (global.float64Array == LAZY_SENTINEL) {
   726             global.float64Array = global.getBuiltinFloat64Array();
   727         }
   728         return global.float64Array;
   729     }
   731     /**
   732      * Setter for the Float64Array property.
   733      *
   734      * @param self self reference
   735      * @param value value of the Float64Array property
   736      */
   737     @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
   738     public static void setFloat64Array(final Object self, final Object value) {
   739         final Global global = Global.instanceFrom(self);
   740         global.float64Array = value;
   741     }
   743     private volatile Object float64Array;
   745     /** Nashorn extension: Java access - global.Packages */
   746     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
   747     public volatile Object packages;
   749     /** Nashorn extension: Java access - global.com */
   750     @Property(attributes = Attribute.NOT_ENUMERABLE)
   751     public volatile Object com;
   753     /** Nashorn extension: Java access - global.edu */
   754     @Property(attributes = Attribute.NOT_ENUMERABLE)
   755     public volatile Object edu;
   757     /** Nashorn extension: Java access - global.java */
   758     @Property(attributes = Attribute.NOT_ENUMERABLE)
   759     public volatile Object java;
   761     /** Nashorn extension: Java access - global.javafx */
   762     @Property(attributes = Attribute.NOT_ENUMERABLE)
   763     public volatile Object javafx;
   765     /** Nashorn extension: Java access - global.javax */
   766     @Property(attributes = Attribute.NOT_ENUMERABLE)
   767     public volatile Object javax;
   769     /** Nashorn extension: Java access - global.org */
   770     @Property(attributes = Attribute.NOT_ENUMERABLE)
   771     public volatile Object org;
   773     /**
   774      * Getter for the Nashorn extension: Java access - global.javaImporter.
   775      *
   776      * @param self self reference
   777      * @return the value of the JavaImporter property
   778      */
   779     @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   780     public static Object getJavaImporter(final Object self) {
   781         final Global global = Global.instanceFrom(self);
   782         if (global.javaImporter == LAZY_SENTINEL) {
   783             global.javaImporter = global.getBuiltinJavaImporter();
   784         }
   785         return global.javaImporter;
   786     }
   788     /**
   789      * Setter for the Nashorn extension: Java access - global.javaImporter.
   790      *
   791      * @param self self reference
   792      * @param value value of the JavaImporter property
   793      */
   794     @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
   795     public static void setJavaImporter(final Object self, final Object value) {
   796         final Global global = Global.instanceFrom(self);
   797         global.javaImporter = value;
   798     }
   800     private volatile Object javaImporter;
   802     /**
   803      * Getter for the Nashorn extension: global.Java property.
   804      *
   805      * @param self self reference
   806      * @return the value of the Java property
   807      */
   808     @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   809     public static Object getJavaApi(final Object self) {
   810         final Global global = Global.instanceFrom(self);
   811         if (global.javaApi == LAZY_SENTINEL) {
   812             global.javaApi = global.getBuiltinJavaApi();
   813         }
   814         return global.javaApi;
   815     }
   817     /**
   818      * Setter for the Nashorn extension: global.Java property.
   819      *
   820      * @param self self reference
   821      * @param value value of the Java property
   822      */
   823     @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
   824     public static void setJavaApi(final Object self, final Object value) {
   825         final Global global = Global.instanceFrom(self);
   826         global.javaApi = value;
   827     }
   829     private volatile Object javaApi;
   831     /** Nashorn extension: current script's file name */
   832     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   833     public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
   835     /** Nashorn extension: current script's directory */
   836     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   837     public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
   839     /** Nashorn extension: current source line number being executed */
   840     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
   841     public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
   843     private volatile NativeDate DEFAULT_DATE;
   845     /** Used as Date.prototype's default value */
   846     NativeDate getDefaultDate() {
   847         return DEFAULT_DATE;
   848     }
   850     private volatile NativeRegExp DEFAULT_REGEXP;
   852     /** Used as RegExp.prototype's default value */
   853     NativeRegExp getDefaultRegExp() {
   854         return DEFAULT_REGEXP;
   855     }
   857     /*
   858      * Built-in constructor objects: Even if user changes dynamic values of
   859      * "Object", "Array" etc., we still want to keep original values of these
   860      * constructors here. For example, we need to be able to create array,
   861      * regexp literals even after user overwrites global "Array" or "RegExp"
   862      * constructor - see also ECMA 262 spec. Annex D.
   863      */
   864     private ScriptFunction builtinFunction;
   865     private ScriptFunction builtinObject;
   866     private ScriptFunction builtinArray;
   867     private ScriptFunction builtinBoolean;
   868     private ScriptFunction builtinDate;
   869     private ScriptObject   builtinJSON;
   870     private ScriptFunction builtinJSAdapter;
   871     private ScriptObject   builtinMath;
   872     private ScriptFunction builtinNumber;
   873     private ScriptFunction builtinRegExp;
   874     private ScriptFunction builtinString;
   875     private ScriptFunction builtinError;
   876     private ScriptFunction builtinEval;
   877     private ScriptFunction builtinEvalError;
   878     private ScriptFunction builtinRangeError;
   879     private ScriptFunction builtinReferenceError;
   880     private ScriptFunction builtinSyntaxError;
   881     private ScriptFunction builtinTypeError;
   882     private ScriptFunction builtinURIError;
   883     private ScriptObject   builtinPackages;
   884     private ScriptObject   builtinCom;
   885     private ScriptObject   builtinEdu;
   886     private ScriptObject   builtinJava;
   887     private ScriptObject   builtinJavafx;
   888     private ScriptObject   builtinJavax;
   889     private ScriptObject   builtinOrg;
   890     private ScriptFunction builtinJavaImporter;
   891     private ScriptObject   builtinJavaApi;
   892     private ScriptFunction builtinArrayBuffer;
   893     private ScriptFunction builtinDataView;
   894     private ScriptFunction builtinInt8Array;
   895     private ScriptFunction builtinUint8Array;
   896     private ScriptFunction builtinUint8ClampedArray;
   897     private ScriptFunction builtinInt16Array;
   898     private ScriptFunction builtinUint16Array;
   899     private ScriptFunction builtinInt32Array;
   900     private ScriptFunction builtinUint32Array;
   901     private ScriptFunction builtinFloat32Array;
   902     private ScriptFunction builtinFloat64Array;
   904     /*
   905      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
   906      */
   907     private ScriptFunction typeErrorThrower;
   909     // Flag to indicate that a split method issued a return statement
   910     private int splitState = -1;
   912     // Used to store the last RegExp result to support deprecated RegExp constructor properties
   913     private RegExpResult lastRegExpResult;
   915     private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
   916     private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
   917     private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
   918     private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
   919     private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
   920     private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
   921     private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
   922     private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter",  Object.class, Object.class);
   924     // initialized by nasgen
   925     private static PropertyMap $nasgenmap$;
   927     // context to which this global belongs to
   928     private final Context context;
   930     // current ScriptContext to use - can be null.
   931     private ScriptContext scontext;
   932     // current ScriptEngine associated - can be null.
   933     private ScriptEngine engine;
   935     // ES6 global lexical scope.
   936     private final LexicalScope lexicalScope;
   938     // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
   939     private SwitchPoint lexicalScopeSwitchPoint;
   941     /**
   942      * Set the current script context
   943      * @param scontext script context
   944      */
   945     public void setScriptContext(final ScriptContext scontext) {
   946         this.scontext = scontext;
   947     }
   949     @Override
   950     protected Context getContext() {
   951         return context;
   952     }
   954     @Override
   955     protected boolean useDualFields() {
   956         return context.useDualFields();
   957     }
   959     // performs initialization checks for Global constructor and returns the
   960     // PropertyMap, if everything is fine.
   961     private static PropertyMap checkAndGetMap(final Context context) {
   962         // security check first
   963         final SecurityManager sm = System.getSecurityManager();
   964         if (sm != null) {
   965             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
   966         }
   968         Objects.requireNonNull(context);
   970         return $nasgenmap$;
   971     }
   973     /**
   974      * Constructor
   975      *
   976      * @param context the context
   977      */
   978     public Global(final Context context) {
   979         super(checkAndGetMap(context));
   980         this.context = context;
   981         this.setIsScope();
   982         this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
   983     }
   985     /**
   986      * Script access to "current" Global instance
   987      *
   988      * @return the global singleton
   989      */
   990     public static Global instance() {
   991         final Global global = Context.getGlobal();
   992         Objects.requireNonNull(global);
   993         return global;
   994     }
   996     private static Global instanceFrom(final Object self) {
   997         return self instanceof Global? (Global)self : instance();
   998     }
  1000     /**
  1001      * Check if we have a Global instance
  1002      * @return true if one exists
  1003      */
  1004     public static boolean hasInstance() {
  1005         return Context.getGlobal() != null;
  1008     /**
  1009      * Script access to {@link ScriptEnvironment}
  1011      * @return the script environment
  1012      */
  1013     static ScriptEnvironment getEnv() {
  1014         return instance().getContext().getEnv();
  1017     /**
  1018      * Script access to {@link Context}
  1020      * @return the context
  1021      */
  1022     static Context getThisContext() {
  1023         return instance().getContext();
  1026     // Runtime interface to Global
  1028     /**
  1029      * Is there a class filter in the current Context?
  1030      * @return class filter
  1031      */
  1032     public ClassFilter getClassFilter() {
  1033         return context.getClassFilter();
  1036     /**
  1037      * Is this global of the given Context?
  1038      * @param ctxt the context
  1039      * @return true if this global belongs to the given Context
  1040      */
  1041     public boolean isOfContext(final Context ctxt) {
  1042         return this.context == ctxt;
  1045     /**
  1046      * Does this global belong to a strict Context?
  1047      * @return true if this global belongs to a strict Context
  1048      */
  1049     public boolean isStrictContext() {
  1050         return context.getEnv()._strict;
  1053     /**
  1054      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
  1055      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
  1056      * of the global scope object.
  1058      * @param engine ScriptEngine to initialize
  1059      */
  1060     @SuppressWarnings("hiding")
  1061     public void initBuiltinObjects(final ScriptEngine engine) {
  1062         if (this.builtinObject != null) {
  1063             // already initialized, just return
  1064             return;
  1067         this.engine = engine;
  1068         init(engine);
  1071     /**
  1072      * Wrap a Java object as corresponding script object
  1074      * @param obj object to wrap
  1075      * @return    wrapped object
  1076      */
  1077     public Object wrapAsObject(final Object obj) {
  1078         if (obj instanceof Boolean) {
  1079             return new NativeBoolean((Boolean)obj, this);
  1080         } else if (obj instanceof Number) {
  1081             return new NativeNumber(((Number)obj).doubleValue(), this);
  1082         } else if (isString(obj)) {
  1083             return new NativeString((CharSequence)obj, this);
  1084         } else if (obj instanceof Object[]) { // extension
  1085             return new NativeArray(ArrayData.allocate((Object[])obj), this);
  1086         } else if (obj instanceof double[]) { // extension
  1087             return new NativeArray(ArrayData.allocate((double[])obj), this);
  1088         } else if (obj instanceof long[]) {
  1089             return new NativeArray(ArrayData.allocate((long[])obj), this);
  1090         } else if (obj instanceof int[]) {
  1091             return new NativeArray(ArrayData.allocate((int[]) obj), this);
  1092         } else if (obj instanceof ArrayData) {
  1093             return new NativeArray((ArrayData) obj, this);
  1094         } else {
  1095             // FIXME: more special cases? Map? List?
  1096             return obj;
  1100     /**
  1101      * Lookup helper for JS primitive types
  1103      * @param request the link request for the dynamic call site.
  1104      * @param self     self reference
  1106      * @return guarded invocation
  1107      */
  1108     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
  1109         if (isString(self)) {
  1110             return NativeString.lookupPrimitive(request, self);
  1111         } else if (self instanceof Number) {
  1112             return NativeNumber.lookupPrimitive(request, self);
  1113         } else if (self instanceof Boolean) {
  1114             return NativeBoolean.lookupPrimitive(request, self);
  1116         throw new IllegalArgumentException("Unsupported primitive: " + self);
  1119     /**
  1120      * Returns a method handle that creates a wrapper object for a JS primitive value.
  1122      * @param self receiver object
  1123      * @return method handle to create wrapper objects for primitive receiver
  1124      */
  1125     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
  1126         if (isString(self)) {
  1127             return NativeString.WRAPFILTER;
  1128         } else if (self instanceof Number) {
  1129             return NativeNumber.WRAPFILTER;
  1130         } else if (self instanceof Boolean) {
  1131             return NativeBoolean.WRAPFILTER;
  1133         throw new IllegalArgumentException("Unsupported primitive: " + self);
  1137     /**
  1138      * Create a new empty script object
  1140      * @return the new ScriptObject
  1141      */
  1142     public ScriptObject newObject() {
  1143         return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
  1146     /**
  1147      * Default value of given type
  1149      * @param sobj     script object
  1150      * @param typeHint type hint
  1152      * @return default value
  1153      */
  1154     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
  1155         // When the [[DefaultValue]] internal method of O is called with no hint,
  1156         // then it behaves as if the hint were Number, unless O is a Date object
  1157         // in which case it behaves as if the hint were String.
  1158         Class<?> hint = typeHint;
  1159         if (hint == null) {
  1160             hint = Number.class;
  1163         try {
  1164             if (hint == String.class) {
  1166                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
  1168                 if (Bootstrap.isCallable(toString)) {
  1169                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
  1170                     if (JSType.isPrimitive(value)) {
  1171                         return value;
  1175                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
  1176                 if (Bootstrap.isCallable(valueOf)) {
  1177                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
  1178                     if (JSType.isPrimitive(value)) {
  1179                         return value;
  1182                 throw typeError(this, "cannot.get.default.string");
  1185             if (hint == Number.class) {
  1186                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
  1187                 if (Bootstrap.isCallable(valueOf)) {
  1188                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
  1189                     if (JSType.isPrimitive(value)) {
  1190                         return value;
  1194                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
  1195                 if (Bootstrap.isCallable(toString)) {
  1196                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
  1197                     if (JSType.isPrimitive(value)) {
  1198                         return value;
  1202                 throw typeError(this, "cannot.get.default.number");
  1204         } catch (final RuntimeException | Error e) {
  1205             throw e;
  1206         } catch (final Throwable t) {
  1207             throw new RuntimeException(t);
  1210         return UNDEFINED;
  1213     /**
  1214      * Is the given ScriptObject an ECMAScript Error object?
  1216      * @param sobj the object being checked
  1217      * @return true if sobj is an Error object
  1218      */
  1219     public boolean isError(final ScriptObject sobj) {
  1220         final ScriptObject errorProto = getErrorPrototype();
  1221         ScriptObject proto = sobj.getProto();
  1222         while (proto != null) {
  1223             if (proto == errorProto) {
  1224                 return true;
  1226             proto = proto.getProto();
  1228         return false;
  1231     /**
  1232      * Create a new ECMAScript Error object.
  1234      * @param msg error message
  1235      * @return newly created Error object
  1236      */
  1237     public ScriptObject newError(final String msg) {
  1238         return new NativeError(msg, this);
  1241     /**
  1242      * Create a new ECMAScript EvalError object.
  1244      * @param msg error message
  1245      * @return newly created EvalError object
  1246      */
  1247     public ScriptObject newEvalError(final String msg) {
  1248         return new NativeEvalError(msg, this);
  1251     /**
  1252      * Create a new ECMAScript RangeError object.
  1254      * @param msg error message
  1255      * @return newly created RangeError object
  1256      */
  1257     public ScriptObject newRangeError(final String msg) {
  1258         return new NativeRangeError(msg, this);
  1261     /**
  1262      * Create a new ECMAScript ReferenceError object.
  1264      * @param msg error message
  1265      * @return newly created ReferenceError object
  1266      */
  1267     public ScriptObject newReferenceError(final String msg) {
  1268         return new NativeReferenceError(msg, this);
  1271     /**
  1272      * Create a new ECMAScript SyntaxError object.
  1274      * @param msg error message
  1275      * @return newly created SyntaxError object
  1276      */
  1277     public ScriptObject newSyntaxError(final String msg) {
  1278         return new NativeSyntaxError(msg, this);
  1281     /**
  1282      * Create a new ECMAScript TypeError object.
  1284      * @param msg error message
  1285      * @return newly created TypeError object
  1286      */
  1287     public ScriptObject newTypeError(final String msg) {
  1288         return new NativeTypeError(msg, this);
  1291     /**
  1292      * Create a new ECMAScript URIError object.
  1294      * @param msg error message
  1295      * @return newly created URIError object
  1296      */
  1297     public ScriptObject newURIError(final String msg) {
  1298         return new NativeURIError(msg, this);
  1301     /**
  1302      * Create a new ECMAScript GenericDescriptor object.
  1304      * @param configurable is the property configurable?
  1305      * @param enumerable is the property enumerable?
  1306      * @return newly created GenericDescriptor object
  1307      */
  1308     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
  1309         return new GenericPropertyDescriptor(configurable, enumerable, this);
  1312     /**
  1313      * Create a new ECMAScript DatePropertyDescriptor object.
  1315      * @param value of the data property
  1316      * @param configurable is the property configurable?
  1317      * @param enumerable is the property enumerable?
  1318      * @param writable is the property writable?
  1319      * @return newly created DataPropertyDescriptor object
  1320      */
  1321     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
  1322         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
  1325     /**
  1326      * Create a new ECMAScript AccessorPropertyDescriptor object.
  1328      * @param get getter function of the user accessor property
  1329      * @param set setter function of the user accessor property
  1330      * @param configurable is the property configurable?
  1331      * @param enumerable is the property enumerable?
  1332      * @return newly created AccessorPropertyDescriptor object
  1333      */
  1334     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
  1335         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
  1337         if (get == null) {
  1338             desc.delete(PropertyDescriptor.GET, false);
  1341         if (set == null) {
  1342             desc.delete(PropertyDescriptor.SET, false);
  1345         return desc;
  1348     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
  1349         final T obj = map.get(key);
  1350         if (obj != null) {
  1351             return obj;
  1354         try {
  1355             final T newObj = creator.call();
  1356             final T existingObj = map.putIfAbsent(key, newObj);
  1357             return existingObj != null ? existingObj : newObj;
  1358         } catch (final Exception exp) {
  1359             throw new RuntimeException(exp);
  1363     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
  1366     /**
  1367      * Get cached InvokeByName object for the given key
  1368      * @param key key to be associated with InvokeByName object
  1369      * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
  1370      * @return InvokeByName object associated with the key.
  1371      */
  1372     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
  1373         return getLazilyCreatedValue(key, creator, namedInvokers);
  1376     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
  1378     /**
  1379      * Get cached dynamic method handle for the given key
  1380      * @param key key to be associated with dynamic method handle
  1381      * @param creator if method handle is absent 'creator' is called to make one (lazy init)
  1382      * @return dynamic method handle associated with the key.
  1383      */
  1384     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
  1385         return getLazilyCreatedValue(key, creator, dynamicInvokers);
  1388     /**
  1389      * Hook to search missing variables in ScriptContext if available
  1390      * @param self used to detect if scope call or not (this function is 'strict')
  1391      * @param name name of the variable missing
  1392      * @return value of the missing variable or undefined (or TypeError for scope search)
  1393      */
  1394     public static Object __noSuchProperty__(final Object self, final Object name) {
  1395         final Global global = Global.instance();
  1396         final ScriptContext sctxt = global.scontext;
  1397         final String nameStr = name.toString();
  1399         if (sctxt != null) {
  1400             final int scope = sctxt.getAttributesScope(nameStr);
  1401             if (scope != -1) {
  1402                 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
  1406         switch (nameStr) {
  1407         case "context":
  1408             return sctxt;
  1409         case "engine":
  1410             return global.engine;
  1411         default:
  1412             break;
  1415         if (self == UNDEFINED) {
  1416             // scope access and so throw ReferenceError
  1417             throw referenceError(global, "not.defined", nameStr);
  1420         return UNDEFINED;
  1423     /**
  1424      * This is the eval used when 'indirect' eval call is made.
  1426      * var global = this;
  1427      * global.eval("print('hello')");
  1429      * @param self  eval scope
  1430      * @param str   eval string
  1432      * @return the result of eval
  1433      */
  1434     public static Object eval(final Object self, final Object str) {
  1435         return directEval(self, str, UNDEFINED, UNDEFINED, false);
  1438     /**
  1439      * Direct eval
  1441      * @param self     The scope of eval passed as 'self'
  1442      * @param str      Evaluated code
  1443      * @param callThis "this" to be passed to the evaluated code
  1444      * @param location location of the eval call
  1445      * @param strict   is eval called a strict mode code?
  1447      * @return the return value of the eval
  1449      * This is directly invoked from generated when eval(code) is called in user code
  1450      */
  1451     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
  1452         if (!isString(str)) {
  1453             return str;
  1455         final Global global = Global.instanceFrom(self);
  1456         final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
  1458         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
  1461     /**
  1462      * Global print implementation - Nashorn extension
  1464      * @param self    scope
  1465      * @param objects arguments to print
  1467      * @return result of print (undefined)
  1468      */
  1469     public static Object print(final Object self, final Object... objects) {
  1470         return Global.instanceFrom(self).printImpl(false, objects);
  1473     /**
  1474      * Global println implementation - Nashorn extension
  1476      * @param self    scope
  1477      * @param objects arguments to print
  1479      * @return result of println (undefined)
  1480      */
  1481     public static Object println(final Object self, final Object... objects) {
  1482         return Global.instanceFrom(self).printImpl(true, objects);
  1485     /**
  1486      * Global load implementation - Nashorn extension
  1488      * @param self    scope
  1489      * @param source  source to load
  1491      * @return result of load (undefined)
  1493      * @throws IOException if source could not be read
  1494      */
  1495     public static Object load(final Object self, final Object source) throws IOException {
  1496         final Global global = Global.instanceFrom(self);
  1497         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
  1498         return global.getContext().load(scope, source);
  1501     /**
  1502      * Global loadWithNewGlobal implementation - Nashorn extension
  1504      * @param self scope
  1505      * @param args from plus (optional) arguments to be passed to the loaded script
  1507      * @return result of load (may be undefined)
  1509      * @throws IOException if source could not be read
  1510      */
  1511     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
  1512         final Global global = Global.instanceFrom(self);
  1513         final int length = args.length;
  1514         final boolean hasArgs = 0 < length;
  1515         final Object from = hasArgs ? args[0] : UNDEFINED;
  1516         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
  1518         return global.getContext().loadWithNewGlobal(from, arguments);
  1521     /**
  1522      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
  1524      * @param self  self reference
  1525      * @param code  exit code
  1527      * @return undefined (will never be reached)
  1528      */
  1529     public static Object exit(final Object self, final Object code) {
  1530         System.exit(JSType.toInt32(code));
  1531         return UNDEFINED;
  1534     // builtin prototype accessors
  1536     /**
  1537      * Get the builtin Object prototype.
  1538      * @return the object prototype.
  1539      */
  1540     public ScriptObject getObjectPrototype() {
  1541         return ScriptFunction.getPrototype(builtinObject);
  1544     ScriptObject getFunctionPrototype() {
  1545         return ScriptFunction.getPrototype(builtinFunction);
  1548     ScriptObject getArrayPrototype() {
  1549         return ScriptFunction.getPrototype(builtinArray);
  1552     ScriptObject getBooleanPrototype() {
  1553         return ScriptFunction.getPrototype(builtinBoolean);
  1556     ScriptObject getNumberPrototype() {
  1557         return ScriptFunction.getPrototype(builtinNumber);
  1560     ScriptObject getDatePrototype() {
  1561         return ScriptFunction.getPrototype(getBuiltinDate());
  1564     ScriptObject getRegExpPrototype() {
  1565         return ScriptFunction.getPrototype(getBuiltinRegExp());
  1568     ScriptObject getStringPrototype() {
  1569         return ScriptFunction.getPrototype(builtinString);
  1572     ScriptObject getErrorPrototype() {
  1573         return ScriptFunction.getPrototype(builtinError);
  1576     ScriptObject getEvalErrorPrototype() {
  1577         return ScriptFunction.getPrototype(getBuiltinEvalError());
  1580     ScriptObject getRangeErrorPrototype() {
  1581         return ScriptFunction.getPrototype(getBuiltinRangeError());
  1584     ScriptObject getReferenceErrorPrototype() {
  1585         return ScriptFunction.getPrototype(builtinReferenceError);
  1588     ScriptObject getSyntaxErrorPrototype() {
  1589         return ScriptFunction.getPrototype(builtinSyntaxError);
  1592     ScriptObject getTypeErrorPrototype() {
  1593         return ScriptFunction.getPrototype(builtinTypeError);
  1596     ScriptObject getURIErrorPrototype() {
  1597         return ScriptFunction.getPrototype(getBuiltinURIError());
  1600     ScriptObject getJavaImporterPrototype() {
  1601         return ScriptFunction.getPrototype(getBuiltinJavaImporter());
  1604     ScriptObject getJSAdapterPrototype() {
  1605         return ScriptFunction.getPrototype(getBuiltinJSAdapter());
  1608     private synchronized ScriptFunction getBuiltinArrayBuffer() {
  1609         if (this.builtinArrayBuffer == null) {
  1610             this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
  1612         return this.builtinArrayBuffer;
  1615     ScriptObject getArrayBufferPrototype() {
  1616         return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
  1619     private synchronized ScriptFunction getBuiltinDataView() {
  1620         if (this.builtinDataView == null) {
  1621             this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
  1623         return this.builtinDataView;
  1626     ScriptObject getDataViewPrototype() {
  1627         return ScriptFunction.getPrototype(getBuiltinDataView());
  1630     private synchronized ScriptFunction getBuiltinInt8Array() {
  1631         if (this.builtinInt8Array == null) {
  1632             this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
  1634         return this.builtinInt8Array;
  1637     ScriptObject getInt8ArrayPrototype() {
  1638         return ScriptFunction.getPrototype(getBuiltinInt8Array());
  1641     private synchronized ScriptFunction getBuiltinUint8Array() {
  1642         if (this.builtinUint8Array == null) {
  1643             this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
  1645         return this.builtinUint8Array;
  1648     ScriptObject getUint8ArrayPrototype() {
  1649         return ScriptFunction.getPrototype(getBuiltinUint8Array());
  1652     private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
  1653         if (this.builtinUint8ClampedArray == null) {
  1654             this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
  1656         return this.builtinUint8ClampedArray;
  1659     ScriptObject getUint8ClampedArrayPrototype() {
  1660         return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
  1663     private synchronized ScriptFunction getBuiltinInt16Array() {
  1664         if (this.builtinInt16Array == null) {
  1665             this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
  1667         return this.builtinInt16Array;
  1670     ScriptObject getInt16ArrayPrototype() {
  1671         return ScriptFunction.getPrototype(getBuiltinInt16Array());
  1674     private synchronized ScriptFunction getBuiltinUint16Array() {
  1675         if (this.builtinUint16Array == null) {
  1676             this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
  1678         return this.builtinUint16Array;
  1681     ScriptObject getUint16ArrayPrototype() {
  1682         return ScriptFunction.getPrototype(getBuiltinUint16Array());
  1685     private synchronized ScriptFunction getBuiltinInt32Array() {
  1686         if (this.builtinInt32Array == null) {
  1687             this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
  1689         return this.builtinInt32Array;
  1692     ScriptObject getInt32ArrayPrototype() {
  1693         return ScriptFunction.getPrototype(getBuiltinInt32Array());
  1696     private synchronized ScriptFunction getBuiltinUint32Array() {
  1697         if (this.builtinUint32Array == null) {
  1698             this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
  1700         return this.builtinUint32Array;
  1703     ScriptObject getUint32ArrayPrototype() {
  1704         return ScriptFunction.getPrototype(getBuiltinUint32Array());
  1707     private synchronized ScriptFunction getBuiltinFloat32Array() {
  1708         if (this.builtinFloat32Array == null) {
  1709             this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
  1711         return this.builtinFloat32Array;
  1714     ScriptObject getFloat32ArrayPrototype() {
  1715         return ScriptFunction.getPrototype(getBuiltinFloat32Array());
  1718     private synchronized ScriptFunction getBuiltinFloat64Array() {
  1719         if (this.builtinFloat64Array == null) {
  1720             this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
  1722         return this.builtinFloat64Array;
  1725     ScriptObject getFloat64ArrayPrototype() {
  1726         return ScriptFunction.getPrototype(getBuiltinFloat64Array());
  1729     private ScriptFunction getBuiltinArray() {
  1730         return builtinArray;
  1733     ScriptFunction getTypeErrorThrower() {
  1734         return typeErrorThrower;
  1737     /**
  1738      * Called from compiled script code to test if builtin has been overridden
  1740      * @return true if builtin array has not been overridden
  1741      */
  1742     public static boolean isBuiltinArray() {
  1743         final Global instance = Global.instance();
  1744         return instance.array == instance.getBuiltinArray();
  1747     private ScriptFunction getBuiltinBoolean() {
  1748         return builtinBoolean;
  1751     /**
  1752      * Called from compiled script code to test if builtin has been overridden
  1754      * @return true if builtin boolean has not been overridden
  1755      */
  1756     public static boolean isBuiltinBoolean() {
  1757         final Global instance = Global.instance();
  1758         return instance._boolean == instance.getBuiltinBoolean();
  1761     private synchronized ScriptFunction getBuiltinDate() {
  1762         if (this.builtinDate == null) {
  1763             this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
  1764             final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
  1765             // initialize default date
  1766             this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
  1768         return this.builtinDate;
  1771     /**
  1772      * Called from compiled script code to test if builtin has been overridden
  1774      * @return true if builtin date has not been overridden
  1775      */
  1776     public static boolean isBuiltinDate() {
  1777         final Global instance = Global.instance();
  1778         return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
  1781     private ScriptFunction getBuiltinError() {
  1782         return builtinError;
  1785     /**
  1786      * Called from compiled script code to test if builtin has been overridden
  1788      * @return true if builtin error has not been overridden
  1789      */
  1790     public static boolean isBuiltinError() {
  1791         final Global instance = Global.instance();
  1792         return instance.error == instance.getBuiltinError();
  1795     private synchronized ScriptFunction getBuiltinEvalError() {
  1796         if (this.builtinEvalError == null) {
  1797             this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
  1799         return this.builtinEvalError;
  1802     /**
  1803      * Called from compiled script code to test if builtin has been overridden
  1805      * @return true if builtin eval error has not been overridden
  1806      */
  1807     public static boolean isBuiltinEvalError() {
  1808         final Global instance = Global.instance();
  1809         return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
  1812     private ScriptFunction getBuiltinFunction() {
  1813         return builtinFunction;
  1816     /**
  1817      * Called from compiled script code to test if builtin has been overridden
  1819      * @return true if builtin function has not been overridden
  1820      */
  1821     public static boolean isBuiltinFunction() {
  1822         final Global instance = Global.instance();
  1823         return instance.function == instance.getBuiltinFunction();
  1826     /**
  1827      * Get the switchpoint used to check property changes for Function.prototype.apply
  1828      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
  1829      */
  1830     public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
  1831         return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
  1834     private static boolean isBuiltinFunctionProperty(final String name) {
  1835         final Global instance = Global.instance();
  1836         final ScriptFunction builtinFunction = instance.getBuiltinFunction();
  1837         if (builtinFunction == null) {
  1838             return false; //conservative for compile-only mode
  1840         final boolean isBuiltinFunction = instance.function == builtinFunction;
  1841         return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
  1844     /**
  1845      * Check if the Function.prototype.apply has not been replaced
  1846      * @return true if Function.prototype.apply has been replaced
  1847      */
  1848     public static boolean isBuiltinFunctionPrototypeApply() {
  1849         return isBuiltinFunctionProperty("apply");
  1852     /**
  1853      * Check if the Function.prototype.apply has not been replaced
  1854      * @return true if Function.prototype.call has been replaced
  1855      */
  1856     public static boolean isBuiltinFunctionPrototypeCall() {
  1857         return isBuiltinFunctionProperty("call");
  1860     private synchronized ScriptFunction getBuiltinJSAdapter() {
  1861         if (this.builtinJSAdapter == null) {
  1862             this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
  1864         return builtinJSAdapter;
  1867     /**
  1868      * Called from compiled script code to test if builtin has been overridden
  1870      * @return true if builtin JSAdapter has not been overridden
  1871      */
  1872     public static boolean isBuiltinJSAdapter() {
  1873         final Global instance = Global.instance();
  1874         return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
  1877     private synchronized ScriptObject getBuiltinJSON() {
  1878         if (this.builtinJSON == null) {
  1879             this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
  1881         return this.builtinJSON;
  1884     /**
  1885      * Called from compiled script code to test if builtin has been overridden
  1887      * @return true if builtin JSON has has not been overridden
  1888      */
  1889     public static boolean isBuiltinJSON() {
  1890         final Global instance = Global.instance();
  1891         return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
  1894     private ScriptObject getBuiltinJava() {
  1895         return builtinJava;
  1898     /**
  1899      * Called from compiled script code to test if builtin has been overridden
  1901      * @return true if builtin Java has not been overridden
  1902      */
  1903     public static boolean isBuiltinJava() {
  1904         final Global instance = Global.instance();
  1905         return instance.java == instance.getBuiltinJava();
  1908     private ScriptObject getBuiltinJavax() {
  1909         return builtinJavax;
  1912     /**
  1913      * Called from compiled script code to test if builtin has been overridden
  1915      * @return true if builtin Javax has not been overridden
  1916      */
  1917     public static boolean isBuiltinJavax() {
  1918         final Global instance = Global.instance();
  1919         return instance.javax == instance.getBuiltinJavax();
  1922     private synchronized ScriptFunction getBuiltinJavaImporter() {
  1923         if (this.builtinJavaImporter == null) {
  1924             this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
  1926         return this.builtinJavaImporter;
  1929     private synchronized ScriptObject getBuiltinJavaApi() {
  1930         if (this.builtinJavaApi == null) {
  1931             this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
  1933         return this.builtinJavaApi;
  1936     /**
  1937      * Called from compiled script code to test if builtin has been overridden
  1939      * @return true if builtin Java importer has not been overridden
  1940      */
  1941     public static boolean isBuiltinJavaImporter() {
  1942         final Global instance = Global.instance();
  1943         return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
  1946     /**
  1947      * Called from compiled script code to test if builtin has been overridden
  1949      * @return true if builtin math has not been overridden
  1950      */
  1951     public static boolean isBuiltinMath() {
  1952         final Global instance = Global.instance();
  1953         return instance.math == instance.builtinMath;
  1956     private ScriptFunction getBuiltinNumber() {
  1957         return builtinNumber;
  1960     /**
  1961      * Called from compiled script code to test if builtin has been overridden
  1963      * @return true if builtin number has not been overridden
  1964      */
  1965     public static boolean isBuiltinNumber() {
  1966         final Global instance = Global.instance();
  1967         return instance.number == instance.getBuiltinNumber();
  1970     private ScriptFunction getBuiltinObject() {
  1971         return builtinObject;
  1974     /**
  1975      * Called from compiled script code to test if builtin has been overridden
  1977      * @return true if builtin object has not been overridden
  1978      */
  1979     public static boolean isBuiltinObject() {
  1980         final Global instance = Global.instance();
  1981         return instance.object == instance.getBuiltinObject();
  1984     private ScriptObject getBuiltinPackages() {
  1985         return builtinPackages;
  1988     /**
  1989      * Called from compiled script code to test if builtin has been overridden
  1991      * @return true if builtin package has not been overridden
  1992      */
  1993     public static boolean isBuiltinPackages() {
  1994         final Global instance = Global.instance();
  1995         return instance.packages == instance.getBuiltinPackages();
  1998     private synchronized ScriptFunction getBuiltinRangeError() {
  1999         if (this.builtinRangeError == null) {
  2000             this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
  2002         return builtinRangeError;
  2005     /**
  2006      * Called from compiled script code to test if builtin has been overridden
  2008      * @return true if builtin range error has not been overridden
  2009      */
  2010     public static boolean isBuiltinRangeError() {
  2011         final Global instance = Global.instance();
  2012         return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
  2015     private synchronized ScriptFunction getBuiltinReferenceError() {
  2016         return builtinReferenceError;
  2019     /**
  2020      * Called from compiled script code to test if builtin has been overridden
  2022      * @return true if builtin reference error has not been overridden
  2023      */
  2024     public static boolean isBuiltinReferenceError() {
  2025         final Global instance = Global.instance();
  2026         return instance.referenceError == instance.getBuiltinReferenceError();
  2029     private synchronized ScriptFunction getBuiltinRegExp() {
  2030         if (this.builtinRegExp == null) {
  2031             this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
  2032             final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
  2033             // initialize default regexp object
  2034             this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
  2035             // RegExp.prototype should behave like a RegExp object. So copy the
  2036             // properties.
  2037             regExpProto.addBoundProperties(DEFAULT_REGEXP);
  2039         return builtinRegExp;
  2042     /**
  2043      * Called from compiled script code to test if builtin has been overridden
  2045      * @return true if builtin regexp has not been overridden
  2046      */
  2047     public static boolean isBuiltinRegExp() {
  2048         final Global instance = Global.instance();
  2049         return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
  2052     private ScriptFunction getBuiltinString() {
  2053         return builtinString;
  2056     /**
  2057      * Called from compiled script code to test if builtin has been overridden
  2059      * @return true if builtin Java has not been overridden
  2060      */
  2061     public static boolean isBuiltinString() {
  2062         final Global instance = Global.instance();
  2063         return instance.string == instance.getBuiltinString();
  2066     private ScriptFunction getBuiltinSyntaxError() {
  2067         return builtinSyntaxError;
  2070     /**
  2071      * Called from compiled script code to test if builtin has been overridden
  2073      * @return true if builtin syntax error has not been overridden
  2074      */
  2075     public static boolean isBuiltinSyntaxError() {
  2076         final Global instance = Global.instance();
  2077         return instance.syntaxError == instance.getBuiltinSyntaxError();
  2080     private ScriptFunction getBuiltinTypeError() {
  2081         return builtinTypeError;
  2084     /**
  2085      * Called from compiled script code to test if builtin has been overridden
  2087      * @return true if builtin type error has not been overridden
  2088      */
  2089     public static boolean isBuiltinTypeError() {
  2090         final Global instance = Global.instance();
  2091         return instance.typeError == instance.getBuiltinTypeError();
  2094     private synchronized ScriptFunction getBuiltinURIError() {
  2095         if (this.builtinURIError == null) {
  2096             this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
  2098         return this.builtinURIError;
  2101     /**
  2102      * Called from compiled script code to test if builtin has been overridden
  2104      * @return true if builtin URI error has not been overridden
  2105      */
  2106     public static boolean isBuiltinURIError() {
  2107         final Global instance = Global.instance();
  2108         return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
  2111     @Override
  2112     public String getClassName() {
  2113         return "global";
  2116     /**
  2117      * Copy function used to clone NativeRegExp objects.
  2119      * @param regexp a NativeRegExp to clone
  2121      * @return copy of the given regexp object
  2122      */
  2123     public static Object regExpCopy(final Object regexp) {
  2124         return new NativeRegExp((NativeRegExp)regexp);
  2127     /**
  2128      * Convert given object to NativeRegExp type.
  2130      * @param obj object to be converted
  2131      * @return NativeRegExp instance
  2132      */
  2133     public static NativeRegExp toRegExp(final Object obj) {
  2134         if (obj instanceof NativeRegExp) {
  2135             return (NativeRegExp)obj;
  2137         return new NativeRegExp(JSType.toString(obj));
  2140     /**
  2141      * ECMA 9.9 ToObject implementation
  2143      * @param obj  an item for which to run ToObject
  2144      * @return ToObject version of given item
  2145      */
  2146     public static Object toObject(final Object obj) {
  2147         if (obj == null || obj == UNDEFINED) {
  2148             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  2151         if (obj instanceof ScriptObject) {
  2152             return obj;
  2155         return instance().wrapAsObject(obj);
  2158     /**
  2159      * Allocate a new object array.
  2161      * @param initial object values.
  2162      * @return the new array
  2163      */
  2164     public static NativeArray allocate(final Object[] initial) {
  2165         ArrayData arrayData = ArrayData.allocate(initial);
  2167         for (int index = 0; index < initial.length; index++) {
  2168             final Object value = initial[index];
  2170             if (value == ScriptRuntime.EMPTY) {
  2171                 arrayData = arrayData.delete(index);
  2175         return new NativeArray(arrayData);
  2178     /**
  2179      * Allocate a new number array.
  2181      * @param initial number values.
  2182      * @return the new array
  2183      */
  2184     public static NativeArray allocate(final double[] initial) {
  2185         return new NativeArray(ArrayData.allocate(initial));
  2188     /**
  2189      * Allocate a new long array.
  2191      * @param initial number values.
  2192      * @return the new array
  2193      */
  2194     public static NativeArray allocate(final long[] initial) {
  2195         return new NativeArray(ArrayData.allocate(initial));
  2198     /**
  2199      * Allocate a new integer array.
  2201      * @param initial number values.
  2202      * @return the new array
  2203      */
  2204     public static NativeArray allocate(final int[] initial) {
  2205         return new NativeArray(ArrayData.allocate(initial));
  2208     /**
  2209      * Allocate a new object array for arguments.
  2211      * @param arguments initial arguments passed.
  2212      * @param callee reference to the function that uses arguments object
  2213      * @param numParams actual number of declared parameters
  2215      * @return the new array
  2216      */
  2217     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
  2218         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
  2221     /**
  2222      * Called from generated to check if given function is the builtin 'eval'. If
  2223      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
  2225      * @param  fn function object that is checked
  2226      * @return true if fn is the builtin eval
  2227      */
  2228     public static boolean isEval(final Object fn) {
  2229         return fn == Global.instance().builtinEval;
  2232     /**
  2233      * Called from generated to replace a location property placeholder with the actual location property value.
  2235      * @param  placeholder the value tested for being a placeholder for a location property
  2236      * @param  locationProperty the actual value for the location property
  2237      * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
  2238      */
  2239     public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
  2240         return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
  2243     /**
  2244      * Called from runtime internals to check if the passed value is a location property placeholder.
  2245      * @param  placeholder the value tested for being a placeholder for a location property
  2246      * @return true if the value is a placeholder, false otherwise.
  2247      */
  2248     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
  2249         return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
  2252     /**
  2253      * Create a new RegExp object.
  2255      * @param expression Regular expression.
  2256      * @param options    Search options.
  2258      * @return New RegExp object.
  2259      */
  2260     public static Object newRegExp(final String expression, final String options) {
  2261         if (options == null) {
  2262             return new NativeRegExp(expression);
  2264         return new NativeRegExp(expression, options);
  2267     /**
  2268      * Get the object prototype
  2270      * @return the object prototype
  2271      */
  2272     public static ScriptObject objectPrototype() {
  2273         return Global.instance().getObjectPrototype();
  2276     /**
  2277      * Create a new empty object instance.
  2279      * @return New empty object.
  2280      */
  2281     public static ScriptObject newEmptyInstance() {
  2282         return Global.instance().newObject();
  2285     /**
  2286      * Check if a given object is a ScriptObject, raises an exception if this is
  2287      * not the case
  2289      * @param obj and object to check
  2290      * @return the script object
  2291      */
  2292     public static ScriptObject checkObject(final Object obj) {
  2293         if (!(obj instanceof ScriptObject)) {
  2294             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  2296         return (ScriptObject)obj;
  2299     /**
  2300      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
  2301      * if this object is null or undefined.
  2303      * @param obj an object to check
  2304      */
  2305     public static void checkObjectCoercible(final Object obj) {
  2306         if (obj == null || obj == UNDEFINED) {
  2307             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
  2311     /**
  2312      * Get the current split state.
  2314      * @return current split state
  2315      */
  2316     @Override
  2317     public int getSplitState() {
  2318         return splitState;
  2321     /**
  2322      * Set the current split state.
  2324      * @param state current split state
  2325      */
  2326     @Override
  2327     public void setSplitState(final int state) {
  2328         splitState = state;
  2331     /**
  2332      * Return the ES6 global scope for lexically declared bindings.
  2333      * @return the ES6 lexical global scope.
  2334      */
  2335     public final ScriptObject getLexicalScope() {
  2336         assert context.getEnv()._es6;
  2337         return lexicalScope;
  2340     @Override
  2341     public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
  2342         PropertyMap ownMap = getMap();
  2343         LexicalScope lexScope = null;
  2344         PropertyMap lexicalMap = null;
  2345         boolean hasLexicalDefinitions = false;
  2347         if (context.getEnv()._es6) {
  2348             lexScope = (LexicalScope) getLexicalScope();
  2349             lexicalMap = lexScope.getMap();
  2351             for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2352                 if (property.isLexicalBinding()) {
  2353                     hasLexicalDefinitions = true;
  2355                 // ES6 15.1.8 steps 6. and 7.
  2356                 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
  2357                 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
  2358                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
  2360                 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
  2361                 if (lexicalProperty != null && !property.isConfigurable()) {
  2362                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
  2367         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2368             if (property.isLexicalBinding()) {
  2369                 assert lexScope != null;
  2370                 lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property);
  2372                 if (ownMap.findProperty(property.getKey()) != null) {
  2373                     // If property exists in the global object invalidate any global constant call sites.
  2374                     invalidateGlobalConstant(property.getKey());
  2376             } else {
  2377                 ownMap = addBoundProperty(ownMap, source, property);
  2381         setMap(ownMap);
  2383         if (hasLexicalDefinitions) {
  2384             assert lexScope != null;
  2385             lexScope.setMap(lexicalMap);
  2386             invalidateLexicalSwitchPoint();
  2390     @Override
  2391     public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
  2392         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
  2393         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
  2395         if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
  2396             if (lexicalScope.hasOwnProperty(name)) {
  2397                 return lexicalScope.findGetMethod(desc, request, operator);
  2401         final GuardedInvocation invocation =  super.findGetMethod(desc, request, operator);
  2403         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
  2404         // because those are invalidated per-key in the addBoundProperties method above.
  2405         // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
  2406         // assuming this only applies to global constants. If other non-inherited properties will
  2407         // start using switchpoints some time in the future we'll have to revisit this.
  2408         if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
  2409             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
  2412         return invocation;
  2415     @Override
  2416     protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
  2417         if (lexicalScope != null && start != this && start.isScope()) {
  2418             final FindProperty find = lexicalScope.findProperty(key, false);
  2419             if (find != null) {
  2420                 return find;
  2423         return super.findProperty(key, deep, start);
  2426     @Override
  2427     public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
  2428         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
  2430         if (lexicalScope != null && isScope) {
  2431             final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
  2432             if (lexicalScope.hasOwnProperty(name)) {
  2433                 return lexicalScope.findSetMethod(desc, request);
  2437         final GuardedInvocation invocation = super.findSetMethod(desc, request);
  2439         if (isScope && context.getEnv()._es6) {
  2440             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
  2443         return invocation;
  2446     /**
  2447      * Adds jjs shell interactive mode builtin functions to global scope.
  2448      */
  2449     public void addShellBuiltins() {
  2450         Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
  2451         addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
  2453         value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
  2454         addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
  2457     private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
  2458         SwitchPoint switchPoint = lexicalScopeSwitchPoint;
  2459         if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
  2460             switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
  2462         return switchPoint;
  2465     private synchronized void invalidateLexicalSwitchPoint() {
  2466         if (lexicalScopeSwitchPoint != null) {
  2467             context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
  2468             SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
  2473     @SuppressWarnings("unused")
  2474     private static Object lexicalScopeFilter(final Object self) {
  2475         if (self instanceof Global) {
  2476             return ((Global) self).getLexicalScope();
  2478         return self;
  2481     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
  2482         final T func = initConstructor(name, clazz);
  2483         tagBuiltinProperties(name, func);
  2484         return func;
  2487     @SuppressWarnings("hiding")
  2488     private void init(final ScriptEngine engine) {
  2489         assert Context.getGlobal() == this : "this global is not set as current";
  2491         final ScriptEnvironment env = getContext().getEnv();
  2493         // initialize Function and Object constructor
  2494         initFunctionAndObject();
  2496         // Now fix Global's own proto.
  2497         this.setInitialProto(getObjectPrototype());
  2499         // initialize global function properties
  2500         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
  2502         this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
  2503                     new Specialization[] {
  2504                     new Specialization(GlobalFunctions.PARSEINT_Z),
  2505                     new Specialization(GlobalFunctions.PARSEINT_I),
  2506                     new Specialization(GlobalFunctions.PARSEINT_J),
  2507                     new Specialization(GlobalFunctions.PARSEINT_OI),
  2508                     new Specialization(GlobalFunctions.PARSEINT_O) });
  2509         this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  2510         this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
  2511                    new Specialization[] {
  2512                         new Specialization(GlobalFunctions.IS_NAN_I),
  2513                         new Specialization(GlobalFunctions.IS_NAN_J),
  2514                         new Specialization(GlobalFunctions.IS_NAN_D) });
  2515         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
  2516         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
  2517         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
  2518         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
  2519         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
  2520         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
  2521         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
  2522         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
  2523         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
  2524         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
  2525         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
  2526         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
  2527         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
  2528         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
  2530         // built-in constructors
  2531         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
  2532         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
  2533         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
  2534         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
  2535         this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
  2537         // initialize String.prototype.length to 0
  2538         // add String.prototype.length
  2539         final ScriptObject stringPrototype = getStringPrototype();
  2540         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
  2542         // set isArray flag on Array.prototype
  2543         final ScriptObject arrayPrototype = getArrayPrototype();
  2544         arrayPrototype.setIsArray();
  2546         // Error stuff
  2547         initErrorObjects();
  2549         // java access
  2550         if (! env._no_java) {
  2551             this.javaApi = LAZY_SENTINEL;
  2552             this.javaImporter = LAZY_SENTINEL;
  2553             initJavaAccess();
  2556         if (! env._no_typed_arrays) {
  2557             this.arrayBuffer       = LAZY_SENTINEL;
  2558             this.dataView          = LAZY_SENTINEL;
  2559             this.int8Array         = LAZY_SENTINEL;
  2560             this.uint8Array        = LAZY_SENTINEL;
  2561             this.uint8ClampedArray = LAZY_SENTINEL;
  2562             this.int16Array        = LAZY_SENTINEL;
  2563             this.uint16Array       = LAZY_SENTINEL;
  2564             this.int32Array        = LAZY_SENTINEL;
  2565             this.uint32Array       = LAZY_SENTINEL;
  2566             this.float32Array      = LAZY_SENTINEL;
  2567             this.float64Array      = LAZY_SENTINEL;
  2570         if (env._scripting) {
  2571             initScripting(env);
  2574         if (Context.DEBUG) {
  2575             boolean debugOkay;
  2576             final SecurityManager sm = System.getSecurityManager();
  2577             if (sm != null) {
  2578                 try {
  2579                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
  2580                     debugOkay = true;
  2581                 } catch (final SecurityException ignored) {
  2582                     // if no permission, don't initialize Debug object
  2583                     debugOkay = false;
  2586             } else {
  2587                 debugOkay = true;
  2590             if (debugOkay) {
  2591                 initDebug();
  2595         copyBuiltins();
  2597         // expose script (command line) arguments as "arguments" property of global
  2598         arguments = wrapAsObject(env.getArguments().toArray());
  2599         if (env._scripting) {
  2600             // synonym for "arguments" in scripting mode
  2601             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
  2604         if (engine != null) {
  2605             // default file name
  2606             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
  2607             // __noSuchProperty__ hook for ScriptContext search of missing variables
  2608             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
  2609             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
  2613     private void initErrorObjects() {
  2614         // Error objects
  2615         this.builtinError = initConstructor("Error", ScriptFunction.class);
  2616         final ScriptObject errorProto = getErrorPrototype();
  2618         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
  2619         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
  2620         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
  2621         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
  2622         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
  2623         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
  2624         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
  2625         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
  2626         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
  2627         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
  2628         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
  2629         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
  2630         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
  2632         // ECMA 15.11.4.2 Error.prototype.name
  2633         // Error.prototype.name = "Error";
  2634         errorProto.set(NativeError.NAME, "Error", 0);
  2635         // ECMA 15.11.4.3 Error.prototype.message
  2636         // Error.prototype.message = "";
  2637         errorProto.set(NativeError.MESSAGE, "", 0);
  2639         tagBuiltinProperties("Error", builtinError);
  2641         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
  2642         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
  2643         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
  2646     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
  2647         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
  2648         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
  2649         prototype.set(NativeError.NAME, name, 0);
  2650         prototype.set(NativeError.MESSAGE, "", 0);
  2651         prototype.setInitialProto(errorProto);
  2652         tagBuiltinProperties(name, cons);
  2653         return cons;
  2656     private void initJavaAccess() {
  2657         final ScriptObject objectProto = getObjectPrototype();
  2658         this.builtinPackages = new NativeJavaPackage("", objectProto);
  2659         this.builtinCom = new NativeJavaPackage("com", objectProto);
  2660         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
  2661         this.builtinJava = new NativeJavaPackage("java", objectProto);
  2662         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
  2663         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
  2664         this.builtinOrg = new NativeJavaPackage("org", objectProto);
  2667     private void initScripting(final ScriptEnvironment scriptEnv) {
  2668         Object value;
  2669         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
  2670         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
  2672         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
  2673         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
  2675         final String execName = ScriptingFunctions.EXEC_NAME;
  2676         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
  2677         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
  2679         // Nashorn extension: global.echo (scripting-mode-only)
  2680         // alias for "print"
  2681         value = get("print");
  2682         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
  2684         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
  2685         final ScriptObject options = newObject();
  2686         copyOptions(options, scriptEnv);
  2687         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
  2689         // Nashorn extension: global.$ENV (scripting-mode-only)
  2690         if (System.getSecurityManager() == null) {
  2691             // do not fill $ENV if we have a security manager around
  2692             // Retrieve current state of ENV variables.
  2693             final ScriptObject env = newObject();
  2694             env.putAll(System.getenv(), scriptEnv._strict);
  2695             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
  2696         } else {
  2697             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  2700         // add other special properties for exec support
  2701         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  2702         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  2703         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
  2706     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
  2707         for (final Field f : scriptEnv.getClass().getFields()) {
  2708             try {
  2709                 options.set(f.getName(), f.get(scriptEnv), 0);
  2710             } catch (final IllegalArgumentException | IllegalAccessException exp) {
  2711                 throw new RuntimeException(exp);
  2716     private void copyBuiltins() {
  2717         this.array             = this.builtinArray;
  2718         this._boolean          = this.builtinBoolean;
  2719         this.error             = this.builtinError;
  2720         this.function          = this.builtinFunction;
  2721         this.com               = this.builtinCom;
  2722         this.edu               = this.builtinEdu;
  2723         this.java              = this.builtinJava;
  2724         this.javafx            = this.builtinJavafx;
  2725         this.javax             = this.builtinJavax;
  2726         this.org               = this.builtinOrg;
  2727         this.math              = this.builtinMath;
  2728         this.number            = this.builtinNumber;
  2729         this.object            = this.builtinObject;
  2730         this.packages          = this.builtinPackages;
  2731         this.referenceError    = this.builtinReferenceError;
  2732         this.string            = this.builtinString;
  2733         this.syntaxError       = this.builtinSyntaxError;
  2734         this.typeError         = this.builtinTypeError;
  2737     private void initDebug() {
  2738         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
  2741     private Object printImpl(final boolean newLine, final Object... objects) {
  2742         @SuppressWarnings("resource")
  2743         final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
  2744         final StringBuilder sb = new StringBuilder();
  2746         for (final Object obj : objects) {
  2747             if (sb.length() != 0) {
  2748                 sb.append(' ');
  2751             sb.append(JSType.toString(obj));
  2754         // Print all at once to ensure thread friendly result.
  2755         if (newLine) {
  2756             out.println(sb.toString());
  2757         } else {
  2758             out.print(sb.toString());
  2761         out.flush();
  2763         return UNDEFINED;
  2766     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
  2767         try {
  2768             // Assuming class name pattern for built-in JS constructors.
  2769             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
  2771             sb.append("Native");
  2772             sb.append(name);
  2773             sb.append("$Constructor");
  2775             final Class<?> funcClass = Class.forName(sb.toString());
  2776             final T res = clazz.cast(funcClass.newInstance());
  2778             if (res instanceof ScriptFunction) {
  2779                 // All global constructor prototypes are not-writable,
  2780                 // not-enumerable and not-configurable.
  2781                 final ScriptFunction func = (ScriptFunction)res;
  2782                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
  2785             if (res.getProto() == null) {
  2786                 res.setInitialProto(getObjectPrototype());
  2789             res.setIsBuiltin();
  2791             return res;
  2792         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
  2793             throw new RuntimeException(e);
  2797     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
  2798         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
  2800         list.addAll(Arrays.asList(func.getMap().getProperties()));
  2802         if (func instanceof ScriptFunction) {
  2803             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
  2804             if (proto != null) {
  2805                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
  2809         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
  2810         if (prop != null) {
  2811             list.add(prop);
  2814         return list;
  2817     /**
  2818      * Given a builtin object, traverse its properties recursively and associate them with a name that
  2819      * will be a key to their invalidation switchpoint.
  2820      * @param name name for key
  2821      * @param func builtin script object
  2822      */
  2823     private void tagBuiltinProperties(final String name, final ScriptObject func) {
  2824         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
  2825         if (sp == null) {
  2826             sp = context.newBuiltinSwitchPoint(name);
  2829         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
  2830         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
  2831         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
  2832             prop.setBuiltinSwitchPoint(sp);
  2836     // Function and Object constructors are inter-dependent. Also,
  2837     // Function.prototype
  2838     // functions are not properly initialized. We fix the references here.
  2839     // NOTE: be careful if you want to re-order the operations here. You may
  2840     // have
  2841     // to play with object references carefully!!
  2842     private void initFunctionAndObject() {
  2843         // First-n-foremost is Function
  2845         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
  2847         // create global anonymous function
  2848         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
  2849         // need to copy over members of Function.prototype to anon function
  2850         anon.addBoundProperties(getFunctionPrototype());
  2852         // Function.prototype === Object.getPrototypeOf(Function) ===
  2853         // <anon-function>
  2854         builtinFunction.setInitialProto(anon);
  2855         builtinFunction.setPrototype(anon);
  2856         anon.set("constructor", builtinFunction, 0);
  2857         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
  2859         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
  2860         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
  2861         typeErrorThrower.setPrototype(UNDEFINED);
  2862         // Non-constructor built-in functions do not have "prototype" property
  2863         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
  2864         typeErrorThrower.preventExtensions();
  2866         // now initialize Object
  2867         this.builtinObject = initConstructor("Object", ScriptFunction.class);
  2868         final ScriptObject ObjectPrototype = getObjectPrototype();
  2869         // Object.getPrototypeOf(Function.prototype) === Object.prototype
  2870         anon.setInitialProto(ObjectPrototype);
  2872         // ES6 draft compliant __proto__ property of Object.prototype
  2873         // accessors on Object.prototype for "__proto__"
  2874         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
  2875         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
  2876         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
  2878         // Function valued properties of Function.prototype were not properly
  2879         // initialized. Because, these were created before global.function and
  2880         // global.object were not initialized.
  2881         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
  2882         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2883             final Object key = property.getKey();
  2884             final Object value = builtinFunction.get(key);
  2886             if (value instanceof ScriptFunction && value != anon) {
  2887                 final ScriptFunction func = (ScriptFunction)value;
  2888                 func.setInitialProto(getFunctionPrototype());
  2889                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2890                 if (prototype != null) {
  2891                     prototype.setInitialProto(ObjectPrototype);
  2896         // For function valued properties of Object and Object.prototype, make
  2897         // sure prototype's proto chain ends with Object.prototype
  2898         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
  2899             final Object key = property.getKey();
  2900             final Object value = builtinObject.get(key);
  2902             if (value instanceof ScriptFunction) {
  2903                 final ScriptFunction func = (ScriptFunction)value;
  2904                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2905                 if (prototype != null) {
  2906                     prototype.setInitialProto(ObjectPrototype);
  2911         properties = getObjectPrototype().getMap().getProperties();
  2913         for (final jdk.nashorn.internal.runtime.Property property : properties) {
  2914             final Object key   = property.getKey();
  2915             if (key.equals("constructor")) {
  2916                 continue;
  2919             final Object value = ObjectPrototype.get(key);
  2920             if (value instanceof ScriptFunction) {
  2921                 final ScriptFunction func = (ScriptFunction)value;
  2922                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
  2923                 if (prototype != null) {
  2924                     prototype.setInitialProto(ObjectPrototype);
  2929         tagBuiltinProperties("Object", builtinObject);
  2930         tagBuiltinProperties("Function", builtinFunction);
  2931         tagBuiltinProperties("Function", anon);
  2934     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
  2935         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
  2938     RegExpResult getLastRegExpResult() {
  2939         return lastRegExpResult;
  2942     void setLastRegExpResult(final RegExpResult regExpResult) {
  2943         this.lastRegExpResult = regExpResult;
  2946     @Override
  2947     protected boolean isGlobal() {
  2948         return true;
  2951     /**
  2952      * A class representing the ES6 global lexical scope.
  2953      */
  2954     private static class LexicalScope extends ScriptObject {
  2956         LexicalScope(final Global global) {
  2957             super(global, PropertyMap.newMap());
  2960         @Override
  2961         protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
  2962             return filterInvocation(super.findGetMethod(desc, request, operator));
  2965         @Override
  2966         protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
  2967             return filterInvocation(super.findSetMethod(desc, request));
  2970         @Override
  2971         protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
  2972             // We override this method just to make it callable by Global
  2973             return super.addBoundProperty(propMap, source, property);
  2976         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
  2977             final MethodType type = invocation.getInvocation().type();
  2978             return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);

mercurial