Global.java revision 1015:8a4af0397070
150120Swpaul/*
250120Swpaul * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
350120Swpaul * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
450120Swpaul *
550120Swpaul * This code is free software; you can redistribute it and/or modify it
650120Swpaul * under the terms of the GNU General Public License version 2 only, as
750120Swpaul * published by the Free Software Foundation.  Oracle designates this
850120Swpaul * particular file as subject to the "Classpath" exception as provided
950120Swpaul * by Oracle in the LICENSE file that accompanied this code.
1050120Swpaul *
1150120Swpaul * This code is distributed in the hope that it will be useful, but WITHOUT
1250120Swpaul * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1350120Swpaul * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1450120Swpaul * version 2 for more details (a copy is included in the LICENSE file that
1550120Swpaul * accompanied this code).
1650120Swpaul *
1750120Swpaul * You should have received a copy of the GNU General Public License version
1850120Swpaul * 2 along with this work; if not, write to the Free Software Foundation,
1950120Swpaul * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2050120Swpaul *
2150120Swpaul * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2250120Swpaul * or visit www.oracle.com if you need additional information or have any
2350120Swpaul * questions.
2450120Swpaul */
2550120Swpaul
2650120Swpaulpackage jdk.nashorn.internal.objects;
2750120Swpaul
2850120Swpaulimport static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
2950120Swpaulimport static jdk.nashorn.internal.lookup.Lookup.MH;
3050120Swpaulimport static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
3150120Swpaulimport static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
3250120Swpaulimport static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
3350120Swpaul
3450120Swpaulimport java.io.IOException;
3550120Swpaulimport java.io.PrintWriter;
3650120Swpaulimport java.lang.invoke.CallSite;
3750120Swpaulimport java.lang.invoke.ConstantCallSite;
3850120Swpaulimport java.lang.invoke.MethodHandle;
3950120Swpaulimport java.lang.invoke.MethodHandles;
4050120Swpaulimport java.lang.invoke.MethodType;
4150120Swpaulimport java.lang.invoke.SwitchPoint;
4250120Swpaulimport java.lang.reflect.Field;
4350120Swpaulimport java.util.Arrays;
4450120Swpaulimport java.util.HashMap;
4550120Swpaulimport java.util.Map;
4650120Swpaulimport java.util.concurrent.Callable;
4750120Swpaulimport java.util.concurrent.ConcurrentHashMap;
4850120Swpaulimport java.util.concurrent.atomic.AtomicReference;
4950120Swpaulimport javax.script.ScriptContext;
5050120Swpaulimport javax.script.ScriptEngine;
5150120Swpaulimport jdk.internal.dynalink.linker.GuardedInvocation;
5250120Swpaulimport jdk.internal.dynalink.linker.LinkRequest;
5350120Swpaulimport jdk.nashorn.api.scripting.ClassFilter;
5450120Swpaulimport jdk.nashorn.api.scripting.ScriptObjectMirror;
5550120Swpaulimport jdk.nashorn.internal.codegen.ApplySpecialization;
5650120Swpaulimport jdk.nashorn.internal.codegen.CompilerConstants.Call;
5750120Swpaulimport jdk.nashorn.internal.lookup.Lookup;
5850120Swpaulimport jdk.nashorn.internal.objects.annotations.Attribute;
5950120Swpaulimport jdk.nashorn.internal.objects.annotations.Property;
6050120Swpaulimport jdk.nashorn.internal.objects.annotations.ScriptClass;
6150120Swpaulimport jdk.nashorn.internal.runtime.ConsString;
6250120Swpaulimport jdk.nashorn.internal.runtime.Context;
6350120Swpaulimport jdk.nashorn.internal.runtime.GlobalConstants;
6450120Swpaulimport jdk.nashorn.internal.runtime.GlobalFunctions;
6550120Swpaulimport jdk.nashorn.internal.runtime.JSType;
6650120Swpaulimport jdk.nashorn.internal.runtime.NativeJavaPackage;
6750120Swpaulimport jdk.nashorn.internal.runtime.PropertyDescriptor;
6850120Swpaulimport jdk.nashorn.internal.runtime.PropertyMap;
6950120Swpaulimport jdk.nashorn.internal.runtime.Scope;
7050120Swpaulimport jdk.nashorn.internal.runtime.ScriptEnvironment;
7150120Swpaulimport jdk.nashorn.internal.runtime.ScriptFunction;
7250120Swpaulimport jdk.nashorn.internal.runtime.ScriptObject;
7350120Swpaulimport jdk.nashorn.internal.runtime.ScriptRuntime;
7450120Swpaulimport jdk.nashorn.internal.runtime.ScriptingFunctions;
7550120Swpaulimport jdk.nashorn.internal.runtime.arrays.ArrayData;
7650120Swpaulimport jdk.nashorn.internal.runtime.linker.Bootstrap;
7750120Swpaulimport jdk.nashorn.internal.runtime.linker.InvokeByName;
7850120Swpaulimport jdk.nashorn.internal.runtime.regexp.RegExpResult;
7950120Swpaulimport jdk.nashorn.internal.scripts.JO;
8050120Swpaul
8150120Swpaul/**
8250120Swpaul * Representation of global scope.
8350120Swpaul */
8450120Swpaul@ScriptClass("Global")
8550120Swpaulpublic final class Global extends ScriptObject implements Scope {
8650120Swpaul    // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
8750120Swpaul    private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
8850120Swpaul    private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
8950120Swpaul    private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
9050120Swpaul
9150120Swpaul    /**
9250120Swpaul     * Optimistic builtin names that require switchpoint invalidation
9350120Swpaul     * upon assignment. Overly conservative, but works for now, to avoid
9450120Swpaul     * any complicated scope checks and especially heavy weight guards
9550120Swpaul     * like
9650120Swpaul     *
9750120Swpaul     * <pre>
9850120Swpaul     *     public boolean setterGuard(final Object receiver) {
9950120Swpaul     *         final Global          global = Global.instance();
10050120Swpaul     *         final ScriptObject    sobj   = global.getFunctionPrototype();
10150120Swpaul     *         final Object          apply  = sobj.get("apply");
10250120Swpaul     *         return apply == receiver;
10350120Swpaul     *     }
10450120Swpaul     * </pre>
10550120Swpaul     *
10650120Swpaul     * Naturally, checking for builtin classes like NativeFunction is cheaper,
10750120Swpaul     * it's when you start adding property checks for said builtins you have
10850120Swpaul     * problems with guard speed.
10950120Swpaul     */
11050120Swpaul    public final Map<String, SwitchPoint> optimisticFunctionMap;
11150120Swpaul
11250120Swpaul    /** Name invalidator for things like call/apply */
11350120Swpaul    public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
11450120Swpaul
11550120Swpaul    /** Nashorn extension: arguments array */
11650120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
11750120Swpaul    public Object arguments;
11850120Swpaul
11950120Swpaul    /** ECMA 15.1.2.2 parseInt (string , radix) */
12050120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
12150120Swpaul    public Object parseInt;
12250120Swpaul
12350120Swpaul    /** ECMA 15.1.2.3 parseFloat (string) */
12450120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
12550120Swpaul    public Object parseFloat;
12650120Swpaul
12750120Swpaul    /** ECMA 15.1.2.4 isNaN (number) */
12850120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
12950120Swpaul    public Object isNaN;
13050120Swpaul
13150120Swpaul    /** ECMA 15.1.2.5 isFinite (number) */
13250120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
13350120Swpaul    public Object isFinite;
13450120Swpaul
13550120Swpaul    /** ECMA 15.1.3.3 encodeURI */
13650120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
13750120Swpaul    public Object encodeURI;
13850120Swpaul
13950120Swpaul    /** ECMA 15.1.3.4 encodeURIComponent */
14050120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
14150120Swpaul    public Object encodeURIComponent;
14250120Swpaul
14350120Swpaul    /** ECMA 15.1.3.1 decodeURI */
14450120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
14550120Swpaul    public Object decodeURI;
14650120Swpaul
14750120Swpaul    /** ECMA 15.1.3.2 decodeURIComponent */
14850120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
14950120Swpaul    public Object decodeURIComponent;
15050120Swpaul
15150120Swpaul    /** ECMA B.2.1 escape (string) */
15250120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
15350120Swpaul    public Object escape;
15450120Swpaul
15550120Swpaul    /** ECMA B.2.2 unescape (string) */
15650120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
15750120Swpaul    public Object unescape;
15850120Swpaul
15950120Swpaul    /** Nashorn extension: global.print */
16050120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
16150120Swpaul    public Object print;
16250120Swpaul
16350120Swpaul    /** Nashorn extension: global.load */
16450120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
16550120Swpaul    public Object load;
16650120Swpaul
16750120Swpaul    /** Nashorn extension: global.loadWithNewGlobal */
16850120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
16950120Swpaul    public Object loadWithNewGlobal;
17050120Swpaul
17150120Swpaul    /** Nashorn extension: global.exit */
17250120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
17350120Swpaul    public Object exit;
17450120Swpaul
17550120Swpaul    /** Nashorn extension: global.quit */
17650120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
17750120Swpaul    public Object quit;
17850120Swpaul
17950120Swpaul    /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
18050120Swpaul    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
18150120Swpaul    public final double NaN = Double.NaN;
18250120Swpaul
18350120Swpaul    /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
18450120Swpaul    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
18550120Swpaul    public final double Infinity = Double.POSITIVE_INFINITY;
18650120Swpaul
18750120Swpaul    /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
18850120Swpaul    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
18950120Swpaul    public final Object undefined = UNDEFINED;
19050120Swpaul
19150120Swpaul    /** ECMA 15.1.2.1 eval(x) */
19250120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
19350120Swpaul    public Object eval;
19450120Swpaul
19550120Swpaul    /** ECMA 15.1.4.1 Object constructor. */
19650120Swpaul    @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
19750120Swpaul    public volatile Object object;
19850120Swpaul
19950120Swpaul    /** ECMA 15.1.4.2 Function constructor. */
20050120Swpaul    @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
20150120Swpaul    public volatile Object function;
20250120Swpaul
20350120Swpaul    /** ECMA 15.1.4.3 Array constructor. */
20450120Swpaul    @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
20550120Swpaul    public volatile Object array;
20650120Swpaul
20750120Swpaul    /** ECMA 15.1.4.4 String constructor */
20850120Swpaul    @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
20950120Swpaul    public volatile Object string;
21050120Swpaul
21150120Swpaul    /** ECMA 15.1.4.5 Boolean constructor */
21250120Swpaul    @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
21350120Swpaul    public volatile Object _boolean;
21450120Swpaul
21550120Swpaul    /** ECMA 15.1.4.6 - Number constructor */
21650120Swpaul    @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
21750120Swpaul    public volatile Object number;
21850120Swpaul
21950120Swpaul    /** ECMA 15.1.4.7 Date constructor */
22050120Swpaul    @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
22150120Swpaul    public volatile Object date;
22250120Swpaul
22350120Swpaul    /** ECMA 15.1.4.8 RegExp constructor */
22450120Swpaul    @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
22550120Swpaul    public volatile Object regexp;
22650120Swpaul
22750120Swpaul    /** ECMA 15.12 - The JSON object */
22850120Swpaul    @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
22950120Swpaul    public volatile Object json;
23050120Swpaul
23150120Swpaul    /** Nashorn extension: global.JSAdapter */
23250120Swpaul    @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
23350120Swpaul    public volatile Object jsadapter;
23450120Swpaul
23550120Swpaul    /** ECMA 15.8 - The Math object */
23650120Swpaul    @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
23750120Swpaul    public volatile Object math;
23850120Swpaul
23950120Swpaul    /** Error object */
24050120Swpaul    @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
24150120Swpaul    public volatile Object error;
24250120Swpaul
24350120Swpaul    /** EvalError object */
24450120Swpaul    @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
24550120Swpaul    public volatile Object evalError;
24650120Swpaul
24750120Swpaul    /** RangeError object */
24850120Swpaul    @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
24950120Swpaul    public volatile Object rangeError;
25050120Swpaul
25150120Swpaul    /** ReferenceError object */
25250120Swpaul    @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
25350120Swpaul    public volatile Object referenceError;
25450120Swpaul
25550120Swpaul    /** SyntaxError object */
25650120Swpaul    @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
25750120Swpaul    public volatile Object syntaxError;
25850120Swpaul
25950120Swpaul    /** TypeError object */
26050120Swpaul    @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
26150120Swpaul    public volatile Object typeError;
26250120Swpaul
26350120Swpaul    /** URIError object */
26450120Swpaul    @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
26550120Swpaul    public volatile Object uriError;
26650120Swpaul
26750120Swpaul    /** ArrayBuffer object */
26850120Swpaul    @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
26950120Swpaul    public volatile Object arrayBuffer;
27050120Swpaul
27150120Swpaul    /** DataView object */
27250120Swpaul    @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
27350120Swpaul    public volatile Object dataView;
27450120Swpaul
27550120Swpaul    /** TypedArray (int8) */
27650120Swpaul    @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
27750120Swpaul    public volatile Object int8Array;
27850120Swpaul
27950120Swpaul    /** TypedArray (uint8) */
28050120Swpaul    @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
28150120Swpaul    public volatile Object uint8Array;
28250120Swpaul
28350120Swpaul    /** TypedArray (uint8) - Clamped */
28450120Swpaul    @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
28550120Swpaul    public volatile Object uint8ClampedArray;
28650120Swpaul
28750120Swpaul    /** TypedArray (int16) */
28850120Swpaul    @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
28950120Swpaul    public volatile Object int16Array;
29050120Swpaul
29150120Swpaul    /** TypedArray (uint16) */
29250120Swpaul    @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
29350120Swpaul    public volatile Object uint16Array;
29450120Swpaul
29550120Swpaul    /** TypedArray (int32) */
29650120Swpaul    @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
29750120Swpaul    public volatile Object int32Array;
29850120Swpaul
29950120Swpaul    /** TypedArray (uint32) */
30050120Swpaul    @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
30150120Swpaul    public volatile Object uint32Array;
30250120Swpaul
30350120Swpaul    /** TypedArray (float32) */
30450120Swpaul    @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
30550120Swpaul    public volatile Object float32Array;
30650120Swpaul
30750120Swpaul    /** TypedArray (float64) */
30850120Swpaul    @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
30950120Swpaul    public volatile Object float64Array;
31050120Swpaul
31150120Swpaul    /** Nashorn extension: Java access - global.Packages */
31250120Swpaul    @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
31350120Swpaul    public volatile Object packages;
31450120Swpaul
31550120Swpaul    /** Nashorn extension: Java access - global.com */
31650120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
31750120Swpaul    public volatile Object com;
31850120Swpaul
31950120Swpaul    /** Nashorn extension: Java access - global.edu */
32050120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
32150120Swpaul    public volatile Object edu;
32250120Swpaul
32350120Swpaul    /** Nashorn extension: Java access - global.java */
32450120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
32550120Swpaul    public volatile Object java;
32650120Swpaul
32750120Swpaul    /** Nashorn extension: Java access - global.javafx */
32850120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
32950120Swpaul    public volatile Object javafx;
33050120Swpaul
33150120Swpaul    /** Nashorn extension: Java access - global.javax */
33250120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
33350120Swpaul    public volatile Object javax;
33450120Swpaul
33550120Swpaul    /** Nashorn extension: Java access - global.org */
33650120Swpaul    @Property(attributes = Attribute.NOT_ENUMERABLE)
33750120Swpaul    public volatile Object org;
33850120Swpaul
33950120Swpaul    /** Nashorn extension: Java access - global.javaImporter */
34050120Swpaul    @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
34150120Swpaul    public volatile Object javaImporter;
34250120Swpaul
34350120Swpaul    /** Nashorn extension: global.Java Object constructor. */
34450120Swpaul    @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
34550120Swpaul    public volatile Object javaApi;
34650120Swpaul
34750120Swpaul    /** Nashorn extension: current script's file name */
34850120Swpaul    @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
34950120Swpaul    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
35050120Swpaul
35150120Swpaul    /** Nashorn extension: current script's directory */
35250120Swpaul    @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
35350120Swpaul    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
35450120Swpaul
35550120Swpaul    /** Nashorn extension: current source line number being executed */
35650120Swpaul    @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
35750120Swpaul    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
35850120Swpaul
35950120Swpaul    /** Used as Date.prototype's default value */
36050120Swpaul    public NativeDate   DEFAULT_DATE;
36150120Swpaul
36250120Swpaul    /** Used as RegExp.prototype's default value */
36350120Swpaul    public NativeRegExp DEFAULT_REGEXP;
36450120Swpaul
36550120Swpaul    /*
36650120Swpaul     * Built-in constructor objects: Even if user changes dynamic values of
36750120Swpaul     * "Object", "Array" etc., we still want to keep original values of these
36850120Swpaul     * constructors here. For example, we need to be able to create array,
36950120Swpaul     * regexp literals even after user overwrites global "Array" or "RegExp"
37050120Swpaul     * constructor - see also ECMA 262 spec. Annex D.
37150120Swpaul     */
37250120Swpaul    private ScriptFunction builtinFunction;
37350120Swpaul    private ScriptFunction builtinObject;
37450120Swpaul    private ScriptFunction builtinArray;
37550120Swpaul    private ScriptFunction builtinBoolean;
37650120Swpaul    private ScriptFunction builtinDate;
37750120Swpaul    private ScriptObject   builtinJSON;
37850120Swpaul    private ScriptFunction builtinJSAdapter;
37950120Swpaul    private ScriptObject   builtinMath;
38050120Swpaul    private ScriptFunction builtinNumber;
38150120Swpaul    private ScriptFunction builtinRegExp;
38250120Swpaul    private ScriptFunction builtinString;
38350120Swpaul    private ScriptFunction builtinError;
38450120Swpaul    private ScriptFunction builtinEval;
38550120Swpaul    private ScriptFunction builtinEvalError;
38650120Swpaul    private ScriptFunction builtinRangeError;
38750120Swpaul    private ScriptFunction builtinReferenceError;
38850120Swpaul    private ScriptFunction builtinSyntaxError;
38950120Swpaul    private ScriptFunction builtinTypeError;
39050120Swpaul    private ScriptFunction builtinURIError;
39150120Swpaul    private ScriptObject   builtinPackages;
39250120Swpaul    private ScriptObject   builtinCom;
39350120Swpaul    private ScriptObject   builtinEdu;
39450120Swpaul    private ScriptObject   builtinJava;
39550120Swpaul    private ScriptObject   builtinJavafx;
39650120Swpaul    private ScriptObject   builtinJavax;
39750120Swpaul    private ScriptObject   builtinOrg;
39850120Swpaul    private ScriptFunction builtinJavaImporter;
39950120Swpaul    private ScriptObject   builtinJavaApi;
40050120Swpaul    private ScriptFunction builtinArrayBuffer;
40150120Swpaul    private ScriptFunction builtinDataView;
40250120Swpaul    private ScriptFunction builtinInt8Array;
40350120Swpaul    private ScriptFunction builtinUint8Array;
40450120Swpaul    private ScriptFunction builtinUint8ClampedArray;
40550120Swpaul    private ScriptFunction builtinInt16Array;
40650120Swpaul    private ScriptFunction builtinUint16Array;
40750120Swpaul    private ScriptFunction builtinInt32Array;
40850120Swpaul    private ScriptFunction builtinUint32Array;
40950120Swpaul    private ScriptFunction builtinFloat32Array;
41050120Swpaul    private ScriptFunction builtinFloat64Array;
41150120Swpaul
41250120Swpaul    /*
41350120Swpaul     * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
41450120Swpaul     */
41550120Swpaul    private ScriptFunction typeErrorThrower;
41650120Swpaul
41750120Swpaul    // Flag to indicate that a split method issued a return statement
41850120Swpaul    private int splitState = -1;
41950120Swpaul
42050120Swpaul    // Used to store the last RegExp result to support deprecated RegExp constructor properties
42150120Swpaul    private RegExpResult lastRegExpResult;
42250120Swpaul
42350120Swpaul    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
42450120Swpaul    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
42550120Swpaul    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
42650120Swpaul    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
42750120Swpaul    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
42850120Swpaul    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
42950120Swpaul    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
43050120Swpaul
431    /** Invalidate a reserved name, such as "apply" or "call" if assigned */
432    public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this);
433
434    // initialized by nasgen
435    private static PropertyMap $nasgenmap$;
436
437    // context to which this global belongs to
438    private final Context context;
439
440    // current ScriptContext to use - can be null.
441    private ScriptContext scontext;
442    // associated Property object for "context" property.
443    private jdk.nashorn.internal.runtime.Property scontextProperty;
444
445    /**
446     * Set the current script context
447     * @param scontext script context
448     */
449    public void setScriptContext(final ScriptContext scontext) {
450        this.scontext = scontext;
451        scontextProperty.setValue(this, this, scontext, false);
452    }
453
454    // global constants for this global - they can be replaced with MethodHandle.constant until invalidated
455    private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
456
457    @Override
458    protected Context getContext() {
459        return context;
460    }
461
462    // performs initialization checks for Global constructor and returns the
463    // PropertyMap, if everything is fine.
464    private static PropertyMap checkAndGetMap(final Context context) {
465        // security check first
466        final SecurityManager sm = System.getSecurityManager();
467        if (sm != null) {
468            sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
469        }
470
471        // null check on context
472        context.getClass();
473
474        return $nasgenmap$;
475    }
476
477    /**
478     * Constructor
479     *
480     * @param context the context
481     */
482    public Global(final Context context) {
483        super(checkAndGetMap(context));
484        this.context = context;
485        this.setIsScope();
486        this.optimisticFunctionMap = new HashMap<>();
487        //we can only share one instance of Global constants between globals, or we consume way too much
488        //memory - this is good enough for most programs
489        while (gcsInstance.get() == null) {
490            gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class)));
491        }
492    }
493
494    /**
495     * Script access to "current" Global instance
496     *
497     * @return the global singleton
498     */
499    public static Global instance() {
500        final Global global = Context.getGlobal();
501        global.getClass(); // null check
502        return global;
503    }
504
505    private static Global instanceFrom(final Object self) {
506        return self instanceof Global? (Global)self : instance();
507    }
508
509    /**
510     * Return the global constants map for fields that
511     * can be accessed as MethodHandle.constant
512     * @return constant map
513     */
514    public static GlobalConstants getConstants() {
515        return gcsInstance.get();
516    }
517
518    /**
519     * Check if we have a Global instance
520     * @return true if one exists
521     */
522    public static boolean hasInstance() {
523        return Context.getGlobal() != null;
524    }
525
526    /**
527     * Script access to {@link ScriptEnvironment}
528     *
529     * @return the script environment
530     */
531    static ScriptEnvironment getEnv() {
532        return instance().getContext().getEnv();
533    }
534
535    /**
536     * Script access to {@link Context}
537     *
538     * @return the context
539     */
540    static Context getThisContext() {
541        return instance().getContext();
542    }
543
544    // Runtime interface to Global
545
546    /**
547     * Is there a class filter in the current Context?
548     * @return class filter
549     */
550    public ClassFilter getClassFilter() {
551        return context.getClassFilter();
552    }
553
554    /**
555     * Is this global of the given Context?
556     * @param ctxt the context
557     * @return true if this global belongs to the given Context
558     */
559    public boolean isOfContext(final Context ctxt) {
560        return this.context == ctxt;
561    }
562
563    /**
564     * Does this global belong to a strict Context?
565     * @return true if this global belongs to a strict Context
566     */
567    public boolean isStrictContext() {
568        return context.getEnv()._strict;
569    }
570
571    /**
572     * Initialize standard builtin objects like "Object", "Array", "Function" etc.
573     * as well as our extension builtin objects like "Java", "JSAdapter" as properties
574     * of the global scope object.
575     *
576     * @param engine ScriptEngine to initialize
577     */
578    public void initBuiltinObjects(final ScriptEngine engine) {
579        if (this.builtinObject != null) {
580            // already initialized, just return
581            return;
582        }
583
584        init(engine);
585    }
586
587    /**
588     * Wrap a Java object as corresponding script object
589     *
590     * @param obj object to wrap
591     * @return    wrapped object
592     */
593    public Object wrapAsObject(final Object obj) {
594        if (obj instanceof Boolean) {
595            return new NativeBoolean((Boolean)obj, this);
596        } else if (obj instanceof Number) {
597            return new NativeNumber(((Number)obj).doubleValue(), this);
598        } else if (obj instanceof String || obj instanceof ConsString) {
599            return new NativeString((CharSequence)obj, this);
600        } else if (obj instanceof Object[]) { // extension
601            return new NativeArray((Object[])obj);
602        } else if (obj instanceof double[]) { // extension
603            return new NativeArray((double[])obj);
604        } else if (obj instanceof long[]) {
605            return new NativeArray((long[])obj);
606        } else if (obj instanceof int[]) {
607            return new NativeArray((int[])obj);
608        } else {
609            // FIXME: more special cases? Map? List?
610            return obj;
611        }
612    }
613
614    /**
615     * Lookup helper for JS primitive types
616     *
617     * @param request the link request for the dynamic call site.
618     * @param self     self reference
619     *
620     * @return guarded invocation
621     */
622    public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
623        if (self instanceof String || self instanceof ConsString) {
624            return NativeString.lookupPrimitive(request, self);
625        } else if (self instanceof Number) {
626            return NativeNumber.lookupPrimitive(request, self);
627        } else if (self instanceof Boolean) {
628            return NativeBoolean.lookupPrimitive(request, self);
629        }
630        throw new IllegalArgumentException("Unsupported primitive: " + self);
631    }
632
633    /**
634     * Returns a method handle that creates a wrapper object for a JS primitive value.
635     *
636     * @param self receiver object
637     * @return method handle to create wrapper objects for primitive receiver
638     */
639    public static MethodHandle getPrimitiveWrapFilter(final Object self) {
640        if (self instanceof String || self instanceof ConsString) {
641            return NativeString.WRAPFILTER;
642        } else if (self instanceof Number) {
643            return NativeNumber.WRAPFILTER;
644        } else if (self instanceof Boolean) {
645            return NativeBoolean.WRAPFILTER;
646        }
647        throw new IllegalArgumentException("Unsupported primitive: " + self);
648    }
649
650
651    /**
652     * Create a new empty script object
653     *
654     * @return the new ScriptObject
655     */
656    public ScriptObject newObject() {
657        return new JO(getObjectPrototype(), JO.getInitialMap());
658    }
659
660    /**
661     * Default value of given type
662     *
663     * @param sobj     script object
664     * @param typeHint type hint
665     *
666     * @return default value
667     */
668    public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
669        // When the [[DefaultValue]] internal method of O is called with no hint,
670        // then it behaves as if the hint were Number, unless O is a Date object
671        // in which case it behaves as if the hint were String.
672        Class<?> hint = typeHint;
673        if (hint == null) {
674            hint = Number.class;
675        }
676
677        try {
678            if (hint == String.class) {
679
680                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
681
682                if (Bootstrap.isCallable(toString)) {
683                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
684                    if (JSType.isPrimitive(value)) {
685                        return value;
686                    }
687                }
688
689                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
690                if (Bootstrap.isCallable(valueOf)) {
691                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
692                    if (JSType.isPrimitive(value)) {
693                        return value;
694                    }
695                }
696                throw typeError(this, "cannot.get.default.string");
697            }
698
699            if (hint == Number.class) {
700                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
701                if (Bootstrap.isCallable(valueOf)) {
702                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
703                    if (JSType.isPrimitive(value)) {
704                        return value;
705                    }
706                }
707
708                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
709                if (Bootstrap.isCallable(toString)) {
710                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
711                    if (JSType.isPrimitive(value)) {
712                        return value;
713                    }
714                }
715
716                throw typeError(this, "cannot.get.default.number");
717            }
718        } catch (final RuntimeException | Error e) {
719            throw e;
720        } catch (final Throwable t) {
721            throw new RuntimeException(t);
722        }
723
724        return UNDEFINED;
725    }
726
727    /**
728     * Is the given ScriptObject an ECMAScript Error object?
729     *
730     * @param sobj the object being checked
731     * @return true if sobj is an Error object
732     */
733    public boolean isError(final ScriptObject sobj) {
734        final ScriptObject errorProto = getErrorPrototype();
735        ScriptObject proto = sobj.getProto();
736        while (proto != null) {
737            if (proto == errorProto) {
738                return true;
739            }
740            proto = proto.getProto();
741        }
742        return false;
743    }
744
745    /**
746     * Create a new ECMAScript Error object.
747     *
748     * @param msg error message
749     * @return newly created Error object
750     */
751    public ScriptObject newError(final String msg) {
752        return new NativeError(msg, this);
753    }
754
755    /**
756     * Create a new ECMAScript EvalError object.
757     *
758     * @param msg error message
759     * @return newly created EvalError object
760     */
761    public ScriptObject newEvalError(final String msg) {
762        return new NativeEvalError(msg, this);
763    }
764
765    /**
766     * Create a new ECMAScript RangeError object.
767     *
768     * @param msg error message
769     * @return newly created RangeError object
770     */
771    public ScriptObject newRangeError(final String msg) {
772        return new NativeRangeError(msg, this);
773    }
774
775    /**
776     * Create a new ECMAScript ReferenceError object.
777     *
778     * @param msg error message
779     * @return newly created ReferenceError object
780     */
781    public ScriptObject newReferenceError(final String msg) {
782        return new NativeReferenceError(msg, this);
783    }
784
785    /**
786     * Create a new ECMAScript SyntaxError object.
787     *
788     * @param msg error message
789     * @return newly created SyntaxError object
790     */
791    public ScriptObject newSyntaxError(final String msg) {
792        return new NativeSyntaxError(msg, this);
793    }
794
795    /**
796     * Create a new ECMAScript TypeError object.
797     *
798     * @param msg error message
799     * @return newly created TypeError object
800     */
801    public ScriptObject newTypeError(final String msg) {
802        return new NativeTypeError(msg, this);
803    }
804
805    /**
806     * Create a new ECMAScript URIError object.
807     *
808     * @param msg error message
809     * @return newly created URIError object
810     */
811    public ScriptObject newURIError(final String msg) {
812        return new NativeURIError(msg, this);
813    }
814
815    /**
816     * Create a new ECMAScript GenericDescriptor object.
817     *
818     * @param configurable is the property configurable?
819     * @param enumerable is the property enumerable?
820     * @return newly created GenericDescriptor object
821     */
822    public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
823        return new GenericPropertyDescriptor(configurable, enumerable, this);
824    }
825
826    /**
827     * Create a new ECMAScript DatePropertyDescriptor object.
828     *
829     * @param value of the data property
830     * @param configurable is the property configurable?
831     * @param enumerable is the property enumerable?
832     * @param writable is the property writable?
833     * @return newly created DataPropertyDescriptor object
834     */
835    public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
836        return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
837    }
838
839    /**
840     * Create a new ECMAScript AccessorPropertyDescriptor object.
841     *
842     * @param get getter function of the user accessor property
843     * @param set setter function of the user accessor property
844     * @param configurable is the property configurable?
845     * @param enumerable is the property enumerable?
846     * @return newly created AccessorPropertyDescriptor object
847     */
848    public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
849        final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
850
851        if (get == null) {
852            desc.delete(PropertyDescriptor.GET, false);
853        }
854
855        if (set == null) {
856            desc.delete(PropertyDescriptor.SET, false);
857        }
858
859        return desc;
860    }
861
862    private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
863        final T obj = map.get(key);
864        if (obj != null) {
865            return obj;
866        }
867
868        try {
869            final T newObj = creator.call();
870            final T existingObj = map.putIfAbsent(key, newObj);
871            return existingObj != null ? existingObj : newObj;
872        } catch (final Exception exp) {
873            throw new RuntimeException(exp);
874        }
875    }
876
877    private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
878
879
880    /**
881     * Get cached InvokeByName object for the given key
882     * @param key key to be associated with InvokeByName object
883     * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
884     * @return InvokeByName object associated with the key.
885     */
886    public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
887        return getLazilyCreatedValue(key, creator, namedInvokers);
888    }
889
890    private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
891
892    /**
893     * Get cached dynamic method handle for the given key
894     * @param key key to be associated with dynamic method handle
895     * @param creator if method handle is absent 'creator' is called to make one (lazy init)
896     * @return dynamic method handle associated with the key.
897     */
898    public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
899        return getLazilyCreatedValue(key, creator, dynamicInvokers);
900    }
901
902    /**
903     * Hook to search missing variables in ScriptContext if available
904     * @param self used to detect if scope call or not (this function is 'strict')
905     * @param name name of the variable missing
906     * @return value of the missing variable or undefined (or TypeError for scope search)
907     */
908    public static Object __noSuchProperty__(final Object self, final Object name) {
909        final Global global = Global.instance();
910        final ScriptContext sctxt = global.scontext;
911        final String nameStr = name.toString();
912
913        if (sctxt != null) {
914            final int scope = sctxt.getAttributesScope(nameStr);
915            if (scope != -1) {
916                return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
917            }
918        }
919
920        if (self == UNDEFINED) {
921            // scope access and so throw ReferenceError
922            throw referenceError(global, "not.defined", nameStr);
923        }
924
925        return UNDEFINED;
926    }
927
928    /**
929     * This is the eval used when 'indirect' eval call is made.
930     *
931     * var global = this;
932     * global.eval("print('hello')");
933     *
934     * @param self  eval scope
935     * @param str   eval string
936     *
937     * @return the result of eval
938     */
939    public static Object eval(final Object self, final Object str) {
940        return directEval(self, str, UNDEFINED, UNDEFINED, false);
941    }
942
943    /**
944     * Direct eval
945     *
946     * @param self     The scope of eval passed as 'self'
947     * @param str      Evaluated code
948     * @param callThis "this" to be passed to the evaluated code
949     * @param location location of the eval call
950     * @param strict   is eval called a strict mode code?
951     *
952     * @return the return value of the eval
953     *
954     * This is directly invoked from generated when eval(code) is called in user code
955     */
956    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
957        if (!(str instanceof String || str instanceof ConsString)) {
958            return str;
959        }
960        final Global global = Global.instanceFrom(self);
961        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
962
963        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
964    }
965
966    /**
967     * Global print implementation - Nashorn extension
968     *
969     * @param self    scope
970     * @param objects arguments to print
971     *
972     * @return result of print (undefined)
973     */
974    public static Object print(final Object self, final Object... objects) {
975        return Global.instanceFrom(self).printImpl(false, objects);
976    }
977
978    /**
979     * Global println implementation - Nashorn extension
980     *
981     * @param self    scope
982     * @param objects arguments to print
983     *
984     * @return result of println (undefined)
985     */
986    public static Object println(final Object self, final Object... objects) {
987        return Global.instanceFrom(self).printImpl(true, objects);
988    }
989
990    /**
991     * Global load implementation - Nashorn extension
992     *
993     * @param self    scope
994     * @param source  source to load
995     *
996     * @return result of load (undefined)
997     *
998     * @throws IOException if source could not be read
999     */
1000    public static Object load(final Object self, final Object source) throws IOException {
1001        final Global global = Global.instanceFrom(self);
1002        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
1003        return global.getContext().load(scope, source);
1004    }
1005
1006    /**
1007     * Global loadWithNewGlobal implementation - Nashorn extension
1008     *
1009     * @param self scope
1010     * @param args from plus (optional) arguments to be passed to the loaded script
1011     *
1012     * @return result of load (may be undefined)
1013     *
1014     * @throws IOException if source could not be read
1015     */
1016    public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1017        final Global global = Global.instanceFrom(self);
1018        final int length = args.length;
1019        final boolean hasArgs = 0 < length;
1020        final Object from = hasArgs ? args[0] : UNDEFINED;
1021        final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1022
1023        return global.getContext().loadWithNewGlobal(from, arguments);
1024    }
1025
1026    /**
1027     * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1028     *
1029     * @param self  self reference
1030     * @param code  exit code
1031     *
1032     * @return undefined (will never be reached)
1033     */
1034    public static Object exit(final Object self, final Object code) {
1035        System.exit(JSType.toInt32(code));
1036        return UNDEFINED;
1037    }
1038
1039    // builtin prototype accessors
1040    ScriptObject getFunctionPrototype() {
1041        return ScriptFunction.getPrototype(builtinFunction);
1042    }
1043
1044    ScriptObject getObjectPrototype() {
1045        return ScriptFunction.getPrototype(builtinObject);
1046    }
1047
1048    ScriptObject getArrayPrototype() {
1049        return ScriptFunction.getPrototype(builtinArray);
1050    }
1051
1052    ScriptObject getBooleanPrototype() {
1053        return ScriptFunction.getPrototype(builtinBoolean);
1054    }
1055
1056    ScriptObject getNumberPrototype() {
1057        return ScriptFunction.getPrototype(builtinNumber);
1058    }
1059
1060    ScriptObject getDatePrototype() {
1061        return ScriptFunction.getPrototype(builtinDate);
1062    }
1063
1064    ScriptObject getRegExpPrototype() {
1065        return ScriptFunction.getPrototype(builtinRegExp);
1066    }
1067
1068    ScriptObject getStringPrototype() {
1069        return ScriptFunction.getPrototype(builtinString);
1070    }
1071
1072    ScriptObject getErrorPrototype() {
1073        return ScriptFunction.getPrototype(builtinError);
1074    }
1075
1076    ScriptObject getEvalErrorPrototype() {
1077        return ScriptFunction.getPrototype(builtinEvalError);
1078    }
1079
1080    ScriptObject getRangeErrorPrototype() {
1081        return ScriptFunction.getPrototype(builtinRangeError);
1082    }
1083
1084    ScriptObject getReferenceErrorPrototype() {
1085        return ScriptFunction.getPrototype(builtinReferenceError);
1086    }
1087
1088    ScriptObject getSyntaxErrorPrototype() {
1089        return ScriptFunction.getPrototype(builtinSyntaxError);
1090    }
1091
1092    ScriptObject getTypeErrorPrototype() {
1093        return ScriptFunction.getPrototype(builtinTypeError);
1094    }
1095
1096    ScriptObject getURIErrorPrototype() {
1097        return ScriptFunction.getPrototype(builtinURIError);
1098    }
1099
1100    ScriptObject getJavaImporterPrototype() {
1101        return ScriptFunction.getPrototype(builtinJavaImporter);
1102    }
1103
1104    ScriptObject getJSAdapterPrototype() {
1105        return ScriptFunction.getPrototype(builtinJSAdapter);
1106    }
1107
1108    ScriptObject getArrayBufferPrototype() {
1109        return ScriptFunction.getPrototype(builtinArrayBuffer);
1110    }
1111
1112    ScriptObject getDataViewPrototype() {
1113        return ScriptFunction.getPrototype(builtinDataView);
1114    }
1115
1116    ScriptObject getInt8ArrayPrototype() {
1117        return ScriptFunction.getPrototype(builtinInt8Array);
1118    }
1119
1120    ScriptObject getUint8ArrayPrototype() {
1121        return ScriptFunction.getPrototype(builtinUint8Array);
1122    }
1123
1124    ScriptObject getUint8ClampedArrayPrototype() {
1125        return ScriptFunction.getPrototype(builtinUint8ClampedArray);
1126    }
1127
1128    ScriptObject getInt16ArrayPrototype() {
1129        return ScriptFunction.getPrototype(builtinInt16Array);
1130    }
1131
1132    ScriptObject getUint16ArrayPrototype() {
1133        return ScriptFunction.getPrototype(builtinUint16Array);
1134    }
1135
1136    ScriptObject getInt32ArrayPrototype() {
1137        return ScriptFunction.getPrototype(builtinInt32Array);
1138    }
1139
1140    ScriptObject getUint32ArrayPrototype() {
1141        return ScriptFunction.getPrototype(builtinUint32Array);
1142    }
1143
1144    ScriptObject getFloat32ArrayPrototype() {
1145        return ScriptFunction.getPrototype(builtinFloat32Array);
1146    }
1147
1148    ScriptObject getFloat64ArrayPrototype() {
1149        return ScriptFunction.getPrototype(builtinFloat64Array);
1150    }
1151
1152    private ScriptFunction getBuiltinArray() {
1153        return builtinArray;
1154    }
1155
1156    ScriptFunction getTypeErrorThrower() {
1157        return typeErrorThrower;
1158    }
1159
1160    /**
1161     * Called from compiled script code to test if builtin has been overridden
1162     *
1163     * @return true if builtin array has not been overridden
1164     */
1165    public static boolean isBuiltinArray() {
1166        final Global instance = Global.instance();
1167        return instance.array == instance.getBuiltinArray();
1168    }
1169
1170    private ScriptFunction getBuiltinBoolean() {
1171        return builtinBoolean;
1172    }
1173
1174    /**
1175     * Called from compiled script code to test if builtin has been overridden
1176     *
1177     * @return true if builtin boolean has not been overridden
1178     */
1179    public static boolean isBuiltinBoolean() {
1180        final Global instance = Global.instance();
1181        return instance._boolean == instance.getBuiltinBoolean();
1182    }
1183
1184    private ScriptFunction getBuiltinDate() {
1185        return builtinDate;
1186    }
1187
1188    /**
1189     * Called from compiled script code to test if builtin has been overridden
1190     *
1191     * @return true if builtin date has not been overridden
1192     */
1193    public static boolean isBuiltinDate() {
1194        final Global instance = Global.instance();
1195        return instance.date == instance.getBuiltinDate();
1196    }
1197
1198    private ScriptFunction getBuiltinError() {
1199        return builtinError;
1200    }
1201
1202    /**
1203     * Called from compiled script code to test if builtin has been overridden
1204     *
1205     * @return true if builtin error has not been overridden
1206     */
1207    public static boolean isBuiltinError() {
1208        final Global instance = Global.instance();
1209        return instance.error == instance.getBuiltinError();
1210    }
1211
1212    private ScriptFunction getBuiltinEvalError() {
1213        return builtinEvalError;
1214    }
1215
1216    /**
1217     * Called from compiled script code to test if builtin has been overridden
1218     *
1219     * @return true if builtin eval error has not been overridden
1220     */
1221    public static boolean isBuiltinEvalError() {
1222        final Global instance = Global.instance();
1223        return instance.evalError == instance.getBuiltinEvalError();
1224    }
1225
1226    private ScriptFunction getBuiltinFunction() {
1227        return builtinFunction;
1228    }
1229
1230    /**
1231     * Called from compiled script code to test if builtin has been overridden
1232     *
1233     * @return true if builtin function has not been overridden
1234     */
1235    public static boolean isBuiltinFunction() {
1236        final Global instance = Global.instance();
1237        return instance.function == instance.getBuiltinFunction();
1238    }
1239
1240    private ScriptFunction getBuiltinJSAdapter() {
1241        return builtinJSAdapter;
1242    }
1243
1244    /**
1245     * Called from compiled script code to test if builtin has been overridden
1246     *
1247     * @return true if builtin JSAdapter has not been overridden
1248     */
1249    public static boolean isBuiltinJSAdapter() {
1250        final Global instance = Global.instance();
1251        return instance.jsadapter == instance.getBuiltinJSAdapter();
1252    }
1253
1254    private ScriptObject getBuiltinJSON() {
1255        return builtinJSON;
1256    }
1257
1258    /**
1259     * Called from compiled script code to test if builtin has been overridden
1260     *
1261     * @return true if builtin JSON has has not been overridden
1262     */
1263    public static boolean isBuiltinJSON() {
1264        final Global instance = Global.instance();
1265        return instance.json == instance.getBuiltinJSON();
1266    }
1267
1268    private ScriptObject getBuiltinJava() {
1269        return builtinJava;
1270    }
1271
1272    /**
1273     * Called from compiled script code to test if builtin has been overridden
1274     *
1275     * @return true if builtin Java has not been overridden
1276     */
1277    public static boolean isBuiltinJava() {
1278        final Global instance = Global.instance();
1279        return instance.java == instance.getBuiltinJava();
1280    }
1281
1282    private ScriptObject getBuiltinJavax() {
1283        return builtinJavax;
1284    }
1285
1286    /**
1287     * Called from compiled script code to test if builtin has been overridden
1288     *
1289     * @return true if builtin Javax has not been overridden
1290     */
1291    public static boolean isBuiltinJavax() {
1292        final Global instance = Global.instance();
1293        return instance.javax == instance.getBuiltinJavax();
1294    }
1295
1296    private ScriptObject getBuiltinJavaImporter() {
1297        return builtinJavaImporter;
1298    }
1299
1300    /**
1301     * Called from compiled script code to test if builtin has been overridden
1302     *
1303     * @return true if builtin Java importer has not been overridden
1304     */
1305    public static boolean isBuiltinJavaImporter() {
1306        final Global instance = Global.instance();
1307        return instance.javaImporter == instance.getBuiltinJavaImporter();
1308    }
1309
1310    private ScriptObject getBuiltinMath() {
1311        return builtinMath;
1312    }
1313
1314    /**
1315     * Called from compiled script code to test if builtin has been overridden
1316     *
1317     * @return true if builtin math has not been overridden
1318     */
1319    public static boolean isBuiltinMath() {
1320        final Global instance = Global.instance();
1321        return instance.math == instance.getBuiltinMath();
1322    }
1323
1324    private ScriptFunction getBuiltinNumber() {
1325        return builtinNumber;
1326    }
1327
1328    /**
1329     * Called from compiled script code to test if builtin has been overridden
1330     *
1331     * @return true if builtin number has not been overridden
1332     */
1333    public static boolean isBuiltinNumber() {
1334        final Global instance = Global.instance();
1335        return instance.number == instance.getBuiltinNumber();
1336    }
1337
1338    private ScriptFunction getBuiltinObject() {
1339        return builtinObject;
1340    }
1341
1342    /**
1343     * Called from compiled script code to test if builtin has been overridden
1344     *
1345     * @return true if builtin object has not been overridden
1346     */
1347    public static boolean isBuiltinObject() {
1348        final Global instance = Global.instance();
1349        return instance.object == instance.getBuiltinObject();
1350    }
1351
1352    private ScriptObject getBuiltinPackages() {
1353        return builtinPackages;
1354    }
1355
1356    /**
1357     * Called from compiled script code to test if builtin has been overridden
1358     *
1359     * @return true if builtin package has not been overridden
1360     */
1361    public static boolean isBuiltinPackages() {
1362        final Global instance = Global.instance();
1363        return instance.packages == instance.getBuiltinPackages();
1364    }
1365
1366    private ScriptFunction getBuiltinRangeError() {
1367        return builtinRangeError;
1368    }
1369
1370    /**
1371     * Called from compiled script code to test if builtin has been overridden
1372     *
1373     * @return true if builtin range error has not been overridden
1374     */
1375    public static boolean isBuiltinRangeError() {
1376        final Global instance = Global.instance();
1377        return instance.rangeError == instance.getBuiltinRangeError();
1378    }
1379
1380    private ScriptFunction getBuiltinReferenceError() {
1381        return builtinReferenceError;
1382    }
1383
1384    /**
1385     * Called from compiled script code to test if builtin has been overridden
1386     *
1387     * @return true if builtin reference error has not been overridden
1388     */
1389    public static boolean isBuiltinReferenceError() {
1390        final Global instance = Global.instance();
1391        return instance.referenceError == instance.getBuiltinReferenceError();
1392    }
1393
1394    private ScriptFunction getBuiltinRegExp() {
1395        return builtinRegExp;
1396    }
1397
1398    /**
1399     * Called from compiled script code to test if builtin has been overridden
1400     *
1401     * @return true if builtin regexp has not been overridden
1402     */
1403    public static boolean isBuiltinRegExp() {
1404        final Global instance = Global.instance();
1405        return instance.regexp == instance.getBuiltinRegExp();
1406    }
1407
1408    private ScriptFunction getBuiltinString() {
1409        return builtinString;
1410    }
1411
1412    /**
1413     * Called from compiled script code to test if builtin has been overridden
1414     *
1415     * @return true if builtin Java has not been overridden
1416     */
1417    public static boolean isBuiltinString() {
1418        final Global instance = Global.instance();
1419        return instance.string == instance.getBuiltinString();
1420    }
1421
1422    private ScriptFunction getBuiltinSyntaxError() {
1423        return builtinSyntaxError;
1424    }
1425
1426    /**
1427     * Called from compiled script code to test if builtin has been overridden
1428     *
1429     * @return true if builtin syntax error has not been overridden
1430     */
1431    public static boolean isBuiltinSyntaxError() {
1432        final Global instance = Global.instance();
1433        return instance.syntaxError == instance.getBuiltinSyntaxError();
1434    }
1435
1436    private ScriptFunction getBuiltinTypeError() {
1437        return builtinTypeError;
1438    }
1439
1440    /**
1441     * Called from compiled script code to test if builtin has been overridden
1442     *
1443     * @return true if builtin type error has not been overridden
1444     */
1445    public static boolean isBuiltinTypeError() {
1446        final Global instance = Global.instance();
1447        return instance.typeError == instance.getBuiltinTypeError();
1448    }
1449
1450    private ScriptFunction getBuiltinURIError() {
1451        return builtinURIError;
1452    }
1453
1454    /**
1455     * Called from compiled script code to test if builtin has been overridden
1456     *
1457     * @return true if builtin URI error has not been overridden
1458     */
1459    public static boolean isBuiltinURIError() {
1460        final Global instance = Global.instance();
1461        return instance.uriError == instance.getBuiltinURIError();
1462    }
1463
1464    @Override
1465    public String getClassName() {
1466        return "global";
1467    }
1468
1469    /**
1470     * Copy function used to clone NativeRegExp objects.
1471     *
1472     * @param regexp a NativeRegExp to clone
1473     *
1474     * @return copy of the given regexp object
1475     */
1476    public static Object regExpCopy(final Object regexp) {
1477        return new NativeRegExp((NativeRegExp)regexp);
1478    }
1479
1480    /**
1481     * Convert given object to NativeRegExp type.
1482     *
1483     * @param obj object to be converted
1484     * @return NativeRegExp instance
1485     */
1486    public static NativeRegExp toRegExp(final Object obj) {
1487        if (obj instanceof NativeRegExp) {
1488            return (NativeRegExp)obj;
1489        }
1490        return new NativeRegExp(JSType.toString(obj));
1491    }
1492
1493    /**
1494     * ECMA 9.9 ToObject implementation
1495     *
1496     * @param obj  an item for which to run ToObject
1497     * @return ToObject version of given item
1498     */
1499    public static Object toObject(final Object obj) {
1500        if (obj == null || obj == UNDEFINED) {
1501            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1502        }
1503
1504        if (obj instanceof ScriptObject) {
1505            return obj;
1506        }
1507
1508        return instance().wrapAsObject(obj);
1509    }
1510
1511    /**
1512     * Allocate a new object array.
1513     *
1514     * @param initial object values.
1515     * @return the new array
1516     */
1517    public static NativeArray allocate(final Object[] initial) {
1518        ArrayData arrayData = ArrayData.allocate(initial);
1519
1520        for (int index = 0; index < initial.length; index++) {
1521            final Object value = initial[index];
1522
1523            if (value == ScriptRuntime.EMPTY) {
1524                arrayData = arrayData.delete(index);
1525            }
1526        }
1527
1528        return new NativeArray(arrayData);
1529    }
1530
1531    /**
1532     * Allocate a new number array.
1533     *
1534     * @param initial number values.
1535     * @return the new array
1536     */
1537    public static NativeArray allocate(final double[] initial) {
1538        return new NativeArray(ArrayData.allocate(initial));
1539    }
1540
1541    /**
1542     * Allocate a new long array.
1543     *
1544     * @param initial number values.
1545     * @return the new array
1546     */
1547    public static NativeArray allocate(final long[] initial) {
1548        return new NativeArray(ArrayData.allocate(initial));
1549    }
1550
1551    /**
1552     * Allocate a new integer array.
1553     *
1554     * @param initial number values.
1555     * @return the new array
1556     */
1557    public static NativeArray allocate(final int[] initial) {
1558        return new NativeArray(ArrayData.allocate(initial));
1559    }
1560
1561    /**
1562     * Allocate a new object array for arguments.
1563     *
1564     * @param arguments initial arguments passed.
1565     * @param callee reference to the function that uses arguments object
1566     * @param numParams actual number of declared parameters
1567     *
1568     * @return the new array
1569     */
1570    public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1571        return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1572    }
1573
1574    /**
1575     * Called from generated to check if given function is the builtin 'eval'. If
1576     * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1577     *
1578     * @param  fn function object that is checked
1579     * @return true if fn is the builtin eval
1580     */
1581    public static boolean isEval(final Object fn) {
1582        return fn == Global.instance().builtinEval;
1583    }
1584
1585    /**
1586     * Called from generated to replace a location property placeholder with the actual location property value.
1587     *
1588     * @param  placeholder the value tested for being a placeholder for a location property
1589     * @param  locationProperty the actual value for the location property
1590     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
1591     */
1592    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
1593        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
1594    }
1595
1596    /**
1597     * Called from runtime internals to check if the passed value is a location property placeholder.
1598     * @param  placeholder the value tested for being a placeholder for a location property
1599     * @return true if the value is a placeholder, false otherwise.
1600     */
1601    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
1602        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
1603    }
1604
1605    /**
1606     * Create a new RegExp object.
1607     *
1608     * @param expression Regular expression.
1609     * @param options    Search options.
1610     *
1611     * @return New RegExp object.
1612     */
1613    public static Object newRegExp(final String expression, final String options) {
1614        if (options == null) {
1615            return new NativeRegExp(expression);
1616        }
1617        return new NativeRegExp(expression, options);
1618    }
1619
1620    /**
1621     * Get the object prototype
1622     *
1623     * @return the object prototype
1624     */
1625    public static ScriptObject objectPrototype() {
1626        return Global.instance().getObjectPrototype();
1627    }
1628
1629    /**
1630     * Create a new empty object instance.
1631     *
1632     * @return New empty object.
1633     */
1634    public static ScriptObject newEmptyInstance() {
1635        return Global.instance().newObject();
1636    }
1637
1638    /**
1639     * Check if a given object is a ScriptObject, raises an exception if this is
1640     * not the case
1641     *
1642     * @param obj and object to check
1643     * @return the script object
1644     */
1645    public static ScriptObject checkObject(final Object obj) {
1646        if (!(obj instanceof ScriptObject)) {
1647            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1648        }
1649        return (ScriptObject)obj;
1650    }
1651
1652    /**
1653     * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1654     * if this object is null or undefined.
1655     *
1656     * @param obj an object to check
1657     */
1658    public static void checkObjectCoercible(final Object obj) {
1659        if (obj == null || obj == UNDEFINED) {
1660            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1661        }
1662    }
1663
1664    /**
1665     * Get the current split state.
1666     *
1667     * @return current split state
1668     */
1669    @Override
1670    public int getSplitState() {
1671        return splitState;
1672    }
1673
1674    /**
1675     * Set the current split state.
1676     *
1677     * @param state current split state
1678     */
1679    @Override
1680    public void setSplitState(final int state) {
1681        splitState = state;
1682    }
1683
1684    private void init(final ScriptEngine engine) {
1685        assert Context.getGlobal() == this : "this global is not set as current";
1686
1687        final ScriptEnvironment env = getContext().getEnv();
1688
1689        // initialize Function and Object constructor
1690        initFunctionAndObject();
1691
1692        // Now fix Global's own proto.
1693        this.setInitialProto(getObjectPrototype());
1694
1695        // initialize global function properties
1696        this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1697
1698        this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
1699                new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O });
1700        this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1701        this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1702        this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1703        this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1704        this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1705        this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1706        this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1707        this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1708        this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1709        this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1710        this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1711        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1712        this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1713        this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1714
1715        // built-in constructors
1716        this.builtinArray     = initConstructor("Array", ScriptFunction.class);
1717        this.builtinBoolean   = initConstructor("Boolean", ScriptFunction.class);
1718        this.builtinDate      = initConstructor("Date", ScriptFunction.class);
1719        this.builtinJSON      = initConstructor("JSON", ScriptObject.class);
1720        this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class);
1721        this.builtinMath      = initConstructor("Math", ScriptObject.class);
1722        this.builtinNumber    = initConstructor("Number", ScriptFunction.class);
1723        this.builtinRegExp    = initConstructor("RegExp", ScriptFunction.class);
1724        this.builtinString    = initConstructor("String", ScriptFunction.class);
1725
1726        // initialize String.prototype.length to 0
1727        // add String.prototype.length
1728        final ScriptObject stringPrototype = getStringPrototype();
1729        stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1730
1731        // set isArray flag on Array.prototype
1732        final ScriptObject arrayPrototype = getArrayPrototype();
1733        arrayPrototype.setIsArray();
1734
1735        this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1736
1737        // initialize default regexp object
1738        this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1739
1740        // RegExp.prototype should behave like a RegExp object. So copy the
1741        // properties.
1742        final ScriptObject regExpProto = getRegExpPrototype();
1743        regExpProto.addBoundProperties(DEFAULT_REGEXP);
1744
1745        // Error stuff
1746        initErrorObjects();
1747
1748        // java access
1749        if (! env._no_java) {
1750            initJavaAccess();
1751        }
1752
1753        if (! env._no_typed_arrays) {
1754            initTypedArray();
1755        }
1756
1757        if (env._scripting) {
1758            initScripting(env);
1759        }
1760
1761        if (Context.DEBUG) {
1762            boolean debugOkay;
1763            final SecurityManager sm = System.getSecurityManager();
1764            if (sm != null) {
1765                try {
1766                    sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1767                    debugOkay = true;
1768                } catch (final SecurityException ignored) {
1769                    // if no permission, don't initialize Debug object
1770                    debugOkay = false;
1771                }
1772
1773            } else {
1774                debugOkay = true;
1775            }
1776
1777            if (debugOkay) {
1778                initDebug();
1779            }
1780        }
1781
1782        copyBuiltins();
1783
1784        // expose script (command line) arguments as "arguments" property of global
1785        arguments = wrapAsObject(env.getArguments().toArray());
1786        if (env._scripting) {
1787            // synonym for "arguments" in scripting mode
1788            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
1789        }
1790
1791        if (engine != null) {
1792            final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE;
1793            scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null);
1794            addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine);
1795            // default file name
1796            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
1797            // __noSuchProperty__ hook for ScriptContext search of missing variables
1798            final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
1799            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
1800        }
1801    }
1802
1803    private void initErrorObjects() {
1804        // Error objects
1805        this.builtinError = initConstructor("Error", ScriptFunction.class);
1806        final ScriptObject errorProto = getErrorPrototype();
1807
1808        // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1809        final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1810        final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1811        errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1812        final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1813        final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1814        errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1815        final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1816        final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1817        errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1818        final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1819        final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1820        errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1821
1822        // ECMA 15.11.4.2 Error.prototype.name
1823        // Error.prototype.name = "Error";
1824        errorProto.set(NativeError.NAME, "Error", false);
1825        // ECMA 15.11.4.3 Error.prototype.message
1826        // Error.prototype.message = "";
1827        errorProto.set(NativeError.MESSAGE, "", false);
1828
1829        this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1830        this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1831        this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1832        this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1833        this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1834        this.builtinURIError = initErrorSubtype("URIError", errorProto);
1835    }
1836
1837    private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1838        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
1839        final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1840        prototype.set(NativeError.NAME, name, false);
1841        prototype.set(NativeError.MESSAGE, "", false);
1842        prototype.setInitialProto(errorProto);
1843        return cons;
1844    }
1845
1846    private void initJavaAccess() {
1847        final ScriptObject objectProto = getObjectPrototype();
1848        this.builtinPackages = new NativeJavaPackage("", objectProto);
1849        this.builtinCom = new NativeJavaPackage("com", objectProto);
1850        this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1851        this.builtinJava = new NativeJavaPackage("java", objectProto);
1852        this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1853        this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1854        this.builtinOrg = new NativeJavaPackage("org", objectProto);
1855        this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1856        this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1857    }
1858
1859    private void initScripting(final ScriptEnvironment scriptEnv) {
1860        Object value;
1861        value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1862        addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1863
1864        value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1865        addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1866
1867        final String execName = ScriptingFunctions.EXEC_NAME;
1868        value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1869        addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1870
1871        // Nashorn extension: global.echo (scripting-mode-only)
1872        // alias for "print"
1873        value = get("print");
1874        addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1875
1876        // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1877        final ScriptObject options = newObject();
1878        copyOptions(options, scriptEnv);
1879        addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1880
1881        // Nashorn extension: global.$ENV (scripting-mode-only)
1882        if (System.getSecurityManager() == null) {
1883            // do not fill $ENV if we have a security manager around
1884            // Retrieve current state of ENV variables.
1885            final ScriptObject env = newObject();
1886            env.putAll(System.getenv(), scriptEnv._strict);
1887            addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1888        } else {
1889            addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1890        }
1891
1892        // add other special properties for exec support
1893        addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1894        addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1895        addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1896    }
1897
1898    private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1899        for (final Field f : scriptEnv.getClass().getFields()) {
1900            try {
1901                options.set(f.getName(), f.get(scriptEnv), false);
1902            } catch (final IllegalArgumentException | IllegalAccessException exp) {
1903                throw new RuntimeException(exp);
1904            }
1905        }
1906    }
1907
1908    private void initTypedArray() {
1909        this.builtinArrayBuffer       = initConstructor("ArrayBuffer", ScriptFunction.class);
1910        this.builtinDataView          = initConstructor("DataView", ScriptFunction.class);
1911        this.builtinInt8Array         = initConstructor("Int8Array", ScriptFunction.class);
1912        this.builtinUint8Array        = initConstructor("Uint8Array", ScriptFunction.class);
1913        this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class);
1914        this.builtinInt16Array        = initConstructor("Int16Array", ScriptFunction.class);
1915        this.builtinUint16Array       = initConstructor("Uint16Array", ScriptFunction.class);
1916        this.builtinInt32Array        = initConstructor("Int32Array", ScriptFunction.class);
1917        this.builtinUint32Array       = initConstructor("Uint32Array", ScriptFunction.class);
1918        this.builtinFloat32Array      = initConstructor("Float32Array", ScriptFunction.class);
1919        this.builtinFloat64Array      = initConstructor("Float64Array", ScriptFunction.class);
1920    }
1921
1922    private void copyBuiltins() {
1923        this.array             = this.builtinArray;
1924        this._boolean          = this.builtinBoolean;
1925        this.date              = this.builtinDate;
1926        this.error             = this.builtinError;
1927        this.evalError         = this.builtinEvalError;
1928        this.function          = this.builtinFunction;
1929        this.jsadapter         = this.builtinJSAdapter;
1930        this.json              = this.builtinJSON;
1931        this.com               = this.builtinCom;
1932        this.edu               = this.builtinEdu;
1933        this.java              = this.builtinJava;
1934        this.javafx            = this.builtinJavafx;
1935        this.javax             = this.builtinJavax;
1936        this.org               = this.builtinOrg;
1937        this.javaImporter      = this.builtinJavaImporter;
1938        this.javaApi           = this.builtinJavaApi;
1939        this.math              = this.builtinMath;
1940        this.number            = this.builtinNumber;
1941        this.object            = this.builtinObject;
1942        this.packages          = this.builtinPackages;
1943        this.rangeError        = this.builtinRangeError;
1944        this.referenceError    = this.builtinReferenceError;
1945        this.regexp            = this.builtinRegExp;
1946        this.string            = this.builtinString;
1947        this.syntaxError       = this.builtinSyntaxError;
1948        this.typeError         = this.builtinTypeError;
1949        this.uriError          = this.builtinURIError;
1950        this.arrayBuffer       = this.builtinArrayBuffer;
1951        this.dataView          = this.builtinDataView;
1952        this.int8Array         = this.builtinInt8Array;
1953        this.uint8Array        = this.builtinUint8Array;
1954        this.uint8ClampedArray = this.builtinUint8ClampedArray;
1955        this.int16Array        = this.builtinInt16Array;
1956        this.uint16Array       = this.builtinUint16Array;
1957        this.int32Array        = this.builtinInt32Array;
1958        this.uint32Array       = this.builtinUint32Array;
1959        this.float32Array      = this.builtinFloat32Array;
1960        this.float64Array      = this.builtinFloat64Array;
1961    }
1962
1963    private void initDebug() {
1964        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
1965    }
1966
1967    private Object printImpl(final boolean newLine, final Object... objects) {
1968        @SuppressWarnings("resource")
1969        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
1970        final StringBuilder sb = new StringBuilder();
1971
1972        for (final Object obj : objects) {
1973            if (sb.length() != 0) {
1974                sb.append(' ');
1975            }
1976
1977            sb.append(JSType.toString(obj));
1978        }
1979
1980        // Print all at once to ensure thread friendly result.
1981        if (newLine) {
1982            out.println(sb.toString());
1983        } else {
1984            out.print(sb.toString());
1985        }
1986
1987        out.flush();
1988
1989        return UNDEFINED;
1990    }
1991
1992    /**
1993     * These classes are generated by nasgen tool and so we have to use
1994     * reflection to load and create new instance of these classes.
1995     */
1996    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
1997        try {
1998            // Assuming class name pattern for built-in JS constructors.
1999            final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2000
2001            sb.append("Native");
2002            sb.append(name);
2003            sb.append("$Constructor");
2004
2005            final Class<?> funcClass = Class.forName(sb.toString());
2006            final T res = clazz.cast(funcClass.newInstance());
2007
2008            if (res instanceof ScriptFunction) {
2009                // All global constructor prototypes are not-writable,
2010                // not-enumerable and not-configurable.
2011                final ScriptFunction func = (ScriptFunction)res;
2012                func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2013            }
2014
2015            if (res.getProto() == null) {
2016                res.setInitialProto(getObjectPrototype());
2017            }
2018
2019            res.setIsBuiltin();
2020            return res;
2021        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2022            throw new RuntimeException(e);
2023        }
2024    }
2025
2026    // Function and Object constructors are inter-dependent. Also,
2027    // Function.prototype
2028    // functions are not properly initialized. We fix the references here.
2029    // NOTE: be careful if you want to re-order the operations here. You may
2030    // have
2031    // to play with object references carefully!!
2032    private void initFunctionAndObject() {
2033        // First-n-foremost is Function
2034        this.builtinFunction      = initConstructor("Function", ScriptFunction.class);
2035
2036        // create global anonymous function
2037        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2038        // need to copy over members of Function.prototype to anon function
2039        anon.addBoundProperties(getFunctionPrototype());
2040
2041        // Function.prototype === Object.getPrototypeOf(Function) ===
2042        // <anon-function>
2043        builtinFunction.setInitialProto(anon);
2044        builtinFunction.setPrototype(anon);
2045        anon.set("constructor", builtinFunction, false);
2046        anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2047
2048        // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2049        this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2050        typeErrorThrower.setPrototype(UNDEFINED);
2051        // Non-constructor built-in functions do not have "prototype" property
2052        typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2053        typeErrorThrower.preventExtensions();
2054
2055        // now initialize Object
2056        this.builtinObject = initConstructor("Object", ScriptFunction.class);
2057        final ScriptObject ObjectPrototype = getObjectPrototype();
2058        // Object.getPrototypeOf(Function.prototype) === Object.prototype
2059        anon.setInitialProto(ObjectPrototype);
2060
2061        // ES6 draft compliant __proto__ property of Object.prototype
2062        // accessors on Object.prototype for "__proto__"
2063        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2064        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2065        ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2066
2067        // Function valued properties of Function.prototype were not properly
2068        // initialized. Because, these were created before global.function and
2069        // global.object were not initialized.
2070        jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2071        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2072            final Object key = property.getKey();
2073            final Object value = builtinFunction.get(key);
2074
2075            if (value instanceof ScriptFunction && value != anon) {
2076                final ScriptFunction func = (ScriptFunction)value;
2077                func.setInitialProto(getFunctionPrototype());
2078                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2079                if (prototype != null) {
2080                    prototype.setInitialProto(ObjectPrototype);
2081                }
2082            }
2083        }
2084
2085        // For function valued properties of Object and Object.prototype, make
2086        // sure prototype's proto chain ends with Object.prototype
2087        for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2088            final Object key = property.getKey();
2089            final Object value = builtinObject.get(key);
2090
2091            if (value instanceof ScriptFunction) {
2092                final ScriptFunction func = (ScriptFunction)value;
2093                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2094                if (prototype != null) {
2095                    prototype.setInitialProto(ObjectPrototype);
2096                }
2097            }
2098        }
2099
2100        //make sure apply and call have the same invalidation switchpoint
2101        final SwitchPoint sp = new SwitchPoint();
2102        optimisticFunctionMap.put("apply", sp);
2103        optimisticFunctionMap.put("call", sp);
2104        getFunctionPrototype().getProperty("apply").setChangeCallback(sp);
2105        getFunctionPrototype().getProperty("call").setChangeCallback(sp);
2106
2107        properties = getObjectPrototype().getMap().getProperties();
2108
2109        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2110            final Object key   = property.getKey();
2111            if (key.equals("constructor")) {
2112                continue;
2113            }
2114
2115            final Object value = ObjectPrototype.get(key);
2116            if (value instanceof ScriptFunction) {
2117                final ScriptFunction func = (ScriptFunction)value;
2118                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2119                if (prototype != null) {
2120                    prototype.setInitialProto(ObjectPrototype);
2121                }
2122            }
2123        }
2124    }
2125
2126    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
2127        return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2128    }
2129
2130    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2131        return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2132    }
2133
2134    RegExpResult getLastRegExpResult() {
2135        return lastRegExpResult;
2136    }
2137
2138    void setLastRegExpResult(final RegExpResult regExpResult) {
2139        this.lastRegExpResult = regExpResult;
2140    }
2141
2142    @Override
2143    protected boolean isGlobal() {
2144        return true;
2145    }
2146
2147    /**
2148     * Check if there is a switchpoint for a reserved name. If there
2149     * is, it must be invalidated upon properties with this name
2150     * @param name property name
2151     * @return switchpoint for invalidating this property, or null if not registered
2152     */
2153    public SwitchPoint getChangeCallback(final String name) {
2154        return optimisticFunctionMap.get(name);
2155    }
2156
2157    /**
2158     * Is this a special name, that might be subject to invalidation
2159     * on write, such as "apply" or "call"
2160     * @param name name to check
2161     * @return true if special name
2162     */
2163    public boolean isSpecialName(final String name) {
2164        return getChangeCallback(name) != null;
2165    }
2166
2167    /**
2168     * Check if a reserved property name is invalidated
2169     * @param name property name
2170     * @return true if someone has written to it since Global was instantiated
2171     */
2172    public boolean isSpecialNameValid(final String name) {
2173        final SwitchPoint sp = getChangeCallback(name);
2174        return sp != null && !sp.hasBeenInvalidated();
2175    }
2176
2177    /**
2178     * Tag a reserved name as invalidated - used when someone writes
2179     * to a property with this name - overly conservative, but link time
2180     * is too late to apply e.g. apply-&gt;call specialization
2181     * @param name property name
2182     */
2183    public void invalidateReservedName(final String name) {
2184        final SwitchPoint sp = getChangeCallback(name);
2185        if (sp != null) {
2186            getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
2187            SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
2188        }
2189    }
2190
2191    /**
2192     * Bootstrapper for invalidating a builtin name
2193     * @param lookup lookup
2194     * @param name   name to invalidate
2195     * @param type   methodhandle type
2196     * @return callsite for invalidator
2197     */
2198    public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) {
2199        final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name);
2200        return new ConstantCallSite(target);
2201    }
2202
2203
2204}
2205