Global.java revision 1033:c1f651636d9c
1238104Sdes/*
2238104Sdes * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3238104Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4238104Sdes *
5238104Sdes * This code is free software; you can redistribute it and/or modify it
6238104Sdes * under the terms of the GNU General Public License version 2 only, as
7238104Sdes * published by the Free Software Foundation.  Oracle designates this
8238104Sdes * particular file as subject to the "Classpath" exception as provided
9238104Sdes * by Oracle in the LICENSE file that accompanied this code.
10238104Sdes *
11238104Sdes * This code is distributed in the hope that it will be useful, but WITHOUT
12238104Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13238104Sdes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14238104Sdes * version 2 for more details (a copy is included in the LICENSE file that
15238104Sdes * accompanied this code).
16238104Sdes *
17238104Sdes * You should have received a copy of the GNU General Public License version
18238104Sdes * 2 along with this work; if not, write to the Free Software Foundation,
19238104Sdes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20238104Sdes *
21238104Sdes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22238104Sdes * or visit www.oracle.com if you need additional information or have any
23238104Sdes * questions.
24238104Sdes */
25249307Sdes
26249307Sdespackage jdk.nashorn.internal.objects;
27238104Sdes
28238104Sdesimport static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
29238104Sdesimport static jdk.nashorn.internal.lookup.Lookup.MH;
30238104Sdesimport static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
31238104Sdesimport static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
32238104Sdesimport static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
33238104Sdes
34249307Sdesimport java.io.IOException;
35249307Sdesimport java.io.PrintWriter;
36249307Sdesimport java.lang.invoke.CallSite;
37249307Sdesimport java.lang.invoke.ConstantCallSite;
38238104Sdesimport java.lang.invoke.MethodHandle;
39238104Sdesimport java.lang.invoke.MethodHandles;
40269257Sdesimport java.lang.invoke.MethodType;
41238104Sdesimport java.lang.invoke.SwitchPoint;
42238104Sdesimport java.lang.reflect.Field;
43238104Sdesimport java.util.Arrays;
44269257Sdesimport java.util.HashMap;
45238104Sdesimport java.util.Map;
46238104Sdesimport java.util.concurrent.Callable;
47238104Sdesimport java.util.concurrent.ConcurrentHashMap;
48238104Sdesimport java.util.concurrent.atomic.AtomicReference;
49238104Sdesimport javax.script.ScriptContext;
50238104Sdesimport javax.script.ScriptEngine;
51238104Sdesimport jdk.internal.dynalink.linker.GuardedInvocation;
52238104Sdesimport jdk.internal.dynalink.linker.LinkRequest;
53238104Sdesimport jdk.nashorn.api.scripting.ClassFilter;
54238104Sdesimport jdk.nashorn.api.scripting.ScriptObjectMirror;
55238104Sdesimport jdk.nashorn.internal.codegen.ApplySpecialization;
56238104Sdesimport jdk.nashorn.internal.codegen.CompilerConstants.Call;
57238104Sdesimport jdk.nashorn.internal.lookup.Lookup;
58238104Sdesimport jdk.nashorn.internal.objects.annotations.Attribute;
59238104Sdesimport jdk.nashorn.internal.objects.annotations.Property;
60238104Sdesimport jdk.nashorn.internal.objects.annotations.ScriptClass;
61238104Sdesimport jdk.nashorn.internal.runtime.ConsString;
62238104Sdesimport jdk.nashorn.internal.runtime.Context;
63238104Sdesimport jdk.nashorn.internal.runtime.GlobalConstants;
64238104Sdesimport jdk.nashorn.internal.runtime.GlobalFunctions;
65238104Sdesimport jdk.nashorn.internal.runtime.JSType;
66238104Sdesimport jdk.nashorn.internal.runtime.NativeJavaPackage;
67249307Sdesimport jdk.nashorn.internal.runtime.PropertyDescriptor;
68249307Sdesimport jdk.nashorn.internal.runtime.PropertyMap;
69249307Sdesimport jdk.nashorn.internal.runtime.Scope;
70249307Sdesimport jdk.nashorn.internal.runtime.ScriptEnvironment;
71238104Sdesimport jdk.nashorn.internal.runtime.ScriptFunction;
72238104Sdesimport jdk.nashorn.internal.runtime.ScriptObject;
73238104Sdesimport jdk.nashorn.internal.runtime.ScriptRuntime;
74238104Sdesimport jdk.nashorn.internal.runtime.ScriptingFunctions;
75238104Sdesimport jdk.nashorn.internal.runtime.arrays.ArrayData;
76238104Sdesimport jdk.nashorn.internal.runtime.linker.Bootstrap;
77238104Sdesimport jdk.nashorn.internal.runtime.linker.InvokeByName;
78238104Sdesimport jdk.nashorn.internal.runtime.regexp.RegExpResult;
79238104Sdesimport jdk.nashorn.internal.scripts.JO;
80238104Sdes
81238104Sdes/**
82238104Sdes * Representation of global scope.
83238104Sdes */
84238104Sdes@ScriptClass("Global")
85238104Sdespublic final class Global extends ScriptObject implements Scope {
86238104Sdes    // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
87238104Sdes    private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
88238104Sdes    private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
89238104Sdes    private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
90238104Sdes
91238104Sdes    /**
92238104Sdes     * Optimistic builtin names that require switchpoint invalidation
93238104Sdes     * upon assignment. Overly conservative, but works for now, to avoid
94238104Sdes     * any complicated scope checks and especially heavy weight guards
95238104Sdes     * like
96238104Sdes     *
97238104Sdes     * <pre>
98238104Sdes     *     public boolean setterGuard(final Object receiver) {
99238104Sdes     *         final Global          global = Global.instance();
100238104Sdes     *         final ScriptObject    sobj   = global.getFunctionPrototype();
101238104Sdes     *         final Object          apply  = sobj.get("apply");
102238104Sdes     *         return apply == receiver;
103238104Sdes     *     }
104238104Sdes     * </pre>
105238104Sdes     *
106238104Sdes     * Naturally, checking for builtin classes like NativeFunction is cheaper,
107238104Sdes     * it's when you start adding property checks for said builtins you have
108238104Sdes     * problems with guard speed.
109238104Sdes     */
110238104Sdes    public final Map<String, SwitchPoint> optimisticFunctionMap;
111238104Sdes
112238104Sdes    /** Name invalidator for things like call/apply */
113238104Sdes    public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
114238104Sdes
115238104Sdes    /** Nashorn extension: arguments array */
116238104Sdes    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
117238104Sdes    public Object arguments;
118238104Sdes
119238104Sdes    /** ECMA 15.1.2.2 parseInt (string , radix) */
120238104Sdes    @Property(attributes = Attribute.NOT_ENUMERABLE)
121238104Sdes    public Object parseInt;
122238104Sdes
123238104Sdes    /** ECMA 15.1.2.3 parseFloat (string) */
124238104Sdes    @Property(attributes = Attribute.NOT_ENUMERABLE)
125238104Sdes    public Object parseFloat;
126238104Sdes
127238104Sdes    /** ECMA 15.1.2.4 isNaN (number) */
128238104Sdes    @Property(attributes = Attribute.NOT_ENUMERABLE)
129    public Object isNaN;
130
131    /** ECMA 15.1.2.5 isFinite (number) */
132    @Property(attributes = Attribute.NOT_ENUMERABLE)
133    public Object isFinite;
134
135    /** ECMA 15.1.3.3 encodeURI */
136    @Property(attributes = Attribute.NOT_ENUMERABLE)
137    public Object encodeURI;
138
139    /** ECMA 15.1.3.4 encodeURIComponent */
140    @Property(attributes = Attribute.NOT_ENUMERABLE)
141    public Object encodeURIComponent;
142
143    /** ECMA 15.1.3.1 decodeURI */
144    @Property(attributes = Attribute.NOT_ENUMERABLE)
145    public Object decodeURI;
146
147    /** ECMA 15.1.3.2 decodeURIComponent */
148    @Property(attributes = Attribute.NOT_ENUMERABLE)
149    public Object decodeURIComponent;
150
151    /** ECMA B.2.1 escape (string) */
152    @Property(attributes = Attribute.NOT_ENUMERABLE)
153    public Object escape;
154
155    /** ECMA B.2.2 unescape (string) */
156    @Property(attributes = Attribute.NOT_ENUMERABLE)
157    public Object unescape;
158
159    /** Nashorn extension: global.print */
160    @Property(attributes = Attribute.NOT_ENUMERABLE)
161    public Object print;
162
163    /** Nashorn extension: global.load */
164    @Property(attributes = Attribute.NOT_ENUMERABLE)
165    public Object load;
166
167    /** Nashorn extension: global.loadWithNewGlobal */
168    @Property(attributes = Attribute.NOT_ENUMERABLE)
169    public Object loadWithNewGlobal;
170
171    /** Nashorn extension: global.exit */
172    @Property(attributes = Attribute.NOT_ENUMERABLE)
173    public Object exit;
174
175    /** Nashorn extension: global.quit */
176    @Property(attributes = Attribute.NOT_ENUMERABLE)
177    public Object quit;
178
179    /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
180    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
181    public final double NaN = Double.NaN;
182
183    /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
184    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
185    public final double Infinity = Double.POSITIVE_INFINITY;
186
187    /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
188    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
189    public final Object undefined = UNDEFINED;
190
191    /** ECMA 15.1.2.1 eval(x) */
192    @Property(attributes = Attribute.NOT_ENUMERABLE)
193    public Object eval;
194
195    /** ECMA 15.1.4.1 Object constructor. */
196    @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
197    public volatile Object object;
198
199    /** ECMA 15.1.4.2 Function constructor. */
200    @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
201    public volatile Object function;
202
203    /** ECMA 15.1.4.3 Array constructor. */
204    @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
205    public volatile Object array;
206
207    /** ECMA 15.1.4.4 String constructor */
208    @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
209    public volatile Object string;
210
211    /** ECMA 15.1.4.5 Boolean constructor */
212    @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
213    public volatile Object _boolean;
214
215    /** ECMA 15.1.4.6 - Number constructor */
216    @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
217    public volatile Object number;
218
219    /** ECMA 15.1.4.7 Date constructor */
220    @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
221    public volatile Object date;
222
223    /** ECMA 15.1.4.8 RegExp constructor */
224    @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
225    public volatile Object regexp;
226
227    /** ECMA 15.12 - The JSON object */
228    @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
229    public volatile Object json;
230
231    /** Nashorn extension: global.JSAdapter */
232    @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
233    public volatile Object jsadapter;
234
235    /** ECMA 15.8 - The Math object */
236    @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
237    public volatile Object math;
238
239    /** Error object */
240    @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
241    public volatile Object error;
242
243    /** EvalError object */
244    @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
245    public volatile Object evalError;
246
247    /** RangeError object */
248    @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
249    public volatile Object rangeError;
250
251    /** ReferenceError object */
252    @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
253    public volatile Object referenceError;
254
255    /** SyntaxError object */
256    @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
257    public volatile Object syntaxError;
258
259    /** TypeError object */
260    @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
261    public volatile Object typeError;
262
263    /** URIError object */
264    @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
265    public volatile Object uriError;
266
267    /** ArrayBuffer object */
268    @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
269    public volatile Object arrayBuffer;
270
271    /** DataView object */
272    @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
273    public volatile Object dataView;
274
275    /** TypedArray (int8) */
276    @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
277    public volatile Object int8Array;
278
279    /** TypedArray (uint8) */
280    @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
281    public volatile Object uint8Array;
282
283    /** TypedArray (uint8) - Clamped */
284    @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
285    public volatile Object uint8ClampedArray;
286
287    /** TypedArray (int16) */
288    @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
289    public volatile Object int16Array;
290
291    /** TypedArray (uint16) */
292    @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
293    public volatile Object uint16Array;
294
295    /** TypedArray (int32) */
296    @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
297    public volatile Object int32Array;
298
299    /** TypedArray (uint32) */
300    @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
301    public volatile Object uint32Array;
302
303    /** TypedArray (float32) */
304    @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
305    public volatile Object float32Array;
306
307    /** TypedArray (float64) */
308    @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
309    public volatile Object float64Array;
310
311    /** Nashorn extension: Java access - global.Packages */
312    @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
313    public volatile Object packages;
314
315    /** Nashorn extension: Java access - global.com */
316    @Property(attributes = Attribute.NOT_ENUMERABLE)
317    public volatile Object com;
318
319    /** Nashorn extension: Java access - global.edu */
320    @Property(attributes = Attribute.NOT_ENUMERABLE)
321    public volatile Object edu;
322
323    /** Nashorn extension: Java access - global.java */
324    @Property(attributes = Attribute.NOT_ENUMERABLE)
325    public volatile Object java;
326
327    /** Nashorn extension: Java access - global.javafx */
328    @Property(attributes = Attribute.NOT_ENUMERABLE)
329    public volatile Object javafx;
330
331    /** Nashorn extension: Java access - global.javax */
332    @Property(attributes = Attribute.NOT_ENUMERABLE)
333    public volatile Object javax;
334
335    /** Nashorn extension: Java access - global.org */
336    @Property(attributes = Attribute.NOT_ENUMERABLE)
337    public volatile Object org;
338
339    /** Nashorn extension: Java access - global.javaImporter */
340    @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
341    public volatile Object javaImporter;
342
343    /** Nashorn extension: global.Java Object constructor. */
344    @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
345    public volatile Object javaApi;
346
347    /** Nashorn extension: current script's file name */
348    @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
349    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
350
351    /** Nashorn extension: current script's directory */
352    @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
353    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
354
355    /** Nashorn extension: current source line number being executed */
356    @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
357    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
358
359    /** Used as Date.prototype's default value */
360    public NativeDate   DEFAULT_DATE;
361
362    /** Used as RegExp.prototype's default value */
363    public NativeRegExp DEFAULT_REGEXP;
364
365    /*
366     * Built-in constructor objects: Even if user changes dynamic values of
367     * "Object", "Array" etc., we still want to keep original values of these
368     * constructors here. For example, we need to be able to create array,
369     * regexp literals even after user overwrites global "Array" or "RegExp"
370     * constructor - see also ECMA 262 spec. Annex D.
371     */
372    private ScriptFunction builtinFunction;
373    private ScriptFunction builtinObject;
374    private ScriptFunction builtinArray;
375    private ScriptFunction builtinBoolean;
376    private ScriptFunction builtinDate;
377    private ScriptObject   builtinJSON;
378    private ScriptFunction builtinJSAdapter;
379    private ScriptObject   builtinMath;
380    private ScriptFunction builtinNumber;
381    private ScriptFunction builtinRegExp;
382    private ScriptFunction builtinString;
383    private ScriptFunction builtinError;
384    private ScriptFunction builtinEval;
385    private ScriptFunction builtinEvalError;
386    private ScriptFunction builtinRangeError;
387    private ScriptFunction builtinReferenceError;
388    private ScriptFunction builtinSyntaxError;
389    private ScriptFunction builtinTypeError;
390    private ScriptFunction builtinURIError;
391    private ScriptObject   builtinPackages;
392    private ScriptObject   builtinCom;
393    private ScriptObject   builtinEdu;
394    private ScriptObject   builtinJava;
395    private ScriptObject   builtinJavafx;
396    private ScriptObject   builtinJavax;
397    private ScriptObject   builtinOrg;
398    private ScriptFunction builtinJavaImporter;
399    private ScriptObject   builtinJavaApi;
400    private ScriptFunction builtinArrayBuffer;
401    private ScriptFunction builtinDataView;
402    private ScriptFunction builtinInt8Array;
403    private ScriptFunction builtinUint8Array;
404    private ScriptFunction builtinUint8ClampedArray;
405    private ScriptFunction builtinInt16Array;
406    private ScriptFunction builtinUint16Array;
407    private ScriptFunction builtinInt32Array;
408    private ScriptFunction builtinUint32Array;
409    private ScriptFunction builtinFloat32Array;
410    private ScriptFunction builtinFloat64Array;
411
412    /*
413     * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
414     */
415    private ScriptFunction typeErrorThrower;
416
417    // Flag to indicate that a split method issued a return statement
418    private int splitState = -1;
419
420    // Used to store the last RegExp result to support deprecated RegExp constructor properties
421    private RegExpResult lastRegExpResult;
422
423    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
424    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
425    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
426    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
427    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
428    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
429    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
430
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    // current ScriptEngine associated - can be null.
443    private ScriptEngine engine;
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    }
452
453    // global constants for this global - they can be replaced with MethodHandle.constant until invalidated
454    private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
455
456    @Override
457    protected Context getContext() {
458        return context;
459    }
460
461    // performs initialization checks for Global constructor and returns the
462    // PropertyMap, if everything is fine.
463    private static PropertyMap checkAndGetMap(final Context context) {
464        // security check first
465        final SecurityManager sm = System.getSecurityManager();
466        if (sm != null) {
467            sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
468        }
469
470        // null check on context
471        context.getClass();
472
473        return $nasgenmap$;
474    }
475
476    /**
477     * Constructor
478     *
479     * @param context the context
480     */
481    public Global(final Context context) {
482        super(checkAndGetMap(context));
483        this.context = context;
484        this.setIsScope();
485        this.optimisticFunctionMap = new HashMap<>();
486        //we can only share one instance of Global constants between globals, or we consume way too much
487        //memory - this is good enough for most programs
488        while (gcsInstance.get() == null) {
489            gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class)));
490        }
491    }
492
493    /**
494     * Script access to "current" Global instance
495     *
496     * @return the global singleton
497     */
498    public static Global instance() {
499        final Global global = Context.getGlobal();
500        global.getClass(); // null check
501        return global;
502    }
503
504    private static Global instanceFrom(final Object self) {
505        return self instanceof Global? (Global)self : instance();
506    }
507
508    /**
509     * Return the global constants map for fields that
510     * can be accessed as MethodHandle.constant
511     * @return constant map
512     */
513    public static GlobalConstants getConstants() {
514        return gcsInstance.get();
515    }
516
517    /**
518     * Check if we have a Global instance
519     * @return true if one exists
520     */
521    public static boolean hasInstance() {
522        return Context.getGlobal() != null;
523    }
524
525    /**
526     * Script access to {@link ScriptEnvironment}
527     *
528     * @return the script environment
529     */
530    static ScriptEnvironment getEnv() {
531        return instance().getContext().getEnv();
532    }
533
534    /**
535     * Script access to {@link Context}
536     *
537     * @return the context
538     */
539    static Context getThisContext() {
540        return instance().getContext();
541    }
542
543    // Runtime interface to Global
544
545    /**
546     * Is there a class filter in the current Context?
547     * @return class filter
548     */
549    public ClassFilter getClassFilter() {
550        return context.getClassFilter();
551    }
552
553    /**
554     * Is this global of the given Context?
555     * @param ctxt the context
556     * @return true if this global belongs to the given Context
557     */
558    public boolean isOfContext(final Context ctxt) {
559        return this.context == ctxt;
560    }
561
562    /**
563     * Does this global belong to a strict Context?
564     * @return true if this global belongs to a strict Context
565     */
566    public boolean isStrictContext() {
567        return context.getEnv()._strict;
568    }
569
570    /**
571     * Initialize standard builtin objects like "Object", "Array", "Function" etc.
572     * as well as our extension builtin objects like "Java", "JSAdapter" as properties
573     * of the global scope object.
574     *
575     * @param engine ScriptEngine to initialize
576     */
577    public void initBuiltinObjects(final ScriptEngine engine) {
578        if (this.builtinObject != null) {
579            // already initialized, just return
580            return;
581        }
582
583        this.engine = engine;
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        switch (nameStr) {
921            case "context":
922                return sctxt;
923            case "engine":
924                return global.engine;
925        }
926
927        if (self == UNDEFINED) {
928            // scope access and so throw ReferenceError
929            throw referenceError(global, "not.defined", nameStr);
930        }
931
932        return UNDEFINED;
933    }
934
935    /**
936     * This is the eval used when 'indirect' eval call is made.
937     *
938     * var global = this;
939     * global.eval("print('hello')");
940     *
941     * @param self  eval scope
942     * @param str   eval string
943     *
944     * @return the result of eval
945     */
946    public static Object eval(final Object self, final Object str) {
947        return directEval(self, str, UNDEFINED, UNDEFINED, false);
948    }
949
950    /**
951     * Direct eval
952     *
953     * @param self     The scope of eval passed as 'self'
954     * @param str      Evaluated code
955     * @param callThis "this" to be passed to the evaluated code
956     * @param location location of the eval call
957     * @param strict   is eval called a strict mode code?
958     *
959     * @return the return value of the eval
960     *
961     * This is directly invoked from generated when eval(code) is called in user code
962     */
963    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
964        if (!(str instanceof String || str instanceof ConsString)) {
965            return str;
966        }
967        final Global global = Global.instanceFrom(self);
968        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
969
970        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
971    }
972
973    /**
974     * Global print implementation - Nashorn extension
975     *
976     * @param self    scope
977     * @param objects arguments to print
978     *
979     * @return result of print (undefined)
980     */
981    public static Object print(final Object self, final Object... objects) {
982        return Global.instanceFrom(self).printImpl(false, objects);
983    }
984
985    /**
986     * Global println implementation - Nashorn extension
987     *
988     * @param self    scope
989     * @param objects arguments to print
990     *
991     * @return result of println (undefined)
992     */
993    public static Object println(final Object self, final Object... objects) {
994        return Global.instanceFrom(self).printImpl(true, objects);
995    }
996
997    /**
998     * Global load implementation - Nashorn extension
999     *
1000     * @param self    scope
1001     * @param source  source to load
1002     *
1003     * @return result of load (undefined)
1004     *
1005     * @throws IOException if source could not be read
1006     */
1007    public static Object load(final Object self, final Object source) throws IOException {
1008        final Global global = Global.instanceFrom(self);
1009        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
1010        return global.getContext().load(scope, source);
1011    }
1012
1013    /**
1014     * Global loadWithNewGlobal implementation - Nashorn extension
1015     *
1016     * @param self scope
1017     * @param args from plus (optional) arguments to be passed to the loaded script
1018     *
1019     * @return result of load (may be undefined)
1020     *
1021     * @throws IOException if source could not be read
1022     */
1023    public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1024        final Global global = Global.instanceFrom(self);
1025        final int length = args.length;
1026        final boolean hasArgs = 0 < length;
1027        final Object from = hasArgs ? args[0] : UNDEFINED;
1028        final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1029
1030        return global.getContext().loadWithNewGlobal(from, arguments);
1031    }
1032
1033    /**
1034     * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1035     *
1036     * @param self  self reference
1037     * @param code  exit code
1038     *
1039     * @return undefined (will never be reached)
1040     */
1041    public static Object exit(final Object self, final Object code) {
1042        System.exit(JSType.toInt32(code));
1043        return UNDEFINED;
1044    }
1045
1046    // builtin prototype accessors
1047    ScriptObject getFunctionPrototype() {
1048        return ScriptFunction.getPrototype(builtinFunction);
1049    }
1050
1051    ScriptObject getObjectPrototype() {
1052        return ScriptFunction.getPrototype(builtinObject);
1053    }
1054
1055    ScriptObject getArrayPrototype() {
1056        return ScriptFunction.getPrototype(builtinArray);
1057    }
1058
1059    ScriptObject getBooleanPrototype() {
1060        return ScriptFunction.getPrototype(builtinBoolean);
1061    }
1062
1063    ScriptObject getNumberPrototype() {
1064        return ScriptFunction.getPrototype(builtinNumber);
1065    }
1066
1067    ScriptObject getDatePrototype() {
1068        return ScriptFunction.getPrototype(builtinDate);
1069    }
1070
1071    ScriptObject getRegExpPrototype() {
1072        return ScriptFunction.getPrototype(builtinRegExp);
1073    }
1074
1075    ScriptObject getStringPrototype() {
1076        return ScriptFunction.getPrototype(builtinString);
1077    }
1078
1079    ScriptObject getErrorPrototype() {
1080        return ScriptFunction.getPrototype(builtinError);
1081    }
1082
1083    ScriptObject getEvalErrorPrototype() {
1084        return ScriptFunction.getPrototype(builtinEvalError);
1085    }
1086
1087    ScriptObject getRangeErrorPrototype() {
1088        return ScriptFunction.getPrototype(builtinRangeError);
1089    }
1090
1091    ScriptObject getReferenceErrorPrototype() {
1092        return ScriptFunction.getPrototype(builtinReferenceError);
1093    }
1094
1095    ScriptObject getSyntaxErrorPrototype() {
1096        return ScriptFunction.getPrototype(builtinSyntaxError);
1097    }
1098
1099    ScriptObject getTypeErrorPrototype() {
1100        return ScriptFunction.getPrototype(builtinTypeError);
1101    }
1102
1103    ScriptObject getURIErrorPrototype() {
1104        return ScriptFunction.getPrototype(builtinURIError);
1105    }
1106
1107    ScriptObject getJavaImporterPrototype() {
1108        return ScriptFunction.getPrototype(builtinJavaImporter);
1109    }
1110
1111    ScriptObject getJSAdapterPrototype() {
1112        return ScriptFunction.getPrototype(builtinJSAdapter);
1113    }
1114
1115    ScriptObject getArrayBufferPrototype() {
1116        return ScriptFunction.getPrototype(builtinArrayBuffer);
1117    }
1118
1119    ScriptObject getDataViewPrototype() {
1120        return ScriptFunction.getPrototype(builtinDataView);
1121    }
1122
1123    ScriptObject getInt8ArrayPrototype() {
1124        return ScriptFunction.getPrototype(builtinInt8Array);
1125    }
1126
1127    ScriptObject getUint8ArrayPrototype() {
1128        return ScriptFunction.getPrototype(builtinUint8Array);
1129    }
1130
1131    ScriptObject getUint8ClampedArrayPrototype() {
1132        return ScriptFunction.getPrototype(builtinUint8ClampedArray);
1133    }
1134
1135    ScriptObject getInt16ArrayPrototype() {
1136        return ScriptFunction.getPrototype(builtinInt16Array);
1137    }
1138
1139    ScriptObject getUint16ArrayPrototype() {
1140        return ScriptFunction.getPrototype(builtinUint16Array);
1141    }
1142
1143    ScriptObject getInt32ArrayPrototype() {
1144        return ScriptFunction.getPrototype(builtinInt32Array);
1145    }
1146
1147    ScriptObject getUint32ArrayPrototype() {
1148        return ScriptFunction.getPrototype(builtinUint32Array);
1149    }
1150
1151    ScriptObject getFloat32ArrayPrototype() {
1152        return ScriptFunction.getPrototype(builtinFloat32Array);
1153    }
1154
1155    ScriptObject getFloat64ArrayPrototype() {
1156        return ScriptFunction.getPrototype(builtinFloat64Array);
1157    }
1158
1159    private ScriptFunction getBuiltinArray() {
1160        return builtinArray;
1161    }
1162
1163    ScriptFunction getTypeErrorThrower() {
1164        return typeErrorThrower;
1165    }
1166
1167    /**
1168     * Called from compiled script code to test if builtin has been overridden
1169     *
1170     * @return true if builtin array has not been overridden
1171     */
1172    public static boolean isBuiltinArray() {
1173        final Global instance = Global.instance();
1174        return instance.array == instance.getBuiltinArray();
1175    }
1176
1177    private ScriptFunction getBuiltinBoolean() {
1178        return builtinBoolean;
1179    }
1180
1181    /**
1182     * Called from compiled script code to test if builtin has been overridden
1183     *
1184     * @return true if builtin boolean has not been overridden
1185     */
1186    public static boolean isBuiltinBoolean() {
1187        final Global instance = Global.instance();
1188        return instance._boolean == instance.getBuiltinBoolean();
1189    }
1190
1191    private ScriptFunction getBuiltinDate() {
1192        return builtinDate;
1193    }
1194
1195    /**
1196     * Called from compiled script code to test if builtin has been overridden
1197     *
1198     * @return true if builtin date has not been overridden
1199     */
1200    public static boolean isBuiltinDate() {
1201        final Global instance = Global.instance();
1202        return instance.date == instance.getBuiltinDate();
1203    }
1204
1205    private ScriptFunction getBuiltinError() {
1206        return builtinError;
1207    }
1208
1209    /**
1210     * Called from compiled script code to test if builtin has been overridden
1211     *
1212     * @return true if builtin error has not been overridden
1213     */
1214    public static boolean isBuiltinError() {
1215        final Global instance = Global.instance();
1216        return instance.error == instance.getBuiltinError();
1217    }
1218
1219    private ScriptFunction getBuiltinEvalError() {
1220        return builtinEvalError;
1221    }
1222
1223    /**
1224     * Called from compiled script code to test if builtin has been overridden
1225     *
1226     * @return true if builtin eval error has not been overridden
1227     */
1228    public static boolean isBuiltinEvalError() {
1229        final Global instance = Global.instance();
1230        return instance.evalError == instance.getBuiltinEvalError();
1231    }
1232
1233    private ScriptFunction getBuiltinFunction() {
1234        return builtinFunction;
1235    }
1236
1237    /**
1238     * Called from compiled script code to test if builtin has been overridden
1239     *
1240     * @return true if builtin function has not been overridden
1241     */
1242    public static boolean isBuiltinFunction() {
1243        final Global instance = Global.instance();
1244        return instance.function == instance.getBuiltinFunction();
1245    }
1246
1247    private ScriptFunction getBuiltinJSAdapter() {
1248        return builtinJSAdapter;
1249    }
1250
1251    /**
1252     * Called from compiled script code to test if builtin has been overridden
1253     *
1254     * @return true if builtin JSAdapter has not been overridden
1255     */
1256    public static boolean isBuiltinJSAdapter() {
1257        final Global instance = Global.instance();
1258        return instance.jsadapter == instance.getBuiltinJSAdapter();
1259    }
1260
1261    private ScriptObject getBuiltinJSON() {
1262        return builtinJSON;
1263    }
1264
1265    /**
1266     * Called from compiled script code to test if builtin has been overridden
1267     *
1268     * @return true if builtin JSON has has not been overridden
1269     */
1270    public static boolean isBuiltinJSON() {
1271        final Global instance = Global.instance();
1272        return instance.json == instance.getBuiltinJSON();
1273    }
1274
1275    private ScriptObject getBuiltinJava() {
1276        return builtinJava;
1277    }
1278
1279    /**
1280     * Called from compiled script code to test if builtin has been overridden
1281     *
1282     * @return true if builtin Java has not been overridden
1283     */
1284    public static boolean isBuiltinJava() {
1285        final Global instance = Global.instance();
1286        return instance.java == instance.getBuiltinJava();
1287    }
1288
1289    private ScriptObject getBuiltinJavax() {
1290        return builtinJavax;
1291    }
1292
1293    /**
1294     * Called from compiled script code to test if builtin has been overridden
1295     *
1296     * @return true if builtin Javax has not been overridden
1297     */
1298    public static boolean isBuiltinJavax() {
1299        final Global instance = Global.instance();
1300        return instance.javax == instance.getBuiltinJavax();
1301    }
1302
1303    private ScriptObject getBuiltinJavaImporter() {
1304        return builtinJavaImporter;
1305    }
1306
1307    /**
1308     * Called from compiled script code to test if builtin has been overridden
1309     *
1310     * @return true if builtin Java importer has not been overridden
1311     */
1312    public static boolean isBuiltinJavaImporter() {
1313        final Global instance = Global.instance();
1314        return instance.javaImporter == instance.getBuiltinJavaImporter();
1315    }
1316
1317    private ScriptObject getBuiltinMath() {
1318        return builtinMath;
1319    }
1320
1321    /**
1322     * Called from compiled script code to test if builtin has been overridden
1323     *
1324     * @return true if builtin math has not been overridden
1325     */
1326    public static boolean isBuiltinMath() {
1327        final Global instance = Global.instance();
1328        return instance.math == instance.getBuiltinMath();
1329    }
1330
1331    private ScriptFunction getBuiltinNumber() {
1332        return builtinNumber;
1333    }
1334
1335    /**
1336     * Called from compiled script code to test if builtin has been overridden
1337     *
1338     * @return true if builtin number has not been overridden
1339     */
1340    public static boolean isBuiltinNumber() {
1341        final Global instance = Global.instance();
1342        return instance.number == instance.getBuiltinNumber();
1343    }
1344
1345    private ScriptFunction getBuiltinObject() {
1346        return builtinObject;
1347    }
1348
1349    /**
1350     * Called from compiled script code to test if builtin has been overridden
1351     *
1352     * @return true if builtin object has not been overridden
1353     */
1354    public static boolean isBuiltinObject() {
1355        final Global instance = Global.instance();
1356        return instance.object == instance.getBuiltinObject();
1357    }
1358
1359    private ScriptObject getBuiltinPackages() {
1360        return builtinPackages;
1361    }
1362
1363    /**
1364     * Called from compiled script code to test if builtin has been overridden
1365     *
1366     * @return true if builtin package has not been overridden
1367     */
1368    public static boolean isBuiltinPackages() {
1369        final Global instance = Global.instance();
1370        return instance.packages == instance.getBuiltinPackages();
1371    }
1372
1373    private ScriptFunction getBuiltinRangeError() {
1374        return builtinRangeError;
1375    }
1376
1377    /**
1378     * Called from compiled script code to test if builtin has been overridden
1379     *
1380     * @return true if builtin range error has not been overridden
1381     */
1382    public static boolean isBuiltinRangeError() {
1383        final Global instance = Global.instance();
1384        return instance.rangeError == instance.getBuiltinRangeError();
1385    }
1386
1387    private ScriptFunction getBuiltinReferenceError() {
1388        return builtinReferenceError;
1389    }
1390
1391    /**
1392     * Called from compiled script code to test if builtin has been overridden
1393     *
1394     * @return true if builtin reference error has not been overridden
1395     */
1396    public static boolean isBuiltinReferenceError() {
1397        final Global instance = Global.instance();
1398        return instance.referenceError == instance.getBuiltinReferenceError();
1399    }
1400
1401    private ScriptFunction getBuiltinRegExp() {
1402        return builtinRegExp;
1403    }
1404
1405    /**
1406     * Called from compiled script code to test if builtin has been overridden
1407     *
1408     * @return true if builtin regexp has not been overridden
1409     */
1410    public static boolean isBuiltinRegExp() {
1411        final Global instance = Global.instance();
1412        return instance.regexp == instance.getBuiltinRegExp();
1413    }
1414
1415    private ScriptFunction getBuiltinString() {
1416        return builtinString;
1417    }
1418
1419    /**
1420     * Called from compiled script code to test if builtin has been overridden
1421     *
1422     * @return true if builtin Java has not been overridden
1423     */
1424    public static boolean isBuiltinString() {
1425        final Global instance = Global.instance();
1426        return instance.string == instance.getBuiltinString();
1427    }
1428
1429    private ScriptFunction getBuiltinSyntaxError() {
1430        return builtinSyntaxError;
1431    }
1432
1433    /**
1434     * Called from compiled script code to test if builtin has been overridden
1435     *
1436     * @return true if builtin syntax error has not been overridden
1437     */
1438    public static boolean isBuiltinSyntaxError() {
1439        final Global instance = Global.instance();
1440        return instance.syntaxError == instance.getBuiltinSyntaxError();
1441    }
1442
1443    private ScriptFunction getBuiltinTypeError() {
1444        return builtinTypeError;
1445    }
1446
1447    /**
1448     * Called from compiled script code to test if builtin has been overridden
1449     *
1450     * @return true if builtin type error has not been overridden
1451     */
1452    public static boolean isBuiltinTypeError() {
1453        final Global instance = Global.instance();
1454        return instance.typeError == instance.getBuiltinTypeError();
1455    }
1456
1457    private ScriptFunction getBuiltinURIError() {
1458        return builtinURIError;
1459    }
1460
1461    /**
1462     * Called from compiled script code to test if builtin has been overridden
1463     *
1464     * @return true if builtin URI error has not been overridden
1465     */
1466    public static boolean isBuiltinURIError() {
1467        final Global instance = Global.instance();
1468        return instance.uriError == instance.getBuiltinURIError();
1469    }
1470
1471    @Override
1472    public String getClassName() {
1473        return "global";
1474    }
1475
1476    /**
1477     * Copy function used to clone NativeRegExp objects.
1478     *
1479     * @param regexp a NativeRegExp to clone
1480     *
1481     * @return copy of the given regexp object
1482     */
1483    public static Object regExpCopy(final Object regexp) {
1484        return new NativeRegExp((NativeRegExp)regexp);
1485    }
1486
1487    /**
1488     * Convert given object to NativeRegExp type.
1489     *
1490     * @param obj object to be converted
1491     * @return NativeRegExp instance
1492     */
1493    public static NativeRegExp toRegExp(final Object obj) {
1494        if (obj instanceof NativeRegExp) {
1495            return (NativeRegExp)obj;
1496        }
1497        return new NativeRegExp(JSType.toString(obj));
1498    }
1499
1500    /**
1501     * ECMA 9.9 ToObject implementation
1502     *
1503     * @param obj  an item for which to run ToObject
1504     * @return ToObject version of given item
1505     */
1506    public static Object toObject(final Object obj) {
1507        if (obj == null || obj == UNDEFINED) {
1508            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1509        }
1510
1511        if (obj instanceof ScriptObject) {
1512            return obj;
1513        }
1514
1515        return instance().wrapAsObject(obj);
1516    }
1517
1518    /**
1519     * Allocate a new object array.
1520     *
1521     * @param initial object values.
1522     * @return the new array
1523     */
1524    public static NativeArray allocate(final Object[] initial) {
1525        ArrayData arrayData = ArrayData.allocate(initial);
1526
1527        for (int index = 0; index < initial.length; index++) {
1528            final Object value = initial[index];
1529
1530            if (value == ScriptRuntime.EMPTY) {
1531                arrayData = arrayData.delete(index);
1532            }
1533        }
1534
1535        return new NativeArray(arrayData);
1536    }
1537
1538    /**
1539     * Allocate a new number array.
1540     *
1541     * @param initial number values.
1542     * @return the new array
1543     */
1544    public static NativeArray allocate(final double[] initial) {
1545        return new NativeArray(ArrayData.allocate(initial));
1546    }
1547
1548    /**
1549     * Allocate a new long array.
1550     *
1551     * @param initial number values.
1552     * @return the new array
1553     */
1554    public static NativeArray allocate(final long[] initial) {
1555        return new NativeArray(ArrayData.allocate(initial));
1556    }
1557
1558    /**
1559     * Allocate a new integer array.
1560     *
1561     * @param initial number values.
1562     * @return the new array
1563     */
1564    public static NativeArray allocate(final int[] initial) {
1565        return new NativeArray(ArrayData.allocate(initial));
1566    }
1567
1568    /**
1569     * Allocate a new object array for arguments.
1570     *
1571     * @param arguments initial arguments passed.
1572     * @param callee reference to the function that uses arguments object
1573     * @param numParams actual number of declared parameters
1574     *
1575     * @return the new array
1576     */
1577    public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1578        return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1579    }
1580
1581    /**
1582     * Called from generated to check if given function is the builtin 'eval'. If
1583     * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1584     *
1585     * @param  fn function object that is checked
1586     * @return true if fn is the builtin eval
1587     */
1588    public static boolean isEval(final Object fn) {
1589        return fn == Global.instance().builtinEval;
1590    }
1591
1592    /**
1593     * Called from generated to replace a location property placeholder with the actual location property value.
1594     *
1595     * @param  placeholder the value tested for being a placeholder for a location property
1596     * @param  locationProperty the actual value for the location property
1597     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
1598     */
1599    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
1600        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
1601    }
1602
1603    /**
1604     * Called from runtime internals to check if the passed value is a location property placeholder.
1605     * @param  placeholder the value tested for being a placeholder for a location property
1606     * @return true if the value is a placeholder, false otherwise.
1607     */
1608    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
1609        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
1610    }
1611
1612    /**
1613     * Create a new RegExp object.
1614     *
1615     * @param expression Regular expression.
1616     * @param options    Search options.
1617     *
1618     * @return New RegExp object.
1619     */
1620    public static Object newRegExp(final String expression, final String options) {
1621        if (options == null) {
1622            return new NativeRegExp(expression);
1623        }
1624        return new NativeRegExp(expression, options);
1625    }
1626
1627    /**
1628     * Get the object prototype
1629     *
1630     * @return the object prototype
1631     */
1632    public static ScriptObject objectPrototype() {
1633        return Global.instance().getObjectPrototype();
1634    }
1635
1636    /**
1637     * Create a new empty object instance.
1638     *
1639     * @return New empty object.
1640     */
1641    public static ScriptObject newEmptyInstance() {
1642        return Global.instance().newObject();
1643    }
1644
1645    /**
1646     * Check if a given object is a ScriptObject, raises an exception if this is
1647     * not the case
1648     *
1649     * @param obj and object to check
1650     * @return the script object
1651     */
1652    public static ScriptObject checkObject(final Object obj) {
1653        if (!(obj instanceof ScriptObject)) {
1654            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1655        }
1656        return (ScriptObject)obj;
1657    }
1658
1659    /**
1660     * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1661     * if this object is null or undefined.
1662     *
1663     * @param obj an object to check
1664     */
1665    public static void checkObjectCoercible(final Object obj) {
1666        if (obj == null || obj == UNDEFINED) {
1667            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1668        }
1669    }
1670
1671    /**
1672     * Get the current split state.
1673     *
1674     * @return current split state
1675     */
1676    @Override
1677    public int getSplitState() {
1678        return splitState;
1679    }
1680
1681    /**
1682     * Set the current split state.
1683     *
1684     * @param state current split state
1685     */
1686    @Override
1687    public void setSplitState(final int state) {
1688        splitState = state;
1689    }
1690
1691    private void init(final ScriptEngine engine) {
1692        assert Context.getGlobal() == this : "this global is not set as current";
1693
1694        final ScriptEnvironment env = getContext().getEnv();
1695
1696        // initialize Function and Object constructor
1697        initFunctionAndObject();
1698
1699        // Now fix Global's own proto.
1700        this.setInitialProto(getObjectPrototype());
1701
1702        // initialize global function properties
1703        this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1704
1705        this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
1706                new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O });
1707        this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1708        this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1709        this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1710        this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1711        this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1712        this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1713        this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1714        this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1715        this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1716        this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1717        this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1718        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1719        this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1720        this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1721
1722        // built-in constructors
1723        this.builtinArray     = initConstructor("Array", ScriptFunction.class);
1724        this.builtinBoolean   = initConstructor("Boolean", ScriptFunction.class);
1725        this.builtinDate      = initConstructor("Date", ScriptFunction.class);
1726        this.builtinJSON      = initConstructor("JSON", ScriptObject.class);
1727        this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class);
1728        this.builtinMath      = initConstructor("Math", ScriptObject.class);
1729        this.builtinNumber    = initConstructor("Number", ScriptFunction.class);
1730        this.builtinRegExp    = initConstructor("RegExp", ScriptFunction.class);
1731        this.builtinString    = initConstructor("String", ScriptFunction.class);
1732
1733        // initialize String.prototype.length to 0
1734        // add String.prototype.length
1735        final ScriptObject stringPrototype = getStringPrototype();
1736        stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1737
1738        // set isArray flag on Array.prototype
1739        final ScriptObject arrayPrototype = getArrayPrototype();
1740        arrayPrototype.setIsArray();
1741
1742        this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1743
1744        // initialize default regexp object
1745        this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1746
1747        // RegExp.prototype should behave like a RegExp object. So copy the
1748        // properties.
1749        final ScriptObject regExpProto = getRegExpPrototype();
1750        regExpProto.addBoundProperties(DEFAULT_REGEXP);
1751
1752        // Error stuff
1753        initErrorObjects();
1754
1755        // java access
1756        if (! env._no_java) {
1757            initJavaAccess();
1758        }
1759
1760        if (! env._no_typed_arrays) {
1761            initTypedArray();
1762        }
1763
1764        if (env._scripting) {
1765            initScripting(env);
1766        }
1767
1768        if (Context.DEBUG) {
1769            boolean debugOkay;
1770            final SecurityManager sm = System.getSecurityManager();
1771            if (sm != null) {
1772                try {
1773                    sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1774                    debugOkay = true;
1775                } catch (final SecurityException ignored) {
1776                    // if no permission, don't initialize Debug object
1777                    debugOkay = false;
1778                }
1779
1780            } else {
1781                debugOkay = true;
1782            }
1783
1784            if (debugOkay) {
1785                initDebug();
1786            }
1787        }
1788
1789        copyBuiltins();
1790
1791        // expose script (command line) arguments as "arguments" property of global
1792        arguments = wrapAsObject(env.getArguments().toArray());
1793        if (env._scripting) {
1794            // synonym for "arguments" in scripting mode
1795            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
1796        }
1797
1798        if (engine != null) {
1799            // default file name
1800            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
1801            // __noSuchProperty__ hook for ScriptContext search of missing variables
1802            final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
1803            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
1804        }
1805    }
1806
1807    private void initErrorObjects() {
1808        // Error objects
1809        this.builtinError = initConstructor("Error", ScriptFunction.class);
1810        final ScriptObject errorProto = getErrorPrototype();
1811
1812        // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1813        final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1814        final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1815        errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1816        final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1817        final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1818        errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1819        final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1820        final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1821        errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1822        final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1823        final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1824        errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1825
1826        // ECMA 15.11.4.2 Error.prototype.name
1827        // Error.prototype.name = "Error";
1828        errorProto.set(NativeError.NAME, "Error", 0);
1829        // ECMA 15.11.4.3 Error.prototype.message
1830        // Error.prototype.message = "";
1831        errorProto.set(NativeError.MESSAGE, "", 0);
1832
1833        this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1834        this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1835        this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1836        this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1837        this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1838        this.builtinURIError = initErrorSubtype("URIError", errorProto);
1839    }
1840
1841    private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1842        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
1843        final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1844        prototype.set(NativeError.NAME, name, 0);
1845        prototype.set(NativeError.MESSAGE, "", 0);
1846        prototype.setInitialProto(errorProto);
1847        return cons;
1848    }
1849
1850    private void initJavaAccess() {
1851        final ScriptObject objectProto = getObjectPrototype();
1852        this.builtinPackages = new NativeJavaPackage("", objectProto);
1853        this.builtinCom = new NativeJavaPackage("com", objectProto);
1854        this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1855        this.builtinJava = new NativeJavaPackage("java", objectProto);
1856        this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1857        this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1858        this.builtinOrg = new NativeJavaPackage("org", objectProto);
1859        this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1860        this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1861    }
1862
1863    private void initScripting(final ScriptEnvironment scriptEnv) {
1864        Object value;
1865        value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1866        addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1867
1868        value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1869        addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1870
1871        final String execName = ScriptingFunctions.EXEC_NAME;
1872        value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1873        addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1874
1875        // Nashorn extension: global.echo (scripting-mode-only)
1876        // alias for "print"
1877        value = get("print");
1878        addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1879
1880        // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1881        final ScriptObject options = newObject();
1882        copyOptions(options, scriptEnv);
1883        addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1884
1885        // Nashorn extension: global.$ENV (scripting-mode-only)
1886        if (System.getSecurityManager() == null) {
1887            // do not fill $ENV if we have a security manager around
1888            // Retrieve current state of ENV variables.
1889            final ScriptObject env = newObject();
1890            env.putAll(System.getenv(), scriptEnv._strict);
1891            addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1892        } else {
1893            addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1894        }
1895
1896        // add other special properties for exec support
1897        addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1898        addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1899        addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1900    }
1901
1902    private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1903        for (final Field f : scriptEnv.getClass().getFields()) {
1904            try {
1905                options.set(f.getName(), f.get(scriptEnv), 0);
1906            } catch (final IllegalArgumentException | IllegalAccessException exp) {
1907                throw new RuntimeException(exp);
1908            }
1909        }
1910    }
1911
1912    private void initTypedArray() {
1913        this.builtinArrayBuffer       = initConstructor("ArrayBuffer", ScriptFunction.class);
1914        this.builtinDataView          = initConstructor("DataView", ScriptFunction.class);
1915        this.builtinInt8Array         = initConstructor("Int8Array", ScriptFunction.class);
1916        this.builtinUint8Array        = initConstructor("Uint8Array", ScriptFunction.class);
1917        this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class);
1918        this.builtinInt16Array        = initConstructor("Int16Array", ScriptFunction.class);
1919        this.builtinUint16Array       = initConstructor("Uint16Array", ScriptFunction.class);
1920        this.builtinInt32Array        = initConstructor("Int32Array", ScriptFunction.class);
1921        this.builtinUint32Array       = initConstructor("Uint32Array", ScriptFunction.class);
1922        this.builtinFloat32Array      = initConstructor("Float32Array", ScriptFunction.class);
1923        this.builtinFloat64Array      = initConstructor("Float64Array", ScriptFunction.class);
1924    }
1925
1926    private void copyBuiltins() {
1927        this.array             = this.builtinArray;
1928        this._boolean          = this.builtinBoolean;
1929        this.date              = this.builtinDate;
1930        this.error             = this.builtinError;
1931        this.evalError         = this.builtinEvalError;
1932        this.function          = this.builtinFunction;
1933        this.jsadapter         = this.builtinJSAdapter;
1934        this.json              = this.builtinJSON;
1935        this.com               = this.builtinCom;
1936        this.edu               = this.builtinEdu;
1937        this.java              = this.builtinJava;
1938        this.javafx            = this.builtinJavafx;
1939        this.javax             = this.builtinJavax;
1940        this.org               = this.builtinOrg;
1941        this.javaImporter      = this.builtinJavaImporter;
1942        this.javaApi           = this.builtinJavaApi;
1943        this.math              = this.builtinMath;
1944        this.number            = this.builtinNumber;
1945        this.object            = this.builtinObject;
1946        this.packages          = this.builtinPackages;
1947        this.rangeError        = this.builtinRangeError;
1948        this.referenceError    = this.builtinReferenceError;
1949        this.regexp            = this.builtinRegExp;
1950        this.string            = this.builtinString;
1951        this.syntaxError       = this.builtinSyntaxError;
1952        this.typeError         = this.builtinTypeError;
1953        this.uriError          = this.builtinURIError;
1954        this.arrayBuffer       = this.builtinArrayBuffer;
1955        this.dataView          = this.builtinDataView;
1956        this.int8Array         = this.builtinInt8Array;
1957        this.uint8Array        = this.builtinUint8Array;
1958        this.uint8ClampedArray = this.builtinUint8ClampedArray;
1959        this.int16Array        = this.builtinInt16Array;
1960        this.uint16Array       = this.builtinUint16Array;
1961        this.int32Array        = this.builtinInt32Array;
1962        this.uint32Array       = this.builtinUint32Array;
1963        this.float32Array      = this.builtinFloat32Array;
1964        this.float64Array      = this.builtinFloat64Array;
1965    }
1966
1967    private void initDebug() {
1968        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
1969    }
1970
1971    private Object printImpl(final boolean newLine, final Object... objects) {
1972        @SuppressWarnings("resource")
1973        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
1974        final StringBuilder sb = new StringBuilder();
1975
1976        for (final Object obj : objects) {
1977            if (sb.length() != 0) {
1978                sb.append(' ');
1979            }
1980
1981            sb.append(JSType.toString(obj));
1982        }
1983
1984        // Print all at once to ensure thread friendly result.
1985        if (newLine) {
1986            out.println(sb.toString());
1987        } else {
1988            out.print(sb.toString());
1989        }
1990
1991        out.flush();
1992
1993        return UNDEFINED;
1994    }
1995
1996    /**
1997     * These classes are generated by nasgen tool and so we have to use
1998     * reflection to load and create new instance of these classes.
1999     */
2000    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2001        try {
2002            // Assuming class name pattern for built-in JS constructors.
2003            final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2004
2005            sb.append("Native");
2006            sb.append(name);
2007            sb.append("$Constructor");
2008
2009            final Class<?> funcClass = Class.forName(sb.toString());
2010            final T res = clazz.cast(funcClass.newInstance());
2011
2012            if (res instanceof ScriptFunction) {
2013                // All global constructor prototypes are not-writable,
2014                // not-enumerable and not-configurable.
2015                final ScriptFunction func = (ScriptFunction)res;
2016                func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2017            }
2018
2019            if (res.getProto() == null) {
2020                res.setInitialProto(getObjectPrototype());
2021            }
2022
2023            res.setIsBuiltin();
2024            return res;
2025        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2026            throw new RuntimeException(e);
2027        }
2028    }
2029
2030    // Function and Object constructors are inter-dependent. Also,
2031    // Function.prototype
2032    // functions are not properly initialized. We fix the references here.
2033    // NOTE: be careful if you want to re-order the operations here. You may
2034    // have
2035    // to play with object references carefully!!
2036    private void initFunctionAndObject() {
2037        // First-n-foremost is Function
2038        this.builtinFunction      = initConstructor("Function", ScriptFunction.class);
2039
2040        // create global anonymous function
2041        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2042        // need to copy over members of Function.prototype to anon function
2043        anon.addBoundProperties(getFunctionPrototype());
2044
2045        // Function.prototype === Object.getPrototypeOf(Function) ===
2046        // <anon-function>
2047        builtinFunction.setInitialProto(anon);
2048        builtinFunction.setPrototype(anon);
2049        anon.set("constructor", builtinFunction, 0);
2050        anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2051
2052        // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2053        this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2054        typeErrorThrower.setPrototype(UNDEFINED);
2055        // Non-constructor built-in functions do not have "prototype" property
2056        typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2057        typeErrorThrower.preventExtensions();
2058
2059        // now initialize Object
2060        this.builtinObject = initConstructor("Object", ScriptFunction.class);
2061        final ScriptObject ObjectPrototype = getObjectPrototype();
2062        // Object.getPrototypeOf(Function.prototype) === Object.prototype
2063        anon.setInitialProto(ObjectPrototype);
2064
2065        // ES6 draft compliant __proto__ property of Object.prototype
2066        // accessors on Object.prototype for "__proto__"
2067        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2068        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2069        ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2070
2071        // Function valued properties of Function.prototype were not properly
2072        // initialized. Because, these were created before global.function and
2073        // global.object were not initialized.
2074        jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2075        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2076            final Object key = property.getKey();
2077            final Object value = builtinFunction.get(key);
2078
2079            if (value instanceof ScriptFunction && value != anon) {
2080                final ScriptFunction func = (ScriptFunction)value;
2081                func.setInitialProto(getFunctionPrototype());
2082                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2083                if (prototype != null) {
2084                    prototype.setInitialProto(ObjectPrototype);
2085                }
2086            }
2087        }
2088
2089        // For function valued properties of Object and Object.prototype, make
2090        // sure prototype's proto chain ends with Object.prototype
2091        for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2092            final Object key = property.getKey();
2093            final Object value = builtinObject.get(key);
2094
2095            if (value instanceof ScriptFunction) {
2096                final ScriptFunction func = (ScriptFunction)value;
2097                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2098                if (prototype != null) {
2099                    prototype.setInitialProto(ObjectPrototype);
2100                }
2101            }
2102        }
2103
2104        //make sure apply and call have the same invalidation switchpoint
2105        final SwitchPoint sp = new SwitchPoint();
2106        optimisticFunctionMap.put("apply", sp);
2107        optimisticFunctionMap.put("call", sp);
2108        getFunctionPrototype().getProperty("apply").setChangeCallback(sp);
2109        getFunctionPrototype().getProperty("call").setChangeCallback(sp);
2110
2111        properties = getObjectPrototype().getMap().getProperties();
2112
2113        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2114            final Object key   = property.getKey();
2115            if (key.equals("constructor")) {
2116                continue;
2117            }
2118
2119            final Object value = ObjectPrototype.get(key);
2120            if (value instanceof ScriptFunction) {
2121                final ScriptFunction func = (ScriptFunction)value;
2122                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2123                if (prototype != null) {
2124                    prototype.setInitialProto(ObjectPrototype);
2125                }
2126            }
2127        }
2128    }
2129
2130    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
2131        return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2132    }
2133
2134    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2135        return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2136    }
2137
2138    RegExpResult getLastRegExpResult() {
2139        return lastRegExpResult;
2140    }
2141
2142    void setLastRegExpResult(final RegExpResult regExpResult) {
2143        this.lastRegExpResult = regExpResult;
2144    }
2145
2146    @Override
2147    protected boolean isGlobal() {
2148        return true;
2149    }
2150
2151    /**
2152     * Check if there is a switchpoint for a reserved name. If there
2153     * is, it must be invalidated upon properties with this name
2154     * @param name property name
2155     * @return switchpoint for invalidating this property, or null if not registered
2156     */
2157    public SwitchPoint getChangeCallback(final String name) {
2158        return optimisticFunctionMap.get(name);
2159    }
2160
2161    /**
2162     * Is this a special name, that might be subject to invalidation
2163     * on write, such as "apply" or "call"
2164     * @param name name to check
2165     * @return true if special name
2166     */
2167    public boolean isSpecialName(final String name) {
2168        return getChangeCallback(name) != null;
2169    }
2170
2171    /**
2172     * Check if a reserved property name is invalidated
2173     * @param name property name
2174     * @return true if someone has written to it since Global was instantiated
2175     */
2176    public boolean isSpecialNameValid(final String name) {
2177        final SwitchPoint sp = getChangeCallback(name);
2178        return sp != null && !sp.hasBeenInvalidated();
2179    }
2180
2181    /**
2182     * Tag a reserved name as invalidated - used when someone writes
2183     * to a property with this name - overly conservative, but link time
2184     * is too late to apply e.g. apply-&gt;call specialization
2185     * @param name property name
2186     */
2187    public void invalidateReservedName(final String name) {
2188        final SwitchPoint sp = getChangeCallback(name);
2189        if (sp != null) {
2190            getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
2191            SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
2192        }
2193    }
2194
2195    /**
2196     * Bootstrapper for invalidating a builtin name
2197     * @param lookup lookup
2198     * @param name   name to invalidate
2199     * @param type   methodhandle type
2200     * @return callsite for invalidator
2201     */
2202    public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) {
2203        final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name);
2204        return new ConstantCallSite(target);
2205    }
2206
2207
2208}
2209